@kywi-software/cli 0.14.0 → 0.15.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/dist/commands/migrate.js +46 -13
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/upgrade-variant-containers.d.ts +160 -0
- package/dist/commands/upgrade-variant-containers.d.ts.map +1 -0
- package/dist/commands/upgrade-variant-containers.js +625 -0
- package/dist/commands/upgrade-variant-containers.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/dist/__tests__/command-wiring.test.d.ts +0 -2
- package/dist/__tests__/command-wiring.test.d.ts.map +0 -1
- package/dist/__tests__/command-wiring.test.js +0 -55
- package/dist/__tests__/command-wiring.test.js.map +0 -1
- package/dist/__tests__/migrate-generate.test.d.ts +0 -2
- package/dist/__tests__/migrate-generate.test.d.ts.map +0 -1
- package/dist/__tests__/migrate-generate.test.js +0 -53
- package/dist/__tests__/migrate-generate.test.js.map +0 -1
package/dist/commands/migrate.js
CHANGED
|
@@ -50,12 +50,17 @@ program
|
|
|
50
50
|
// (offline generate, or a config that failed to import) — every post step
|
|
51
51
|
// is then skipped rather than guessed at.
|
|
52
52
|
let migratedDb;
|
|
53
|
+
// Held for the same reason as `migratedDb`: the post-migrate steps below
|
|
54
|
+
// run outside the try that reads the config, and some of them are
|
|
55
|
+
// Postgres-only. Undefined means the config never loaded.
|
|
56
|
+
let dbProvider;
|
|
53
57
|
// Pre-flight the database connection so a missing DB / wrong DATABASE_URL /
|
|
54
58
|
// stopped server surfaces as one actionable line here, instead of drizzle-kit
|
|
55
59
|
// dumping a raw pg 3D000 stack (F1a-J01-G2).
|
|
56
60
|
try {
|
|
57
61
|
const configPath = resolve(process.cwd(), options.config);
|
|
58
62
|
const config = (await import(configPath)).default;
|
|
63
|
+
dbProvider = config.db?.provider ?? 'postgresql';
|
|
59
64
|
const { createDb, resolveDatabaseUrl, explainDbError } = await import('@kywi-software/core');
|
|
60
65
|
const { sql } = await import('drizzle-orm');
|
|
61
66
|
let dbUrl;
|
|
@@ -113,7 +118,7 @@ program
|
|
|
113
118
|
// Databases that predate the composite membership constraints (#40) can
|
|
114
119
|
// hold duplicate rows the new PKs would refuse to apply over. Dedupe
|
|
115
120
|
// before drizzle-kit runs; Postgres-only (the cleanup uses ctid/jsonb).
|
|
116
|
-
if (
|
|
121
|
+
if (dbProvider !== 'mysql') {
|
|
117
122
|
try {
|
|
118
123
|
const { dedupeMembershipRows } = await import('@kywi-software/core');
|
|
119
124
|
const deduped = await dedupeMembershipRows(db);
|
|
@@ -149,6 +154,17 @@ program
|
|
|
149
154
|
// bug — surface it rather than swallow.
|
|
150
155
|
if (err?.userFacing)
|
|
151
156
|
throw err;
|
|
157
|
+
// Everything else used to be dropped on the floor here. That is not
|
|
158
|
+
// harmless: this block is what sets `migratedDb`, so swallowing an error
|
|
159
|
+
// silently skips EVERY data step below — the two dedupes and the
|
|
160
|
+
// component-instance reindex — and a migrate that quietly did two thirds
|
|
161
|
+
// of its job printed exactly what one that did all of it printed. Name
|
|
162
|
+
// the error and the steps that did not run; the schema migration itself
|
|
163
|
+
// still applies, so this is a warning, not a failure.
|
|
164
|
+
console.warn(`\nWarning: the database pre-flight did not complete (${err.message}).`);
|
|
165
|
+
console.warn(' Skipped: membership dedupe (#40), content-permission grant dedupe, and the ' +
|
|
166
|
+
'component instance reindex (#147/#156). The schema migration below still runs; ' +
|
|
167
|
+
're-run `kywi migrate` once the cause is fixed to complete these steps.');
|
|
152
168
|
}
|
|
153
169
|
// Step 2: keep the migration journal current, then apply it.
|
|
154
170
|
const drizzleKitBin = resolve(process.cwd(), 'node_modules', '.bin', 'drizzle-kit');
|
|
@@ -282,20 +298,37 @@ program
|
|
|
282
298
|
// happened to be re-saved. Rebuilding it here — idempotent, and only parsing
|
|
283
299
|
// layouts that mention a component id — makes the upgrade self-completing
|
|
284
300
|
// and doubles as the repair path if the index is ever suspected of drift.
|
|
301
|
+
//
|
|
302
|
+
// The same post-step carries kywi-cms#156: saved layouts became a holder in
|
|
303
|
+
// that index, and their rows ship empty for exactly the same reason, so the
|
|
304
|
+
// rebuild backfills them with no operator action either.
|
|
285
305
|
if (result.status === 0 && migratedDb) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
// Never fail a successful migration over a derived cache — say what
|
|
295
|
-
// happened and how to redo it.
|
|
296
|
-
console.warn(`Warning: could not rebuild the component instance index (${err.message}). ` +
|
|
297
|
-
'Component usage counts may read low until the next `kywi migrate`.');
|
|
306
|
+
if (dbProvider === 'mysql') {
|
|
307
|
+
// Same Postgres-only caveat as the dedupes above: the reindex's
|
|
308
|
+
// candidate filter is `<jsonb column>::text like …`. Ungated it ran on
|
|
309
|
+
// MySQL and threw, so the operator got the generic "could not rebuild"
|
|
310
|
+
// warning below naming a driver error instead of the real reason.
|
|
311
|
+
console.warn('Warning: skipping the component instance reindex — it uses Postgres-only SQL ' +
|
|
312
|
+
"(`::text like`) and this project's provider is mysql. Linked-component usage " +
|
|
313
|
+
'counts (#147/#156) stay empty until each layout is re-saved.');
|
|
298
314
|
}
|
|
315
|
+
else
|
|
316
|
+
try {
|
|
317
|
+
const { reindexComponentInstances } = await import('@kywi-software/core');
|
|
318
|
+
const { instances, documentsScanned, blueprintsScanned } = await reindexComponentInstances(migratedDb);
|
|
319
|
+
if (instances > 0) {
|
|
320
|
+
const holders = blueprintsScanned > 0
|
|
321
|
+
? `${documentsScanned} document(s) and ${blueprintsScanned} saved layout(s)`
|
|
322
|
+
: `${documentsScanned} document(s)`;
|
|
323
|
+
console.log(`Indexed ${instances} linked component instance(s) across ${holders}.`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch (err) {
|
|
327
|
+
// Never fail a successful migration over a derived cache — say what
|
|
328
|
+
// happened and how to redo it.
|
|
329
|
+
console.warn(`Warning: could not rebuild the component instance index (${err.message}). ` +
|
|
330
|
+
'Component usage counts may read low until the next `kywi migrate`.');
|
|
331
|
+
}
|
|
299
332
|
}
|
|
300
333
|
process.exit(result.status ?? 1);
|
|
301
334
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAG9C,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,MAAM,UAAU,mBAAmB,CAAC,aAAqB;IACvD,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,eAAe,CAAC,CAAA;IACnE,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;QAC9C,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CACV,8GAA8G,CAC/G;KACA,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,gBAAgB,CAAC;KACzE,MAAM,CAAC,QAAQ,EAAE,gFAAgF,EAAE,KAAK,CAAC;KACzG,MAAM,CACL,cAAc,EACd,qHAAqH,EACrH,KAAK,CACN;KACA,MAAM,CAAC,KAAK,EAAE,OAA8D,EAAE,EAAE;IAC/E,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAA;IAErE,mCAAmC;IACnC,4EAA4E;IAC5E,2EAA2E;IAC3E,2EAA2E;IAC3E,gDAAgD;IAChD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;IACjD,MAAM,cAAc,GAAG,SAAS,CAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,EAChB,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,EACvF,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CACvC,CAAA;IACD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;IAC1C,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,kCAAkC,iBAAiB,EAAE,CAAC,CAAA;QACpE,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,yEAAyE;IACzE,uEAAuE;IACvE,0EAA0E;IAC1E,0CAA0C;IAC1C,IAAI,UAA8B,CAAA;IAElC,4EAA4E;IAC5E,8EAA8E;IAC9E,6CAA6C;IAC7C,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QACzD,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAA;QACjD,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;QAC5F,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QAC3C,IAAI,KAAa,CAAA;QACjB,IAAI,CAAC;YACH,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,oCAAoC,CAAC,CAAC,GAAG,CAAA;QACtF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,OAAQ,GAAa,CAAC,OAAO,IAAI,CAAC,CAAA;YAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;QAC/C,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA,UAAU,CAAC,CAAA;YAC/B,UAAU,GAAG,EAAE,CAAA;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YAC3C,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,IAAI,CAAC,CAAA;gBAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAM,GAAG,CAAA;QACX,CAAC;QAED,2EAA2E;QAC3E,wEAAwE;QACxE,uEAAuE;QACvE,sEAAsE;QACtE,4EAA4E;QAC5E,mEAAmE;QACnE,IAAI,WAAW,GAAa,EAAE,CAAA;QAC9B,IAAI,CAAC;YACH,MAAM,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;YACvE,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,EAAE,CAAC,CAAA;YACpD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;YAChD,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,CAAC;gBACrD,CAAC,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC;gBAC1C,CAAC,CAAC,EAAE,CAAA;YACN,WAAW,GAAG,UAAU,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC1E,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;gBACtC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CACzC,CAAA;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yEAAyE;YACzE,OAAO,CAAC,IAAI,CACV,mDAAoD,GAAa,CAAC,OAAO,gBAAgB,CAC1F,CAAA;QACH,CAAC;QACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CACX,oCAAoC,WAAW,CAAC,MAAM,8BAA8B;gBAClF,6EAA6E;gBAC7E,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC7C,sFAAsF;gBACtF,oFAAoF;gBACpF,mDAAmD,CACtD,CAAA;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,wEAAwE;QACxE,qEAAqE;QACrE,wEAAwE;QACxE,IAAI,
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAG9C,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,MAAM,UAAU,mBAAmB,CAAC,aAAqB;IACvD,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,eAAe,CAAC,CAAA;IACnE,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;QAC9C,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,yEAAyE;QACzE,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CACV,8GAA8G,CAC/G;KACA,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,gBAAgB,CAAC;KACzE,MAAM,CAAC,QAAQ,EAAE,gFAAgF,EAAE,KAAK,CAAC;KACzG,MAAM,CACL,cAAc,EACd,qHAAqH,EACrH,KAAK,CACN;KACA,MAAM,CAAC,KAAK,EAAE,OAA8D,EAAE,EAAE;IAC/E,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAA;IAErE,mCAAmC;IACnC,4EAA4E;IAC5E,2EAA2E;IAC3E,2EAA2E;IAC3E,gDAAgD;IAChD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;IACjD,MAAM,cAAc,GAAG,SAAS,CAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,EAChB,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,kBAAkB,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,EACvF,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CACvC,CAAA;IACD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;IAC1C,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,kCAAkC,iBAAiB,EAAE,CAAC,CAAA;QACpE,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,yEAAyE;IACzE,uEAAuE;IACvE,0EAA0E;IAC1E,0CAA0C;IAC1C,IAAI,UAA8B,CAAA;IAClC,yEAAyE;IACzE,kEAAkE;IAClE,0DAA0D;IAC1D,IAAI,UAA8B,CAAA;IAElC,4EAA4E;IAC5E,8EAA8E;IAC9E,6CAA6C;IAC7C,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QACzD,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAA;QACjD,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,QAAQ,IAAI,YAAY,CAAA;QAChD,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;QAC5F,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QAC3C,IAAI,KAAa,CAAA;QACjB,IAAI,CAAC;YACH,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,oCAAoC,CAAC,CAAC,GAAG,CAAA;QACtF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,OAAQ,GAAa,CAAC,OAAO,IAAI,CAAC,CAAA;YAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;QAC/C,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA,UAAU,CAAC,CAAA;YAC/B,UAAU,GAAG,EAAE,CAAA;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YAC3C,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,IAAI,CAAC,CAAA;gBAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAM,GAAG,CAAA;QACX,CAAC;QAED,2EAA2E;QAC3E,wEAAwE;QACxE,uEAAuE;QACvE,sEAAsE;QACtE,4EAA4E;QAC5E,mEAAmE;QACnE,IAAI,WAAW,GAAa,EAAE,CAAA;QAC9B,IAAI,CAAC;YACH,MAAM,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;YACvE,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,EAAE,CAAC,CAAA;YACpD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;YAChD,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,CAAC;gBACrD,CAAC,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC;gBAC1C,CAAC,CAAC,EAAE,CAAA;YACN,WAAW,GAAG,UAAU,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC1E,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;gBACtC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CACzC,CAAA;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yEAAyE;YACzE,OAAO,CAAC,IAAI,CACV,mDAAoD,GAAa,CAAC,OAAO,gBAAgB,CAC1F,CAAA;QACH,CAAC;QACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CACX,oCAAoC,WAAW,CAAC,MAAM,8BAA8B;gBAClF,6EAA6E;gBAC7E,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC7C,sFAAsF;gBACtF,oFAAoF;gBACpF,mDAAmD,CACtD,CAAA;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,wEAAwE;QACxE,qEAAqE;QACrE,wEAAwE;QACxE,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;gBACpE,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,EAAE,CAAC,CAAA;gBAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,eAAe,CAAA;gBAC1D,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACd,OAAO,CAAC,GAAG,CACT,WAAW,KAAK,2FAA2F,CAC5G,CAAA;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CACV,8CAA+C,GAAa,CAAC,OAAO,KAAK;oBACvE,2HAA2H,CAC9H,CAAA;YACH,CAAC;YAED,2DAA2D;YAC3D,kEAAkE;YAClE,8DAA8D;YAC9D,8DAA8D;YAC9D,IAAI,CAAC;gBACH,MAAM,EAAE,2BAA2B,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;gBAC3E,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC,EAAE,CAAC,CAAA;gBACrD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,WAAW,CAAA;gBACtD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACd,OAAO,CAAC,GAAG,CACT,WAAW,KAAK,qFAAqF,CACtG,CAAA;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CACV,sDAAuD,GAAa,CAAC,OAAO,KAAK;oBAC/E,sGAAsG,CACzG,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,wEAAwE;QACxE,wCAAwC;QACxC,IAAK,GAAgC,EAAE,UAAU;YAAE,MAAM,GAAG,CAAA;QAC5D,oEAAoE;QACpE,yEAAyE;QACzE,iEAAiE;QACjE,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,sDAAsD;QACtD,OAAO,CAAC,IAAI,CACV,wDAAyD,GAAa,CAAC,OAAO,IAAI,CACnF,CAAA;QACD,OAAO,CAAC,IAAI,CACV,+EAA+E;YAC7E,iFAAiF;YACjF,wEAAwE,CAC3E,CAAA;IACH,CAAC;IAED,6DAA6D;IAC7D,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,CAAC,CAAA;IACnF,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAA;IAC5E,IAAI,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;IAElD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,kEAAkE;QAClE,oEAAoE;QACpE,sEAAsE;QACtE,sEAAsE;QACtE,sEAAsE;QACtE,oEAAoE;QACpE,+DAA+D;QAC/D,mEAAmE;QACnE,uEAAuE;QACvE,sEAAsE;QACtE,IAAI,mBAAmB,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC7D,OAAO,CAAC,KAAK,CACX,0EAA0E;gBACxE,kCAAkC,aAAa,gCAAgC;gBAC/E,wEAAwE;gBACxE,0DAA0D;gBAC1D,+EAA+E;gBAC/E,yCAAyC,CAC5C,CAAA;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACf,OAAM;QACR,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,cAAc,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAA;QAEzD,4DAA4D;QAC5D,qEAAqE;QACrE,qEAAqE;QACrE,uEAAuE;QACvE,qEAAqE;QACrE,uEAAuE;QACvE,8DAA8D;QAC9D,EAAE;QACF,gEAAgE;QAChE,oEAAoE;QACpE,0DAA0D;QAC1D,kEAAkE;QAClE,uEAAuE;QACvE,wEAAwE;QACxE,sEAAsE;QACtE,mEAAmE;QACnE,gEAAgE;QAChE,wEAAwE;QACxE,sEAAsE;QACtE,qEAAqE;QACrE,qEAAqE;QACrE,mEAAmE;QACnE,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAA;QAC9E,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC,EAAE;YACvD,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAA;QACF,MAAM,SAAS,GAAG,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,EAAE,CAAA;QACtE,IAAI,SAAS;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAE9C,sEAAsE;QACtE,oEAAoE;QACpE,oEAAoE;QACpE,sEAAsE;QACtE,qEAAqE;QACrE,sEAAsE;QACtE,qEAAqE;QACrE,yDAAyD;QACzD,MAAM,SAAS,GAAG,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAE5D,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CACX,kFAAkF;gBAChF,kFAAkF;gBAClF,mFAAmF;gBACnF,yFAAyF;gBACzF,oBAAoB,CACvB,CAAA;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACf,OAAM;QACR,CAAC;aAAM,IAAI,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrD,IAAI,cAAc,EAAE,CAAC;gBACnB,8DAA8D;gBAC9D,iEAAiE;gBACjE,+DAA+D;gBAC/D,wDAAwD;gBACxD,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;oBACpB,gEAAgE;oBAChE,+DAA+D;oBAC/D,8DAA8D;oBAC9D,iDAAiD;oBACjD,OAAO,CAAC,KAAK,CAAC,6CAA6C,SAAS,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;gBACzF,CAAC;gBACD,OAAO,CAAC,KAAK,CACX,mFAAmF;oBACjF,GAAG,aAAa,gEAAgE,CACnF,CAAA;gBACD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;gBACnC,OAAM;YACR,CAAC;YACD,oEAAoE;YACpE,gEAAgE;YAChE,wDAAwD;YACxD,OAAO,CAAC,IAAI,CACV,8EAA8E;gBAC5E,4CAA4C;gBAC5C,8FAA8F,CACjG,CAAA;YACD,UAAU,GAAG,MAAM,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,SAAS,CAAA;YACtB,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,GAAG,CACT,wDAAwD,aAAa,YAAY;oBAC/E,gFAAgF,CACnF,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,UAAU,KAAK,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC,EAAE;QACpD,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAA;IAEF,wEAAwE;IACxE,wDAAwD;IACxD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,kCAAkC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;QACzE,OAAO,CAAC,KAAK,CAAC,gGAAgG,CAAC,CAAA;QAC/G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,4EAA4E;IAC5E,6DAA6D;IAC7D,EAAE;IACF,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,6EAA6E;IAC7E,0EAA0E;IAC1E,0EAA0E;IAC1E,EAAE;IACF,4EAA4E;IAC5E,4EAA4E;IAC5E,yDAAyD;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;QACtC,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;YAC3B,gEAAgE;YAChE,uEAAuE;YACvE,uEAAuE;YACvE,kEAAkE;YAClE,OAAO,CAAC,IAAI,CACV,+EAA+E;gBAC7E,+EAA+E;gBAC/E,8DAA8D,CACjE,CAAA;QACH,CAAC;;YAAM,IAAI,CAAC;gBACV,MAAM,EAAE,yBAAyB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;gBACzE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,GACtD,MAAM,yBAAyB,CAAC,UAAU,CAAC,CAAA;gBAC7C,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;oBAClB,MAAM,OAAO,GAAG,iBAAiB,GAAG,CAAC;wBACnC,CAAC,CAAC,GAAG,gBAAgB,oBAAoB,iBAAiB,kBAAkB;wBAC5E,CAAC,CAAC,GAAG,gBAAgB,cAAc,CAAA;oBACrC,OAAO,CAAC,GAAG,CAAC,WAAW,SAAS,wCAAwC,OAAO,GAAG,CAAC,CAAA;gBACrF,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,oEAAoE;gBACpE,+BAA+B;gBAC/B,OAAO,CAAC,IAAI,CACV,4DAA6D,GAAa,CAAC,OAAO,KAAK;oBACrF,oEAAoE,CACvE,CAAA;YACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;AAClC,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { LayoutDocument, LegacyVariantContainerPlacement } from '@kywi-software/core';
|
|
2
|
+
export interface UpgradeOptions {
|
|
3
|
+
config: string;
|
|
4
|
+
/** Site slug or uuid. Absent = every site. */
|
|
5
|
+
site?: string | undefined;
|
|
6
|
+
/** One content uuid. Absent = every document. */
|
|
7
|
+
content?: string | undefined;
|
|
8
|
+
/** One legacy module id — the per-placement, owner-invoked migration. */
|
|
9
|
+
node?: string | undefined;
|
|
10
|
+
/** Explicit report-only. Wins over `--apply` if both are passed. */
|
|
11
|
+
dryRun?: boolean | undefined;
|
|
12
|
+
apply?: boolean | undefined;
|
|
13
|
+
/** Where the before-layouts are written. Absent = a timestamped default. */
|
|
14
|
+
backup?: string | undefined;
|
|
15
|
+
json?: boolean | undefined;
|
|
16
|
+
ignoreOpenChangesets?: boolean | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface ContentCandidate {
|
|
19
|
+
id: string;
|
|
20
|
+
siteId: string;
|
|
21
|
+
title: string;
|
|
22
|
+
status: string;
|
|
23
|
+
layout: LayoutDocument | null;
|
|
24
|
+
}
|
|
25
|
+
export interface BlueprintCandidate {
|
|
26
|
+
id: string;
|
|
27
|
+
siteId: string;
|
|
28
|
+
name: string;
|
|
29
|
+
definition: LayoutDocument | null;
|
|
30
|
+
}
|
|
31
|
+
export interface OpenChangesetItem {
|
|
32
|
+
changesetId: string;
|
|
33
|
+
changesetName: string;
|
|
34
|
+
contentId: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One content row, re-read `FOR UPDATE` inside its own transaction.
|
|
38
|
+
*
|
|
39
|
+
* `layout` is deliberately the LOCKED read, not the one the scan saw: a
|
|
40
|
+
* concurrent editor save between the two is exactly the race this exists to
|
|
41
|
+
* close, so the conversion must run on this copy.
|
|
42
|
+
*/
|
|
43
|
+
export interface ContentWriteSession {
|
|
44
|
+
layout: LayoutDocument | null;
|
|
45
|
+
/**
|
|
46
|
+
* Record a version carrying the PRE-migration row, then write the new layout
|
|
47
|
+
* through `setContentLayout`. Both in the same transaction.
|
|
48
|
+
*/
|
|
49
|
+
commit(next: LayoutDocument, changeNote: string): Promise<boolean>;
|
|
50
|
+
}
|
|
51
|
+
export interface UpgradeGateway {
|
|
52
|
+
/** Slug or uuid → site uuid; null when no such site exists. */
|
|
53
|
+
resolveSiteId(ref: string): Promise<string | null>;
|
|
54
|
+
listContentCandidates(filter: {
|
|
55
|
+
siteId?: string | undefined;
|
|
56
|
+
contentId?: string | undefined;
|
|
57
|
+
}): Promise<ContentCandidate[]>;
|
|
58
|
+
listBlueprintCandidates(filter: {
|
|
59
|
+
siteId?: string | undefined;
|
|
60
|
+
}): Promise<BlueprintCandidate[]>;
|
|
61
|
+
/** Items of OPEN changesets that hold any of these content ids. */
|
|
62
|
+
listOpenChangesetItems(contentIds: readonly string[]): Promise<OpenChangesetItem[]>;
|
|
63
|
+
/** Returns null when the row no longer exists; otherwise `fn`'s result. */
|
|
64
|
+
withContentLock<T>(contentId: string, siteId: string, fn: (session: ContentWriteSession) => Promise<T>): Promise<T | null>;
|
|
65
|
+
writeBlueprintDefinition(id: string, siteId: string, definition: LayoutDocument): Promise<boolean>;
|
|
66
|
+
}
|
|
67
|
+
export interface UpgradeIo {
|
|
68
|
+
log(line: string): void;
|
|
69
|
+
error(line: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Write (or rewrite) the backup file.
|
|
72
|
+
*
|
|
73
|
+
* `exclusive` is true for the FIRST write of a run: the file must not already
|
|
74
|
+
* exist, so a second run with the same `--backup` path can never silently
|
|
75
|
+
* overwrite the only copy of a previous run's before-layouts. Later calls in
|
|
76
|
+
* the same run rewrite the file this run created (see the per-document
|
|
77
|
+
* capture in the apply loop), so they are not exclusive.
|
|
78
|
+
*/
|
|
79
|
+
writeBackup(path: string, contents: string, options: {
|
|
80
|
+
exclusive: boolean;
|
|
81
|
+
}): Promise<void>;
|
|
82
|
+
now(): Date;
|
|
83
|
+
}
|
|
84
|
+
export type DocumentOutcome = 'reported' | 'migrated' | 'skipped';
|
|
85
|
+
export interface DocumentReport {
|
|
86
|
+
kind: 'content' | 'blueprint';
|
|
87
|
+
id: string;
|
|
88
|
+
siteId: string;
|
|
89
|
+
title: string;
|
|
90
|
+
/** Content only. */
|
|
91
|
+
status: string | null;
|
|
92
|
+
published: boolean;
|
|
93
|
+
placements: LegacyVariantContainerPlacement[];
|
|
94
|
+
openChangesets: Array<{
|
|
95
|
+
id: string;
|
|
96
|
+
name: string;
|
|
97
|
+
}>;
|
|
98
|
+
outcome: DocumentOutcome;
|
|
99
|
+
skipReason?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface UpgradeReport {
|
|
102
|
+
mode: 'report' | 'apply';
|
|
103
|
+
/** Candidate rows the text match returned, before the structural confirm. */
|
|
104
|
+
scanned: number;
|
|
105
|
+
documents: DocumentReport[];
|
|
106
|
+
totals: {
|
|
107
|
+
documents: number;
|
|
108
|
+
placements: number;
|
|
109
|
+
/** Placements that would convert / did convert. */
|
|
110
|
+
converted: number;
|
|
111
|
+
/** Placements reported but deliberately left alone. */
|
|
112
|
+
refused: number;
|
|
113
|
+
/** Documents actually written. */
|
|
114
|
+
migrated: number;
|
|
115
|
+
/** Documents left alone because writing them would be wrong. */
|
|
116
|
+
skipped: number;
|
|
117
|
+
/** Candidate documents whose content row is published. */
|
|
118
|
+
published: number;
|
|
119
|
+
};
|
|
120
|
+
backupPath: string | null;
|
|
121
|
+
warnings: string[];
|
|
122
|
+
/** True only for a clean run: nothing skipped, nothing refused, no warnings. */
|
|
123
|
+
ok: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* The process exit code.
|
|
126
|
+
*
|
|
127
|
+
* 0 — clean: everything asked for was done.
|
|
128
|
+
* 2 — some placements were REFUSED. Nothing is broken and the rest of the
|
|
129
|
+
* run succeeded, but a human has to decide what to do about them, so it
|
|
130
|
+
* must not read as success in a script.
|
|
131
|
+
* 1 — something the operator asked for did not happen: a document was
|
|
132
|
+
* skipped, or a scoping flag matched nothing.
|
|
133
|
+
*
|
|
134
|
+
* 1 wins over 2 when both apply — the more severe outcome is the one a caller
|
|
135
|
+
* branches on.
|
|
136
|
+
*/
|
|
137
|
+
exitCode: 0 | 1 | 2;
|
|
138
|
+
}
|
|
139
|
+
export declare const CHANGE_NOTE = "variantContainer module migrated to a module variant container (kywi-cms#172)";
|
|
140
|
+
/** `./kywi-vc-backup-<ISO seconds, colons dashed>.json`. */
|
|
141
|
+
export declare function defaultBackupPath(now: Date): string;
|
|
142
|
+
export declare function runVariantContainerUpgrade(gateway: UpgradeGateway, io: UpgradeIo, options: UpgradeOptions): Promise<UpgradeReport>;
|
|
143
|
+
/** The human-readable report body. Pure — the CLI prints what this returns. */
|
|
144
|
+
export declare function renderReport(report: UpgradeReport): string[];
|
|
145
|
+
/**
|
|
146
|
+
* The live database implementation of {@link UpgradeGateway}.
|
|
147
|
+
*
|
|
148
|
+
* `core` and `orm` are passed in rather than imported at module scope for the
|
|
149
|
+
* same reason every other command dynamically imports them: the CLI must not
|
|
150
|
+
* load the DB stack to print `--help`.
|
|
151
|
+
*/
|
|
152
|
+
export declare function createDbGateway(db: unknown, core: typeof import('@kywi-software/core'), orm: typeof import('drizzle-orm')): UpgradeGateway;
|
|
153
|
+
/**
|
|
154
|
+
* The production {@link UpgradeIo}: stdout/stderr, real files, the real clock.
|
|
155
|
+
*
|
|
156
|
+
* Exported so the integration test drives the same code path the command does,
|
|
157
|
+
* rather than a hand-rolled double that could drift from it.
|
|
158
|
+
*/
|
|
159
|
+
export declare function createFileIo(cwd?: string): UpgradeIo;
|
|
160
|
+
//# sourceMappingURL=upgrade-variant-containers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade-variant-containers.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade-variant-containers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kywi upgrade:variant-containers` — migrate deprecated `variantContainer`
|
|
3
|
+
* MODULES to real `moduleVariantContainer` column nodes (kywi-cms#172).
|
|
4
|
+
*
|
|
5
|
+
* The conversion itself is pure and lives in core
|
|
6
|
+
* (`layout/legacy-variant-container.ts`); this file is the driver — the scan,
|
|
7
|
+
* the report, the safety refusals, and the writes.
|
|
8
|
+
*
|
|
9
|
+
* REPORT-ONLY BY DEFAULT (owner decision D2(a)). The issue asks for "no forced
|
|
10
|
+
* migration — owner-invoked per placement", and a data rewrite that runs on a
|
|
11
|
+
* bare command is the wrong default. `--apply` writes; `--dry-run` is kept as an
|
|
12
|
+
* explicit synonym for the default so a script can say what it means.
|
|
13
|
+
*
|
|
14
|
+
* The DB work is behind {@link UpgradeGateway} so the whole flow — refusals,
|
|
15
|
+
* ordering, skip-and-continue — is testable against a fake, and so the one
|
|
16
|
+
* function that opens transactions is small enough to read in a sitting.
|
|
17
|
+
*/
|
|
18
|
+
import { program } from 'commander';
|
|
19
|
+
import { resolve } from 'node:path';
|
|
20
|
+
import { writeFile } from 'node:fs/promises';
|
|
21
|
+
export const CHANGE_NOTE = 'variantContainer module migrated to a module variant container (kywi-cms#172)';
|
|
22
|
+
/** `./kywi-vc-backup-<ISO seconds, colons dashed>.json`. */
|
|
23
|
+
export function defaultBackupPath(now) {
|
|
24
|
+
const stamp = now.toISOString().slice(0, 19).replace(/:/g, '-');
|
|
25
|
+
return `./kywi-vc-backup-${stamp}.json`;
|
|
26
|
+
}
|
|
27
|
+
export async function runVariantContainerUpgrade(gateway, io, options) {
|
|
28
|
+
const core = await import('@kywi-software/core');
|
|
29
|
+
const { migrateLegacyVariantContainers, validateLayoutDocument } = core;
|
|
30
|
+
// `--dry-run` wins: an explicit "do not write" must never be overridden by a
|
|
31
|
+
// flag that happens to sit later on the same line.
|
|
32
|
+
const apply = options.apply === true && options.dryRun !== true;
|
|
33
|
+
// Progress chatter would corrupt `--json`, whose whole output is meant to be
|
|
34
|
+
// one parseable document. The report itself carries the same facts.
|
|
35
|
+
const progress = (line) => {
|
|
36
|
+
if (!options.json)
|
|
37
|
+
io.log(line);
|
|
38
|
+
};
|
|
39
|
+
const moduleIds = options.node ? [options.node] : undefined;
|
|
40
|
+
const warnings = [];
|
|
41
|
+
const report = {
|
|
42
|
+
mode: apply ? 'apply' : 'report',
|
|
43
|
+
scanned: 0,
|
|
44
|
+
documents: [],
|
|
45
|
+
totals: {
|
|
46
|
+
documents: 0,
|
|
47
|
+
placements: 0,
|
|
48
|
+
converted: 0,
|
|
49
|
+
refused: 0,
|
|
50
|
+
migrated: 0,
|
|
51
|
+
skipped: 0,
|
|
52
|
+
published: 0,
|
|
53
|
+
},
|
|
54
|
+
backupPath: null,
|
|
55
|
+
warnings,
|
|
56
|
+
ok: true,
|
|
57
|
+
exitCode: 0,
|
|
58
|
+
};
|
|
59
|
+
// ── Scope ──────────────────────────────────────────────────────────────────
|
|
60
|
+
let siteId;
|
|
61
|
+
if (options.site) {
|
|
62
|
+
const resolved = await gateway.resolveSiteId(options.site);
|
|
63
|
+
if (!resolved) {
|
|
64
|
+
warnings.push(`No site matches "${options.site}" — nothing was scanned.`);
|
|
65
|
+
finish(io, report, options);
|
|
66
|
+
return report;
|
|
67
|
+
}
|
|
68
|
+
siteId = resolved;
|
|
69
|
+
}
|
|
70
|
+
// ── Scan + structural confirm ──────────────────────────────────────────────
|
|
71
|
+
const pending = [];
|
|
72
|
+
const contentRows = await gateway.listContentCandidates({
|
|
73
|
+
...(siteId ? { siteId } : {}),
|
|
74
|
+
...(options.content ? { contentId: options.content } : {}),
|
|
75
|
+
});
|
|
76
|
+
// Blueprints hold no content id, so `--content` narrows them out entirely.
|
|
77
|
+
const blueprintRows = options.content
|
|
78
|
+
? []
|
|
79
|
+
: await gateway.listBlueprintCandidates({ ...(siteId ? { siteId } : {}) });
|
|
80
|
+
report.scanned = contentRows.length + blueprintRows.length;
|
|
81
|
+
for (const row of contentRows) {
|
|
82
|
+
const result = migrateLegacyVariantContainers(row.layout, {
|
|
83
|
+
...(moduleIds ? { moduleIds } : {}),
|
|
84
|
+
});
|
|
85
|
+
// The candidate query matches `"variantContainer"` as TEXT, which also hits
|
|
86
|
+
// the section-level VariantContainer region node. Zero placements after the
|
|
87
|
+
// structural walk is that false positive, and it is simply dropped.
|
|
88
|
+
if (result.placements.length === 0)
|
|
89
|
+
continue;
|
|
90
|
+
pending.push({
|
|
91
|
+
report: {
|
|
92
|
+
kind: 'content',
|
|
93
|
+
id: row.id,
|
|
94
|
+
siteId: row.siteId,
|
|
95
|
+
title: row.title,
|
|
96
|
+
status: row.status,
|
|
97
|
+
published: row.status === 'published',
|
|
98
|
+
placements: result.placements,
|
|
99
|
+
openChangesets: [],
|
|
100
|
+
outcome: 'reported',
|
|
101
|
+
},
|
|
102
|
+
before: row.layout,
|
|
103
|
+
next: result.document,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
for (const row of blueprintRows) {
|
|
107
|
+
const result = migrateLegacyVariantContainers(row.definition, {
|
|
108
|
+
...(moduleIds ? { moduleIds } : {}),
|
|
109
|
+
});
|
|
110
|
+
if (result.placements.length === 0)
|
|
111
|
+
continue;
|
|
112
|
+
pending.push({
|
|
113
|
+
report: {
|
|
114
|
+
kind: 'blueprint',
|
|
115
|
+
id: row.id,
|
|
116
|
+
siteId: row.siteId,
|
|
117
|
+
title: row.name,
|
|
118
|
+
status: null,
|
|
119
|
+
published: false,
|
|
120
|
+
placements: result.placements,
|
|
121
|
+
openChangesets: [],
|
|
122
|
+
outcome: 'reported',
|
|
123
|
+
},
|
|
124
|
+
before: row.definition,
|
|
125
|
+
next: result.document,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
report.documents = pending.map((p) => p.report);
|
|
129
|
+
// ── Empty explicit scopes ──────────────────────────────────────────────────
|
|
130
|
+
//
|
|
131
|
+
// `--site` with no match already failed above. `--content` and `--node` name
|
|
132
|
+
// one specific thing the operator expects work on, so matching nothing is a
|
|
133
|
+
// failed instruction — a typo'd id, or a document that is already migrated —
|
|
134
|
+
// not the quiet success a bare `kywi upgrade:variant-containers` finding
|
|
135
|
+
// nothing is. Both warn and exit non-zero rather than printing "No legacy
|
|
136
|
+
// variantContainer modules found." and exiting 0.
|
|
137
|
+
if (options.content && !pending.some((p) => p.report.kind === 'content')) {
|
|
138
|
+
warnings.push(`No document matches --content ${options.content} with a legacy variantContainer ` +
|
|
139
|
+
`module. Check the id — or it may already be migrated.`);
|
|
140
|
+
}
|
|
141
|
+
if (options.node && pending.length === 0) {
|
|
142
|
+
warnings.push(`No placement matches --node ${options.node}. Check the module id — or it may ` +
|
|
143
|
+
`already be migrated.`);
|
|
144
|
+
}
|
|
145
|
+
if (warnings.length > 0) {
|
|
146
|
+
finish(io, report, options);
|
|
147
|
+
return report;
|
|
148
|
+
}
|
|
149
|
+
// ── Open changesets ────────────────────────────────────────────────────────
|
|
150
|
+
//
|
|
151
|
+
// `publishChangeset` applies a VERSION SNAPSHOT onto the live row, and
|
|
152
|
+
// snapshots carry `layout`. An open changeset whose attached version predates
|
|
153
|
+
// this migration will therefore put the legacy shape straight back on publish.
|
|
154
|
+
// Migrating the snapshots is out of scope; re-running this command after the
|
|
155
|
+
// changeset publishes is the remedy.
|
|
156
|
+
const contentIds = pending.filter((p) => p.report.kind === 'content').map((p) => p.report.id);
|
|
157
|
+
if (contentIds.length > 0) {
|
|
158
|
+
const items = await gateway.listOpenChangesetItems(contentIds);
|
|
159
|
+
const byContent = new Map();
|
|
160
|
+
for (const item of items) {
|
|
161
|
+
const list = byContent.get(item.contentId) ?? [];
|
|
162
|
+
list.push({ id: item.changesetId, name: item.changesetName });
|
|
163
|
+
byContent.set(item.contentId, list);
|
|
164
|
+
}
|
|
165
|
+
for (const p of pending) {
|
|
166
|
+
p.report.openChangesets = byContent.get(p.report.id) ?? [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// ── Totals, before anything is written ─────────────────────────────────────
|
|
170
|
+
tally(report);
|
|
171
|
+
emitHeader(io, report, options, apply);
|
|
172
|
+
if (!apply) {
|
|
173
|
+
emit(io, report, options);
|
|
174
|
+
return report;
|
|
175
|
+
}
|
|
176
|
+
// ── Apply ──────────────────────────────────────────────────────────────────
|
|
177
|
+
const writable = pending.filter((p) => {
|
|
178
|
+
if (p.report.placements.every((pl) => pl.refusal !== null)) {
|
|
179
|
+
// Every placement refused: nothing would change, so this is not a skip.
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
if (!options.ignoreOpenChangesets && p.report.openChangesets.length > 0) {
|
|
183
|
+
p.report.outcome = 'skipped';
|
|
184
|
+
p.report.skipReason =
|
|
185
|
+
`held by open changeset(s) ${p.report.openChangesets.map((c) => c.name).join(', ')} — ` +
|
|
186
|
+
`publishing one would re-introduce the legacy shape from its version snapshot. ` +
|
|
187
|
+
`Publish it first, then re-run, or pass --ignore-open-changesets.`;
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return true;
|
|
191
|
+
});
|
|
192
|
+
if (writable.length === 0) {
|
|
193
|
+
finish(io, report, options);
|
|
194
|
+
return report;
|
|
195
|
+
}
|
|
196
|
+
// ── The backup ─────────────────────────────────────────────────────────────
|
|
197
|
+
//
|
|
198
|
+
// Created up front and EXCLUSIVELY, so a name collision with an earlier run's
|
|
199
|
+
// backup fails the whole command before a single row is touched — never while
|
|
200
|
+
// a row lock is held. It is then rewritten as each document's true
|
|
201
|
+
// before-layout becomes known, so at every instant the file on disk already
|
|
202
|
+
// contains the before-layout of every document written so far, plus the one
|
|
203
|
+
// in flight. A crash mid-run leaves a usable backup, not a plausible-looking
|
|
204
|
+
// wrong one.
|
|
205
|
+
const backupPath = options.backup ?? defaultBackupPath(io.now());
|
|
206
|
+
const backupEntries = [];
|
|
207
|
+
const renderBackup = () => JSON.stringify({
|
|
208
|
+
tool: 'kywi upgrade:variant-containers',
|
|
209
|
+
issue: 'kywi-cms#172',
|
|
210
|
+
createdAt: io.now().toISOString(),
|
|
211
|
+
documents: backupEntries,
|
|
212
|
+
}, null, 2);
|
|
213
|
+
const captureBackup = async (p) => {
|
|
214
|
+
backupEntries.push({
|
|
215
|
+
kind: p.report.kind,
|
|
216
|
+
id: p.report.id,
|
|
217
|
+
siteId: p.report.siteId,
|
|
218
|
+
title: p.report.title,
|
|
219
|
+
layout: p.before,
|
|
220
|
+
});
|
|
221
|
+
await io.writeBackup(backupPath, renderBackup(), { exclusive: false });
|
|
222
|
+
};
|
|
223
|
+
await io.writeBackup(backupPath, renderBackup(), { exclusive: true });
|
|
224
|
+
report.backupPath = backupPath;
|
|
225
|
+
progress(`Backup file created at ${backupPath}`);
|
|
226
|
+
for (const p of writable) {
|
|
227
|
+
try {
|
|
228
|
+
if (p.report.kind === 'blueprint') {
|
|
229
|
+
const validation = validateLayoutDocument(p.next);
|
|
230
|
+
if (!validation.success) {
|
|
231
|
+
skip(p.report, `migrated definition failed validation: ${validation.error}`);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
// Since kywi-cms#156 `updateSectionTemplate` delegates to
|
|
235
|
+
// `setSectionTemplateDefinition` (SELECT … FOR UPDATE → write → index
|
|
236
|
+
// sync) whenever a definition is supplied, so the blueprint write is
|
|
237
|
+
// locked and indexed like a page write. The backup entry is still the
|
|
238
|
+
// definition the scan read (the lock is taken inside the write itself).
|
|
239
|
+
await captureBackup(p);
|
|
240
|
+
const written = await gateway.writeBlueprintDefinition(p.report.id, p.report.siteId, p.next);
|
|
241
|
+
if (!written) {
|
|
242
|
+
skip(p.report, 'blueprint row no longer exists');
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
p.report.outcome = 'migrated';
|
|
246
|
+
progress(` migrated blueprint ${p.report.id} (${p.report.title})`);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const outcome = await gateway.withContentLock(p.report.id, p.report.siteId, async (session) => {
|
|
250
|
+
// Re-convert the LOCKED layout, not the scanned one — a concurrent
|
|
251
|
+
// save between scan and lock is exactly what the lock is for.
|
|
252
|
+
const fresh = migrateLegacyVariantContainers(session.layout, {
|
|
253
|
+
...(moduleIds ? { moduleIds } : {}),
|
|
254
|
+
});
|
|
255
|
+
if (!fresh.changed) {
|
|
256
|
+
return { status: 'skipped', reason: 'nothing left to migrate under the lock' };
|
|
257
|
+
}
|
|
258
|
+
const validation = validateLayoutDocument(fresh.document);
|
|
259
|
+
if (!validation.success) {
|
|
260
|
+
// Never write an invalid layout: it would leave the page permanently
|
|
261
|
+
// un-editable. One bad document must not block the rest, so this is
|
|
262
|
+
// a per-document skip, the same rule detachComponentEverywhere uses.
|
|
263
|
+
return { status: 'skipped', reason: `migrated layout failed validation: ${validation.error}` };
|
|
264
|
+
}
|
|
265
|
+
// What the lock actually holds is what the backup must record.
|
|
266
|
+
if (session.layout)
|
|
267
|
+
p.before = session.layout;
|
|
268
|
+
await captureBackup(p);
|
|
269
|
+
const written = await session.commit(fresh.document, CHANGE_NOTE);
|
|
270
|
+
return written
|
|
271
|
+
? { status: 'migrated', reason: '' }
|
|
272
|
+
: { status: 'skipped', reason: 'row disappeared mid-write' };
|
|
273
|
+
});
|
|
274
|
+
if (outcome === null) {
|
|
275
|
+
skip(p.report, 'row no longer exists');
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (outcome.status === 'skipped') {
|
|
279
|
+
skip(p.report, outcome.reason);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
p.report.outcome = 'migrated';
|
|
283
|
+
progress(` migrated ${p.report.id} (${p.report.title})`);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
skip(p.report, `write failed: ${err.message}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
finish(io, report, options);
|
|
290
|
+
return report;
|
|
291
|
+
}
|
|
292
|
+
function skip(doc, reason) {
|
|
293
|
+
doc.outcome = 'skipped';
|
|
294
|
+
doc.skipReason = reason;
|
|
295
|
+
}
|
|
296
|
+
function tally(report) {
|
|
297
|
+
const t = report.totals;
|
|
298
|
+
t.documents = report.documents.length;
|
|
299
|
+
t.placements = 0;
|
|
300
|
+
t.converted = 0;
|
|
301
|
+
t.refused = 0;
|
|
302
|
+
t.published = 0;
|
|
303
|
+
t.migrated = 0;
|
|
304
|
+
t.skipped = 0;
|
|
305
|
+
for (const doc of report.documents) {
|
|
306
|
+
t.placements += doc.placements.length;
|
|
307
|
+
for (const placement of doc.placements) {
|
|
308
|
+
if (placement.refusal)
|
|
309
|
+
t.refused++;
|
|
310
|
+
else
|
|
311
|
+
t.converted++;
|
|
312
|
+
}
|
|
313
|
+
if (doc.published)
|
|
314
|
+
t.published++;
|
|
315
|
+
if (doc.outcome === 'migrated')
|
|
316
|
+
t.migrated++;
|
|
317
|
+
if (doc.outcome === 'skipped')
|
|
318
|
+
t.skipped++;
|
|
319
|
+
}
|
|
320
|
+
const failed = t.skipped > 0 || report.warnings.length > 0;
|
|
321
|
+
report.exitCode = failed ? 1 : t.refused > 0 ? 2 : 0;
|
|
322
|
+
report.ok = report.exitCode === 0;
|
|
323
|
+
}
|
|
324
|
+
function finish(io, report, options) {
|
|
325
|
+
tally(report);
|
|
326
|
+
emit(io, report, options);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* The pre-write header: what will change, and how much of it is live.
|
|
330
|
+
*
|
|
331
|
+
* `kywi_content.layout` is a single live column — there is no draft/published
|
|
332
|
+
* split — so a published page changes the moment `--apply` writes. The rendered
|
|
333
|
+
* output is designed to be equivalent but is NOT byte-identical (arms now carry
|
|
334
|
+
* module wrappers and are chosen server-side), so this says so out loud rather
|
|
335
|
+
* than leaving it in the docs.
|
|
336
|
+
*/
|
|
337
|
+
function emitHeader(io, report, options, apply) {
|
|
338
|
+
if (options.json)
|
|
339
|
+
return;
|
|
340
|
+
const t = report.totals;
|
|
341
|
+
io.log('');
|
|
342
|
+
io.log(apply
|
|
343
|
+
? 'kywi upgrade:variant-containers — APPLYING (writes below are live)'
|
|
344
|
+
: 'kywi upgrade:variant-containers — report only. Pass --apply to write.');
|
|
345
|
+
io.log(`Scanned ${report.scanned} candidate row(s); ${t.documents} hold a legacy ` +
|
|
346
|
+
`variantContainer module (${t.placements} placement(s), ${t.converted} migratable, ` +
|
|
347
|
+
`${t.refused} refused).`);
|
|
348
|
+
if (t.published > 0) {
|
|
349
|
+
io.log(`${t.published} of them are published — their LIVE pages change as soon as this writes. ` +
|
|
350
|
+
`The rendered output is equivalent but not byte-identical: each arm gains a ` +
|
|
351
|
+
`.kywi-module wrapper and is now chosen server-side instead of swapped in the browser.`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function emit(io, report, options) {
|
|
355
|
+
if (options.json) {
|
|
356
|
+
io.log(JSON.stringify(report, null, 2));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
for (const line of renderReport(report))
|
|
360
|
+
io.log(line);
|
|
361
|
+
for (const warning of report.warnings)
|
|
362
|
+
io.error(warning);
|
|
363
|
+
}
|
|
364
|
+
/** The human-readable report body. Pure — the CLI prints what this returns. */
|
|
365
|
+
export function renderReport(report) {
|
|
366
|
+
const lines = [];
|
|
367
|
+
if (report.documents.length === 0) {
|
|
368
|
+
lines.push('');
|
|
369
|
+
lines.push('No legacy variantContainer modules found.');
|
|
370
|
+
return lines;
|
|
371
|
+
}
|
|
372
|
+
for (const doc of report.documents) {
|
|
373
|
+
lines.push('');
|
|
374
|
+
const label = doc.kind === 'blueprint' ? 'blueprint' : (doc.status ?? 'content');
|
|
375
|
+
lines.push(`${doc.id} ${doc.title} [${label}]`);
|
|
376
|
+
for (const p of doc.placements) {
|
|
377
|
+
const where = p.scope === 'regions'
|
|
378
|
+
? `region ${p.region}`
|
|
379
|
+
: `${p.scope} ${p.scopeId} / region ${p.region}`;
|
|
380
|
+
const weightNote = p.unboundArms > 0 ? `, ${p.unboundArms} unbound` : '';
|
|
381
|
+
lines.push(` · ${p.moduleId} ${where}, section ${p.sectionId}, column ${p.columnId} [${p.index}] ` +
|
|
382
|
+
`${p.mode}, ${p.armCount} arm(s)${weightNote}, ${p.htmlBytes} HTML bytes`);
|
|
383
|
+
if (p.refusal)
|
|
384
|
+
lines.push(` REFUSED — ${p.refusal}`);
|
|
385
|
+
}
|
|
386
|
+
for (const cs of doc.openChangesets) {
|
|
387
|
+
lines.push(` ! open changeset "${cs.name}" (${cs.id}) holds this document`);
|
|
388
|
+
}
|
|
389
|
+
if (doc.outcome === 'skipped')
|
|
390
|
+
lines.push(` SKIPPED — ${doc.skipReason}`);
|
|
391
|
+
if (doc.outcome === 'migrated')
|
|
392
|
+
lines.push(' migrated');
|
|
393
|
+
}
|
|
394
|
+
const t = report.totals;
|
|
395
|
+
lines.push('');
|
|
396
|
+
lines.push(`${t.documents} document(s), ${t.placements} placement(s): ` +
|
|
397
|
+
`${t.converted} migratable, ${t.refused} refused, ` +
|
|
398
|
+
`${t.migrated} written, ${t.skipped} skipped.`);
|
|
399
|
+
if (report.backupPath)
|
|
400
|
+
lines.push(`Backup: ${report.backupPath}`);
|
|
401
|
+
if (report.mode === 'report' && t.converted > 0) {
|
|
402
|
+
lines.push('Nothing was written. Re-run with --apply to migrate.');
|
|
403
|
+
}
|
|
404
|
+
if (report.exitCode === 2) {
|
|
405
|
+
lines.push(`Exiting 2: ${t.refused} placement(s) were refused and need a decision (see REFUSED above).`);
|
|
406
|
+
}
|
|
407
|
+
if (report.exitCode === 1) {
|
|
408
|
+
lines.push('Exiting 1: something asked for did not happen (see SKIPPED and warnings above).');
|
|
409
|
+
}
|
|
410
|
+
return lines;
|
|
411
|
+
}
|
|
412
|
+
// ── The real gateway ─────────────────────────────────────────────────────────
|
|
413
|
+
/**
|
|
414
|
+
* The live database implementation of {@link UpgradeGateway}.
|
|
415
|
+
*
|
|
416
|
+
* `core` and `orm` are passed in rather than imported at module scope for the
|
|
417
|
+
* same reason every other command dynamically imports them: the CLI must not
|
|
418
|
+
* load the DB stack to print `--help`.
|
|
419
|
+
*/
|
|
420
|
+
export function createDbGateway(db, core, orm) {
|
|
421
|
+
const { kywiContent, kywiSites, kywiSectionTemplates, kywiChangesets, kywiChangesetItems, recordContentVersion, setContentLayout, updateSectionTemplate, } = core;
|
|
422
|
+
const { and, eq, inArray, sql } = orm;
|
|
423
|
+
const database = db;
|
|
424
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
425
|
+
return {
|
|
426
|
+
async resolveSiteId(ref) {
|
|
427
|
+
const [row] = await database
|
|
428
|
+
.select({ id: kywiSites.id })
|
|
429
|
+
.from(kywiSites)
|
|
430
|
+
.where(UUID.test(ref) ? eq(kywiSites.id, ref) : eq(kywiSites.slug, ref))
|
|
431
|
+
.limit(1);
|
|
432
|
+
return row?.id ?? null;
|
|
433
|
+
},
|
|
434
|
+
async listContentCandidates(filter) {
|
|
435
|
+
// The same text narrowing `detachComponentEverywhere` uses. It
|
|
436
|
+
// over-selects (the section-level VariantContainer shares the name); the
|
|
437
|
+
// structural walk in core is what confirms.
|
|
438
|
+
const predicates = [sql `${kywiContent.layout}::text like '%"variantContainer"%'`];
|
|
439
|
+
if (filter.siteId)
|
|
440
|
+
predicates.push(eq(kywiContent.siteId, filter.siteId));
|
|
441
|
+
if (filter.contentId)
|
|
442
|
+
predicates.push(eq(kywiContent.id, filter.contentId));
|
|
443
|
+
const rows = await database
|
|
444
|
+
.select({
|
|
445
|
+
id: kywiContent.id,
|
|
446
|
+
siteId: kywiContent.siteId,
|
|
447
|
+
title: kywiContent.title,
|
|
448
|
+
status: kywiContent.status,
|
|
449
|
+
layout: kywiContent.layout,
|
|
450
|
+
})
|
|
451
|
+
.from(kywiContent)
|
|
452
|
+
.where(and(...predicates));
|
|
453
|
+
return rows.map((row) => ({
|
|
454
|
+
id: row.id,
|
|
455
|
+
siteId: row.siteId,
|
|
456
|
+
title: row.title,
|
|
457
|
+
status: row.status,
|
|
458
|
+
layout: (row.layout ?? null),
|
|
459
|
+
}));
|
|
460
|
+
},
|
|
461
|
+
async listBlueprintCandidates(filter) {
|
|
462
|
+
const predicates = [
|
|
463
|
+
sql `${kywiSectionTemplates.definition}::text like '%"variantContainer"%'`,
|
|
464
|
+
];
|
|
465
|
+
if (filter.siteId)
|
|
466
|
+
predicates.push(eq(kywiSectionTemplates.siteId, filter.siteId));
|
|
467
|
+
const rows = await database
|
|
468
|
+
.select({
|
|
469
|
+
id: kywiSectionTemplates.id,
|
|
470
|
+
siteId: kywiSectionTemplates.siteId,
|
|
471
|
+
name: kywiSectionTemplates.name,
|
|
472
|
+
definition: kywiSectionTemplates.definition,
|
|
473
|
+
})
|
|
474
|
+
.from(kywiSectionTemplates)
|
|
475
|
+
.where(and(...predicates));
|
|
476
|
+
return rows.map((row) => ({
|
|
477
|
+
id: row.id,
|
|
478
|
+
siteId: row.siteId,
|
|
479
|
+
name: row.name,
|
|
480
|
+
definition: (row.definition ?? null),
|
|
481
|
+
}));
|
|
482
|
+
},
|
|
483
|
+
async listOpenChangesetItems(contentIds) {
|
|
484
|
+
if (contentIds.length === 0)
|
|
485
|
+
return [];
|
|
486
|
+
const rows = await database
|
|
487
|
+
.select({
|
|
488
|
+
changesetId: kywiChangesets.id,
|
|
489
|
+
changesetName: kywiChangesets.name,
|
|
490
|
+
contentId: kywiChangesetItems.contentId,
|
|
491
|
+
})
|
|
492
|
+
.from(kywiChangesetItems)
|
|
493
|
+
// `kywi_changesets.id` is uuid; `kywi_changeset_items.changeset_id` is
|
|
494
|
+
// text. Postgres has no `uuid = text` operator, so a bare column-to-column
|
|
495
|
+
// eq() here fails EVERY real run with
|
|
496
|
+
// "operator does not exist: uuid = text". The cast is on the uuid side so
|
|
497
|
+
// the text column's index (if any) stays usable.
|
|
498
|
+
.innerJoin(kywiChangesets, eq(sql `${kywiChangesets.id}::text`, kywiChangesetItems.changesetId))
|
|
499
|
+
.where(and(inArray(kywiChangesetItems.contentId, [...contentIds]), eq(kywiChangesets.status, 'open')));
|
|
500
|
+
return rows;
|
|
501
|
+
},
|
|
502
|
+
async withContentLock(contentId, siteId, fn) {
|
|
503
|
+
const run = async (tx) => {
|
|
504
|
+
const [row] = await tx
|
|
505
|
+
.select()
|
|
506
|
+
.from(kywiContent)
|
|
507
|
+
.where(and(eq(kywiContent.id, contentId), eq(kywiContent.siteId, siteId)))
|
|
508
|
+
.for('update')
|
|
509
|
+
.limit(1);
|
|
510
|
+
if (!row)
|
|
511
|
+
return null;
|
|
512
|
+
const session = {
|
|
513
|
+
layout: (row.layout ?? null),
|
|
514
|
+
async commit(next, changeNote) {
|
|
515
|
+
// The snapshot is the row as it stands NOW — pre-migration — so the
|
|
516
|
+
// ordinary revision UI can restore the legacy layout.
|
|
517
|
+
await recordContentVersion(tx, {
|
|
518
|
+
contentId,
|
|
519
|
+
siteId,
|
|
520
|
+
snapshot: row,
|
|
521
|
+
status: row.status,
|
|
522
|
+
changeNote,
|
|
523
|
+
createdBy: null,
|
|
524
|
+
});
|
|
525
|
+
// `setContentLayout`, never a raw update: it is the one layout write
|
|
526
|
+
// path and it reconciles `kywi_component_instances` in the same
|
|
527
|
+
// transaction, so a grandfathered componentId on a migrated arm
|
|
528
|
+
// keeps its index row.
|
|
529
|
+
//
|
|
530
|
+
// It returns the written row's identity (kywi-cms#195); all this
|
|
531
|
+
// caller asks is whether the row was still there, so narrow to that
|
|
532
|
+
// rather than widening the session contract with fields the
|
|
533
|
+
// migration has no use for.
|
|
534
|
+
return (await setContentLayout(tx, contentId, next, siteId)) !== null;
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
return fn(session);
|
|
538
|
+
};
|
|
539
|
+
// Guarded the same way `setContentLayout`'s own `runInTransaction` guards
|
|
540
|
+
// it: unit tests hand these queries a chainable mock with no `.transaction`.
|
|
541
|
+
const maybeTx = database;
|
|
542
|
+
if (typeof maybeTx.transaction === 'function')
|
|
543
|
+
return maybeTx.transaction(run);
|
|
544
|
+
return run(database);
|
|
545
|
+
},
|
|
546
|
+
async writeBlueprintDefinition(id, siteId, definition) {
|
|
547
|
+
const row = await updateSectionTemplate(database, id, { definition: definition }, siteId);
|
|
548
|
+
return row !== null;
|
|
549
|
+
},
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* The production {@link UpgradeIo}: stdout/stderr, real files, the real clock.
|
|
554
|
+
*
|
|
555
|
+
* Exported so the integration test drives the same code path the command does,
|
|
556
|
+
* rather than a hand-rolled double that could drift from it.
|
|
557
|
+
*/
|
|
558
|
+
export function createFileIo(cwd = process.cwd()) {
|
|
559
|
+
return {
|
|
560
|
+
log: (line) => console.log(line),
|
|
561
|
+
error: (line) => console.error(line),
|
|
562
|
+
async writeBackup(path, contents, { exclusive }) {
|
|
563
|
+
const full = resolve(cwd, path);
|
|
564
|
+
try {
|
|
565
|
+
// 'wx' fails rather than truncating. The backup is the only copy of a
|
|
566
|
+
// layout this command is about to overwrite; clobbering an earlier run's
|
|
567
|
+
// backup would destroy the very thing it exists to preserve.
|
|
568
|
+
await writeFile(full, contents, { encoding: 'utf8', flag: exclusive ? 'wx' : 'w' });
|
|
569
|
+
}
|
|
570
|
+
catch (err) {
|
|
571
|
+
if (exclusive && err.code === 'EEXIST') {
|
|
572
|
+
throw new Error(`Backup file ${full} already exists — refusing to overwrite it. ` +
|
|
573
|
+
`Move it aside, or pass --backup <path> with a name that is free.`);
|
|
574
|
+
}
|
|
575
|
+
throw err;
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
now: () => new Date(),
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
// ── Registration ─────────────────────────────────────────────────────────────
|
|
582
|
+
program
|
|
583
|
+
.command('upgrade:variant-containers')
|
|
584
|
+
.description('Migrate deprecated variantContainer MODULES to real module variant containers. ' +
|
|
585
|
+
'Reports only unless --apply is passed.')
|
|
586
|
+
.option('-c, --config <path>', 'Path to kywi.config.ts', 'kywi.config.ts')
|
|
587
|
+
.option('--site <slug|uuid>', 'Limit to one site (default: all sites)')
|
|
588
|
+
.option('--content <uuid>', 'Limit to one content document')
|
|
589
|
+
.option('--node <moduleId>', 'Limit to one legacy module placement')
|
|
590
|
+
.option('--dry-run', 'Report only — the default, stated explicitly', false)
|
|
591
|
+
.option('--apply', 'Actually write the migrated layouts', false)
|
|
592
|
+
.option('--backup <path>', 'Where to write the before-layouts (default: ./kywi-vc-backup-<ts>.json)')
|
|
593
|
+
.option('--json', 'Machine-readable report', false)
|
|
594
|
+
.option('--ignore-open-changesets', 'Migrate documents held by an open changeset (their publish may re-introduce the legacy shape)', false)
|
|
595
|
+
.action(async (options) => {
|
|
596
|
+
const configPath = resolve(process.cwd(), options.config);
|
|
597
|
+
const configModule = await import(configPath);
|
|
598
|
+
const config = configModule.default;
|
|
599
|
+
const core = await import('@kywi-software/core');
|
|
600
|
+
const orm = await import('drizzle-orm');
|
|
601
|
+
const { createDb, resolveDatabaseUrl, explainDbError } = core;
|
|
602
|
+
let dbUrl;
|
|
603
|
+
try {
|
|
604
|
+
dbUrl = resolveDatabaseUrl(config.db.url, 'postgres://localhost:5432/kywi_dev').url;
|
|
605
|
+
}
|
|
606
|
+
catch (err) {
|
|
607
|
+
console.error(`\n✖ ${err.message}\n`);
|
|
608
|
+
process.exit(1);
|
|
609
|
+
}
|
|
610
|
+
const db = createDb(dbUrl, config.db.provider);
|
|
611
|
+
const io = createFileIo();
|
|
612
|
+
try {
|
|
613
|
+
const report = await runVariantContainerUpgrade(createDbGateway(db, core, orm), io, options);
|
|
614
|
+
process.exit(report.exitCode);
|
|
615
|
+
}
|
|
616
|
+
catch (err) {
|
|
617
|
+
const friendly = explainDbError(err, dbUrl);
|
|
618
|
+
if (friendly) {
|
|
619
|
+
console.error(`\n✖ ${friendly}\n`);
|
|
620
|
+
process.exit(1);
|
|
621
|
+
}
|
|
622
|
+
throw err;
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
//# sourceMappingURL=upgrade-variant-containers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade-variant-containers.js","sourceRoot":"","sources":["../../src/commands/upgrade-variant-containers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAgK5C,MAAM,CAAC,MAAM,WAAW,GACtB,+EAA+E,CAAA;AAEjF,4DAA4D;AAC5D,MAAM,UAAU,iBAAiB,CAAC,GAAS;IACzC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC/D,OAAO,oBAAoB,KAAK,OAAO,CAAA;AACzC,CAAC;AA6BD,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAuB,EACvB,EAAa,EACb,OAAuB;IAEvB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAChD,MAAM,EAAE,8BAA8B,EAAE,sBAAsB,EAAE,GAAG,IAAI,CAAA;IAEvE,6EAA6E;IAC7E,mDAAmD;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,CAAA;IAC/D,6EAA6E;IAC7E,oEAAoE;IACpE,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAQ,EAAE;QACtC,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC,CAAA;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC3D,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,MAAM,MAAM,GAAkB;QAC5B,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;QAChC,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,EAAE;QACb,MAAM,EAAE;YACN,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,CAAC;SACb;QACD,UAAU,EAAE,IAAI;QAChB,QAAQ;QACR,EAAE,EAAE,IAAI;QACR,QAAQ,EAAE,CAAC;KACZ,CAAA;IAED,8EAA8E;IAC9E,IAAI,MAA0B,CAAA;IAC9B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,IAAI,0BAA0B,CAAC,CAAA;YACzE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;YAC3B,OAAO,MAAM,CAAA;QACf,CAAC;QACD,MAAM,GAAG,QAAQ,CAAA;IACnB,CAAC;IAED,8EAA8E;IAC9E,MAAM,OAAO,GAAsB,EAAE,CAAA;IAErC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,qBAAqB,CAAC;QACtD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC,CAAA;IACF,2EAA2E;IAC3E,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO;QACnC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,MAAM,OAAO,CAAC,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC5E,MAAM,CAAC,OAAO,GAAG,WAAW,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAA;IAE1D,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,8BAA8B,CAAC,GAAG,CAAC,MAAM,EAAE;YACxD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpC,CAAC,CAAA;QACF,4EAA4E;QAC5E,4EAA4E;QAC5E,oEAAoE;QACpE,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QAC5C,OAAO,CAAC,IAAI,CAAC;YACX,MAAM,EAAE;gBACN,IAAI,EAAE,SAAS;gBACf,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,SAAS,EAAE,GAAG,CAAC,MAAM,KAAK,WAAW;gBACrC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,cAAc,EAAE,EAAE;gBAClB,OAAO,EAAE,UAAU;aACpB;YACD,MAAM,EAAE,GAAG,CAAC,MAAwB;YACpC,IAAI,EAAE,MAAM,CAAC,QAAQ;SACtB,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,8BAA8B,CAAC,GAAG,CAAC,UAAU,EAAE;YAC5D,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpC,CAAC,CAAA;QACF,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QAC5C,OAAO,CAAC,IAAI,CAAC;YACX,MAAM,EAAE;gBACN,IAAI,EAAE,WAAW;gBACjB,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,cAAc,EAAE,EAAE;gBAClB,OAAO,EAAE,UAAU;aACpB;YACD,MAAM,EAAE,GAAG,CAAC,UAA4B;YACxC,IAAI,EAAE,MAAM,CAAC,QAAQ;SACtB,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IAE/C,8EAA8E;IAC9E,EAAE;IACF,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,yEAAyE;IACzE,0EAA0E;IAC1E,kDAAkD;IAClD,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,CAAC;QACzE,QAAQ,CAAC,IAAI,CACX,iCAAiC,OAAO,CAAC,OAAO,kCAAkC;YAChF,uDAAuD,CAC1D,CAAA;IACH,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CACX,+BAA+B,OAAO,CAAC,IAAI,oCAAoC;YAC7E,sBAAsB,CACzB,CAAA;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;QAC3B,OAAO,MAAM,CAAA;IACf,CAAC;IAED,8EAA8E;IAC9E,EAAE;IACF,uEAAuE;IACvE,8EAA8E;IAC9E,+EAA+E;IAC/E,6EAA6E;IAC7E,qCAAqC;IACrC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC7F,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAA;QAC9D,MAAM,SAAS,GAAG,IAAI,GAAG,EAA+C,CAAA;QACxE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;YAChD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAA;YAC7D,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACrC,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,CAAC,CAAC,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAA;QAC5D,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,MAAM,CAAC,CAAA;IACb,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;QACzB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACpC,IAAI,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC;YAC3D,wEAAwE;YACxE,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,oBAAoB,IAAI,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxE,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,SAAS,CAAA;YAC5B,CAAC,CAAC,MAAM,CAAC,UAAU;gBACjB,6BAA6B,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;oBACvF,gFAAgF;oBAChF,kEAAkE,CAAA;YACpE,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;IAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;QAC3B,OAAO,MAAM,CAAA;IACf,CAAC;IAED,8EAA8E;IAC9E,EAAE;IACF,8EAA8E;IAC9E,8EAA8E;IAC9E,mEAAmE;IACnE,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,aAAa;IACb,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;IAChE,MAAM,aAAa,GAAkB,EAAE,CAAA;IACvC,MAAM,YAAY,GAAG,GAAW,EAAE,CAChC,IAAI,CAAC,SAAS,CACZ;QACE,IAAI,EAAE,iCAAiC;QACvC,KAAK,EAAE,cAAc;QACrB,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QACjC,SAAS,EAAE,aAAa;KACzB,EACD,IAAI,EACJ,CAAC,CACF,CAAA;IACH,MAAM,aAAa,GAAG,KAAK,EAAE,CAAkB,EAAiB,EAAE;QAChE,aAAa,CAAC,IAAI,CAAC;YACjB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI;YACnB,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE;YACf,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM;YACvB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK;YACrB,MAAM,EAAE,CAAC,CAAC,MAAM;SACjB,CAAC,CAAA;QACF,MAAM,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;IACxE,CAAC,CAAA;IAED,MAAM,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,QAAQ,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAA;IAEhD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAClC,MAAM,UAAU,GAAG,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBACjD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,0CAA0C,UAAU,CAAC,KAAK,EAAE,CAAC,CAAA;oBAC5E,SAAQ;gBACV,CAAC;gBACD,0DAA0D;gBAC1D,sEAAsE;gBACtE,qEAAqE;gBACrE,sEAAsE;gBACtE,wEAAwE;gBACxE,MAAM,aAAa,CAAC,CAAC,CAAC,CAAA;gBACtB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC5F,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAA;oBAChD,SAAQ;gBACV,CAAC;gBACD,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,UAAU,CAAA;gBAC7B,QAAQ,CAAC,wBAAwB,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAA;gBACnE,SAAQ;YACV,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,eAAe,CAC3C,CAAC,CAAC,MAAM,CAAC,EAAE,EACX,CAAC,CAAC,MAAM,CAAC,MAAM,EACf,KAAK,EAAE,OAAO,EAAE,EAAE;gBAChB,mEAAmE;gBACnE,8DAA8D;gBAC9D,MAAM,KAAK,GAAG,8BAA8B,CAAC,OAAO,CAAC,MAAM,EAAE;oBAC3D,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpC,CAAC,CAAA;gBACF,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnB,OAAO,EAAE,MAAM,EAAE,SAAkB,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAA;gBACzF,CAAC;gBACD,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;gBACzD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;oBACxB,qEAAqE;oBACrE,oEAAoE;oBACpE,qEAAqE;oBACrE,OAAO,EAAE,MAAM,EAAE,SAAkB,EAAE,MAAM,EAAE,sCAAsC,UAAU,CAAC,KAAK,EAAE,EAAE,CAAA;gBACzG,CAAC;gBACD,+DAA+D;gBAC/D,IAAI,OAAO,CAAC,MAAM;oBAAE,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;gBAC7C,MAAM,aAAa,CAAC,CAAC,CAAC,CAAA;gBACtB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;gBACjE,OAAO,OAAO;oBACZ,CAAC,CAAC,EAAE,MAAM,EAAE,UAAmB,EAAE,MAAM,EAAE,EAAE,EAAE;oBAC7C,CAAC,CAAC,EAAE,MAAM,EAAE,SAAkB,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAA;YACzE,CAAC,CACF,CAAA;YAED,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;gBACtC,SAAQ;YACV,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;gBAC9B,SAAQ;YACV,CAAC;YACD,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,UAAU,CAAA;YAC7B,QAAQ,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAA;QAC3D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,iBAAkB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3B,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,IAAI,CAAC,GAAmB,EAAE,MAAc;IAC/C,GAAG,CAAC,OAAO,GAAG,SAAS,CAAA;IACvB,GAAG,CAAC,UAAU,GAAG,MAAM,CAAA;AACzB,CAAC;AAED,SAAS,KAAK,CAAC,MAAqB;IAClC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;IACvB,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAA;IACrC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAA;IAChB,CAAC,CAAC,SAAS,GAAG,CAAC,CAAA;IACf,CAAC,CAAC,OAAO,GAAG,CAAC,CAAA;IACb,CAAC,CAAC,SAAS,GAAG,CAAC,CAAA;IACf,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAA;IACd,CAAC,CAAC,OAAO,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,CAAC,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAA;QACrC,KAAK,MAAM,SAAS,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACvC,IAAI,SAAS,CAAC,OAAO;gBAAE,CAAC,CAAC,OAAO,EAAE,CAAA;;gBAC7B,CAAC,CAAC,SAAS,EAAE,CAAA;QACpB,CAAC;QACD,IAAI,GAAG,CAAC,SAAS;YAAE,CAAC,CAAC,SAAS,EAAE,CAAA;QAChC,IAAI,GAAG,CAAC,OAAO,KAAK,UAAU;YAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC5C,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;YAAE,CAAC,CAAC,OAAO,EAAE,CAAA;IAC5C,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAC1D,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAA;AACnC,CAAC;AAED,SAAS,MAAM,CAAC,EAAa,EAAE,MAAqB,EAAE,OAAuB;IAC3E,KAAK,CAAC,MAAM,CAAC,CAAA;IACb,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CACjB,EAAa,EACb,MAAqB,EACrB,OAAuB,EACvB,KAAc;IAEd,IAAI,OAAO,CAAC,IAAI;QAAE,OAAM;IACxB,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;IACvB,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACV,EAAE,CAAC,GAAG,CACJ,KAAK;QACH,CAAC,CAAC,oEAAoE;QACtE,CAAC,CAAC,uEAAuE,CAC5E,CAAA;IACD,EAAE,CAAC,GAAG,CACJ,WAAW,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC,SAAS,iBAAiB;QACzE,4BAA4B,CAAC,CAAC,UAAU,kBAAkB,CAAC,CAAC,SAAS,eAAe;QACpF,GAAG,CAAC,CAAC,OAAO,YAAY,CAC3B,CAAA;IACD,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QACpB,EAAE,CAAC,GAAG,CACJ,GAAG,CAAC,CAAC,SAAS,2EAA2E;YACvF,6EAA6E;YAC7E,uFAAuF,CAC1F,CAAA;IACH,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,EAAa,EAAE,MAAqB,EAAE,OAAuB;IACzE,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACvC,OAAM;IACR,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,MAAM,CAAC;QAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACrD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ;QAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC1D,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;QACvD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC,CAAA;QAChF,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,KAAK,MAAM,KAAK,GAAG,CAAC,CAAA;QACjD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YAC/B,MAAM,KAAK,GACT,CAAC,CAAC,KAAK,KAAK,SAAS;gBACnB,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE;gBACtB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,EAAE,CAAA;YACpD,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;YACxE,KAAK,CAAC,IAAI,CACR,OAAO,CAAC,CAAC,QAAQ,KAAK,KAAK,aAAa,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,KAAK;gBACxF,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,QAAQ,UAAU,UAAU,KAAK,CAAC,CAAC,SAAS,aAAa,CAC5E,CAAA;YACD,IAAI,CAAC,CAAC,OAAO;gBAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;QAC3D,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAA;QAC9E,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;QAC1E,IAAI,GAAG,CAAC,OAAO,KAAK,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC1D,CAAC;IAED,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;IACvB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,CAAC,SAAS,iBAAiB,CAAC,CAAC,UAAU,iBAAiB;QAC1D,GAAG,CAAC,CAAC,SAAS,gBAAgB,CAAC,CAAC,OAAO,YAAY;QACnD,GAAG,CAAC,CAAC,QAAQ,aAAa,CAAC,CAAC,OAAO,WAAW,CACjD,CAAA;IACD,IAAI,MAAM,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,UAAU,EAAE,CAAC,CAAA;IACjE,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAA;IACpE,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CACR,cAAc,CAAC,CAAC,OAAO,qEAAqE,CAC7F,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAA;IAC/F,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAW,EACX,IAA0C,EAC1C,GAAiC;IAEjC,MAAM,EACJ,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,GACtB,GAAG,IAAI,CAAA;IACR,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;IAKrC,MAAM,QAAQ,GAAG,EAAQ,CAAA;IAEzB,MAAM,IAAI,GAAG,iEAAiE,CAAA;IAE9E,OAAO;QACL,KAAK,CAAC,aAAa,CAAC,GAAG;YACrB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,QAAQ;iBACzB,MAAM,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;iBAC5B,IAAI,CAAC,SAAS,CAAC;iBACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;iBACvE,KAAK,CAAC,CAAC,CAAC,CAAA;YACX,OAAO,GAAG,EAAE,EAAE,IAAI,IAAI,CAAA;QACxB,CAAC;QAED,KAAK,CAAC,qBAAqB,CAAC,MAAM;YAChC,+DAA+D;YAC/D,yEAAyE;YACzE,4CAA4C;YAC5C,MAAM,UAAU,GAAG,CAAC,GAAG,CAAA,GAAG,WAAW,CAAC,MAAM,oCAAoC,CAAC,CAAA;YACjF,IAAI,MAAM,CAAC,MAAM;gBAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;YACzE,IAAI,MAAM,CAAC,SAAS;gBAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAA;YAC3E,MAAM,IAAI,GAAG,MAAM,QAAQ;iBACxB,MAAM,CAAC;gBACN,EAAE,EAAE,WAAW,CAAC,EAAE;gBAClB,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,MAAM,EAAE,WAAW,CAAC,MAAM;aAC3B,CAAC;iBACD,IAAI,CAAC,WAAW,CAAC;iBACjB,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAA;YAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACxB,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAA0B;aACtD,CAAC,CAAC,CAAA;QACL,CAAC;QAED,KAAK,CAAC,uBAAuB,CAAC,MAAM;YAClC,MAAM,UAAU,GAAG;gBACjB,GAAG,CAAA,GAAG,oBAAoB,CAAC,UAAU,oCAAoC;aAC1E,CAAA;YACD,IAAI,MAAM,CAAC,MAAM;gBAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;YAClF,MAAM,IAAI,GAAG,MAAM,QAAQ;iBACxB,MAAM,CAAC;gBACN,EAAE,EAAE,oBAAoB,CAAC,EAAE;gBAC3B,MAAM,EAAE,oBAAoB,CAAC,MAAM;gBACnC,IAAI,EAAE,oBAAoB,CAAC,IAAI;gBAC/B,UAAU,EAAE,oBAAoB,CAAC,UAAU;aAC5C,CAAC;iBACD,IAAI,CAAC,oBAAoB,CAAC;iBAC1B,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAA;YAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACxB,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,UAAU,EAAE,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAA0B;aAC9D,CAAC,CAAC,CAAA;QACL,CAAC;QAED,KAAK,CAAC,sBAAsB,CAAC,UAAU;YACrC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAA;YACtC,MAAM,IAAI,GAAG,MAAM,QAAQ;iBACxB,MAAM,CAAC;gBACN,WAAW,EAAE,cAAc,CAAC,EAAE;gBAC9B,aAAa,EAAE,cAAc,CAAC,IAAI;gBAClC,SAAS,EAAE,kBAAkB,CAAC,SAAS;aACxC,CAAC;iBACD,IAAI,CAAC,kBAAkB,CAAC;gBACzB,uEAAuE;gBACvE,2EAA2E;gBAC3E,sCAAsC;gBACtC,0EAA0E;gBAC1E,iDAAiD;iBAChD,SAAS,CACR,cAAc,EACd,EAAE,CAAC,GAAG,CAAA,GAAG,cAAc,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC,WAAW,CAAC,CACpE;iBACA,KAAK,CACJ,GAAG,CACD,OAAO,CAAC,kBAAkB,CAAC,SAAS,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,EACtD,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAClC,CACF,CAAA;YACH,OAAO,IAAI,CAAA;QACb,CAAC;QAED,KAAK,CAAC,eAAe,CACnB,SAAiB,EACjB,MAAc,EACd,EAAgD;YAEhD,MAAM,GAAG,GAAG,KAAK,EAAE,EAAM,EAAqB,EAAE;gBAC9C,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;qBACnB,MAAM,EAAE;qBACR,IAAI,CAAC,WAAW,CAAC;qBACjB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;qBACzE,GAAG,CAAC,QAAQ,CAAC;qBACb,KAAK,CAAC,CAAC,CAAC,CAAA;gBACX,IAAI,CAAC,GAAG;oBAAE,OAAO,IAAI,CAAA;gBACrB,MAAM,OAAO,GAAwB;oBACnC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAA0B;oBACrD,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU;wBAC3B,oEAAoE;wBACpE,sDAAsD;wBACtD,MAAM,oBAAoB,CAAC,EAAE,EAAE;4BAC7B,SAAS;4BACT,MAAM;4BACN,QAAQ,EAAE,GAAyC;4BACnD,MAAM,EAAE,GAAG,CAAC,MAAM;4BAClB,UAAU;4BACV,SAAS,EAAE,IAAI;yBAChB,CAAC,CAAA;wBACF,qEAAqE;wBACrE,gEAAgE;wBAChE,gEAAgE;wBAChE,uBAAuB;wBACvB,EAAE;wBACF,iEAAiE;wBACjE,oEAAoE;wBACpE,4DAA4D;wBAC5D,4BAA4B;wBAC5B,OAAO,CAAC,MAAM,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,CAAA;oBACvE,CAAC;iBACF,CAAA;gBACD,OAAO,EAAE,CAAC,OAAO,CAAC,CAAA;YACpB,CAAC,CAAA;YACD,0EAA0E;YAC1E,6EAA6E;YAC7E,MAAM,OAAO,GAAG,QAEf,CAAA;YACD,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU;gBAAE,OAAO,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YAC9E,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAA;QACtB,CAAC;QAED,KAAK,CAAC,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU;YACnD,MAAM,GAAG,GAAG,MAAM,qBAAqB,CACrC,QAAQ,EACR,EAAE,EACF,EAAE,UAAU,EAAE,UAAgD,EAAE,EAChE,MAAM,CACP,CAAA;YACD,OAAO,GAAG,KAAK,IAAI,CAAA;QACrB,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACtD,OAAO;QACL,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QAChC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;QACpC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE;YAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAC/B,IAAI,CAAC;gBACH,sEAAsE;gBACtE,yEAAyE;gBACzE,6DAA6D;gBAC7D,MAAM,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAA;YACrF,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,SAAS,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAClE,MAAM,IAAI,KAAK,CACb,eAAe,IAAI,8CAA8C;wBAC/D,kEAAkE,CACrE,CAAA;gBACH,CAAC;gBACD,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;QACD,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE;KACtB,CAAA;AACH,CAAC;AAED,gFAAgF;AAEhF,OAAO;KACJ,OAAO,CAAC,4BAA4B,CAAC;KACrC,WAAW,CACV,iFAAiF;IAC/E,wCAAwC,CAC3C;KACA,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,gBAAgB,CAAC;KACzE,MAAM,CAAC,oBAAoB,EAAE,wCAAwC,CAAC;KACtE,MAAM,CAAC,kBAAkB,EAAE,+BAA+B,CAAC;KAC3D,MAAM,CAAC,mBAAmB,EAAE,sCAAsC,CAAC;KACnE,MAAM,CAAC,WAAW,EAAE,8CAA8C,EAAE,KAAK,CAAC;KAC1E,MAAM,CAAC,SAAS,EAAE,qCAAqC,EAAE,KAAK,CAAC;KAC/D,MAAM,CAAC,iBAAiB,EAAE,yEAAyE,CAAC;KACpG,MAAM,CAAC,QAAQ,EAAE,yBAAyB,EAAE,KAAK,CAAC;KAClD,MAAM,CACL,0BAA0B,EAC1B,+FAA+F,EAC/F,KAAK,CACN;KACA,MAAM,CAAC,KAAK,EAAE,OAAuB,EAAE,EAAE;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACzD,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAA;IAEnC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAChD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,GAAG,IAAI,CAAA;IAE7D,IAAI,KAAa,CAAA;IACjB,IAAI,CAAC;QACH,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,oCAAoC,CAAC,CAAC,GAAG,CAAA;IACrF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,OAAQ,GAAa,CAAC,OAAO,IAAI,CAAC,CAAA;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAA;IAE9C,MAAM,EAAE,GAAG,YAAY,EAAE,CAAA;IAEzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;QAC5F,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC3C,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,OAAO,QAAQ,IAAI,CAAC,CAAA;YAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC,CAAC,CAAA"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,gCAAgC,CAAA;AACvC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,8BAA8B,CAAA;AACrC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,yBAAyB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,gCAAgC,CAAA;AACvC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,8BAA8B,CAAA;AACrC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,yBAAyB,CAAA;AAChC,OAAO,0CAA0C,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import './commands/migrate.js';
|
|
|
5
5
|
import './commands/migrate-status.js';
|
|
6
6
|
import './commands/seed.js';
|
|
7
7
|
import './commands/seed-demo.js';
|
|
8
|
+
import './commands/upgrade-variant-containers.js';
|
|
8
9
|
// Load a project-root .env before commands run, so `kywi migrate` / `kywi seed`
|
|
9
10
|
// work with nothing but a .env present (no `export DATABASE_URL=…` needed). Uses
|
|
10
11
|
// Node 20.6+'s built-in loader (this package requires node >=20.6.0). Runs before
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,gCAAgC,CAAA;AACvC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,8BAA8B,CAAA;AACrC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,gCAAgC,CAAA;AACvC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,8BAA8B,CAAA;AACrC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,yBAAyB,CAAA;AAChC,OAAO,0CAA0C,CAAA;AAEjD,gFAAgF;AAChF,iFAAiF;AACjF,kFAAkF;AAClF,iFAAiF;AACjF,iEAAiE;AACjE,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;IACpE,IAAI,CAAC;QACH,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;QACxE,8DAA8D;IAChE,CAAC;AACH,CAAC;AAED,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,cAAc,CAAC;KAC3B,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kywi-software/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Kywi CMS command-line tool — migrate, seed, and generate schema from a kywi.config.ts project.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"commander": "^12.0.0",
|
|
37
37
|
"drizzle-orm": "^0.38.0",
|
|
38
38
|
"tsx": "^4.7.0",
|
|
39
|
-
"@kywi-software/core": "0.
|
|
39
|
+
"@kywi-software/core": "0.15.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^20.0.0",
|
|
@@ -45,8 +45,9 @@
|
|
|
45
45
|
"vitest": "^1.6.1"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "tsc",
|
|
48
|
+
"build": "rm -rf dist && tsc",
|
|
49
49
|
"dev": "tsx src/index.ts",
|
|
50
|
+
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
|
|
50
51
|
"test": "vitest run"
|
|
51
52
|
}
|
|
52
53
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"command-wiring.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/command-wiring.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
-
import { program } from 'commander';
|
|
3
|
-
// Importing each command module registers its command on the shared commander
|
|
4
|
-
// `program` singleton as a side effect (the same way src/index.ts wires them).
|
|
5
|
-
// We import the modules — NOT index.ts, which would call program.parse(argv) —
|
|
6
|
-
// so nothing runs; we only inspect the registered command graph.
|
|
7
|
-
beforeAll(async () => {
|
|
8
|
-
await import('../commands/migrate-generate.js');
|
|
9
|
-
await import('../commands/migrate.js');
|
|
10
|
-
await import('../commands/migrate-status.js');
|
|
11
|
-
await import('../commands/seed.js');
|
|
12
|
-
await import('../commands/seed-demo.js');
|
|
13
|
-
});
|
|
14
|
-
function command(name) {
|
|
15
|
-
const cmd = program.commands.find((c) => c.name() === name);
|
|
16
|
-
if (!cmd)
|
|
17
|
-
throw new Error(`command "${name}" is not registered`);
|
|
18
|
-
return cmd;
|
|
19
|
-
}
|
|
20
|
-
function optionDefaults(cmd) {
|
|
21
|
-
const out = {};
|
|
22
|
-
for (const opt of cmd.options)
|
|
23
|
-
out[opt.attributeName()] = opt.defaultValue;
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
describe('CLI command wiring', () => {
|
|
27
|
-
it('registers every command index.ts imports', () => {
|
|
28
|
-
const names = program.commands.map((c) => c.name()).sort();
|
|
29
|
-
expect(names).toEqual(['migrate', 'migrate:generate', 'migrate:status', 'seed', 'seed:demo']);
|
|
30
|
-
});
|
|
31
|
-
it('every command has a description and an action handler', () => {
|
|
32
|
-
for (const name of ['migrate', 'migrate:generate', 'migrate:status', 'seed', 'seed:demo']) {
|
|
33
|
-
const cmd = command(name);
|
|
34
|
-
expect(cmd.description().length).toBeGreaterThan(0);
|
|
35
|
-
// commander stores the action callback on a private field; presence proves wiring.
|
|
36
|
-
expect(cmd._actionHandler).toBeTypeOf('function');
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
it('migrate:generate exposes --config and --out with their defaults', () => {
|
|
40
|
-
const defaults = optionDefaults(command('migrate:generate'));
|
|
41
|
-
expect(defaults).toMatchObject({ config: 'kywi.config.ts', out: 'kywi-generated/schema' });
|
|
42
|
-
});
|
|
43
|
-
it('migrate exposes --config and a --push flag defaulting to false', () => {
|
|
44
|
-
const defaults = optionDefaults(command('migrate'));
|
|
45
|
-
expect(defaults).toMatchObject({ config: 'kywi.config.ts', push: false });
|
|
46
|
-
});
|
|
47
|
-
it('migrate:status takes no options', () => {
|
|
48
|
-
expect(command('migrate:status').options).toHaveLength(0);
|
|
49
|
-
});
|
|
50
|
-
it('seed and seed:demo both accept --config', () => {
|
|
51
|
-
expect(optionDefaults(command('seed'))).toMatchObject({ config: 'kywi.config.ts' });
|
|
52
|
-
expect(optionDefaults(command('seed:demo'))).toMatchObject({ config: 'kywi.config.ts' });
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
//# sourceMappingURL=command-wiring.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"command-wiring.test.js","sourceRoot":"","sources":["../../src/__tests__/command-wiring.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-generate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/migrate-generate.test.ts"],"names":[],"mappings":"AA0BA,OAAO,iCAAiC,CAAA"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
// Capture every file the command would write, without touching the filesystem.
|
|
3
|
-
const writes = [];
|
|
4
|
-
vi.mock('node:fs', () => ({
|
|
5
|
-
mkdirSync: vi.fn(),
|
|
6
|
-
writeFileSync: vi.fn((path, content) => { writes.push({ path, content }); }),
|
|
7
|
-
}));
|
|
8
|
-
// Keep the real (pure) schema generators; only stub the config loader so the
|
|
9
|
-
// command runs without a real kywi.config.ts on disk.
|
|
10
|
-
vi.mock('@kywi/core', async (importOriginal) => {
|
|
11
|
-
const actual = await importOriginal();
|
|
12
|
-
return {
|
|
13
|
-
...actual,
|
|
14
|
-
parseKywiConfig: vi.fn().mockResolvedValue({
|
|
15
|
-
contentTypes: [
|
|
16
|
-
{ name: 'blogPost', label: 'Blog Post', baseType: 'content', fields: [{ name: 'excerpt', type: 'richText', label: 'Excerpt' }] },
|
|
17
|
-
],
|
|
18
|
-
db: { provider: 'postgresql', url: 'postgres://localhost/test' },
|
|
19
|
-
}),
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
import { program } from 'commander';
|
|
23
|
-
import { parseKywiConfig } from '@kywi/core';
|
|
24
|
-
import '../commands/migrate-generate.js';
|
|
25
|
-
function fileEndingWith(suffix) {
|
|
26
|
-
return writes.find((w) => w.path.endsWith(suffix));
|
|
27
|
-
}
|
|
28
|
-
describe('migrate:generate command', () => {
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
writes.length = 0;
|
|
31
|
-
vi.clearAllMocks();
|
|
32
|
-
program.exitOverride(); // throw instead of process.exit on any commander error
|
|
33
|
-
});
|
|
34
|
-
it('loads the config and generates schema files via the core generators', async () => {
|
|
35
|
-
await program.parseAsync(['migrate:generate', '--out', 'build/schema'], { from: 'user' });
|
|
36
|
-
// The command loaded the config through the core loader.
|
|
37
|
-
expect(parseKywiConfig).toHaveBeenCalledTimes(1);
|
|
38
|
-
expect(parseKywiConfig.mock.calls[0][0])
|
|
39
|
-
.toMatch(/kywi\.config\.ts$/);
|
|
40
|
-
// One schema file per content type, built by generateContentTypeSchema.
|
|
41
|
-
const blogSchema = fileEndingWith('kywi_ct_blog_post.ts');
|
|
42
|
-
expect(blogSchema).toBeDefined();
|
|
43
|
-
expect(blogSchema.content).toContain("pgTable('kywi_ct_blog_post'");
|
|
44
|
-
expect(blogSchema.content).toContain('excerpt');
|
|
45
|
-
// Barrel index, base re-export, and the drizzle config are all emitted.
|
|
46
|
-
expect(fileEndingWith('schema/index.ts')).toBeDefined();
|
|
47
|
-
expect(fileEndingWith('base.ts')).toBeDefined();
|
|
48
|
-
const drizzle = fileEndingWith('drizzle.config.ts');
|
|
49
|
-
expect(drizzle).toBeDefined();
|
|
50
|
-
expect(drizzle.content.toLowerCase()).toContain('postgres');
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
//# sourceMappingURL=migrate-generate.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-generate.test.js","sourceRoot":"","sources":["../../src/__tests__/migrate-generate.test.ts"],"names":[],"mappings":"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"}
|