@fougere/adapter-sql 0.2.0-alpha.2 → 0.4.0-alpha.0

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.
Files changed (52) hide show
  1. package/README.md +1 -1
  2. package/dist/crud.d.ts +14 -3
  3. package/dist/crud.d.ts.map +1 -1
  4. package/dist/crud.js +33 -4
  5. package/dist/crud.js.map +1 -1
  6. package/dist/ddl.d.ts.map +1 -1
  7. package/dist/ddl.js +2 -2
  8. package/dist/ddl.js.map +1 -1
  9. package/dist/dialect.d.ts +20 -0
  10. package/dist/dialect.d.ts.map +1 -1
  11. package/dist/dialect.js +27 -1
  12. package/dist/dialect.js.map +1 -1
  13. package/dist/diff.d.ts.map +1 -1
  14. package/dist/diff.js +2 -2
  15. package/dist/diff.js.map +1 -1
  16. package/dist/fields.d.ts +22 -0
  17. package/dist/fields.d.ts.map +1 -0
  18. package/dist/fields.js +2 -0
  19. package/dist/fields.js.map +1 -0
  20. package/dist/index.d.ts +6 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +7 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/setup.d.ts +18 -10
  25. package/dist/setup.d.ts.map +1 -1
  26. package/dist/setup.js +10 -23
  27. package/dist/setup.js.map +1 -1
  28. package/dist/sqlite.d.ts +12 -0
  29. package/dist/sqlite.d.ts.map +1 -0
  30. package/dist/sqlite.js +34 -0
  31. package/dist/sqlite.js.map +1 -0
  32. package/dist/step.d.ts +78 -0
  33. package/dist/step.d.ts.map +1 -0
  34. package/dist/step.js +233 -0
  35. package/dist/step.js.map +1 -0
  36. package/dist/table.d.ts +19 -10
  37. package/dist/table.d.ts.map +1 -1
  38. package/dist/table.js +36 -30
  39. package/dist/table.js.map +1 -1
  40. package/package.json +11 -4
  41. package/src/check.ts +76 -0
  42. package/src/crud.ts +570 -0
  43. package/src/ddl.ts +242 -0
  44. package/src/dialect.ts +204 -0
  45. package/src/diff.ts +196 -0
  46. package/src/fields.ts +24 -0
  47. package/src/index.ts +40 -0
  48. package/src/setup.ts +63 -0
  49. package/src/sqlite.ts +43 -0
  50. package/src/step.ts +287 -0
  51. package/src/table.ts +447 -0
  52. package/src/values.ts +105 -0
package/dist/setup.d.ts CHANGED
@@ -1,5 +1,13 @@
1
+ /**
2
+ * Storage setup — the shape every engine answers, and no driver at all.
3
+ *
4
+ * Fougere has no business choosing a driver (`pg`, `mysql2`, `tedious`, `better-sqlite3`,
5
+ * a D1 binding), so the caller builds the Kysely dialect and hands it over — no dynamic
6
+ * import, no optional dependency. This file therefore reaches for nothing: it is what a
7
+ * runtime with no filesystem imports. The one driver this package does own lives behind
8
+ * `@fougere/adapter-sql/sqlite`.
9
+ */
1
10
  import { Kysely, type Dialect as KyselyDialect } from 'kysely';
2
- import Database from 'better-sqlite3';
3
11
  import { createOrmFactory, type OrmFactoryOptions } from './crud.js';
4
12
  import type { DialectName } from './dialect.js';
5
13
  import type { SqlSink } from './ddl.js';
@@ -7,10 +15,6 @@ export interface SetupOptions {
7
15
  /** Override naming for specific entities (e.g. better-auth wants singular table names). */
8
16
  ormFactoryOptions?: OrmFactoryOptions;
9
17
  }
10
- export interface SqliteSetupOptions extends SetupOptions {
11
- /** Filesystem path to the database. Defaults to a project-local file. */
12
- path?: string;
13
- }
14
18
  export interface Setup {
15
19
  dialect: DialectName;
16
20
  ormFactory: ReturnType<typeof createOrmFactory>;
@@ -24,14 +28,18 @@ export interface Setup {
24
28
  * whose `client` gives the same handle while keeping the scope of its entity.
25
29
  */
26
30
  db: Kysely<any>;
27
- }
28
- export interface SqliteSetup extends Setup {
29
- /** The raw handle, for pragmas and synchronous exec. */
30
- sqlite: Database.Database;
31
+ /**
32
+ * Run `fn` inside one transaction of this engine, with an ORM factory bound to it.
33
+ *
34
+ * The transaction belongs to the engine, so obtaining one is a gesture on the engine and
35
+ * nowhere else. Nothing new is handed back: `Transaction<DB> extends Kysely<DB>` and
36
+ * `SqlEntityOrm` takes a `Kysely<any>`, so the SAME ORM is rebuilt over the substituted
37
+ * connection — which is why a frame needs no support in this package.
38
+ */
39
+ transacted<R>(fn: (ormFactory: ReturnType<typeof createOrmFactory>) => Promise<R>): Promise<R>;
31
40
  }
32
41
  /** A sink that runs statements through Kysely — works on every engine. */
33
42
  export declare function sqlSink(db: Kysely<any>): SqlSink;
34
43
  /** Wrap any Kysely dialect — Postgres, MySQL, SQL Server. */
35
44
  export declare function setupKysely(kyselyDialect: KyselyDialect, dialect: DialectName, opts?: SetupOptions): Setup;
36
- export declare function setupSqlite(opts?: SqliteSetupOptions): SqliteSetup;
37
45
  //# sourceMappingURL=setup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAsB,KAAK,OAAO,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAC;AACnF,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAChD,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;IACd;;;;;;OAMG;IACH,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,wDAAwD;IACxD,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC;CAC3B;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAEhD;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CACzB,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,YAAiB,GACtB,KAAK,CAGP;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,WAAW,CAetE"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,EAAO,KAAK,OAAO,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAChD,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;IACd;;;;;;OAMG;IACH,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAChB;;;;;;;OAOG;IACH,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAChG;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAEhD;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CACzB,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,YAAiB,GACtB,KAAK,CASP"}
package/dist/setup.js CHANGED
@@ -1,15 +1,13 @@
1
1
  /**
2
- * Storage setup — convention for SQLite, an escape hatch for the rest.
2
+ * Storage setup — the shape every engine answers, and no driver at all.
3
3
  *
4
- * SQLite is the default a first run meets, so it gets a concrete helper that
5
- * owns its driver. Every other engine needs a driver Fougere has no business
6
- * choosing (`pg`, `mysql2`, `tedious`), so the caller builds the Kysely dialect
7
- * and hands it over no dynamic import, no optional dependency.
4
+ * Fougere has no business choosing a driver (`pg`, `mysql2`, `tedious`, `better-sqlite3`,
5
+ * a D1 binding), so the caller builds the Kysely dialect and hands it over — no dynamic
6
+ * import, no optional dependency. This file therefore reaches for nothing: it is what a
7
+ * runtime with no filesystem imports. The one driver this package does own lives behind
8
+ * `@fougere/adapter-sql/sqlite`.
8
9
  */
9
- import { mkdirSync } from 'node:fs';
10
- import { dirname } from 'node:path';
11
- import { Kysely, SqliteDialect, sql } from 'kysely';
12
- import Database from 'better-sqlite3';
10
+ import { Kysely, sql } from 'kysely';
13
11
  import { createOrmFactory } from './crud.js';
14
12
  /** A sink that runs statements through Kysely — works on every engine. */
15
13
  export function sqlSink(db) {
@@ -18,23 +16,12 @@ export function sqlSink(db) {
18
16
  /** Wrap any Kysely dialect — Postgres, MySQL, SQL Server. */
19
17
  export function setupKysely(kyselyDialect, dialect, opts = {}) {
20
18
  const db = new Kysely({ dialect: kyselyDialect });
21
- return { db, dialect, ormFactory: createOrmFactory(db, opts.ormFactoryOptions, dialect), sink: sqlSink(db) };
22
- }
23
- export function setupSqlite(opts = {}) {
24
- const path = opts.path ?? 'fougere.db';
25
- // A file-backed DB needs its directory — SQLite won't create it.
26
- if (path !== ':memory:')
27
- mkdirSync(dirname(path), { recursive: true });
28
- const sqlite = new Database(path);
29
- sqlite.pragma('journal_mode = WAL');
30
- sqlite.pragma('foreign_keys = ON');
31
- const db = new Kysely({ dialect: new SqliteDialect({ database: sqlite }) });
32
19
  return {
33
20
  db,
34
- sqlite,
35
- dialect: 'sqlite',
36
- ormFactory: createOrmFactory(db, opts.ormFactoryOptions, 'sqlite'),
21
+ dialect,
22
+ ormFactory: createOrmFactory(db, opts.ormFactoryOptions, dialect),
37
23
  sink: sqlSink(db),
24
+ transacted: (fn) => db.transaction().execute((trx) => fn(createOrmFactory(trx, opts.ormFactoryOptions, dialect))),
38
25
  };
39
26
  }
40
27
  //# sourceMappingURL=setup.js.map
package/dist/setup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,EAAiC,MAAM,QAAQ,CAAC;AACnF,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAA0B,MAAM,WAAW,CAAC;AAkCrE,0EAA0E;AAC1E,MAAM,UAAU,OAAO,CAAC,EAAe;IACrC,OAAO,EAAE,OAAO,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CACzB,aAA4B,EAC5B,OAAoB,EACpB,IAAI,GAAiB,EAAE;IAEvB,MAAM,EAAE,GAAG,IAAI,MAAM,CAAM,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IACvD,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/G,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAI,GAAuB,EAAE;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,iEAAiE;IACjE,IAAI,IAAI,KAAK,UAAU;QAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAM,EAAE,OAAO,EAAE,IAAI,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACjF,OAAO;QACL,EAAE;QACF,MAAM;QACN,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;QAClE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;KAClB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAiC,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAA0B,MAAM,WAAW,CAAC;AAiCrE,0EAA0E;AAC1E,MAAM,UAAU,OAAO,CAAC,EAAe;IACrC,OAAO,EAAE,OAAO,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CACzB,aAA4B,EAC5B,OAAoB,EACpB,IAAI,GAAiB,EAAE;IAEvB,MAAM,EAAE,GAAG,IAAI,MAAM,CAAM,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IACvD,OAAO;QACL,EAAE;QACF,OAAO;QACP,UAAU,EAAE,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC;QACjE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;QACjB,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,CAAC;KAClH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import Database from 'better-sqlite3';
2
+ import { type Setup, type SetupOptions } from './setup.js';
3
+ export interface SqliteSetupOptions extends SetupOptions {
4
+ /** Filesystem path to the database. Defaults to a project-local file. */
5
+ path?: string;
6
+ }
7
+ export interface SqliteSetup extends Setup {
8
+ /** The raw handle, for pragmas and synchronous exec. */
9
+ sqlite: Database.Database;
10
+ }
11
+ export declare function setupSqlite(opts?: SqliteSetupOptions): SqliteSetup;
12
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAYA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,EAAW,KAAK,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,wDAAwD;IACxD,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC;CAC3B;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,WAAW,CAgBtE"}
package/dist/sqlite.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * SQLite on a file — the convention a first run meets, and the only driver this package owns.
3
+ *
4
+ * It sits behind its own subpath because `better-sqlite3` is a NATIVE module and `node:fs`
5
+ * is a builtin: a bundler cannot prune a module that imports them, so re-exporting this
6
+ * from the index made the whole adapter unreachable from a runtime that has neither. Same
7
+ * cut as `@fougere/transport-http/receive`, and for the same reason — share the projection,
8
+ * never the plumbing.
9
+ */
10
+ import { mkdirSync } from 'node:fs';
11
+ import { dirname } from 'node:path';
12
+ import { Kysely, SqliteDialect } from 'kysely';
13
+ import Database from 'better-sqlite3';
14
+ import { createOrmFactory } from './crud.js';
15
+ import { sqlSink } from './setup.js';
16
+ export function setupSqlite(opts = {}) {
17
+ const path = opts.path ?? 'fougere.db';
18
+ // A file-backed DB needs its directory — SQLite won't create it.
19
+ if (path !== ':memory:')
20
+ mkdirSync(dirname(path), { recursive: true });
21
+ const sqlite = new Database(path);
22
+ sqlite.pragma('journal_mode = WAL');
23
+ sqlite.pragma('foreign_keys = ON');
24
+ const db = new Kysely({ dialect: new SqliteDialect({ database: sqlite }) });
25
+ return {
26
+ db,
27
+ sqlite,
28
+ dialect: 'sqlite',
29
+ ormFactory: createOrmFactory(db, opts.ormFactoryOptions, 'sqlite'),
30
+ sink: sqlSink(db),
31
+ transacted: (fn) => db.transaction().execute((trx) => fn(createOrmFactory(trx, opts.ormFactoryOptions, 'sqlite'))),
32
+ };
33
+ }
34
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAiC,MAAM,YAAY,CAAC;AAYpE,MAAM,UAAU,WAAW,CAAC,IAAI,GAAuB,EAAE;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC;IACvC,iEAAiE;IACjE,IAAI,IAAI,KAAK,UAAU;QAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAM,EAAE,OAAO,EAAE,IAAI,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACjF,OAAO;QACL,EAAE;QACF,MAAM;QACN,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;QAClE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;QACjB,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;KACnH,CAAC;AACJ,CAAC"}
package/dist/step.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The half `delta()` refuses — realised from an intention that was written down.
3
+ *
4
+ * `diff.ts` states its own guarantee: additive only, because "a rename is not even
5
+ * detectable from a diff (it reads as a drop plus an add)". That still holds, and this
6
+ * file does not weaken it. What changed is upstream: a frozen step (`fougere freeze`)
7
+ * carries a rename because a human declared it at the moment they made it. The intention
8
+ * exists now, so it can be realised — and only what the step actually says.
9
+ *
10
+ * A drop and a rename both touch live data, so this is the only place either can come
11
+ * from: never introspection, never a guess.
12
+ */
13
+ import { type Kysely } from 'kysely';
14
+ import type { SetDiff } from '@fougere/schema';
15
+ import { type DialectName } from './dialect.js';
16
+ import { type TableDef } from './table.js';
17
+ import type { SchemaState } from './diff.js';
18
+ /** What a step asks of the tables — beyond what an additive pass already covers. */
19
+ export type StepChange = {
20
+ kind: 'renameColumn';
21
+ table: string;
22
+ from: string;
23
+ to: string;
24
+ } | {
25
+ kind: 'dropColumn';
26
+ table: string;
27
+ column: string;
28
+ };
29
+ /** Something the step asks and the DDL will not do, naming why and what fixes it. */
30
+ export interface Refusal {
31
+ entity: string;
32
+ field: string;
33
+ reason: string;
34
+ }
35
+ export interface Plan {
36
+ changes: StepChange[];
37
+ /**
38
+ * Empty means the step is realisable whole. Anything here is a decision the DDL may
39
+ * not take alone — reported together so one run names every one of them.
40
+ */
41
+ refusals: Refusal[];
42
+ }
43
+ export interface PlanOptions {
44
+ /** Entity key → table name. Same resolver `desiredTables` takes. */
45
+ tableName?: (name: string) => string;
46
+ /**
47
+ * What the database actually holds, from `actualState`. Given, a change already
48
+ * realised is skipped.
49
+ *
50
+ * Idempotence by OBSERVATION and not by bookkeeping — the same choice `delta` makes.
51
+ * A ledger of applied steps would be a second record of a fact the columns already
52
+ * carry, and the two would disagree the day someone renamed a column by hand.
53
+ */
54
+ actual?: SchemaState;
55
+ }
56
+ /**
57
+ * Collapse a chain of steps into one, following each field through its renames.
58
+ *
59
+ * A step judges itself on two names — old gone, new here — so an intermediate rename is
60
+ * unrecognisable once its target has been renamed again: both names are absent and it is
61
+ * proposed forever. Composing the chain first asks the question about the name the field
62
+ * ENDS on, which is the only one the tables can answer.
63
+ */
64
+ export declare function collapseChain(steps: readonly SetDiff[]): SetDiff;
65
+ /**
66
+ * Turn a frozen step into what the tables must do, and what nobody may decide for you.
67
+ *
68
+ * Pure, like `delta` — the comparison is one thing, running it is another.
69
+ */
70
+ export declare function planStep(step: SetDiff, tables: TableDef[], options?: PlanOptions): Plan;
71
+ /** One statement per change — the same rule `migrate` follows: no driver here batches. */
72
+ export declare function stepSQL(change: StepChange, dialectName?: DialectName): string;
73
+ /**
74
+ * Run a step. Refuses whole rather than part-way: a plan with any refusal in it is a
75
+ * plan someone has to read, and half a rename is worse than none.
76
+ */
77
+ export declare function applyStep(plan: Plan, db: Kysely<any>, dialectName?: DialectName): Promise<string[]>;
78
+ //# sourceMappingURL=step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAO,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EAAyB,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAGtE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAA4B,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,oFAAoF;AACpF,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,qFAAqF;AACrF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB;;;OAGG;IACH,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAgBhE;AAoCD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAwB3F;AAsHD,0FAA0F;AAC1F,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,GAAE,WAAsB,GAAG,MAAM,CAKvF;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,WAAW,GAAE,WAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAYnH"}
package/dist/step.js ADDED
@@ -0,0 +1,233 @@
1
+ /**
2
+ * The half `delta()` refuses — realised from an intention that was written down.
3
+ *
4
+ * `diff.ts` states its own guarantee: additive only, because "a rename is not even
5
+ * detectable from a diff (it reads as a drop plus an add)". That still holds, and this
6
+ * file does not weaken it. What changed is upstream: a frozen step (`fougere freeze`)
7
+ * carries a rename because a human declared it at the moment they made it. The intention
8
+ * exists now, so it can be realised — and only what the step actually says.
9
+ *
10
+ * A drop and a rename both touch live data, so this is the only place either can come
11
+ * from: never introspection, never a guess.
12
+ */
13
+ import { sql } from 'kysely';
14
+ import { dequal } from 'dequal';
15
+ import { compiler } from './ddl.js';
16
+ import { toSnakeCase, toTableName } from './table.js';
17
+ /**
18
+ * Collapse a chain of steps into one, following each field through its renames.
19
+ *
20
+ * A step judges itself on two names — old gone, new here — so an intermediate rename is
21
+ * unrecognisable once its target has been renamed again: both names are absent and it is
22
+ * proposed forever. Composing the chain first asks the question about the name the field
23
+ * ENDS on, which is the only one the tables can answer.
24
+ */
25
+ export function collapseChain(steps) {
26
+ const entities = {};
27
+ const added = [];
28
+ const removed = [];
29
+ for (const step of steps) {
30
+ added.push(...step.entitiesAdded);
31
+ removed.push(...step.entitiesRemoved);
32
+ for (const [entity, answer] of Object.entries(step.entities)) {
33
+ const held = (entities[entity] ??= { changes: [], ambiguous: [] });
34
+ held.ambiguous.push(...answer.ambiguous);
35
+ for (const change of answer.changes)
36
+ compose(held.changes, change);
37
+ }
38
+ }
39
+ return { entities, entitiesAdded: [...new Set(added)], entitiesRemoved: [...new Set(removed)] };
40
+ }
41
+ /**
42
+ * Add one change to what the chain has said so far, rewriting rather than appending when
43
+ * it continues a field already moved. A rename back to its origin cancels: the tables
44
+ * never held the name in between, so there is nothing for them to do.
45
+ */
46
+ function compose(held, change) {
47
+ if (change.kind === 'renamed') {
48
+ const at = held.findIndex((each) => each.kind === 'renamed' && each.to === change.from);
49
+ if (at === -1) {
50
+ held.push(change);
51
+ return;
52
+ }
53
+ const first = held[at];
54
+ if (first.from === change.to)
55
+ held.splice(at, 1);
56
+ else
57
+ held[at] = { ...first, to: change.to };
58
+ return;
59
+ }
60
+ // Anything else names a field; if the chain renamed it earlier, the tables know it
61
+ // under the name it started with.
62
+ const field = 'field' in change ? change.field : undefined;
63
+ const at = held.findIndex((each) => each.kind === 'renamed' && each.to === field);
64
+ if (at === -1) {
65
+ held.push(change);
66
+ return;
67
+ }
68
+ const origin = held[at];
69
+ // A field the chain ends by dropping is dropped under its original name, and the
70
+ // renames that led there are work nobody has to do.
71
+ if (change.kind === 'removed')
72
+ held.splice(at, 1);
73
+ held.push({ ...change, field: origin.from });
74
+ }
75
+ /**
76
+ * Turn a frozen step into what the tables must do, and what nobody may decide for you.
77
+ *
78
+ * Pure, like `delta` — the comparison is one thing, running it is another.
79
+ */
80
+ export function planStep(step, tables, options = {}) {
81
+ const resolve = options.tableName ?? toTableName;
82
+ const actual = options.actual;
83
+ const byName = new Map(tables.map((table) => [table.name, table]));
84
+ const changes = [];
85
+ const refusals = [];
86
+ for (const [entity, answer] of Object.entries(step.entities)) {
87
+ const table = resolve(entity);
88
+ // A step for an entity this app no longer projects has nothing to act on. Saying so
89
+ // beats emitting SQL against a table that is not there.
90
+ if (!byName.has(table)) {
91
+ refusals.push({ entity, field: '*', reason: `no table '${table}' in this app — did the entity move?` });
92
+ continue;
93
+ }
94
+ for (const change of answer.changes) {
95
+ const decided = realise(entity, table, change, byName.get(table));
96
+ if ('reason' in decided)
97
+ refusals.push(decided);
98
+ else if (decided.change && !done(decided.change, actual?.get(table)))
99
+ changes.push(decided.change);
100
+ }
101
+ }
102
+ return { changes, refusals };
103
+ }
104
+ /** One shape change: a column instruction, nothing to do, or a refusal that names itself. */
105
+ function realise(entity, table, change, target) {
106
+ switch (change.kind) {
107
+ case 'renamed':
108
+ // The one thing introspection could never infer, and the reason a step exists.
109
+ return { change: { kind: 'renameColumn', table, from: toSnakeCase(change.from), to: toSnakeCase(change.to) } };
110
+ case 'removed':
111
+ return { change: { kind: 'dropColumn', table, column: toSnakeCase(change.field) } };
112
+ case 'added': {
113
+ // The additive pass adds it — unless it cannot: a NOT NULL column with no default
114
+ // fails on a table that already holds rows, and `addColumn` silently leaves it
115
+ // nullable instead. Two guarantees for one entity, decided by whether the table
116
+ // existed yesterday. Refusing here is what makes the declaration true either way.
117
+ if (!change.required)
118
+ return {};
119
+ const column = target.columns.find((each) => each.field === change.field);
120
+ if (column?.default !== undefined)
121
+ return {};
122
+ return {
123
+ entity,
124
+ field: change.field,
125
+ reason: `required with no default — existing rows have nothing to hold. Declare one: default(…)`,
126
+ };
127
+ }
128
+ case 'required':
129
+ if (!change.to)
130
+ return {}; // Loosening is the engine's business, and no row is at risk.
131
+ return {
132
+ entity,
133
+ field: change.field,
134
+ reason: `became required — rows written before it may hold nothing. Declare a default, or keep it optional`,
135
+ };
136
+ case 'retyped':
137
+ return {
138
+ entity,
139
+ field: change.field,
140
+ reason: `type moved ${change.from.join('|')} → ${change.to.join('|')} — no conversion is derivable, write the migration`,
141
+ };
142
+ case 'reshaped':
143
+ // A tightened bound is a CHECK, and altering one on a live table is engine-specific
144
+ // AND may be refused by rows already stored. The judge still enforces it at the door.
145
+ return {
146
+ entity,
147
+ field: change.field,
148
+ reason: `bounds moved — the door enforces them, the table keeps its old CHECK until you migrate it`,
149
+ };
150
+ case 'restated':
151
+ return restated(entity, change);
152
+ }
153
+ }
154
+ /**
155
+ * An axis other than shape moved. Only some of it is a fact about the table.
156
+ *
157
+ * `boundary` never is — it says who may read or write, which no column holds. `lifecycle`
158
+ * is one only through the DEFAULT clause. `role` is one three times over, and two of those
159
+ * are constraints a live table may already contradict.
160
+ */
161
+ function restated(entity, change) {
162
+ const refuse = (reason) => ({ entity, field: change.field, reason });
163
+ if (change.axis === 'boundary')
164
+ return {};
165
+ if (change.axis === 'lifecycle') {
166
+ const was = literalOf(change.from);
167
+ const is = literalOf(change.to);
168
+ if (was === is)
169
+ return {};
170
+ return refuse(`default moved ${show(was)} → ${show(is)} — the table keeps the old one, and nothing here alters a DEFAULT`);
171
+ }
172
+ const from = change.from ?? {};
173
+ const to = change.to ?? {};
174
+ if (from.primary !== to.primary)
175
+ return refuse(`primary moved — a key is not something a step may take from live rows`);
176
+ if (!dequal(from.unique, to.unique)) {
177
+ // The same reason `delta` cannot add one: CREATE UNIQUE INDEX fails on a table that
178
+ // already holds duplicates, so it is a decision about the rows, not about the DDL.
179
+ return refuse(`unique group moved — rows already stored may contradict it, so it is declared and applied by hand`);
180
+ }
181
+ if (!dequal(from.relation, to.relation))
182
+ return refuse(`relation moved — a foreign key is a constraint, and nothing here alters one`);
183
+ // What is left is the index, and only its appearance: the additive pass proposes every
184
+ // declared index at every boot, and nothing has ever dropped one.
185
+ if (from.index && !to.index)
186
+ return refuse(`index gone — nothing drops an index today, so the table keeps it`);
187
+ return {};
188
+ }
189
+ /** The value a lifecycle declares at create, when it declares one — what reaches DEFAULT. */
190
+ function literalOf(rules) {
191
+ const create = rules?.create;
192
+ return create && typeof create === 'object' && 'value' in create ? create.value : undefined;
193
+ }
194
+ const show = (value) => (value === undefined ? 'none' : JSON.stringify(value));
195
+ /**
196
+ * Has the table already moved? Read off the columns themselves.
197
+ *
198
+ * A rename whose old name is gone and whose new one is there has happened; a drop whose
199
+ * column is absent has happened. Unknown state (no introspection given) answers no, so a
200
+ * plan built without it proposes everything the step says.
201
+ */
202
+ function done(change, columns) {
203
+ if (!columns)
204
+ return false;
205
+ return change.kind === 'renameColumn'
206
+ ? !columns.has(change.from) && columns.has(change.to)
207
+ : !columns.has(change.column);
208
+ }
209
+ /** One statement per change — the same rule `migrate` follows: no driver here batches. */
210
+ export function stepSQL(change, dialectName = 'sqlite') {
211
+ const alter = compiler(dialectName).schema.alterTable(change.table);
212
+ return change.kind === 'renameColumn'
213
+ ? alter.renameColumn(change.from, change.to).compile().sql
214
+ : alter.dropColumn(change.column).compile().sql;
215
+ }
216
+ /**
217
+ * Run a step. Refuses whole rather than part-way: a plan with any refusal in it is a
218
+ * plan someone has to read, and half a rename is worse than none.
219
+ */
220
+ export async function applyStep(plan, db, dialectName = 'sqlite') {
221
+ if (plan.refusals.length > 0) {
222
+ const named = plan.refusals.map((one) => ` ${one.entity}.${one.field} — ${one.reason}`).join('\n');
223
+ throw new Error(`This step cannot be realised as it stands:\n${named}`);
224
+ }
225
+ const run = [];
226
+ for (const change of plan.changes) {
227
+ const statement = stepSQL(change, dialectName);
228
+ await sql.raw(statement).execute(db);
229
+ run.push(statement);
230
+ }
231
+ return run;
232
+ }
233
+ //# sourceMappingURL=step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.js","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"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"}
package/dist/table.d.ts CHANGED
@@ -3,18 +3,22 @@
3
3
  *
4
4
  * This is the neutral middle term: one projection reads the entity's axes and
5
5
  * produces a `TableDef`; a `Dialect` turns that into SQL. Neither half knows the
6
- * other — the entity never mentions a column type, the dialect never mentions a
7
- * field. Adding a dialect touches only the second half.
6
+ * other — the dialect never mentions a field. Adding a dialect touches only the
7
+ * second half.
8
+ *
9
+ * `ColumnDef.stated` is the one member the axes did not produce. It names one engine's
10
+ * column type, so dropping it leaves every column describable.
8
11
  */
9
- import { type SchemaSource } from '@fougere/schema';
12
+ import { type SchemaOrCard } from '@fougere/schema';
10
13
  import { type ShapeBounds } from './check.js';
14
+ import type { SqlField } from './fields.js';
11
15
  /** The shape keywords a dialect needs to choose a column type. */
12
16
  export interface ColumnShape {
13
17
  type?: string;
14
18
  format?: string;
15
19
  maxLength?: number;
16
20
  }
17
- /** One column, described by the axes — never by a SQL type. */
21
+ /** One column, described by the axes — plus, at most, what the entity stated for sql. */
18
22
  export interface ColumnDef {
19
23
  /** Field key on the entity. */
20
24
  field: string;
@@ -26,7 +30,7 @@ export interface ColumnDef {
26
30
  primary: boolean;
27
31
  /** A literal default (`lifecycle.create.value`), when the field declares one. */
28
32
  default?: unknown;
29
- /** `role.unique` — realized as a column constraint the database enforces. */
33
+ /** A {@link Unique} of one — realized as a column constraint the database enforces. */
30
34
  unique?: boolean;
31
35
  /** `role.index` — realized as a separate `CREATE INDEX`, never a constraint. */
32
36
  index?: boolean;
@@ -37,6 +41,11 @@ export interface ColumnDef {
37
41
  bounds?: ShapeBounds;
38
42
  /** The FK target, from `role.relation` when it's a `ref()` (kind `'one'`). */
39
43
  references?: ColumnReference;
44
+ /**
45
+ * What the entity stated for THIS adapter — never an axis. It says how the column is
46
+ * realized here; drop it and the column is still describable.
47
+ */
48
+ stated?: SqlField;
40
49
  }
41
50
  export interface ColumnReference {
42
51
  table: string;
@@ -62,7 +71,7 @@ export interface RelationResolve {
62
71
  /** Same resolver used for every entity's own table (default or a custom `tableName`). */
63
72
  resolve: (name: string) => string;
64
73
  /** Live entity class → its already-resolved table name, reused instead of re-derived. */
65
- tableNameOf?: Map<SchemaSource, string>;
74
+ tableNameOf?: Map<SchemaOrCard, string>;
66
75
  /** Which entities this batch holds and which live in another source — decided by NAME. */
67
76
  hosted?: HostedNames;
68
77
  }
@@ -82,10 +91,10 @@ export interface HostedNames {
82
91
  *
83
92
  * A lone card has no live relation targets, so a `ref()` falls back to the conventions
84
93
  * `referenceFor`/`primaryColumnOf` already document (name-derived table, `id` as the key).
85
- * Pass a bundle through `reconstructSet` first when the FKs matter — it resolves the
94
+ * Pass a descriptor through `Bundle.toSchemas` first when the FKs matter — it resolves the
86
95
  * targets, and its output is the live-class case again.
87
96
  */
88
- export declare function toTable(tableName: string, entity: SchemaSource, relations?: RelationResolve): TableDef;
97
+ export declare function toTable(tableName: string, entity: SchemaOrCard, relations?: RelationResolve): TableDef;
89
98
  /**
90
99
  * Is this column part of a key? MySQL and SQL Server refuse an unbounded text
91
100
  * column in a primary key or an index, so the dialect needs to know.
@@ -100,7 +109,7 @@ export declare function toTableName(name: string): string;
100
109
  export interface EntityEntry {
101
110
  name: string;
102
111
  /** A live class in-process, a card from a frond whose class never crossed. */
103
- entityClass: SchemaSource;
112
+ entityClass: SchemaOrCard;
104
113
  }
105
114
  export interface FrondLike {
106
115
  name: string;
@@ -110,7 +119,7 @@ export interface AppLike {
110
119
  fronds: FrondLike[];
111
120
  /** Auth runtime entities are migrated alongside scanned fronds when present. */
112
121
  auth?: {
113
- entities: Record<string, SchemaSource>;
122
+ entities: Record<string, SchemaOrCard>;
114
123
  };
115
124
  /**
116
125
  * Entities this app hosts in ANOTHER source — named so a miss can be read.
@@ -1 +1 @@
1
- {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}