@nodefony/drizzle 10.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +544 -0
- package/README.md +162 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js +9 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js +6 -0
- package/dist/index.js +105 -0
- package/dist/nodefony/command/migrateShared.js +247 -0
- package/dist/nodefony/command/orm-generate.js +356 -0
- package/dist/nodefony/command/orm-migrate-baseline.js +208 -0
- package/dist/nodefony/command/orm-migrate-repair.js +114 -0
- package/dist/nodefony/command/orm-migrate-status.js +67 -0
- package/dist/nodefony/command/orm-migrate.js +141 -0
- package/dist/nodefony/command/orm-reset.js +166 -0
- package/dist/nodefony/config/config.js +107 -0
- package/dist/nodefony/config/defineModuleConfig.js +63 -0
- package/dist/nodefony/entity/auditEventEntity.js +93 -0
- package/dist/nodefony/entity/colKit.js +260 -0
- package/dist/nodefony/entity/idempotencyEntity.js +74 -0
- package/dist/nodefony/entity/sessionEntity.js +75 -0
- package/dist/nodefony/entity/tokenEntity.js +198 -0
- package/dist/nodefony/entity/totpSecretEntity.js +98 -0
- package/dist/nodefony/entity/userTable.js +141 -0
- package/dist/nodefony/entity/webAuthnCredentialEntity.js +114 -0
- package/dist/nodefony/entity/webhookEndpointEntity.js +106 -0
- package/dist/nodefony/interfaces/IDrizzleConfig.js +1 -0
- package/dist/nodefony/interfaces/index.js +1 -0
- package/dist/nodefony/migrations-schema/mysql.js +48 -0
- package/dist/nodefony/migrations-schema/postgres.js +48 -0
- package/dist/nodefony/migrations-schema/sqlite.js +48 -0
- package/dist/nodefony/registerStores.js +218 -0
- package/dist/nodefony/service/DrizzleService.js +282 -0
- package/dist/nodefony/src/DrizzleAuditStore.js +203 -0
- package/dist/nodefony/src/DrizzleIdempotencyStore.js +278 -0
- package/dist/nodefony/src/DrizzleTokenStore.js +244 -0
- package/dist/nodefony/src/DrizzleTotpSecretStore.js +151 -0
- package/dist/nodefony/src/DrizzleUserRepository.js +217 -0
- package/dist/nodefony/src/DrizzleWebAuthnCredentialStore.js +159 -0
- package/dist/nodefony/src/DrizzleWebhookStore.js +169 -0
- package/dist/nodefony/src/SessionStorage.js +259 -0
- package/dist/nodefony/src/connectorTarget.js +59 -0
- package/dist/nodefony/src/likeSql.js +50 -0
- package/dist/nodefony/src/migrator/DrizzleMigrator.js +775 -0
- package/dist/nodefony/src/migrator/adopt.js +553 -0
- package/dist/nodefony/src/migrator/appSchema.js +414 -0
- package/dist/nodefony/src/migrator/catalog.js +76 -0
- package/dist/nodefony/src/migrator/destructive.js +213 -0
- package/dist/nodefony/src/migrator/divergence.js +84 -0
- package/dist/nodefony/src/migrator/drivers/index.js +39 -0
- package/dist/nodefony/src/migrator/drivers/mysqlDriver.js +147 -0
- package/dist/nodefony/src/migrator/drivers/postgresDriver.js +151 -0
- package/dist/nodefony/src/migrator/drivers/sqliteDriver.js +121 -0
- package/dist/nodefony/src/migrator/explain.js +565 -0
- package/dist/nodefony/src/migrator/hash.js +47 -0
- package/dist/nodefony/src/migrator/history.js +219 -0
- package/dist/nodefony/src/migrator/index.js +16 -0
- package/dist/nodefony/src/migrator/kit.js +296 -0
- package/dist/nodefony/src/migrator/name.js +68 -0
- package/dist/nodefony/src/migrator/paths.js +88 -0
- package/dist/nodefony/src/migrator/refusals.js +143 -0
- package/dist/nodefony/src/migrator/resolve.js +281 -0
- package/dist/nodefony/src/migrator/schemaDiff.js +86 -0
- package/dist/nodefony/src/migrator/sources.js +419 -0
- package/dist/nodefony/src/migrator/status.js +231 -0
- package/dist/nodefony/src/migrator/types.js +91 -0
- package/dist/nodefony/src/orm-core/DrizzleOrm.js +1154 -0
- package/dist/nodefony/src/orm-core/DrizzleRepository.js +610 -0
- package/dist/nodefony/src/orm-core/DrizzleTransaction.js +106 -0
- package/dist/nodefony/src/orm-core/index.js +4 -0
- package/dist/nodefony/src/queryKit.js +318 -0
- package/dist/nodefony/src/safeTarget.js +55 -0
- package/dist/types/index.d.ts +76 -0
- package/dist/types/nodefony/command/migrateShared.d.ts +137 -0
- package/dist/types/nodefony/command/orm-generate.d.ts +53 -0
- package/dist/types/nodefony/command/orm-migrate-baseline.d.ts +87 -0
- package/dist/types/nodefony/command/orm-migrate-repair.d.ts +66 -0
- package/dist/types/nodefony/command/orm-migrate-status.d.ts +38 -0
- package/dist/types/nodefony/command/orm-migrate.d.ts +65 -0
- package/dist/types/nodefony/command/orm-reset.d.ts +55 -0
- package/dist/types/nodefony/config/config.d.ts +110 -0
- package/dist/types/nodefony/config/defineModuleConfig.d.ts +24 -0
- package/dist/types/nodefony/entity/auditEventEntity.d.ts +56 -0
- package/dist/types/nodefony/entity/colKit.d.ts +130 -0
- package/dist/types/nodefony/entity/idempotencyEntity.d.ts +52 -0
- package/dist/types/nodefony/entity/sessionEntity.d.ts +50 -0
- package/dist/types/nodefony/entity/tokenEntity.d.ts +53 -0
- package/dist/types/nodefony/entity/totpSecretEntity.d.ts +61 -0
- package/dist/types/nodefony/entity/userTable.d.ts +65 -0
- package/dist/types/nodefony/entity/webAuthnCredentialEntity.d.ts +57 -0
- package/dist/types/nodefony/entity/webhookEndpointEntity.d.ts +58 -0
- package/dist/types/nodefony/interfaces/IDrizzleConfig.d.ts +17 -0
- package/dist/types/nodefony/interfaces/index.d.ts +1 -0
- package/dist/types/nodefony/migrations-schema/mysql.d.ts +9 -0
- package/dist/types/nodefony/migrations-schema/postgres.d.ts +9 -0
- package/dist/types/nodefony/migrations-schema/sqlite.d.ts +9 -0
- package/dist/types/nodefony/registerStores.d.ts +52 -0
- package/dist/types/nodefony/service/DrizzleService.d.ts +27 -0
- package/dist/types/nodefony/src/DrizzleAuditStore.d.ts +65 -0
- package/dist/types/nodefony/src/DrizzleIdempotencyStore.d.ts +129 -0
- package/dist/types/nodefony/src/DrizzleTokenStore.d.ts +146 -0
- package/dist/types/nodefony/src/DrizzleTotpSecretStore.d.ts +60 -0
- package/dist/types/nodefony/src/DrizzleUserRepository.d.ts +67 -0
- package/dist/types/nodefony/src/DrizzleWebAuthnCredentialStore.d.ts +62 -0
- package/dist/types/nodefony/src/DrizzleWebhookStore.d.ts +79 -0
- package/dist/types/nodefony/src/SessionStorage.d.ts +72 -0
- package/dist/types/nodefony/src/connectorTarget.d.ts +48 -0
- package/dist/types/nodefony/src/likeSql.d.ts +29 -0
- package/dist/types/nodefony/src/migrator/DrizzleMigrator.d.ts +94 -0
- package/dist/types/nodefony/src/migrator/adopt.d.ts +280 -0
- package/dist/types/nodefony/src/migrator/appSchema.d.ts +223 -0
- package/dist/types/nodefony/src/migrator/catalog.d.ts +100 -0
- package/dist/types/nodefony/src/migrator/destructive.d.ts +123 -0
- package/dist/types/nodefony/src/migrator/divergence.d.ts +61 -0
- package/dist/types/nodefony/src/migrator/drivers/index.d.ts +26 -0
- package/dist/types/nodefony/src/migrator/drivers/mysqlDriver.d.ts +83 -0
- package/dist/types/nodefony/src/migrator/drivers/postgresDriver.d.ts +81 -0
- package/dist/types/nodefony/src/migrator/drivers/sqliteDriver.d.ts +53 -0
- package/dist/types/nodefony/src/migrator/explain.d.ts +424 -0
- package/dist/types/nodefony/src/migrator/hash.d.ts +39 -0
- package/dist/types/nodefony/src/migrator/history.d.ts +139 -0
- package/dist/types/nodefony/src/migrator/index.d.ts +20 -0
- package/dist/types/nodefony/src/migrator/kit.d.ts +141 -0
- package/dist/types/nodefony/src/migrator/name.d.ts +52 -0
- package/dist/types/nodefony/src/migrator/paths.d.ts +54 -0
- package/dist/types/nodefony/src/migrator/refusals.d.ts +170 -0
- package/dist/types/nodefony/src/migrator/resolve.d.ts +201 -0
- package/dist/types/nodefony/src/migrator/schemaDiff.d.ts +112 -0
- package/dist/types/nodefony/src/migrator/sources.d.ts +119 -0
- package/dist/types/nodefony/src/migrator/status.d.ts +132 -0
- package/dist/types/nodefony/src/migrator/types.d.ts +273 -0
- package/dist/types/nodefony/src/orm-core/DrizzleOrm.d.ts +241 -0
- package/dist/types/nodefony/src/orm-core/DrizzleRepository.d.ts +98 -0
- package/dist/types/nodefony/src/orm-core/DrizzleTransaction.d.ts +71 -0
- package/dist/types/nodefony/src/orm-core/index.d.ts +11 -0
- package/dist/types/nodefony/src/queryKit.d.ts +136 -0
- package/dist/types/nodefony/src/safeTarget.d.ts +42 -0
- package/docs/index.md +954 -0
- package/docs/migrations.md +691 -0
- package/migrations/mysql/0000_framework_init.sql +137 -0
- package/migrations/mysql/meta/_journal.json +13 -0
- package/migrations/postgres/0000_framework_init.sql +128 -0
- package/migrations/postgres/meta/_journal.json +13 -0
- package/migrations/sqlite/0000_framework_init.sql +127 -0
- package/migrations/sqlite/meta/_journal.json +13 -0
- package/package.json +126 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Command, type CliKernel } from "nodefony";
|
|
2
|
+
import type { IDrizzleConfig } from "../interfaces/IDrizzleConfig.js";
|
|
3
|
+
import type { DrizzleMigrator } from "../src/migrator/DrizzleMigrator.js";
|
|
4
|
+
import { MigrationVerdictError } from "../src/migrator/types.js";
|
|
5
|
+
import type { IMigrationAction } from "../src/migrator/types.js";
|
|
6
|
+
import { type IMigrationReport, type IStyle } from "../src/migrator/explain.js";
|
|
7
|
+
import type { IMigrationPlan } from "../src/migrator/types.js";
|
|
8
|
+
import { type IConnectorResolution } from "../src/migrator/resolve.js";
|
|
9
|
+
import { type CommandFailureCode, type IDiscoveryFacts } from "../src/migrator/refusals.js";
|
|
10
|
+
export type { ICommandFailure } from "../src/migrator/refusals.js";
|
|
11
|
+
/** Options communes à toutes les commandes de migration. */
|
|
12
|
+
export interface IMigrateSharedOptions {
|
|
13
|
+
connector?: string;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Classe de base des commandes `orm:*`.
|
|
18
|
+
*
|
|
19
|
+
* Elle n'impose rien du verbe : chaque commande écrit son `generate`. Elle
|
|
20
|
+
* impose la FORME de ce qui sort, parce que c'est cette forme qui fait la
|
|
21
|
+
* différence entre un outil qu'on sait utiliser et un outil qu'on subit.
|
|
22
|
+
*/
|
|
23
|
+
export declare abstract class OrmMigrateCommand extends Command {
|
|
24
|
+
/**
|
|
25
|
+
* Faut-il colorer la sortie ?
|
|
26
|
+
*
|
|
27
|
+
* 🔴 La question n'est PAS « est-ce un terminal ? », et la confondre avec ça
|
|
28
|
+
* a deux conséquences que personne ne signale :
|
|
29
|
+
*
|
|
30
|
+
* - **`NO_COLOR` est ignoré.** C'est une convention publique
|
|
31
|
+
* (no-color.org) qu'un utilisateur pose une fois pour toutes ses commandes ;
|
|
32
|
+
* la manquer rend une sortie illisible sur un terminal à palette
|
|
33
|
+
* inhabituelle, et le framework passe pour cassé.
|
|
34
|
+
* - **`FORCE_COLOR` est ignoré.** Sans lui, aucune sortie colorée n'est
|
|
35
|
+
* CAPTURABLE : ni dans un fichier, ni dans une passe d'intégration continue
|
|
36
|
+
* qui sait rendre les couleurs, ni dans un rapport de validation. On ne peut
|
|
37
|
+
* alors pas relire ce que l'exploitant voit vraiment.
|
|
38
|
+
*
|
|
39
|
+
* La règle vit au CŒUR (`resolveColorEnabled`), qui sert déjà les journaux :
|
|
40
|
+
* la réécrire ici en ferait une SECONDE implémentation, et les deux
|
|
41
|
+
* divergeraient — le journal obéirait à `NO_COLOR`, la commande non.
|
|
42
|
+
*/
|
|
43
|
+
protected get tty(): boolean;
|
|
44
|
+
/** Mise en forme, neutralisée hors terminal. */
|
|
45
|
+
protected get style(): IStyle;
|
|
46
|
+
/**
|
|
47
|
+
* Configuration validée du module qui porte les connecteurs SQL.
|
|
48
|
+
*
|
|
49
|
+
* @returns la configuration, ou `null` si le module n'est pas chargé.
|
|
50
|
+
*/
|
|
51
|
+
protected drizzleConfig(): IDrizzleConfig | null;
|
|
52
|
+
/**
|
|
53
|
+
* Écrit une charge utile sur la sortie standard et pose le code de sortie.
|
|
54
|
+
*
|
|
55
|
+
* `process.exitCode` et jamais `process.exit()` : couper le processus laisse
|
|
56
|
+
* la sortie standard non vidée, et un `| jq` reçoit alors un objet tronqué —
|
|
57
|
+
* un échec qui ressemble à un défaut de la commande.
|
|
58
|
+
*
|
|
59
|
+
* @param payload - l'objet, en mode machine.
|
|
60
|
+
* @param human - le texte, en mode humain.
|
|
61
|
+
* @param exitCode - `0`, `1` ou `2`.
|
|
62
|
+
* @param json - la commande a-t-elle reçu `--json` ?
|
|
63
|
+
*/
|
|
64
|
+
protected respond(payload: unknown, human: string, exitCode: number, json: boolean | undefined): void;
|
|
65
|
+
/**
|
|
66
|
+
* Arrête la commande en disant le fait, la cause et le geste.
|
|
67
|
+
*
|
|
68
|
+
* @param connector - connecteur concerné (ou le nom demandé).
|
|
69
|
+
* @param code - code d'arrêt stable, lu par les machines.
|
|
70
|
+
* @param summary - le fait, en français.
|
|
71
|
+
* @param meaning - ce que ça veut dire.
|
|
72
|
+
* @param actions - les commandes exactes à copier.
|
|
73
|
+
* @param json - la commande a-t-elle reçu `--json` ?
|
|
74
|
+
* @param exitCode - `2` par défaut : la commande n'a pas pu travailler.
|
|
75
|
+
* @param discovery - ce que la découverte des entités a vu, quand le refus
|
|
76
|
+
* peut avoir pour cause un schéma déclaré amputé.
|
|
77
|
+
*/
|
|
78
|
+
protected fail(connector: string, code: CommandFailureCode | MigrationVerdictError["verdict"]["code"], summary: string, meaning: string, actions: IMigrationAction[], json: boolean | undefined, exitCode?: 1 | 2, discovery?: IDiscoveryFacts): void;
|
|
79
|
+
/**
|
|
80
|
+
* Résout le connecteur demandé, ou ARRÊTE la commande en le disant.
|
|
81
|
+
*
|
|
82
|
+
* Les **trois** réponses sont un contrat public, et elles restent distinctes :
|
|
83
|
+
* un connecteur inconnu, un connecteur porté par un ORM sans migrations, un
|
|
84
|
+
* connecteur prêt. Le jour où un second ORM apporte ses propres migrations,
|
|
85
|
+
* seule la deuxième cesse de sortir pour ses connecteurs — répondre « ne
|
|
86
|
+
* porte pas de migrations » à un connecteur qui en porte serait un message
|
|
87
|
+
* FAUX, et un message faux publié est appris par les scripts qui le lisent.
|
|
88
|
+
*
|
|
89
|
+
* @param opts - options de la commande (connecteur, mode machine).
|
|
90
|
+
* @param allowMigrateUrl - la commande honore-t-elle {@link MIGRATE_URL_ENV} ?
|
|
91
|
+
* @returns le connecteur prêt, ou `null` si la commande est déjà arrêtée.
|
|
92
|
+
*/
|
|
93
|
+
protected resolveOrFail(opts: IMigrateSharedOptions, allowMigrateUrl: boolean): {
|
|
94
|
+
resolution: Extract<IConnectorResolution, {
|
|
95
|
+
kind: "ready";
|
|
96
|
+
}>;
|
|
97
|
+
config: IDrizzleConfig;
|
|
98
|
+
} | null;
|
|
99
|
+
/**
|
|
100
|
+
* Construit l'applicateur d'un connecteur résolu.
|
|
101
|
+
*
|
|
102
|
+
* @param resolution - connecteur prêt.
|
|
103
|
+
* @param config - configuration validée.
|
|
104
|
+
* @returns l'applicateur, sources chargées.
|
|
105
|
+
*/
|
|
106
|
+
protected migrator(resolution: Extract<IConnectorResolution, {
|
|
107
|
+
kind: "ready";
|
|
108
|
+
}>, config: IDrizzleConfig): Promise<DrizzleMigrator>;
|
|
109
|
+
/**
|
|
110
|
+
* Compose la charge utile d'un état.
|
|
111
|
+
*
|
|
112
|
+
* L'assemblage lui-même vit dans `migrator/status.ts` : le plan
|
|
113
|
+
* d'administration publie le MÊME objet, et deux assemblages divergeaient
|
|
114
|
+
* d'un champ à l'autre sans qu'aucun test ne le voie.
|
|
115
|
+
*
|
|
116
|
+
* @param plan - plan calculé par l'applicateur, en lecture seule.
|
|
117
|
+
* @param resolution - connecteur prêt (porte le mode de schéma effectif).
|
|
118
|
+
* @param config - configuration validée du module.
|
|
119
|
+
* @returns la charge utile, prête pour `--json` comme pour l'écran.
|
|
120
|
+
*/
|
|
121
|
+
protected report(plan: IMigrationPlan, resolution: Extract<IConnectorResolution, {
|
|
122
|
+
kind: "ready";
|
|
123
|
+
}>, config: IDrizzleConfig): Promise<IMigrationReport>;
|
|
124
|
+
protected failFrom(e: unknown, connector: string, json: boolean | undefined, ddl?: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Écrit un état lu et pose son code de sortie.
|
|
127
|
+
*
|
|
128
|
+
* @param report - charge utile complète.
|
|
129
|
+
* @param human - rendu humain déjà composé.
|
|
130
|
+
* @param json - la commande a-t-elle reçu `--json` ?
|
|
131
|
+
*/
|
|
132
|
+
protected emitReport(report: IMigrationReport, human: string, json: boolean | undefined): void;
|
|
133
|
+
/** Déclare les deux options que toutes les commandes de migration portent. */
|
|
134
|
+
protected addSharedOptions(): void;
|
|
135
|
+
/** Le CLI courant, typé — utilisé pour les réglages de boot silencieux. */
|
|
136
|
+
protected get cliKernel(): CliKernel;
|
|
137
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type CliKernel } from "nodefony";
|
|
2
|
+
import { OrmMigrateCommand, type IMigrateSharedOptions } from "./migrateShared.js";
|
|
3
|
+
/** Options propres à `orm:generate`. */
|
|
4
|
+
interface IGenerateOptions extends IMigrateSharedOptions {
|
|
5
|
+
name?: string;
|
|
6
|
+
custom?: boolean;
|
|
7
|
+
allowDestructive?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* `nodefony orm:generate` — écrit la migration qui fera passer la base au
|
|
11
|
+
* schéma que décrivent les entités de l'application.
|
|
12
|
+
*
|
|
13
|
+
* ## Ce que l'utilisateur n'a pas à connaître
|
|
14
|
+
*
|
|
15
|
+
* Rien de `drizzle-kit`. Ni son installation, ni sa configuration par dialecte,
|
|
16
|
+
* ni la notion de « schéma matérialisé », ni son dossier de sortie, ni le format
|
|
17
|
+
* de son journal. Il tape un verbe et un nom. La commande découvre les fichiers
|
|
18
|
+
* d'entités par la convention du générateur, écrit ce qu'il faut dans un dossier
|
|
19
|
+
* de travail qu'elle efface ensuite, et pilote l'outil — dont elle EXIGE la
|
|
20
|
+
* preuve qu'il a travaillé, parce qu'il rend 0 même quand il échoue.
|
|
21
|
+
*
|
|
22
|
+
* ## Ce qu'elle refuse, et pourquoi elle le refuse plutôt que de continuer
|
|
23
|
+
*
|
|
24
|
+
* Une migration est **immuable une fois appliquée**. Une migration amputée n'est
|
|
25
|
+
* pas un désagrément qu'on rattrape à la génération suivante : elle grave dans
|
|
26
|
+
* l'historique une table qui n'existera jamais, et toute base qui l'a reçue
|
|
27
|
+
* restera incomplète. Trois situations valent donc un arrêt qui NOMME :
|
|
28
|
+
*
|
|
29
|
+
* - un fichier d'entité qui ne s'importe pas (le schéma serait incomplet) ;
|
|
30
|
+
* - une entité enregistrée qu'aucun fichier ne fournit (idem, et c'est le
|
|
31
|
+
* contrôle que le registre est le seul à pouvoir faire) ;
|
|
32
|
+
* - un fichier de l'application qui fournit une table du FRAMEWORK — la
|
|
33
|
+
* migration porterait un second `CREATE TABLE` de cette table, qui échoue sur
|
|
34
|
+
* toute base déjà migrée, c'est-à-dire en production et nulle part ailleurs.
|
|
35
|
+
*
|
|
36
|
+
* @example Le cas courant
|
|
37
|
+
* ```bash
|
|
38
|
+
* nodefony orm:generate --name ajout_du_titre
|
|
39
|
+
* nodefony orm:migrate # ou : le travail de déploiement
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @example Ce que le modèle déclaratif ne peut pas déduire
|
|
43
|
+
* ```bash
|
|
44
|
+
* nodefony orm:generate --custom --name vue_des_ventes
|
|
45
|
+
* # → un fichier SQL vide, déjà inscrit au journal : à écrire à la main.
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare class OrmGenerate extends OrmMigrateCommand {
|
|
49
|
+
#private;
|
|
50
|
+
constructor(cli: CliKernel);
|
|
51
|
+
generate(opts?: IGenerateOptions): Promise<this>;
|
|
52
|
+
}
|
|
53
|
+
export default OrmGenerate;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { CliKernel } from "nodefony";
|
|
2
|
+
import { MIGRATION_FORMAT_VERSION, action } from "../src/migrator/explain.js";
|
|
3
|
+
import { OrmMigrateCommand, type IMigrateSharedOptions } from "./migrateShared.js";
|
|
4
|
+
/** Options propres à l'adoption d'une base existante. */
|
|
5
|
+
interface IBaselineOptions extends IMigrateSharedOptions {
|
|
6
|
+
upTo?: string;
|
|
7
|
+
fromDatabase?: boolean;
|
|
8
|
+
name?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* `nodefony orm:migrate:baseline` — déclare une base existante « à niveau »,
|
|
12
|
+
* SANS exécuter une seule instruction de schéma.
|
|
13
|
+
*
|
|
14
|
+
* ## Quand on en a besoin
|
|
15
|
+
*
|
|
16
|
+
* La base contient déjà les tables — parce qu'on branche Nodefony sur une base
|
|
17
|
+
* qui existait avant, ou parce que le schéma a été créé autrement (mode `auto`
|
|
18
|
+
* en développement) — mais aucune migration n'y est enregistrée. Appliquer les
|
|
19
|
+
* migrations dans cet état exécuterait des créations de tables qui existent
|
|
20
|
+
* déjà, et échouerait.
|
|
21
|
+
*
|
|
22
|
+
* ## Pourquoi ce n'est PAS automatique
|
|
23
|
+
*
|
|
24
|
+
* Adopter tout seul retirerait le filet qui protège de la pire erreur : se
|
|
25
|
+
* tromper de base. Une adresse de base héritée d'un autre environnement, et
|
|
26
|
+
* l'outil déclarerait « à niveau » une base qui n'a rien à voir — puis
|
|
27
|
+
* appliquerait dessus les migrations suivantes. La documentation de Flyway
|
|
28
|
+
* elle-même met en garde contre son propre mode automatique pour cette raison.
|
|
29
|
+
*
|
|
30
|
+
* **Vérifie que c'est la bonne base avant de taper cette commande.** Elle ne
|
|
31
|
+
* modifie pas le schéma, mais elle change ce que le framework CROIT du schéma —
|
|
32
|
+
* et tout le reste en découle.
|
|
33
|
+
*
|
|
34
|
+
* ## Ce qu'elle fait exactement
|
|
35
|
+
*
|
|
36
|
+
* Elle inscrit dans l'historique, comme appliquées avec succès et une durée
|
|
37
|
+
* nulle, les migrations qui n'y sont pas encore. Rejouée, elle n'inscrit que ce
|
|
38
|
+
* qui manque : elle est donc sûre à relancer.
|
|
39
|
+
*
|
|
40
|
+
* ## Ce qu'elle REFUSE
|
|
41
|
+
*
|
|
42
|
+
* Adopter, c'est affirmer que la base est à l'état que décrivent ces
|
|
43
|
+
* migrations. Quand la base s'écarte du schéma déclaré, l'affirmation serait
|
|
44
|
+
* fausse — et une affirmation fausse gravée dans l'historique n'est rattrapable
|
|
45
|
+
* par aucune commande. La commande constate donc la base AVANT d'écrire, et
|
|
46
|
+
* refuse (`NF_MIGRATE_BASELINE_AMBIGUOUS`) en nommant ce qui manque.
|
|
47
|
+
*
|
|
48
|
+
* Trois cas y échappent, et pour la même raison — la garde n'a plus rien à
|
|
49
|
+
* deviner : `--up-to`, qui borne l'adoption explicitement ; `--from-database`,
|
|
50
|
+
* dont la référence DÉCRIT la base et rend donc l'affirmation vraie par
|
|
51
|
+
* construction ; et une cible détournée par `NF_MIGRATE_DATABASE_URL`, où la
|
|
52
|
+
* comparaison porterait sur la base de la configuration et non sur celle qu'on
|
|
53
|
+
* migre.
|
|
54
|
+
*
|
|
55
|
+
* ## Une base qui n'a JAMAIS eu de migrations — `--from-database`
|
|
56
|
+
*
|
|
57
|
+
* Adopter suppose des fichiers à inscrire. Une application passée du mode
|
|
58
|
+
* dérivé, où le démarrage fabrique le schéma, au mode de production n'en a
|
|
59
|
+
* aucun : sa base porte tout, son dossier de migrations est vide. Sans
|
|
60
|
+
* référence, la première génération décrirait ce que le CODE déclare — un
|
|
61
|
+
* schéma que cette base n'a peut-être jamais eu, si quelqu'un vient de changer
|
|
62
|
+
* une entité — et l'inscrire graverait une affirmation fausse.
|
|
63
|
+
*
|
|
64
|
+
* `--from-database` LIT le schéma de la base et en écrit la migration de
|
|
65
|
+
* référence, puis l'inscrit. Rien n'est exécuté sur la base. La suite redevient
|
|
66
|
+
* ordinaire : le champ ajouté produit un `ALTER TABLE`.
|
|
67
|
+
*
|
|
68
|
+
* @example Adopter jusqu'à une migration précise
|
|
69
|
+
* ```bash
|
|
70
|
+
* nodefony orm:migrate:baseline --up-to 0003_audit_severity
|
|
71
|
+
* nodefony orm:migrate # applique la suite normalement
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example Reprendre une base qui existait avant toute migration
|
|
75
|
+
* ```bash
|
|
76
|
+
* nodefony orm:migrate:baseline --from-database # la référence est LUE sur la base
|
|
77
|
+
* nodefony orm:generate --name ajout_du_slug # produit un ALTER, plus un CREATE
|
|
78
|
+
* nodefony orm:migrate # applique
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
declare class OrmMigrateBaseline extends OrmMigrateCommand {
|
|
82
|
+
#private;
|
|
83
|
+
constructor(cli: CliKernel);
|
|
84
|
+
generate(opts?: IBaselineOptions): Promise<this>;
|
|
85
|
+
}
|
|
86
|
+
export default OrmMigrateBaseline;
|
|
87
|
+
export { MIGRATION_FORMAT_VERSION, action };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { CliKernel } from "nodefony";
|
|
2
|
+
import { OrmMigrateCommand, type IMigrateSharedOptions } from "./migrateShared.js";
|
|
3
|
+
/** Options propres à la réparation de l'historique. */
|
|
4
|
+
interface IRepairOptions extends IMigrateSharedOptions {
|
|
5
|
+
source?: string;
|
|
6
|
+
updateHashes?: boolean;
|
|
7
|
+
forget?: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* `nodefony orm:migrate:repair` — lève les marqueurs d'échec, **après**
|
|
11
|
+
* inspection humaine.
|
|
12
|
+
*
|
|
13
|
+
* ## Ce que « réparer » veut dire ici, et ce que ça ne veut pas dire
|
|
14
|
+
*
|
|
15
|
+
* Cette commande **ne répare pas la base**. Elle efface la trace d'une
|
|
16
|
+
* migration qui n'a pas abouti, pour que l'applicateur accepte de reprendre.
|
|
17
|
+
* C'est une déclaration : « j'ai regardé la base, elle est dans l'état que je
|
|
18
|
+
* crois ».
|
|
19
|
+
*
|
|
20
|
+
* Pourquoi ce n'est pas automatique : quand une migration s'arrête en cours de
|
|
21
|
+
* route, l'état laissé dépend de la base. PostgreSQL et SQLite annulent la
|
|
22
|
+
* migration fautive entière — l'état est net. MySQL valide chaque instruction
|
|
23
|
+
* de schéma au fur et à mesure, sans retour possible : la moitié des
|
|
24
|
+
* changements peut être en place. Aucun programme ne peut décider à la place
|
|
25
|
+
* d'un humain si cette moitié est acceptable.
|
|
26
|
+
*
|
|
27
|
+
* **L'ordre des gestes, et il ne s'inverse pas :**
|
|
28
|
+
*
|
|
29
|
+
* 1. `nodefony orm:migrate:status --json` — voir ce qui a échoué et pourquoi ;
|
|
30
|
+
* 2. regarder la base elle-même, et la remettre d'aplomb si besoin ;
|
|
31
|
+
* 3. `nodefony orm:migrate:repair` — lever le marqueur ;
|
|
32
|
+
* 4. `nodefony orm:migrate` — reprendre.
|
|
33
|
+
*
|
|
34
|
+
* ## `--update-hashes` : à ne taper que sur instruction d'un message
|
|
35
|
+
*
|
|
36
|
+
* Ré-aligner les empreintes déclare que les fichiers modifiés APRÈS avoir été
|
|
37
|
+
* appliqués sont réputés conformes. C'est presque toujours faux : les autres
|
|
38
|
+
* bases ont reçu l'ancienne version et ne recevront jamais la nouvelle. Le
|
|
39
|
+
* geste normal face à un fichier modifié est de le restaurer
|
|
40
|
+
* (`git checkout -- migrations/`) et d'écrire une NOUVELLE migration.
|
|
41
|
+
*
|
|
42
|
+
* L'option existe pour le cas où l'on sait que la modification était sans effet
|
|
43
|
+
* — une reformulation, un commentaire. Elle ne touche jamais la base.
|
|
44
|
+
*
|
|
45
|
+
* ## `--forget <source>/<tag>` : l'issue d'un historique qui MENT
|
|
46
|
+
*
|
|
47
|
+
* Il existait un état dont aucune commande ne sortait : une migration inscrite
|
|
48
|
+
* comme réussie que personne n'a jamais exécutée — une adoption mal bornée, ou
|
|
49
|
+
* une base héritée d'une version antérieure aux gardes. La base ne porte pas
|
|
50
|
+
* les tables, l'historique affirme le contraire, et rien n'est « en attente ».
|
|
51
|
+
* Le générateur disait alors « c'est l'historique qu'il faut reprendre » et
|
|
52
|
+
* renvoyait ici ; mais cette commande ne savait lever que des marqueurs
|
|
53
|
+
* d'ÉCHEC, et répondait « rien à réparer ». Trois messages vrais, aucun geste
|
|
54
|
+
* — et le seul chemin restant était de détruire la base.
|
|
55
|
+
*
|
|
56
|
+
* `--forget` désinscrit UNE entrée nommée, pour qu'elle soit rejouée au
|
|
57
|
+
* passage suivant. Bornée par construction : il faut la nommer
|
|
58
|
+
* (`--forget app/0003_ajout_facture`), il n'y a ni motif ni lot. La base n'est
|
|
59
|
+
* pas touchée — si la migration avait réellement été appliquée, son rejeu
|
|
60
|
+
* échouera, bruyamment, ce qui est le comportement voulu.
|
|
61
|
+
*/
|
|
62
|
+
declare class OrmMigrateRepair extends OrmMigrateCommand {
|
|
63
|
+
constructor(cli: CliKernel);
|
|
64
|
+
generate(opts?: IRepairOptions): Promise<this>;
|
|
65
|
+
}
|
|
66
|
+
export default OrmMigrateRepair;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CliKernel } from "nodefony";
|
|
2
|
+
import { OrmMigrateCommand, type IMigrateSharedOptions } from "./migrateShared.js";
|
|
3
|
+
/**
|
|
4
|
+
* `nodefony orm:migrate:status` — dit ce que la base a reçu, ce qui reste, et
|
|
5
|
+
* ce qu'il faut taper.
|
|
6
|
+
*
|
|
7
|
+
* **Lecture seule et sans verrou.** Elle n'écrit rien, pas même la table
|
|
8
|
+
* d'historique : un état qui se consulte ne doit pas modifier ce qu'il
|
|
9
|
+
* observe — et une sonde qui écrit dans la base n'est plus une sonde.
|
|
10
|
+
*
|
|
11
|
+
* ## Son autre métier : barrière d'intégration continue
|
|
12
|
+
*
|
|
13
|
+
* Le code de sortie porte le verdict, et il ne changera jamais de sens :
|
|
14
|
+
*
|
|
15
|
+
* | Code | Ce que ça veut dire |
|
|
16
|
+
* | ---- | ------------------------------------------------------------------ |
|
|
17
|
+
* | `0` | à jour — rien à faire |
|
|
18
|
+
* | `1` | une action humaine est requise (migrations en attente, écart, échec) |
|
|
19
|
+
* | `2` | la commande n'a pas pu travailler (base injoignable, verrou, usage) |
|
|
20
|
+
*
|
|
21
|
+
* Une passe de déploiement peut donc s'arrêter dessus sans lire un mot :
|
|
22
|
+
*
|
|
23
|
+
* ```bash
|
|
24
|
+
* nodefony orm:migrate:status --json || exit 1
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example Ce qu'un agent lit
|
|
28
|
+
* ```bash
|
|
29
|
+
* nodefony orm:migrate:status --json | jq -r '.verdict, .nextActions[0].command'
|
|
30
|
+
* # pending
|
|
31
|
+
* # nodefony orm:migrate
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare class OrmMigrateStatus extends OrmMigrateCommand {
|
|
35
|
+
constructor(cli: CliKernel);
|
|
36
|
+
generate(opts?: IMigrateSharedOptions): Promise<this>;
|
|
37
|
+
}
|
|
38
|
+
export default OrmMigrateStatus;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { CliKernel } from "nodefony";
|
|
2
|
+
import { EXIT, action } from "../src/migrator/explain.js";
|
|
3
|
+
import { OrmMigrateCommand, type IMigrateSharedOptions } from "./migrateShared.js";
|
|
4
|
+
/**
|
|
5
|
+
* Options propres à l'application des migrations.
|
|
6
|
+
*
|
|
7
|
+
* Pas de `--source` ici, et c'est délibéré : l'applicateur applique l'ordre
|
|
8
|
+
* complet (le framework d'abord, l'application ensuite) et n'a pas de filtre
|
|
9
|
+
* par source. Déclarer l'option pour l'ignorer serait pire qu'un refus — un
|
|
10
|
+
* argument accepté puis jeté fait croire à un comportement qui n'existe pas.
|
|
11
|
+
*/
|
|
12
|
+
interface IMigrateOptions extends IMigrateSharedOptions {
|
|
13
|
+
dryRun?: boolean;
|
|
14
|
+
outOfOrder?: boolean;
|
|
15
|
+
ignoreMissing?: boolean;
|
|
16
|
+
allowDestructive?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `nodefony orm:migrate` — applique les migrations restantes, sous verrou.
|
|
20
|
+
*
|
|
21
|
+
* ## Ce que la commande fait, dans cet ordre exact
|
|
22
|
+
*
|
|
23
|
+
* 1. **prend le verrou** de la base (verrou natif du serveur : il se libère
|
|
24
|
+
* tout seul si le processus meurt — aucun verrou fantôme à débloquer à la
|
|
25
|
+
* main) ;
|
|
26
|
+
* 2. **crée la table d'historique** si elle n'existe pas ;
|
|
27
|
+
* 3. **valide TOUT** — empreintes, ordre, échecs passés, fichiers manquants ;
|
|
28
|
+
* 4. **applique** les migrations une par une, chacune dans sa transaction là où
|
|
29
|
+
* la base le permet.
|
|
30
|
+
*
|
|
31
|
+
* La validation précède toute écriture : **un refus laisse la base
|
|
32
|
+
* intacte**. C'est ce qui rend sûr de relancer la commande après un refus.
|
|
33
|
+
*
|
|
34
|
+
* ## Elle ne s'exécute jamais toute seule au démarrage — sauf si on le demande
|
|
35
|
+
*
|
|
36
|
+
* Appliquer des migrations au démarrage n'est pas un défaut, et ce n'est pas de
|
|
37
|
+
* la prudence : au démarrage, plusieurs exemplaires partent en même temps. Le
|
|
38
|
+
* mode `ddl: "migrate"` existe pour les déploiements à exemplaire unique et
|
|
39
|
+
* s'écrit à la main. En production orchestrée, c'est un travail séparé qui
|
|
40
|
+
* lance cette commande AVANT que les nouveaux exemplaires ne démarrent.
|
|
41
|
+
*
|
|
42
|
+
* ## Le compte qui migre n'est pas le compte qui sert
|
|
43
|
+
*
|
|
44
|
+
* `NF_MIGRATE_DATABASE_URL` remplace, pour cette commande seulement, la
|
|
45
|
+
* connexion du connecteur. C'est le véhicule du moindre privilège : le secret
|
|
46
|
+
* qui a le droit de modifier le schéma est monté dans le travail de migration,
|
|
47
|
+
* et nulle part ailleurs. Elle doit désigner une connexion **directe** — un
|
|
48
|
+
* répartiteur de connexions en mode transaction casse le verrou.
|
|
49
|
+
*
|
|
50
|
+
* @example Voir sans rien appliquer
|
|
51
|
+
* ```bash
|
|
52
|
+
* nodefony orm:migrate --dry-run
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example Dans un travail de déploiement
|
|
56
|
+
* ```bash
|
|
57
|
+
* NF_MIGRATE_DATABASE_URL="postgres://migrator:…@db:5432/app" nodefony orm:migrate --json
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare class OrmMigrate extends OrmMigrateCommand {
|
|
61
|
+
constructor(cli: CliKernel);
|
|
62
|
+
generate(opts?: IMigrateOptions): Promise<this>;
|
|
63
|
+
}
|
|
64
|
+
export default OrmMigrate;
|
|
65
|
+
export { EXIT, action };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CliKernel } from "nodefony";
|
|
2
|
+
import { OrmMigrateCommand, type IMigrateSharedOptions } from "./migrateShared.js";
|
|
3
|
+
/** Options propres à la remise à zéro d'une base de développement. */
|
|
4
|
+
interface IResetOptions extends IMigrateSharedOptions {
|
|
5
|
+
yes?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* `nodefony orm:reset` — vide la base de DÉVELOPPEMENT et la laisse prête à
|
|
9
|
+
* être recréée.
|
|
10
|
+
*
|
|
11
|
+
* ## Le geste qu'elle remplace
|
|
12
|
+
*
|
|
13
|
+
* Jusqu'ici, le générateur d'applications disait « supprime ta base de dev, ou
|
|
14
|
+
* passe par une migration » : deux gestes manuels, aucun outil, et chacun s'en
|
|
15
|
+
* tirait comme il pouvait. Une seule commande à retenir pour toute l'équipe,
|
|
16
|
+
* au lieu d'un arbre de décision.
|
|
17
|
+
*
|
|
18
|
+
* ## Ce qu'elle fait exactement
|
|
19
|
+
*
|
|
20
|
+
* Elle supprime **toutes les tables du schéma courant** de la connexion —
|
|
21
|
+
* l'historique des migrations compris. Elle ne supprime NI la base, NI le
|
|
22
|
+
* fichier : supprimer une base demande des droits d'administration que le
|
|
23
|
+
* compte de l'application n'a pas, et supprimer un fichier ouvert échoue sous
|
|
24
|
+
* Windows. Le résultat est le même — une base vide — et il s'obtient partout de
|
|
25
|
+
* la même façon.
|
|
26
|
+
*
|
|
27
|
+
* Ensuite : en mode `auto` (le défaut en développement), le prochain démarrage
|
|
28
|
+
* recrée le schéma depuis le code. Dans les autres modes, la commande dit quoi
|
|
29
|
+
* lancer.
|
|
30
|
+
*
|
|
31
|
+
* ## Le refus est une LISTE BLANCHE, pas une liste noire
|
|
32
|
+
*
|
|
33
|
+
* Elle n'accepte de travailler que si l'environnement est `development`. Pas
|
|
34
|
+
* « refusée en production » : `staging`, `preprod`, `test` et tout
|
|
35
|
+
* environnement inconnu refusent aussi. La différence n'est pas théorique — une
|
|
36
|
+
* garde écrite « si production » laisse passer tout ce qu'on n'a pas pensé à
|
|
37
|
+
* nommer, et c'est exactement là que l'accident arrive.
|
|
38
|
+
*
|
|
39
|
+
* `NF_MIGRATE_DATABASE_URL` n'est **pas** lue par cette commande. Cette
|
|
40
|
+
* variable porte le compte qui a le droit de modifier le schéma en
|
|
41
|
+
* production : lui laisser désigner la cible d'un effacement serait offrir la
|
|
42
|
+
* seule combinaison qu'il ne faut jamais rendre possible.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```bash
|
|
46
|
+
* nodefony orm:reset # demande confirmation en terminal
|
|
47
|
+
* nodefony orm:reset --yes # sans question (script)
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
declare class OrmReset extends OrmMigrateCommand {
|
|
51
|
+
#private;
|
|
52
|
+
constructor(cli: CliKernel);
|
|
53
|
+
generate(opts?: IResetOptions): Promise<this>;
|
|
54
|
+
}
|
|
55
|
+
export default OrmReset;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* @nodefony/drizzle — CONFIGURATION DU MODULE (schéma Zod = source unique).
|
|
4
|
+
*
|
|
5
|
+
* ⭐ TL;DR : CE SCHÉMA EST LA CONFIG. Chaque `.default(...)` = la valeur d'usine ;
|
|
6
|
+
* changer un défaut du module = ÉDITER ICI (et nulle part ailleurs). L'app, elle,
|
|
7
|
+
* surcharge via `use("@nodefony/...", { … })` dans SON `nodefony.config.ts`.
|
|
8
|
+
*
|
|
9
|
+
* RÈGLE D'OR (ADR-0006) : ce fichier porte le **schéma Zod commenté** (type +
|
|
10
|
+
* validation + défaut + doc) ET matérialise les défauts via `parse({})`. Aucune
|
|
11
|
+
* valeur n'est re-tapée ailleurs. Le builder (`defineDrizzleConfig`) et les types
|
|
12
|
+
* (`interfaces/IDrizzleConfig.ts`) importent le schéma D'ICI (nœud bas : ce fichier
|
|
13
|
+
* n'importe que `zod` → pas de cycle).
|
|
14
|
+
*
|
|
15
|
+
* Convention figée (cf `feedback_config_validation_zod` + audit config ORM
|
|
16
|
+
* 2026-06), alignée sur `@nodefony/mongoose`/`@nodefony/redis`/`@nodefony/realtime`.
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ Le schéma reste **PUR** : `filename` est **optionnel SANS défaut** — le chemin
|
|
19
|
+
* SQLite par défaut dépend de `kernel.path` (indisponible à l'évaluation du schéma)
|
|
20
|
+
* et est résolu au boot par `DrizzleService`. Aucune lecture `process.env` ici
|
|
21
|
+
* (l'env est appliqué dans `defineDrizzleConfig`).
|
|
22
|
+
*
|
|
23
|
+
* SURCHARGE (précédence croissante — cf ADR-0006) :
|
|
24
|
+
* • App (typé) : `use("@nodefony/drizzle", { connectors: { … } })` ;
|
|
25
|
+
* • Par environnement : infra database `NF_DATABASE_URL`/`DATABASE_URL`
|
|
26
|
+
* (dialecte déduit du scheme, appliqué dans `defineDrizzleConfig`) ;
|
|
27
|
+
* • Déploiement/Docker : `NF__DRIZZLE__<CHEMIN>=valeur` (override env générique).
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Dialectes SQL supportés par l'adapter Drizzle. `sqlite` (better-sqlite3) est le
|
|
31
|
+
* défaut bootable ; `postgres` (pg) / `mysql` (mysql2) sont des drivers chargés en
|
|
32
|
+
* LAZY (`optionalDependencies` + `await import` au connect) — un framework doit
|
|
33
|
+
* porter ses entités sur les bases majeures (cf chantier portabilité multi-dialecte).
|
|
34
|
+
*/
|
|
35
|
+
export declare const SQL_DIALECTS: readonly ["sqlite", "postgres", "mysql"];
|
|
36
|
+
/** Dialecte SQL d'un connecteur Drizzle. */
|
|
37
|
+
export type SqlDialect = (typeof SQL_DIALECTS)[number];
|
|
38
|
+
/**
|
|
39
|
+
* Stratégies de fabrication du schéma d'un connecteur.
|
|
40
|
+
*
|
|
41
|
+
* Trois valeurs, et pas une de plus : ce qui fait le schéma est soit le
|
|
42
|
+
* démarrage à partir du code (`auto`), soit le démarrage à partir des fichiers
|
|
43
|
+
* de migration (`migrate`), soit personne (`none`). Un quatrième mode serait un
|
|
44
|
+
* mélange, donc un comportement que personne ne saurait décrire dans un
|
|
45
|
+
* incident.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DDL_MODES: readonly ["auto", "migrate", "none"];
|
|
48
|
+
/** Stratégie de fabrication du schéma d'un connecteur. */
|
|
49
|
+
export type DdlMode = (typeof DDL_MODES)[number];
|
|
50
|
+
/**
|
|
51
|
+
* Conduites de la sonde de disponibilité quand le schéma est en retard.
|
|
52
|
+
*
|
|
53
|
+
* `fail` retient la mise en service (le processus ne reçoit pas de trafic),
|
|
54
|
+
* `warn` journalise et sert quand même, `off` ne regarde pas.
|
|
55
|
+
*/
|
|
56
|
+
export declare const MIGRATION_CHECK_MODES: readonly ["fail", "warn", "off"];
|
|
57
|
+
/** Conduite de la sonde de disponibilité face à un schéma en retard. */
|
|
58
|
+
export type MigrationCheckMode = (typeof MIGRATION_CHECK_MODES)[number];
|
|
59
|
+
/**
|
|
60
|
+
* Conduites face à une base qui ne correspond plus au code alors que
|
|
61
|
+
* l'historique est complet.
|
|
62
|
+
*
|
|
63
|
+
* Le défaut est `report` — et il est structurel, pas prudent : une application
|
|
64
|
+
* qui écrit des migrations libres (vues, déclencheurs, colonnes ajoutées à une
|
|
65
|
+
* table d'entité) a une base légitimement différente du schéma déclaré, en
|
|
66
|
+
* permanence. Faire tomber sa mise en service dessus rendrait le constat
|
|
67
|
+
* inutilisable, donc mort. Superviser ne fait pas tomber un déploiement.
|
|
68
|
+
*/
|
|
69
|
+
export declare const DIVERGENCE_MODES: readonly ["report", "fail", "off"];
|
|
70
|
+
/** Conduite face à une base qui a divergé du schéma déclaré. */
|
|
71
|
+
export type DivergenceMode = (typeof DIVERGENCE_MODES)[number];
|
|
72
|
+
export declare const drizzleConfigSchema: z.ZodObject<{
|
|
73
|
+
connectors: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
74
|
+
dialect: z.ZodDefault<z.ZodEnum<{
|
|
75
|
+
mysql: "mysql";
|
|
76
|
+
postgres: "postgres";
|
|
77
|
+
sqlite: "sqlite";
|
|
78
|
+
}>>;
|
|
79
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
80
|
+
url: z.ZodOptional<z.ZodString>;
|
|
81
|
+
ddl: z.ZodOptional<z.ZodEnum<{
|
|
82
|
+
auto: "auto";
|
|
83
|
+
migrate: "migrate";
|
|
84
|
+
none: "none";
|
|
85
|
+
}>>;
|
|
86
|
+
}, z.core.$strict>>>;
|
|
87
|
+
migrations: z.ZodDefault<z.ZodObject<{
|
|
88
|
+
dir: z.ZodDefault<z.ZodString>;
|
|
89
|
+
check: z.ZodOptional<z.ZodEnum<{
|
|
90
|
+
fail: "fail";
|
|
91
|
+
off: "off";
|
|
92
|
+
warn: "warn";
|
|
93
|
+
}>>;
|
|
94
|
+
lockTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
95
|
+
divergence: z.ZodDefault<z.ZodEnum<{
|
|
96
|
+
fail: "fail";
|
|
97
|
+
off: "off";
|
|
98
|
+
report: "report";
|
|
99
|
+
}>>;
|
|
100
|
+
}, z.core.$strict>>;
|
|
101
|
+
frameworkEntities: z.ZodDefault<z.ZodBoolean>;
|
|
102
|
+
}, z.core.$strict>;
|
|
103
|
+
/** Type de sortie (config normalisée + défauts appliqués). */
|
|
104
|
+
export type DrizzleConfig = z.infer<typeof drizzleConfigSchema>;
|
|
105
|
+
/**
|
|
106
|
+
* Défauts du module, matérialisés depuis le schéma (source unique). Toujours
|
|
107
|
+
* valides par construction ; passés au `super(..., config)` du Module class.
|
|
108
|
+
*/
|
|
109
|
+
declare const config: DrizzleConfig;
|
|
110
|
+
export default config;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IDrizzleConfig, IDrizzleConfigInput } from "../interfaces/IDrizzleConfig.js";
|
|
2
|
+
/**
|
|
3
|
+
* Builder type-safe de la configuration de `@nodefony/drizzle`.
|
|
4
|
+
*
|
|
5
|
+
* ⭐ TL;DR : MACHINERIE DE BOOT — on n'édite (presque) jamais ce fichier. Même
|
|
6
|
+
* pattern que `nodefony.config.ts` ↔ `defineConfig()` du core : `config.ts` PORTE
|
|
7
|
+
* la config (schéma + défauts), `define<X>Config()` la VALIDE au boot (parse +
|
|
8
|
+
* env + freeze) et publie le JSON Schema Studio.
|
|
9
|
+
*
|
|
10
|
+
* Aligné sur `defineMongooseConfig` (l'autre driver ORM) : source unique
|
|
11
|
+
* (`./config.ts`), VALIDE + applique l'ENV + GÈLE. Le **chemin SQLite par défaut**
|
|
12
|
+
* (kernel-dépendant) n'est PAS résolu ici (schéma pur) mais dans `DrizzleService`
|
|
13
|
+
* au boot — cf audit config ORM 2026-06 §3.2.
|
|
14
|
+
*
|
|
15
|
+
* @param config - configuration brute (sections omises = défauts sûrs).
|
|
16
|
+
* @returns config validée, surchargée par l'env, et gelée.
|
|
17
|
+
* @throws ZodError si la config est invalide.
|
|
18
|
+
*/
|
|
19
|
+
export declare function defineDrizzleConfig(config?: IDrizzleConfigInput): IDrizzleConfig;
|
|
20
|
+
/**
|
|
21
|
+
* JSON Schema introspectable de la config Drizzle — destiné au formulaire
|
|
22
|
+
* d'édition Studio (futur) et à la documentation générée.
|
|
23
|
+
*/
|
|
24
|
+
export declare function drizzleConfigJsonSchema(): unknown;
|