@substrat-run/model-emit 0.0.1 → 0.2.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.
package/dist/plan.js ADDED
@@ -0,0 +1,179 @@
1
+ /**
2
+ * The migration journal — derived, and the one artifact that stays a file.
3
+ *
4
+ * The manifest and the route table are pure functions of live objects, so they
5
+ * are computed when the module loads. A journal cannot be: it is append-only,
6
+ * frozen once shipped, and read by a human in a pull request.
7
+ *
8
+ * **Nobody writes the version number.** The model states the current shape; the
9
+ * journal states what has already been applied. Reconstruct the second, diff
10
+ * against the first, and if the diff is non-empty append exactly ONE entry with
11
+ * a derived counter. Declaring a version is declaring a fact a diff already
12
+ * knows — and hand-numbering has failed in practice: a production journal in a
13
+ * real app ships two entries numbered 0010, because two people numbered by hand
14
+ * in two branches.
15
+ *
16
+ * Two branches both generating `0003` collide in `journal.json`, which is the
17
+ * right signal on an ordered append-only list. Resolution is mechanical: merge
18
+ * the model, re-run, it renumbers.
19
+ *
20
+ * **What this refuses.** Anything that would rewrite history or lose data: a
21
+ * dropped table or column, a retyped column, or a required column added to a
22
+ * table that may already hold rows. Those are real decisions (expand/contract,
23
+ * a backfill, a `renamedFrom` declaration) and a generator that guessed at them
24
+ * would be guessing with somebody's data.
25
+ */
26
+ import { z } from 'zod';
27
+ import { columnsOf, emitTables, uniqueConstraints } from './emit-sql.js';
28
+ import { journalColumns, journalUniques } from './journal.js';
29
+ const pad = (n) => String(n).padStart(4, '0');
30
+ /**
31
+ * What one entry would have to say to bring the journal up to the model.
32
+ *
33
+ * Pure: same model + same journal → same plan, every time. It reads no clock and
34
+ * mints no id, which is what lets the result be committed and diffed.
35
+ */
36
+ export function planMigration(entities, journal) {
37
+ const journalSql = journal.entries.map((e) => e.sql).join('\n');
38
+ const applied = journalColumns(journalSql);
39
+ const desired = journalColumns(emitTables(entities));
40
+ const appliedUniques = journalUniques(journalSql);
41
+ // table name → the entity that owns it, so a diff can be reported in the
42
+ // vocabulary the model uses rather than in raw table names.
43
+ const owner = new Map();
44
+ for (const [name, entity] of Object.entries(entities))
45
+ owner.set(entity.table, { name, entity });
46
+ const statements = [];
47
+ const changes = [];
48
+ const refusals = [];
49
+ // -- gone from the model, still in the journal ------------------------------
50
+ for (const table of applied.keys()) {
51
+ if (desired.has(table))
52
+ continue;
53
+ refusals.push(`table '${table}' is in the journal but no longer in the model — dropping a table is ` +
54
+ 'expand/contract, not a diff: retire it deliberately, or restore the entity');
55
+ }
56
+ for (const [table, wanted] of desired) {
57
+ const have = applied.get(table);
58
+ // -- new table ------------------------------------------------------------
59
+ if (!have) {
60
+ const o = owner.get(table);
61
+ if (!o)
62
+ continue;
63
+ // Built here rather than by re-emitting a one-entity registry: parent
64
+ // edges resolve against the FULL model, and a subset would silently drop
65
+ // the REFERENCES clause of every foreign key pointing outside it.
66
+ const cols = [
67
+ ...columnsOf(o.name, o.entity, entities).map((c) => ` ${c.ddl}`),
68
+ ...uniqueConstraints(o.name, o.entity).map((u) => ` ${u}`),
69
+ ];
70
+ statements.push(`CREATE TABLE ${table} (\n${cols.join(',\n')}\n);`);
71
+ changes.push(`add-${table}`);
72
+ continue;
73
+ }
74
+ // -- new columns on an existing table -------------------------------------
75
+ const o = owner.get(table);
76
+ if (!o)
77
+ continue;
78
+ const emitted = columnsOf(o.name, o.entity, entities);
79
+ // `{ current: previous }`, kept only for names the journal still holds. A
80
+ // declaration whose old name has already gone is spent, not wrong — the
81
+ // rename shipped, and the entry is now a gravestone the model may delete.
82
+ const renames = new Map();
83
+ for (const [current, previous] of Object.entries(o.entity.renamedFrom ?? {})) {
84
+ if (typeof previous !== 'string')
85
+ continue;
86
+ if (!emitted.some((c) => c.name === current)) {
87
+ refusals.push(`'${table}.${current}' is declared as renamed from '${previous}', but no such field ` +
88
+ 'exists in the model — a rename names the field it renamed TO');
89
+ continue;
90
+ }
91
+ if (have.has(previous) && !have.has(current))
92
+ renames.set(current, previous);
93
+ }
94
+ for (const [current, previous] of renames) {
95
+ statements.push(`ALTER TABLE ${table} RENAME COLUMN ${previous} TO ${current};`);
96
+ changes.push(`rename-${table}-${previous}-to-${current}`);
97
+ }
98
+ for (const col of emitted) {
99
+ if (have.has(col.name))
100
+ continue;
101
+ // A renamed column is not a new one — emitting both would add it twice.
102
+ if (renames.has(col.name))
103
+ continue;
104
+ if (col.requiredWithoutDefault) {
105
+ refusals.push(`'${table}.${col.name}' is required and has no default, and '${table}' already exists — ` +
106
+ 'SQLite cannot add such a column to a table that may hold rows. Make the field ' +
107
+ 'nullable, give it a default, or backfill it in a hand-written entry');
108
+ continue;
109
+ }
110
+ statements.push(`ALTER TABLE ${table} ADD COLUMN ${col.ddl};`);
111
+ changes.push(`add-${table}-${col.name}`);
112
+ }
113
+ // -- columns the model dropped --------------------------------------------
114
+ const renamedAway = new Set(renames.values());
115
+ for (const name of have) {
116
+ if (emitted.some((c) => c.name === name))
117
+ continue;
118
+ // Accounted for: it did not go away, it got a new name.
119
+ if (renamedAway.has(name))
120
+ continue;
121
+ refusals.push(`'${table}.${name}' is in the journal but no longer in the model — a diff cannot tell a ` +
122
+ 'rename from a drop-plus-add, and guessing wrong loses the data. Declare it with ' +
123
+ `\`renamedFrom: { <newName>: '${name}' }\` on the entity, or retire the column deliberately`);
124
+ }
125
+ // -- a key declared after the table already exists ------------------------
126
+ // SQLite cannot ADD a UNIQUE constraint in place; it needs the table
127
+ // rebuilt, copied and renamed. That is a decision about live data, not a
128
+ // diff, so it is refused rather than guessed — and refused LOUDLY, because
129
+ // silently reporting "up to date" over a missing uniqueness guarantee is
130
+ // how a duplicate gets in.
131
+ const wantUniques = uniqueConstraints(o.name, o.entity).map((u) => (/UNIQUE\s*\(([^)]*)\)/i.exec(u)?.[1] ?? '')
132
+ .split(',')
133
+ .map((c) => c.trim())
134
+ .filter(Boolean)
135
+ .join(', '));
136
+ // Translated through any rename THIS plan is about to emit: the journal
137
+ // still names the old column, and SQLite rewrites the constraint along with
138
+ // it. Comparing untranslated makes a renamed key look like one the journal
139
+ // never had, and refuses the very change that would fix it.
140
+ const toCurrent = new Map([...renames].map(([current, previous]) => [previous, current]));
141
+ const haveUniques = new Set([...(appliedUniques.get(table) ?? new Set())].map((c) => c
142
+ .split(', ')
143
+ .map((col) => toCurrent.get(col) ?? col)
144
+ .join(', ')));
145
+ for (const want of wantUniques) {
146
+ if (haveUniques.has(want))
147
+ continue;
148
+ refusals.push(`'${table}' declares a key over (${want}) that the journal does not have — SQLite ` +
149
+ 'cannot add a UNIQUE constraint to an existing table without rebuilding it. Rebuild ' +
150
+ 'it in a hand-written entry, or drop the key');
151
+ }
152
+ }
153
+ if (refusals.length > 0)
154
+ return { kind: 'refused', reasons: refusals };
155
+ if (statements.length === 0)
156
+ return { kind: 'up-to-date' };
157
+ const version = pad(journal.entries.length + 1);
158
+ // One change names itself; several get a count, so the slug stays readable.
159
+ const slug = changes.length === 1 ? changes[0] : `${changes[0]}-and-${changes.length - 1}-more`;
160
+ return { kind: 'append', entry: { version, slug, sql: statements.join('\n\n') } };
161
+ }
162
+ /** Parsed hostilely: it is our file, and it is also somebody's merge resolution. */
163
+ export function parseJournal(raw) {
164
+ const entry = z.object({
165
+ version: z.string().regex(/^\d{4}$/, 'version is a derived four-digit counter'),
166
+ slug: z.string().min(1),
167
+ sql: z.string().min(1),
168
+ released: z.boolean().optional(),
169
+ });
170
+ const parsed = z.object({ entries: z.array(entry) }).parse(raw);
171
+ parsed.entries.forEach((e, i) => {
172
+ if (e.version !== pad(i + 1)) {
173
+ throw new Error(`journal: entry ${i + 1} is numbered '${e.version}' — the counter is derived from ` +
174
+ 'position, so a gap or a duplicate means a bad merge, not a renumbering');
175
+ }
176
+ });
177
+ return parsed;
178
+ }
179
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/model-emit",
3
- "version": "0.0.1",
3
+ "version": "0.2.0",
4
4
  "description": "Build-time tooling over a Substrat model — DDL emitted from the entity registry, and the journal reader that holds it honest",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -18,16 +18,23 @@
18
18
  "default": "./dist/index.js"
19
19
  }
20
20
  },
21
- "files": ["dist"],
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "dependencies": {
25
+ "zod": "^4.0.0",
26
+ "@substrat-run/contracts": "0.72.0"
27
+ },
28
+ "devDependencies": {
29
+ "typescript": "^7.0.0",
30
+ "vitest": "^3.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
22
35
  "scripts": {
23
36
  "build": "tsc -p tsconfig.json",
24
37
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
25
38
  "test": "vitest run"
26
- },
27
- "dependencies": {
28
- "@substrat-run/contracts": "workspace:*",
29
- "zod": "^4.0.0"
30
- },
31
- "devDependencies": { "typescript": "^7.0.0", "vitest": "^3.0.0" },
32
- "publishConfig": { "access": "public" }
33
- }
39
+ }
40
+ }