---
title: "Référence d'API — @nodefony/drizzle — racine"
source: docs/api/drizzle/racine.md
url: https://nodefony.github.io/nodefony-core/docs/api/drizzle/racine/
---


[Documentation](../../../) › [Référence d'API](../../) › [`@nodefony/drizzle`](../) › racine

> Générée depuis les déclarations de types publiées de `@nodefony/drizzle` **10.0.0-beta.5** : exactement ce que reçoit une application qui l'installe. Cette page n'existe dans aucun dépôt — pour la corriger, on corrige le TSDoc du code.

## `@nodefony/drizzle`

`import { … } from "@nodefony/drizzle"` — 14 symboles.

### Classes (9)

#### `DrizzleAuditStore`

```ts
class DrizzleAuditStore implements IAuditStore
```

Journal d'audit **Drizzle** (driver `better-sqlite3` en test, Postgres/MySQL en prod) — implémentation SQL d'`IAuditStore` (append-only, tamper-evident) pour la **rétention longue** et le **partage cross-pod**, là où le store mémoire par défaut reste affine à un pod et volatile.

- `constructor(resolveDb: () => DrizzleDb | null, now?: () => number, retentionMs?: number, table?: DrizzleTable, location?: string)`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation`.
- `get connector(): string` — Connecteur ORM qui porte ce store, lu par `readStoreConnector` pour le registre des stores : la console rattache la brique à SON connecteur au lieu de le déduire.
- `static from(orm: DrizzleOrm, now?: () => number, retentionMs?: number): DrizzleAuditStore` — Construit le store depuis un `DrizzleOrm`.
- `append(event: IAuditEvent): Promise<void>` — Ajoute un événement (immuable, jamais modifié ensuite).
- `listPage(query: IAuditListQuery): Promise<IPage<IAuditEvent>>` — Lit **une page** d'événements filtrés, du plus récent au plus ancien — l'implémentation ne matérialise jamais plus que `limit` événements.
- `gc(now?: number): Promise<number>` — Purge les événements au-delà de la fenêtre de rétention.

#### `DrizzleIdempotencyStore`

```ts
class DrizzleIdempotencyStore implements IIdempotencyStore
```

Store d'idempotence **Drizzle** (driver `better-sqlite3` en test, Postgres/MySQL en prod) — implémentation SQL d'`IIdempotencyStore` (contrat au CORE) pour dédoublonner les mutations rejouées PARTAGÉ cross-pod, là où le store mémoire par défaut reste affine à un pod.

- `constructor(resolveDb: () => DrizzleDb | null, now?: () => number, leaseMs?: number, ttlMs?: number, table?: DrizzleTable, resolveLocation?: () => string, connector?: string)`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation`.
- `get connector(): string` — Connecteur ORM qui porte ce store, lu par `readStoreConnector` pour le registre des stores : la console rattache la brique à SON connecteur au lieu de le déduire.
- `static from(orm: DrizzleOrm, now?: () => number, leaseMs?: number, ttlMs?: number): DrizzleIdempotencyStore` — Construit le store depuis un `DrizzleOrm`.
- `get size(): number` — Approximation **per-pod, best-effort** : compteur local des réservations faites par CE pod (incrémenté au `fresh`, décrémenté au `complete`/`abort`), non décrémenté si le bail expire sans complétion, …
- `begin(key: string, fingerprint: string): Promise<IdempotencyOutcome>` — Réserve **atomiquement** la clé et renvoie le verdict à suivre.
- `complete(key: string, response: IdempotentResponse): Promise<void>` — Mémorise la réponse d'une clé *in-flight* (TTL) → rejeux futurs = `replayed`.
- `abort(key: string): Promise<void>` — Libère une clé *in-flight* dont l'exécution a échoué : rien n'est mémorisé (un échec doit pouvoir être réessayé).
- `gc(now?: number): Promise<number>` — Purge les entrées mortes (`expiresAt <= now`) — supplée l'absence de TTL natif SQL (≠ Redis `PX`).
- `listPage(query: IIdempotencyListQuery): Promise<IPage<IIdempotencyKeyEntry>>` — {@inheritDoc IIdempotencyStore.listPage}

#### `DrizzleTokenStore`

```ts
class DrizzleTokenStore implements ITokenStore
```

Store de jetons **Drizzle** (driver `better-sqlite3`) — implémentation SQL d'`ITokenStore` au-dessus de trois repositories `@nodefony/orm-core` (`access_token`, `denied_jti`, `subject_revocation`).

- `readonly sortableFields: readonly [ "createdAt", "name", "subjectId", "id" ]` — {@inheritDoc ITokenStore.sortableFields}
- `constructor(records: IRepository<IAccessTokenRecord>, denied: IRepository<DeniedJtiRow>, revocations: IRepository<SubjectRevocationRow>, now?: () => number, retentionRevokedMs?: number, location?: str …`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation`.
- `get connector(): string` — Connecteur ORM qui porte ce store, lu par `readStoreConnector` pour le registre des stores : la console rattache la brique à SON connecteur au lieu de le déduire.
- `static from(orm: DrizzleOrm, now?: () => number, retentionRevokedMs?: number): DrizzleTokenStore` — Construit le store depuis un `DrizzleOrm` connecté.
- `put(record: IAccessTokenRecord): Promise<void>` — Insère ou remplace un record (PAT / refresh) — 1 requête, `upsert` atomique sur la PK `id` plutôt qu'un `findOne` d'existence + `create`/`updateOne` (2 round-trips).
- `findById(id: string): Promise<IAccessTokenRecord | null>` — Recherche par identifiant (`jti`/id public).
- `findByHash(secretHash: string): Promise<IAccessTokenRecord | null>` — Recherche par hash de secret présenté.
- `findBySubject(subjectId: string): Promise<IAccessTokenRecord[]>` — Tous les jetons d'un porteur (console « mes jetons », révocation ciblée).
- `listAll(): Promise<IAccessTokenRecord[]>` — Tous les jetons (PAT + refresh) — vue d'administration cross-porteur.
- `listPage(query: ITokenListQuery): Promise<IPage<IAccessTokenRecord>>` — {@inheritDoc ITokenStore.listPage}
- `countTokens(query: ITokenListQuery): Promise<number>` — {@inheritDoc ITokenStore.countTokens}
- `markUsed(id: string, usage: ITokenUsage): Promise<void>` — Met à jour `lastUsedAt`/IP/UA (no-op si l'id est inconnu).
- `revoke(id: string, reason: TokenRevokeReason): Promise<void>` — Révoque un jeton — **idempotent** : la 1ʳᵉ date/raison de révocation est conservée (l'audit ne se réécrit pas).
- `revokeFamily(family: string, reason: TokenRevokeReason): Promise<void>` — Coupe toute une famille de refresh (détection de rejeu, RFC 9700) — les membres déjà révoqués (ex.
- `denyJti(jti: string, expiresAt: number): Promise<void>` — Inscrit un `jti` d'access sur la denylist jusqu'à `expiresAt` (epoch ms) — révocation immédiate avant l'`exp` du JWT.
- `isJtiDenied(jti: string): Promise<boolean>` — `true` si le `jti` est denylisté et non encore expiré.
- `revokeAllForSubject(subjectId: string, invalidBefore: number): Promise<void>` — Pose le seuil de révocation en masse d'un porteur (« déconnecte-moi de partout ») : tout jeton émis avant `invalidBefore` est mort.
- `getInvalidBefore(subjectId: string): Promise<number | null>` — Seuil `invalidBefore` d'un porteur (epoch ms) ou `null` si aucun.
- `gc(now?: number): Promise<number>` — Purge les entrées devenues inutiles : denylist `jti` expirée, records arrivés à `exp`, PAT révoqués sans expiration au-delà de la fenêtre de rétention.

#### `DrizzleTotpSecretStore`

```ts
class DrizzleTotpSecretStore implements ITotpSecretStore
```

Store de secrets TOTP **Drizzle** (driver `better-sqlite3`) — implémentation SQL d'`ITotpSecretStore` au-dessus d'un unique repository `@nodefony/orm-core` (`totp_secret`). Comble le gap « 2FA persistant sans fichier » : là où `MemoryTotpSecretStore` est volatile, ce store survit au redémarrage et se partage entre pods (base durable).

- `constructor(repo: IRepository<TotpSecretRow>, location?: string)`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation`.
- `get connector(): string` — Connecteur ORM qui porte ce store, lu par `readStoreConnector` pour le registre des stores : la console rattache la brique à SON connecteur au lieu de le déduire.
- `static from(orm: DrizzleOrm): DrizzleTotpSecretStore` — Construit le store depuis un `DrizzleOrm` connecté.
- `findByUser(userId: string): Promise<ITotpSecret | null>` — Secret TOTP de l'utilisateur, ou `null` si non enrôlé.
- `save(secret: ITotpSecret): Promise<void>` — Crée ou remplace le secret de l'utilisateur (upsert — ré-enrôlement).
- `update(userId: string, patch: TotpSecretUpdate): Promise<void>` — Applique un patch partiel (confirmation, anti-rejeu, consommation de codes).
- `delete(userId: string): Promise<void>` — Supprime le secret de l'utilisateur (désactivation du 2FA).
- `listPage(query: ITotpListQuery): Promise<IPage<ITotpEnrollmentSummary>>` — {@inheritDoc ITotpSecretStore.listPage}
- `countEnrollments(query: ITotpListQuery): Promise<number>` — {@inheritDoc ITotpSecretStore.countEnrollments}

#### `DrizzleUserRepository`

```ts
class DrizzleUserRepository implements IUserRepository
```

- `readonly sortableFields: readonly [ "identifier", "enabled", "createdAt", "updatedAt", "id" ]` — Même vocabulaire public que les autres repositories — ici le tri part dans la requête, où il ne coûte qu'un index.
- `constructor(base: IRepository<UserRow>, db: DrizzleDb, dialect?: SqlDialect)`
- `static from(orm: DrizzleOrm): DrizzleUserRepository` — Construit le repository utilisateur depuis un `DrizzleOrm` connecté.
- `find(criteria?: Criteria<IPasswordAuthenticatedUser>, options?: RepositoryReadOptions): Promise<IPasswordAuthenticatedUser[]>` — Retourne toutes les entités correspondant au critère (toutes si omis).
- `findOne(criteria: Criteria<IPasswordAuthenticatedUser>, options?: RepositoryReadOptions): Promise<IPasswordAuthenticatedUser | null>` — Retourne la première entité correspondant au critère, ou `null`.
- `create(data: Partial<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser>` — Persiste une nouvelle entité et retourne sa version persistée (id généré, valeurs par défaut).
- `updateOne(criteria: Criteria<IPasswordAuthenticatedUser>, data: Partial<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser | null>` — Met à jour **au plus une** entité correspondant au critère, de façon **atomique**, et retourne sa version persistée (ou `null` si aucune ne correspond).
- `upsert(criteria: Criteria<IPasswordAuthenticatedUser>, update: Partial<IPasswordAuthenticatedUser>, insertOnly?: Partial<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser>` — Insère **ou** met à jour atomiquement l'entité identifiée par `criteria` (clé unique), en **une seule** requête (`INSERT … ON CONFLICT DO UPDATE … RETURNING` SQL / `findOneAndUpdate({ upsert })` Mongo …
- `createMany(data: Partial<IPasswordAuthenticatedUser>[]): Promise<IPasswordAuthenticatedUser[]>` — Insère **plusieurs** entités en **une seule** requête (`INSERT … VALUES (…),(…)` SQL / `insertMany` Mongo) et retourne leurs versions persistées (ids générés, défauts appliqués), dans l'ordre.
- `exists(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<boolean>` — Indique si **au moins une** entité correspond au critère, sans rapatrier la ligne (`SELECT 1 … LIMIT 1` SQL / `exists` Mongo).
- `deleteOne(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<boolean>` — Supprime **au plus une** entité de façon **atomique** (symétrique d'`IRepository.updateOne` ; `DELETE … LIMIT 1` SQL / `deleteOne` Mongo).
- `findOneAndDelete(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser | null>` — Supprime **au plus une** entité et **retourne** sa valeur supprimée (ou `null`), de façon atomique (`DELETE … RETURNING` SQL / `findOneAndDelete` Mongo) — claim-and-remove (file de jobs, outbox, pop a …
- `increment(criteria: Criteria<IPasswordAuthenticatedUser>, changes: Partial<Record<keyof IPasswordAuthenticatedUser, number>>): Promise<IPasswordAuthenticatedUser | null>` — Incrémente **atomiquement** des champs numériques d'**au plus une** entité (`SET f = f + ?` SQL / `$inc` Mongo), sans read-modify-write (donc sans race) — pour les compteurs (stats, usage/tokens, rate …
- `updateMany(criteria: Criteria<IPasswordAuthenticatedUser>, data: Partial<IPasswordAuthenticatedUser>): Promise<number>` — Met à jour **toutes** les entités correspondant au critère et retourne le **nombre** de lignes modifiées (parité de signature avec `IRepository.delete`).
- `delete(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<number>` — Supprime les entités correspondant au critère.
- `count(criteria?: Criteria<IPasswordAuthenticatedUser>): Promise<number>` — Compte les entités correspondant au critère (toutes si omis).
- `countDistinct(field: Extract<keyof IPasswordAuthenticatedUser, string>, criteria?: Criteria<IPasswordAuthenticatedUser>): Promise<number>` — Compte les **valeurs distinctes** d'un champ parmi les entités qui correspondent au critère (`COUNT(DISTINCT col)` SQL / agrégation Mongo).
- `withTransaction(tx: ITransaction): IUserRepository` — Retourne une **vue de ce repository liée à une transaction** : toutes ses opérations s'exécutent dans `tx` (commit/rollback gérés par `IOrm.transaction()`).
- `findByIdentifier(identifier: string): Promise<IPasswordAuthenticatedUser | null>` — Retrouve un utilisateur par son identifiant fonctionnel (email, login...).
- `findBySocialProvider(provider: string, providerId: string): Promise<IPasswordAuthenticatedUser | null>` — Recherche par compte externe lié — cherche dans le JSON `socialProviders` via le queryKit (forme native du dialecte : `json_each` SQLite / `@>` jsonb PG, 1 requête), récupère l'`id`, puis recharge par …
- `listPage(query: IUserListQuery): Promise<IPage<IPasswordAuthenticatedUser>>` — {@inheritDoc IUserRepository.listPage}
- `countUsers(query: IUserListQuery): Promise<number>` — {@inheritDoc IUserRepository.countUsers}
- `countActiveAdmins(adminRole: string): Promise<number>` — {@inheritDoc IUserRepository.countActiveAdmins}

#### `DrizzleWebAuthnCredentialStore`

```ts
class DrizzleWebAuthnCredentialStore implements IWebAuthnCredentialStore
```

Store de credentials WebAuthn **Drizzle** (driver `better-sqlite3`) — implémentation SQL d'`IWebAuthnCredentialStore` au-dessus d'un unique repository `@nodefony/orm-core` (`webauthn_credential`).

- `constructor(repo: IRepository<WebAuthnCredentialRow>, location?: string)`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation`.
- `get connector(): string` — Connecteur ORM qui porte ce store, lu par `readStoreConnector` pour le registre des stores : la console rattache la brique à SON connecteur au lieu de le déduire.
- `static from(orm: DrizzleOrm): DrizzleWebAuthnCredentialStore` — Construit le store depuis un `DrizzleOrm` connecté.
- `findById(credentialId: string): Promise<IWebAuthnCredential | null>` — Credential par son id (base64url), ou `null` — résolution à l'authentification.
- `findByUser(userId: string): Promise<IWebAuthnCredential[]>` — Tous les credentials d'un utilisateur — pour `allowCredentials` (authentification ciblée) et l'UX « mes appareils ».
- `countByUser(userId: string): Promise<number>` — `COUNT(*)` natif — jamais un `find().length` (le plafond ne charge rien).
- `save(credential: IWebAuthnCredential): Promise<void>` — Persiste un nouveau credential (fin de la cérémonie d'enregistrement).
- `update(credentialId: string, patch: WebAuthnAuthUpdate): Promise<void>` — Met à jour l'état post-authentification (compteur, sauvegarde, UV, usage).
- `delete(credentialId: string): Promise<void>` — Révoque un credential (l'utilisateur retire un appareil).
- `listPage(query: IWebAuthnListQuery): Promise<IPage<IWebAuthnCredentialSummary>>` — {@inheritDoc IWebAuthnCredentialStore.listPage}
- `countCredentials(query: IWebAuthnListQuery): Promise<number>` — {@inheritDoc IWebAuthnCredentialStore.countCredentials}

#### `DrizzleWebhookStore`

```ts
class DrizzleWebhookStore implements IWebhookStore
```

Store d'endpoints webhook **Drizzle** (driver `better-sqlite3`) — implémentation SQL d'`IWebhookStore` au-dessus d'un unique repository `@nodefony/orm-core` (`webhook_endpoint`). Persistance DURABLE du registre (les endpoints survivent au redémarrage, contrairement à `MemoryWebhookStore`).

- `readonly sortableFields: readonly [ "createdAt", "updatedAt", "url", "enabled", "failureCount", "id" ]` — {@inheritDoc IWebhookStore.sortableFields}
- `constructor(repo: IRepository<WebhookEndpointRow>, location?: string, db?: DrizzleDb | null, dialect?: SqlDialect)`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation`.
- `get connector(): string` — Connecteur ORM qui porte ce store, lu par `readStoreConnector` pour le registre des stores : la console rattache la brique à SON connecteur au lieu de le déduire.
- `static from(orm: DrizzleOrm): DrizzleWebhookStore` — Construit le store depuis un `DrizzleOrm` connecté.
- `save(endpoint: IWebhookEndpoint): Promise<void>` — Insère un nouvel endpoint.
- `findById(id: string): Promise<IWebhookEndpoint | null>` — Charge un endpoint par id, ou `null`.
- `update(id: string, patch: WebhookEndpointUpdate): Promise<void>` — Applique un patch partiel (champs mutables) ; no-op si id absent.
- `delete(id: string): Promise<void>` — Supprime un endpoint ; no-op si id absent.
- `listAll(): Promise<IWebhookEndpoint[]>` — **Tous** les endpoints — réservé au **snapshot du dispatcher** (le service garde en mémoire la table complète des abonnements pour router un événement sans I/O, et la recharge au boot puis après chaqu …
- `listPage(query: IWebhookListQuery): Promise<IPage<IWebhookEndpoint>>` — {@inheritDoc IWebhookStore.listPage}
- `countEndpoints(query: IWebhookListQuery): Promise<number>` — {@inheritDoc IWebhookStore.countEndpoints}

#### `SessionStorage`

```ts
class SessionStorage implements ISessionStorage
```

Stockage de session **Drizzle** (driver `better-sqlite3`), branché sur `@nodefony/orm-core`.

- `manager: SessionsService`
- `idleTimeoutS: number`
- `absoluteTimeoutS: number`
- `readonly sortableFields: readonly [ "updatedAt", "createdAt", "user", "id" ]` — Même vocabulaire public que les autres backends — le tri part dans le `ORDER BY`, donc il ne coûte rien de plus qu'un index bien posé.
- `constructor(manager: SessionsService)`
- `get location(): string` — Emplacement physique de la base (fichier SQLite) pour l'écran Studio « Stores » — lu par `readStoreLocation` du core au boot de `SessionsService`.
- `get connector(): string` — Connecteur ORM qui porte les sessions — lu par `readStoreConnector` pour le registre des stores.
- `read(id: string): Promise<ISerializedSession>`
- `start(id: string): Promise<ISerializedSession>`
- `write(id: string, data: ISerializedSession): Promise<ISerializedSession>`
- `open(): Promise<number>`
- `close(): boolean`
- `destroy(id: string): Promise<boolean>`
- `gc(idleSeconds?: number, absoluteSeconds?: number): Promise<void>` — Purge les sessions expirées sur les **deux bornes** NIST/OWASP : idle (inactivité depuis `updatedAt`) ET absolute (âge depuis `createdAt`, jamais prolongé).
- `touch(id: string): Promise<void>` — Prolonge l'idle d'une session (timeout glissant) : `UPDATE updatedAt = now` sur la PK `session_id` — SANS réécrire le blob (touch NIST/OWASP).
- `listAll(filter?: ISessionListFilter): Promise<ISessionRecord[]>` — Énumération admin (capacité optionnelle d'`ISessionStorage`) : un `SELECT` filtrable par `user` (WHERE indexable côté SQL).
- `listPage(query: ISessionListQuery): Promise<IPage<ISessionRecord>>` — Pagination **native** `LIMIT/OFFSET` + `COUNT` (helper `paginate` orm-core) : une page = une requête bornée, quel que soit le nombre de sessions en base.
- `countSessions(query?: Partial<ISessionListQuery>): Promise<number>` — `COUNT(*)` natif filtré — aucune ligne matérialisée.
- `countDistinctUsers(query?: Partial<ISessionListQuery>): Promise<number>` — `COUNT(DISTINCT user)` natif filtré.

#### `default`

```ts
class Drizzle extends Module<IDrizzleConfig>
```

- `constructor(kernel: Kernel)`
- `configSchema(): unknown` — JSON Schema de la config drizzle → data plane admin (config riche Studio).
- `onKernelRegister(): Promise<this>` — Valide la config (défauts + `module.options` + surcharge env) au boot via `defineDrizzleConfig`, et l'expose au container sous `drizzleConfig` pour que le `DrizzleService` la consomme.
- `onKernelBoot(): Promise<this>` — Monte le data plane ORM (`/nodefony/orm/api/*` + providers santé/flux pour la sonde cluster et le drill Studio) via `wireOrmAdminPlane`.

### Fonctions (2)

#### `isFrameworkFallbackEntity`

```ts
function isFrameworkFallbackEntity(entityName: string, connector?: string): boolean
```

Cette entité a-t-elle été posée par le repli du framework ?

#### `registerDrizzleFrameworkStores`

```ts
function registerDrizzleFrameworkStores(dialect: SqlDialect): IFrameworkStoresReport
```

Déclare les entités framework portées sur `dialect` (connecteur `default`) et enregistre leurs fabriques de stores dans les registres de `@nodefony/security` et `@nodefony/framework`. Idempotent (guards) — rejouable sans effet.

### Constantes (1)

#### `FRAMEWORK_CONNECTOR`

```ts
const FRAMEWORK_CONNECTOR = "default"
```

Connecteur conventionnel qui héberge le schéma framework (même convention que `SESSION_CONNECTOR` : `"default"` pour Drizzle, `"nodefony"` pour Mongoose).

### Interfaces (2)

#### `IFrameworkStoresReport`

```ts
interface IFrameworkStoresReport
```

Bilan de l'auto-enregistrement (loggé par le module — jamais silencieux).

- `registered: string[]` — Entités déclarées par l'auto-register (tables créées au connect).
- `appOwned: string[]` — Entités déjà enregistrées par l'app (customisation respectée).
- `unported: string[]` — Entités non portées sur le dialecte configuré (stores indisponibles).

#### `UserRow`

```ts
interface IUserRow
```

Forme plate d'un utilisateur tel qu'un dépôt le rend, avant reconstruction en `BaseUser` — pendant TypeScript de `USER_COLUMNS`.

- `id: string`
- `identifier: string`
- `password: string | null`
- `roles: string[]`
- `enabled: boolean`
- `locked: boolean`
- `currentRole: string | null`
- `socialProviders: ISocialProvider[]`
- `metadata: Record<string, unknown>`
- `credentialsVersion: number | null`
- `createdAt: Date`
- `updatedAt: Date`

---

[← Toutes les références d'API](../../)
