@fougere/adapter-sql 0.3.0-alpha.0 → 0.5.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 (51) hide show
  1. package/README.md +5 -3
  2. package/dist/crud.d.ts +3 -3
  3. package/dist/ddl.d.ts.map +1 -1
  4. package/dist/ddl.js +2 -2
  5. package/dist/ddl.js.map +1 -1
  6. package/dist/dialect.d.ts +8 -0
  7. package/dist/dialect.d.ts.map +1 -1
  8. package/dist/dialect.js +10 -0
  9. package/dist/dialect.js.map +1 -1
  10. package/dist/diff.d.ts.map +1 -1
  11. package/dist/diff.js +2 -2
  12. package/dist/diff.js.map +1 -1
  13. package/dist/fields.d.ts +22 -0
  14. package/dist/fields.d.ts.map +1 -0
  15. package/dist/fields.js +2 -0
  16. package/dist/fields.js.map +1 -0
  17. package/dist/index.d.ts +3 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/query.d.ts +34 -0
  22. package/dist/query.d.ts.map +1 -0
  23. package/dist/query.js +44 -0
  24. package/dist/query.js.map +1 -0
  25. package/dist/setup.d.ts +8 -0
  26. package/dist/setup.d.ts.map +1 -1
  27. package/dist/setup.js +2 -1
  28. package/dist/setup.js.map +1 -1
  29. package/dist/sqlite.d.ts.map +1 -1
  30. package/dist/sqlite.js +2 -1
  31. package/dist/sqlite.js.map +1 -1
  32. package/dist/step.js +3 -3
  33. package/dist/step.js.map +1 -1
  34. package/dist/table.d.ts +18 -22
  35. package/dist/table.d.ts.map +1 -1
  36. package/dist/table.js +40 -41
  37. package/dist/table.js.map +1 -1
  38. package/package.json +7 -5
  39. package/src/check.ts +76 -0
  40. package/src/crud.ts +570 -0
  41. package/src/ddl.ts +242 -0
  42. package/src/dialect.ts +204 -0
  43. package/src/diff.ts +196 -0
  44. package/src/fields.ts +24 -0
  45. package/src/index.ts +41 -0
  46. package/src/query.ts +64 -0
  47. package/src/setup.ts +72 -0
  48. package/src/sqlite.ts +44 -0
  49. package/src/step.ts +287 -0
  50. package/src/table.ts +428 -0
  51. package/src/values.ts +105 -0
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;
@@ -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.
@@ -120,19 +129,6 @@ export interface AppLike {
120
129
  * one source, where a miss can only be a mistake.
121
130
  */
122
131
  elsewhere?: string[];
123
- /**
124
- * The DERIVATIONS this app stores — registration names.
125
- *
126
- * A derivation makes no table by default: `Post.pick('id','title')` describes an
127
- * answer, not a place rows live, and one dropped under `entities/` used to get a
128
- * table of its own — measured on a real app, where a projection of an archived
129
- * entity created a duplicate in the OTHER database.
130
- *
131
- * Naming it in `sources:` is the opt-in, and it changes what the thing is: a stored
132
- * derivation is a dated COPY, not a projection, and it owes what any copy owes —
133
- * who fills it, and how old it is.
134
- */
135
- materialize?: string[];
136
132
  }
137
133
  /**
138
134
  * Every entity an app hosts, as FK-aware tables — the shared middle step behind
@@ -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":"AACA;;;;;;;;;;GAUG;AACH,OAAO,EAA4F,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC9I,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yFAAyF;AACzF,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;CAChD;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,0EAA0E;IAC1E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC;CAC1B;AAED,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAoHD,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,yFAAyF;IACzF,WAAW,CAAC,EAAE,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACxC,0FAA0F;IAC1F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1B,0FAA0F;IAC1F,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAChC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,QAAQ,CAmCtG;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAKnE;AAID,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,WAAW,EAAE,YAAY,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,gFAAgF;IAChF,IAAI,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;KAAE,CAAC;IAClD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,QAAQ,EAAE,CAOpF;AAID,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAsC1D"}
package/dist/table.js CHANGED
@@ -4,10 +4,13 @@ import { Lifecycle, Role } from '@fougere/schema';
4
4
  *
5
5
  * This is the neutral middle term: one projection reads the entity's axes and
6
6
  * produces a `TableDef`; a `Dialect` turns that into SQL. Neither half knows the
7
- * other — the entity never mentions a column type, the dialect never mentions a
8
- * field. Adding a dialect touches only the second half.
7
+ * other — the dialect never mentions a field. Adding a dialect touches only the
8
+ * second half.
9
+ *
10
+ * `ColumnDef.stated` is the one member the axes did not produce. It names one engine's
11
+ * column type, so dropping it leaves every column describable.
9
12
  */
10
- import { Anatomy, FieldGroup, Unique, fieldsOf, registrationKeyOf } from '@fougere/schema';
13
+ import { Anatomy, FieldGroup, Unique, fieldsOf, lowerFirst, schemaOf } from '@fougere/schema';
11
14
  import { boundsOf } from './check.js';
12
15
  /** camelCase → snake_case */
13
16
  export function toSnakeCase(str) {
@@ -22,8 +25,7 @@ function isStored(field) {
22
25
  }
23
26
  /**
24
27
  * The target's primary key column. A live thunk (an in-process entity) answers
25
- * for real; a relation reconstructed from a lone card (`reconstruct()`, no
26
- * bundle — `packages/schema/src/projections/card.ts:18-22`) has lost it to a
28
+ * for real; a relation reconstructed from a lone `Card` (without a `Bundle`) has lost it to a
27
29
  * name stand-in with no `getFields` — the convention there is to assume `id`.
28
30
  */
29
31
  function primaryColumnOf(target) {
@@ -73,7 +75,7 @@ function referenceFor(field, resolve, tableNameOf, hosted) {
73
75
  // `ref(Subscription)` while the table was in the very batch being built. Everything
74
76
  // else that resolves a relation target already resolves it by name, for the same
75
77
  // reason — a target rebuilt from a card is a `{ name }` stand-in.
76
- const key = registrationKeyOf(target.name ?? '');
78
+ const key = lowerFirst(target.name ?? '');
77
79
  if (hosted.elsewhere.has(key))
78
80
  return undefined;
79
81
  if (!hosted.here.has(key)) {
@@ -81,11 +83,11 @@ function referenceFor(field, resolve, tableNameOf, hosted) {
81
83
  `Check the entity is scanned, and that \`sources\` spells its name the same way.`);
82
84
  }
83
85
  }
84
- const table = mapped ?? resolve(registrationKeyOf(target.name ?? ''));
86
+ const table = mapped ?? resolve(lowerFirst(target.name ?? ''));
85
87
  const column = primaryColumnOf(target);
86
88
  return relation.onDelete ? { table, column, onDelete: relation.onDelete } : { table, column };
87
89
  }
88
- function toColumn(fieldName, field, resolve, tableNameOf, hosted) {
90
+ function toColumn(fieldName, field, resolve, tableNameOf, hosted, stated) {
89
91
  // The column type comes from the `shape` axis alone. `anatomy` strips the
90
92
  // nullable union so a nullable integer stays an integer instead of falling
91
93
  // through to text.
@@ -116,6 +118,8 @@ function toColumn(fieldName, field, resolve, tableNameOf, hosted) {
116
118
  const references = referenceFor(field, resolve, tableNameOf, hosted);
117
119
  if (references)
118
120
  column.references = references;
121
+ if (stated)
122
+ column.stated = stated;
119
123
  return column;
120
124
  }
121
125
  /**
@@ -127,17 +131,19 @@ function toColumn(fieldName, field, resolve, tableNameOf, hosted) {
127
131
  *
128
132
  * A lone card has no live relation targets, so a `ref()` falls back to the conventions
129
133
  * `referenceFor`/`primaryColumnOf` already document (name-derived table, `id` as the key).
130
- * Pass a bundle through `reconstructSet` first when the FKs matter — it resolves the
134
+ * Pass a descriptor through `Bundle.toSchemas` first when the FKs matter — it resolves the
131
135
  * targets, and its output is the live-class case again.
132
136
  */
133
137
  export function toTable(tableName, entity, relations) {
134
138
  const resolve = relations?.resolve ?? toTableName;
135
139
  const fields = fieldsOf(entity);
140
+ // Read off the entity, since that is where it is declared and addressed by field key.
141
+ const stated = schemaOf(entity).getAdapters()?.sql;
136
142
  const columns = [];
137
143
  for (const [fieldName, field] of Object.entries(fields)) {
138
144
  if (!isStored(field))
139
145
  continue;
140
- columns.push(toColumn(fieldName, field, resolve, relations?.tableNameOf, relations?.hosted));
146
+ columns.push(toColumn(fieldName, field, resolve, relations?.tableNameOf, relations?.hosted, stated?.[fieldName]));
141
147
  }
142
148
  const primaries = columns.filter((column) => column.primary).map((column) => column.name);
143
149
  const stored = new Set(columns.map((column) => column.name));
@@ -184,47 +190,41 @@ export function toTableName(name) {
184
190
  return name.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`) + 's';
185
191
  }
186
192
  /**
187
- * Does this schema come from another one? `Post` answers no, `Post.pick(…)` answers
188
- * `Post` — a derivation carries its origin, which `sourceNameOf` already reads for two
189
- * other projections. Recognised by that FORM, never by a brand.
193
+ * A schema says whether it holds rows; this adapter decides what to emit for it.
194
+ *
195
+ * A root always did. A derivation describes ANOTHER's rows `Post.pick('id','title')` is
196
+ * a shape, and one dropped under `entities/` used to get a table of its own: measured on a
197
+ * real app, where a projection of an archived entity created a duplicate in the OTHER
198
+ * database. `.anchor()` is what says otherwise, and it is the entity's own word, never a
199
+ * key of the app's config: a frond stays mountable without its host knowing.
190
200
  */
191
- function isDerivation(source) {
192
- return source.source !== undefined;
201
+ function verdictOn(entry) {
202
+ const schema = schemaOf(entry.entityClass);
203
+ return !schema.derivation || schema.anchored ? 'table' : 'answer';
193
204
  }
194
205
  /**
195
- * A stored derivation must be able to say HOW OLD it is.
196
- *
197
- * It is a copy, and a copy read as if it were live is the silent loss this whole
198
- * design exists to refuse: rows from yesterday typed exactly like rows from now. The
199
- * vocabulary already carries the answer — a field with `update: 'now'` records when
200
- * this row last changed HERE, which for a copy is when it was last pulled. So nothing
201
- * new is declared; what is new is that forgetting it is refused, at boot, by name.
202
- *
203
- * An entity is untouched: it is not a copy of anything, and its rows are the truth.
206
+ * Every entity this app hosts, once each. The same class reaches here under one
207
+ * registration name from two lists — a frond's `entities/` and the auth runtime's map —
208
+ * and two entries for one name are two CREATE TABLE for one table.
204
209
  */
205
- function refuseUndated(name, source) {
206
- const dated = Object.values(fieldsOf(source)).some((field) => Lifecycle.of(field).stampedOnUpdate);
207
- if (dated)
208
- return;
209
- throw new Error(`${name} is stored as a derivation but carries no \`updated()\` field — a copy that ` +
210
- `cannot say when it was pulled reads exactly like live rows. Add one, or drop it from \`sources\`.`);
211
- }
212
210
  function collectEntities(app) {
213
- const stored = new Set((app.materialize ?? []).map((name) => registrationKeyOf(name)));
214
211
  const entries = [];
212
+ const held = new Set();
213
+ const hold = (entry) => {
214
+ if (held.has(lowerFirst(entry.name)))
215
+ return;
216
+ held.add(lowerFirst(entry.name));
217
+ entries.push(entry);
218
+ };
215
219
  for (const frond of app.fronds) {
216
220
  for (const entry of frond.entities) {
217
- if (isDerivation(entry.entityClass)) {
218
- if (!stored.has(registrationKeyOf(entry.name)))
219
- continue;
220
- refuseUndated(entry.name, entry.entityClass);
221
- }
222
- entries.push(entry);
221
+ if (verdictOn(entry) === 'table')
222
+ hold(entry);
223
223
  }
224
224
  }
225
225
  if (app.auth?.entities) {
226
226
  for (const [name, entityClass] of Object.entries(app.auth.entities))
227
- entries.push({ name, entityClass });
227
+ hold({ name, entityClass });
228
228
  }
229
229
  return entries;
230
230
  }
@@ -237,9 +237,8 @@ function collectEntities(app) {
237
237
  export function toTables(app, resolve) {
238
238
  const entries = collectEntities(app);
239
239
  const tableNameOf = new Map(entries.map((entry) => [entry.entityClass, resolve(entry.name)]));
240
- const lower = (name) => name.charAt(0).toLowerCase() + name.slice(1);
241
240
  const hosted = app.elsewhere
242
- ? { here: new Set(entries.map((entry) => lower(entry.name))), elsewhere: new Set(app.elsewhere.map(lower)) }
241
+ ? { here: new Set(entries.map((entry) => lowerFirst(entry.name))), elsewhere: new Set(app.elsewhere.map(lowerFirst)) }
243
242
  : undefined;
244
243
  return entries.map((entry) => toTable(resolve(entry.name), entry.entityClass, { resolve, tableNameOf, hosted }));
245
244
  }
package/dist/table.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/adapter-sql",
3
- "version": "0.3.0-alpha.0",
3
+ "version": "0.5.0-alpha.0",
4
4
  "description": "Entity → SQL tables through Kysely (SQLite, PostgreSQL, MySQL, SQL Server).",
5
5
  "keywords": [
6
6
  "fougere",
@@ -33,12 +33,14 @@
33
33
  }
34
34
  },
35
35
  "files": [
36
- "dist"
36
+ "dist",
37
+ "src"
37
38
  ],
38
39
  "dependencies": {
39
40
  "better-sqlite3": "^13.0.3",
40
- "@fougere/schema": "0.3.0-alpha.0",
41
- "@fougere/core": "0.3.0-alpha.0"
41
+ "dequal": "^2.0.3",
42
+ "@fougere/core": "0.5.0-alpha.0",
43
+ "@fougere/schema": "0.5.0-alpha.0"
42
44
  },
43
45
  "peerDependencies": {
44
46
  "kysely": ">=0.28.17"
@@ -47,7 +49,7 @@
47
49
  "@types/better-sqlite3": "^7.6.13",
48
50
  "@types/node": "^22.0.0",
49
51
  "kysely": "^0.28.17",
50
- "@fougere/core": "0.3.0-alpha.0"
52
+ "@fougere/core": "0.5.0-alpha.0"
51
53
  },
52
54
  "publishConfig": {
53
55
  "access": "public"
package/src/check.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Shape → CHECK constraints.
3
+ *
4
+ * `oneOf`, `min`, `max` were declared on the field and read by the façade alone: a
5
+ * handler writing through the ORM put `status: 'brouillon'` in a column that declares
6
+ * two values, and nothing said a word. The rule was in the schema; no one held it on
7
+ * that path.
8
+ *
9
+ * So the storage learns what the shape already says. `validate` judges what a client
10
+ * proposes; this holds what anyone writes — including us.
11
+ *
12
+ * Only the keywords a database can decide alone. `pattern` and `format` are left to
13
+ * the façade: regex dialects diverge (POSIX here, PCRE there, nothing in SQLite
14
+ * without an extension), and a constraint that means something different per engine
15
+ * is worse than none.
16
+ *
17
+ * Every value is inlined with `sql.lit`, not bound: SQLite answers `parameters
18
+ * prohibited in CHECK constraints`, and a constraint is part of the schema rather
19
+ * than of a query. The values are the author's own literals — `oneOf('draft', …)`,
20
+ * `max: 160` — never anything a request carried, and Kysely escapes them.
21
+ */
22
+ import { sql, type Expression, type SqlBool } from 'kysely';
23
+ import type { ColumnDef } from './table.js';
24
+
25
+ /** What a column's shape can be checked for, beyond its type. */
26
+ export interface ShapeBounds {
27
+ enum?: readonly (string | number)[];
28
+ minLength?: number;
29
+ maxLength?: number;
30
+ minimum?: number;
31
+ maximum?: number;
32
+ }
33
+
34
+ /**
35
+ * The CHECK expression for one column, or nothing when its shape bounds nothing.
36
+ *
37
+ * A nullable column passes when it holds `null`: `NOT NULL` is the axis that decides
38
+ * presence, and stacking the two would make `optional()` unwritable.
39
+ */
40
+ export function checkFor(column: ColumnDef): Expression<SqlBool> | undefined {
41
+ const bounds = column.bounds;
42
+ if (!bounds) return undefined;
43
+
44
+ const col = sql.ref(column.name);
45
+ const terms: Expression<SqlBool>[] = [];
46
+
47
+ if (bounds.enum?.length) {
48
+ terms.push(sql<SqlBool>`${col} in (${sql.join(bounds.enum.map((v) => sql.lit(v)))})`);
49
+ }
50
+ // Length, not value: a text bound is about the string, and `maxLength` is already
51
+ // spent on the column type where the dialect uses it (varchar(n)) — stating it
52
+ // again costs nothing and holds where the type does not (text columns).
53
+ if (bounds.minLength !== undefined) terms.push(sql<SqlBool>`length(${col}) >= ${sql.lit(bounds.minLength)}`);
54
+ if (bounds.maxLength !== undefined) terms.push(sql<SqlBool>`length(${col}) <= ${sql.lit(bounds.maxLength)}`);
55
+ if (bounds.minimum !== undefined) terms.push(sql<SqlBool>`${col} >= ${sql.lit(bounds.minimum)}`);
56
+ if (bounds.maximum !== undefined) terms.push(sql<SqlBool>`${col} <= ${sql.lit(bounds.maximum)}`);
57
+
58
+ if (terms.length === 0) return undefined;
59
+
60
+ const all = terms.reduce((left, right) => sql<SqlBool>`${left} and ${right}`);
61
+
62
+ return column.nullable ? sql<SqlBool>`${col} is null or (${all})` : all;
63
+ }
64
+
65
+ /** Read the bounds off a field's base shape — the keywords a database can decide. */
66
+ export function boundsOf(shape: Record<string, unknown> | undefined): ShapeBounds | undefined {
67
+ if (!shape) return undefined;
68
+
69
+ const bounds: ShapeBounds = {};
70
+ if (Array.isArray(shape.enum) && shape.enum.length > 0) bounds.enum = shape.enum as string[];
71
+ for (const key of ['minLength', 'maxLength', 'minimum', 'maximum'] as const) {
72
+ if (typeof shape[key] === 'number') bounds[key] = shape[key] as number;
73
+ }
74
+
75
+ return Object.keys(bounds).length > 0 ? bounds : undefined;
76
+ }