@decocms/blocks-cli 7.37.0 → 7.37.2
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/package.json +2 -2
- package/scripts/deco-migrate-cli.ts +1 -2
- package/scripts/generate-blocks.test.ts +0 -65
- package/scripts/generate-blocks.ts +1 -20
- package/scripts/generate-loaders.test.ts +0 -55
- package/scripts/generate-loaders.ts +0 -13
- package/scripts/generate-schema.test.ts +5 -35
- package/scripts/generate-schema.ts +3 -21
- package/scripts/generate-sections.test.ts +1 -40
- package/scripts/generate-sections.ts +0 -13
- package/scripts/migrate/phase-report.ts +3 -4
- package/scripts/migrate/phase-verify.ts +0 -1
- package/scripts/lib/legacyArtifact.ts +0 -64
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/blocks-cli",
|
|
3
|
-
"version": "7.37.
|
|
3
|
+
"version": "7.37.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deco codegen (generate-blocks, generate-schema, generate-invoke) and Fresh-to-TanStack migration tooling",
|
|
6
6
|
"repository": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"lint:unused": "knip"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@decocms/blocks": "7.37.
|
|
34
|
+
"@decocms/blocks": "7.37.2",
|
|
35
35
|
"ts-morph": "^27.0.0",
|
|
36
36
|
"tsx": "^4.22.5"
|
|
37
37
|
},
|
|
@@ -429,8 +429,7 @@ async function main() {
|
|
|
429
429
|
console.log(`\n ${bold("Next steps:")}`);
|
|
430
430
|
console.log(` cd ${outputDir}`);
|
|
431
431
|
console.log(` npm install`);
|
|
432
|
-
console.log(` npm run generate
|
|
433
|
-
console.log(` npm run generate:schema`);
|
|
432
|
+
console.log(` npm run generate`);
|
|
434
433
|
console.log(` npx tsr generate`);
|
|
435
434
|
console.log(` npm run dev`);
|
|
436
435
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as cp from "node:child_process";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
2
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import * as os from "node:os";
|
|
5
3
|
import { tmpdir } from "node:os";
|
|
6
4
|
import path from "node:path";
|
|
7
5
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
@@ -105,66 +103,3 @@ describe("readBlockDelta", () => {
|
|
|
105
103
|
expect(delta).toEqual({});
|
|
106
104
|
});
|
|
107
105
|
});
|
|
108
|
-
|
|
109
|
-
describe("generate-blocks legacy artifact sync", () => {
|
|
110
|
-
let tmpDir: string;
|
|
111
|
-
|
|
112
|
-
beforeEach(() => {
|
|
113
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "generate-blocks-legacy-"));
|
|
114
|
-
// Minimal .deco/blocks/ dir with one block so output is non-empty.
|
|
115
|
-
fs.mkdirSync(path.join(tmpDir, ".deco", "blocks"), { recursive: true });
|
|
116
|
-
fs.writeFileSync(
|
|
117
|
-
path.join(tmpDir, ".deco", "blocks", "pages-Home.json"),
|
|
118
|
-
JSON.stringify({ path: "/" }),
|
|
119
|
-
);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
afterEach(() => {
|
|
123
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("syncs .ts and .json to the old path when legacy file is detected", () => {
|
|
127
|
-
const oldDir = path.join(tmpDir, "src", "server", "cms");
|
|
128
|
-
fs.mkdirSync(oldDir, { recursive: true });
|
|
129
|
-
fs.writeFileSync(path.join(oldDir, "blocks.gen.ts"), "// stale\n");
|
|
130
|
-
|
|
131
|
-
const { code, stderr } = runGenerator([], { cwd: tmpDir });
|
|
132
|
-
expect(code).toBe(0);
|
|
133
|
-
|
|
134
|
-
expect(stderr).toContain("src/server/cms/blocks.gen.ts");
|
|
135
|
-
expect(stderr).toContain(".deco/blocks.gen.ts");
|
|
136
|
-
expect(stderr).toContain("Update importers to use the new path");
|
|
137
|
-
|
|
138
|
-
// New path must exist.
|
|
139
|
-
expect(fs.existsSync(path.join(tmpDir, ".deco", "blocks.gen.ts"))).toBe(true);
|
|
140
|
-
expect(fs.existsSync(path.join(tmpDir, ".deco", "blocks.gen.json"))).toBe(true);
|
|
141
|
-
|
|
142
|
-
// Old .ts must be synced (stub content, not the stale placeholder).
|
|
143
|
-
const oldTs = fs.readFileSync(path.join(oldDir, "blocks.gen.ts"), "utf-8");
|
|
144
|
-
expect(oldTs).not.toBe("// stale\n");
|
|
145
|
-
|
|
146
|
-
// Old .json sibling must be synced — the Vite plugin reads it by suffix.
|
|
147
|
-
const oldJson = path.join(oldDir, "blocks.gen.json");
|
|
148
|
-
expect(fs.existsSync(oldJson)).toBe(true);
|
|
149
|
-
const oldContent = JSON.parse(fs.readFileSync(oldJson, "utf-8"));
|
|
150
|
-
const newContent = JSON.parse(
|
|
151
|
-
fs.readFileSync(path.join(tmpDir, ".deco", "blocks.gen.json"), "utf-8"),
|
|
152
|
-
);
|
|
153
|
-
expect(oldContent).toEqual(newContent);
|
|
154
|
-
}, 30_000);
|
|
155
|
-
|
|
156
|
-
it("does not warn and does not sync when an explicit --out-file is passed", () => {
|
|
157
|
-
const oldDir = path.join(tmpDir, "src", "server", "cms");
|
|
158
|
-
fs.mkdirSync(oldDir, { recursive: true });
|
|
159
|
-
fs.writeFileSync(path.join(oldDir, "blocks.gen.ts"), "// stale\n");
|
|
160
|
-
|
|
161
|
-
const explicitOut = path.join(tmpDir, "custom", "blocks.gen.ts");
|
|
162
|
-
const { code, stderr } = runGenerator(["--out-file", explicitOut], { cwd: tmpDir });
|
|
163
|
-
expect(code).toBe(0);
|
|
164
|
-
|
|
165
|
-
expect(stderr).not.toContain("Generator default output moved");
|
|
166
|
-
expect(fs.existsSync(explicitOut)).toBe(true);
|
|
167
|
-
// Old file must be untouched.
|
|
168
|
-
expect(fs.readFileSync(path.join(oldDir, "blocks.gen.ts"), "utf-8")).toBe("// stale\n");
|
|
169
|
-
}, 30_000);
|
|
170
|
-
});
|
|
@@ -27,10 +27,6 @@
|
|
|
27
27
|
* --out-file by swapping its extension, so passing --out-file
|
|
28
28
|
* moves both artifacts together)
|
|
29
29
|
*
|
|
30
|
-
* If no `--out-file` is passed and the OLD default (src/server/cms/blocks.gen.ts)
|
|
31
|
-
* still exists on disk, a one-line legacy warning is printed to stderr and the
|
|
32
|
-
* NEW default is written anyway — see lib/legacyArtifact.ts.
|
|
33
|
-
*
|
|
34
30
|
* Programmatic:
|
|
35
31
|
* import { generateBlocks } from "@decocms/blocks-cli/generate-blocks";
|
|
36
32
|
* await generateBlocks({ blocksDir, outFile });
|
|
@@ -49,7 +45,6 @@ import {
|
|
|
49
45
|
singleDecodeBlockName,
|
|
50
46
|
} from "./lib/blocks-dedupe";
|
|
51
47
|
import { buildCsvRedirectBlocks } from "./lib/csv-redirects";
|
|
52
|
-
import { syncLegacyArtifact, warnLegacyArtifact } from "./lib/legacyArtifact";
|
|
53
48
|
|
|
54
49
|
const TS_STUB = [
|
|
55
50
|
"// Auto-generated — thin wrapper around blocks.gen.json.",
|
|
@@ -321,24 +316,10 @@ if (isMainModule()) {
|
|
|
321
316
|
};
|
|
322
317
|
|
|
323
318
|
const blocksDir = path.resolve(process.cwd(), arg("blocks-dir", ".deco/blocks"));
|
|
324
|
-
const OUT_FILE_EXPLICIT = args.includes("--out-file");
|
|
325
319
|
const NEW_DEFAULT_OUT_FILE = ".deco/blocks.gen.ts";
|
|
326
|
-
const OLD_DEFAULT_OUT_FILE = "src/server/cms/blocks.gen.ts";
|
|
327
320
|
const outFile = path.resolve(process.cwd(), arg("out-file", NEW_DEFAULT_OUT_FILE));
|
|
328
|
-
const oldFilePath = path.resolve(process.cwd(), OLD_DEFAULT_OUT_FILE);
|
|
329
|
-
const hasLegacy = !OUT_FILE_EXPLICIT && fs.existsSync(oldFilePath);
|
|
330
|
-
if (hasLegacy) {
|
|
331
|
-
warnLegacyArtifact(OLD_DEFAULT_OUT_FILE, NEW_DEFAULT_OUT_FILE);
|
|
332
|
-
}
|
|
333
321
|
|
|
334
|
-
generateBlocks({ blocksDir, outFile }).
|
|
335
|
-
if (hasLegacy) {
|
|
336
|
-
syncLegacyArtifact(oldFilePath, result.outFile);
|
|
337
|
-
// The .ts is a Vite stub — the plugin reads the .json sibling by suffix.
|
|
338
|
-
// Sync the JSON too so the Vite interceptor at the old path finds it.
|
|
339
|
-
syncLegacyArtifact(oldFilePath.replace(/\.ts$/, ".json"), result.jsonFile);
|
|
340
|
-
}
|
|
341
|
-
}).catch((err) => {
|
|
322
|
+
generateBlocks({ blocksDir, outFile }).catch((err) => {
|
|
342
323
|
console.error(err);
|
|
343
324
|
process.exit(1);
|
|
344
325
|
});
|
|
@@ -62,58 +62,3 @@ describe("generate-loaders — loader vs action emit", () => {
|
|
|
62
62
|
expect(out).not.toContain('createLoaderEntry("site/actions/addToCart"');
|
|
63
63
|
});
|
|
64
64
|
});
|
|
65
|
-
|
|
66
|
-
describe("generate-loaders legacy artifact sync", () => {
|
|
67
|
-
let tmpDir: string;
|
|
68
|
-
|
|
69
|
-
beforeEach(() => {
|
|
70
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "generate-loaders-legacy-"));
|
|
71
|
-
const write = (rel: string, content: string) => {
|
|
72
|
-
const abs = path.join(tmpDir, rel);
|
|
73
|
-
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
74
|
-
fs.writeFileSync(abs, content);
|
|
75
|
-
};
|
|
76
|
-
write("src/loaders/related.ts", "export default async () => [];\n");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
afterEach(() => {
|
|
80
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("syncs to the old path when legacy file is detected", () => {
|
|
84
|
-
const oldDir = path.join(tmpDir, "src", "server", "cms");
|
|
85
|
-
fs.mkdirSync(oldDir, { recursive: true });
|
|
86
|
-
fs.writeFileSync(path.join(oldDir, "loaders.gen.ts"), "// stale\n");
|
|
87
|
-
|
|
88
|
-
const { code, stderr } = run(tmpDir);
|
|
89
|
-
expect(code).toBe(0);
|
|
90
|
-
|
|
91
|
-
expect(stderr).toContain("src/server/cms/loaders.gen.ts");
|
|
92
|
-
expect(stderr).toContain(".deco/loaders.gen.ts");
|
|
93
|
-
expect(stderr).toContain("Update importers to use the new path");
|
|
94
|
-
|
|
95
|
-
// New path must exist.
|
|
96
|
-
expect(fs.existsSync(path.join(tmpDir, ".deco", "loaders.gen.ts"))).toBe(true);
|
|
97
|
-
|
|
98
|
-
// Old file must be synced as a re-export shim (not the stale placeholder,
|
|
99
|
-
// and not a verbatim copy — a byte copy would carry `.deco/`-relative
|
|
100
|
-
// import paths that break at the deeper legacy location).
|
|
101
|
-
const oldContent = fs.readFileSync(path.join(oldDir, "loaders.gen.ts"), "utf-8");
|
|
102
|
-
expect(oldContent).not.toBe("// stale\n");
|
|
103
|
-
expect(oldContent).toContain('export * from "../../../.deco/loaders.gen"');
|
|
104
|
-
}, 30_000);
|
|
105
|
-
|
|
106
|
-
it("does not warn and does not sync when an explicit --out-file is passed", () => {
|
|
107
|
-
const oldDir = path.join(tmpDir, "src", "server", "cms");
|
|
108
|
-
fs.mkdirSync(oldDir, { recursive: true });
|
|
109
|
-
fs.writeFileSync(path.join(oldDir, "loaders.gen.ts"), "// stale\n");
|
|
110
|
-
|
|
111
|
-
const explicitOut = path.join(tmpDir, "custom", "loaders.gen.ts");
|
|
112
|
-
const { code, stderr } = run(tmpDir, ["--out-file", explicitOut]);
|
|
113
|
-
expect(code).toBe(0);
|
|
114
|
-
|
|
115
|
-
expect(stderr).not.toContain("Generator default output moved");
|
|
116
|
-
expect(fs.existsSync(explicitOut)).toBe(true);
|
|
117
|
-
expect(fs.readFileSync(path.join(oldDir, "loaders.gen.ts"), "utf-8")).toBe("// stale\n");
|
|
118
|
-
}, 30_000);
|
|
119
|
-
});
|
|
@@ -43,14 +43,9 @@
|
|
|
43
43
|
* --exclude comma-separated list of loader keys to skip (they have custom wiring)
|
|
44
44
|
* --prune-by-decofile only emit entries whose key appears as `__resolveType` in any JSON
|
|
45
45
|
* --decofile-dir @deprecated alias for --prune-by-decofile
|
|
46
|
-
*
|
|
47
|
-
* If no `--out-file` is passed and the OLD default (src/server/cms/loaders.gen.ts)
|
|
48
|
-
* still exists on disk, a one-line legacy warning is printed to stderr and the
|
|
49
|
-
* NEW default is written anyway — see lib/legacyArtifact.ts.
|
|
50
46
|
*/
|
|
51
47
|
import fs from "node:fs";
|
|
52
48
|
import path from "node:path";
|
|
53
|
-
import { syncLegacyArtifact, warnLegacyArtifact } from "./lib/legacyArtifact";
|
|
54
49
|
|
|
55
50
|
const args = process.argv.slice(2);
|
|
56
51
|
function arg(name: string, fallback: string): string {
|
|
@@ -60,15 +55,8 @@ function arg(name: string, fallback: string): string {
|
|
|
60
55
|
|
|
61
56
|
const loadersDir = path.resolve(process.cwd(), arg("loaders-dir", "src/loaders"));
|
|
62
57
|
const actionsDir = path.resolve(process.cwd(), arg("actions-dir", "src/actions"));
|
|
63
|
-
const OUT_FILE_EXPLICIT = args.includes("--out-file");
|
|
64
58
|
const NEW_DEFAULT_OUT_FILE = ".deco/loaders.gen.ts";
|
|
65
|
-
const OLD_DEFAULT_OUT_FILE = "src/server/cms/loaders.gen.ts";
|
|
66
59
|
const outFile = path.resolve(process.cwd(), arg("out-file", NEW_DEFAULT_OUT_FILE));
|
|
67
|
-
const oldLoadersPath = path.resolve(process.cwd(), OLD_DEFAULT_OUT_FILE);
|
|
68
|
-
const hasLegacy = !OUT_FILE_EXPLICIT && fs.existsSync(oldLoadersPath);
|
|
69
|
-
if (hasLegacy) {
|
|
70
|
-
warnLegacyArtifact(OLD_DEFAULT_OUT_FILE, NEW_DEFAULT_OUT_FILE);
|
|
71
|
-
}
|
|
72
60
|
const excludeRaw = arg("exclude", "");
|
|
73
61
|
const excludeSet = new Set(excludeRaw.split(",").map((s) => s.trim()).filter(Boolean));
|
|
74
62
|
|
|
@@ -256,7 +244,6 @@ lines.push("");
|
|
|
256
244
|
|
|
257
245
|
fs.mkdirSync(path.dirname(outFile), { recursive: true });
|
|
258
246
|
fs.writeFileSync(outFile, lines.join("\n"));
|
|
259
|
-
if (hasLegacy) syncLegacyArtifact(oldLoadersPath, outFile);
|
|
260
247
|
|
|
261
248
|
const filterNote = cmsReferences
|
|
262
249
|
? ` (filtered against ${cmsReferences.size} CMS __resolveType references; pruned ${prunedCount} dead entries)`
|
|
@@ -252,10 +252,10 @@ describe("typeToJsonSchema loader block-ref matching", () => {
|
|
|
252
252
|
});
|
|
253
253
|
|
|
254
254
|
// ---------------------------------------------------------------------------
|
|
255
|
-
// Default output path (.deco/)
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
255
|
+
// Default output path (.deco/) — subprocess, mirrors the pattern in
|
|
256
|
+
// generate-sections.test.ts. generate-schema.ts IS guarded by isMainModule(),
|
|
257
|
+
// but it's still driven as a subprocess here so the CLI's argv-parsed OUT_REL
|
|
258
|
+
// top-level code runs against a real cwd.
|
|
259
259
|
// ---------------------------------------------------------------------------
|
|
260
260
|
|
|
261
261
|
const SCRIPT = path.resolve(__dirname, "generate-schema.ts");
|
|
@@ -313,39 +313,9 @@ describe("generate-schema default output path (.deco/)", () => {
|
|
|
313
313
|
expect(meta.manifest.blocks.sections).toHaveProperty("site/sections/Hero.tsx");
|
|
314
314
|
}, 30_000);
|
|
315
315
|
|
|
316
|
-
it("
|
|
317
|
-
const oldDefaultDir = path.join(tmpDir, "src", "server", "admin");
|
|
318
|
-
fs.mkdirSync(oldDefaultDir, { recursive: true });
|
|
319
|
-
fs.writeFileSync(path.join(oldDefaultDir, "meta.gen.json"), "{}");
|
|
320
|
-
|
|
316
|
+
it("does not warn about a legacy default path", () => {
|
|
321
317
|
const { code, stderr } = runGenerator(["--skip-apps"], { cwd: tmpDir });
|
|
322
318
|
expect(code).toBe(0);
|
|
323
|
-
|
|
324
|
-
expect(stderr).toContain("src/server/admin/meta.gen.json");
|
|
325
|
-
expect(stderr).toContain(".deco/meta.gen.json");
|
|
326
|
-
expect(stderr).toContain("Update importers to use the new path");
|
|
327
|
-
|
|
328
|
-
const newDefault = path.join(tmpDir, ".deco", "meta.gen.json");
|
|
329
|
-
expect(fs.existsSync(newDefault)).toBe(true);
|
|
330
|
-
|
|
331
|
-
// Old file must be kept in sync so mid-migration imports still work.
|
|
332
|
-
const oldDefault = path.join(tmpDir, "src", "server", "admin", "meta.gen.json");
|
|
333
|
-
expect(fs.existsSync(oldDefault)).toBe(true);
|
|
334
|
-
const oldContent = JSON.parse(fs.readFileSync(oldDefault, "utf-8"));
|
|
335
|
-
const newContent = JSON.parse(fs.readFileSync(newDefault, "utf-8"));
|
|
336
|
-
expect(oldContent).toEqual(newContent);
|
|
337
|
-
}, 30_000);
|
|
338
|
-
|
|
339
|
-
it("does not warn when an explicit --out is passed, even if the OLD default file exists", () => {
|
|
340
|
-
const oldDefaultDir = path.join(tmpDir, "src", "server", "admin");
|
|
341
|
-
fs.mkdirSync(oldDefaultDir, { recursive: true });
|
|
342
|
-
fs.writeFileSync(path.join(oldDefaultDir, "meta.gen.json"), "{}");
|
|
343
|
-
|
|
344
|
-
const explicitOut = path.join(tmpDir, "custom", "meta.gen.json");
|
|
345
|
-
const { code, stderr } = runGenerator(["--skip-apps", "--out", explicitOut], { cwd: tmpDir });
|
|
346
|
-
expect(code).toBe(0);
|
|
347
|
-
|
|
348
319
|
expect(stderr).not.toContain("Generator default output moved");
|
|
349
|
-
expect(fs.existsSync(explicitOut)).toBe(true);
|
|
350
320
|
}, 30_000);
|
|
351
321
|
});
|
|
@@ -33,10 +33,6 @@ import { fileURLToPath } from "node:url";
|
|
|
33
33
|
* from disk with no runtime (FS-based Studio / Eitri stack).
|
|
34
34
|
* --framework With --compose, the value written to the `framework` field
|
|
35
35
|
* (default: "tanstack-start").
|
|
36
|
-
*
|
|
37
|
-
* If no `--out` is passed and the OLD default (src/server/admin/meta.gen.json)
|
|
38
|
-
* still exists on disk, a one-line legacy warning is printed to stderr and the
|
|
39
|
-
* NEW default is written anyway — see lib/legacyArtifact.ts.
|
|
40
36
|
*/
|
|
41
37
|
import {
|
|
42
38
|
type Symbol as MorphSymbol,
|
|
@@ -47,7 +43,6 @@ import {
|
|
|
47
43
|
type Type,
|
|
48
44
|
} from "ts-morph";
|
|
49
45
|
import { isExcludedCodegenFile } from "./lib/codegenExclusions";
|
|
50
|
-
import { syncLegacyArtifact, warnLegacyArtifact } from "./lib/legacyArtifact";
|
|
51
46
|
|
|
52
47
|
// ---------------------------------------------------------------------------
|
|
53
48
|
// CLI arg parsing
|
|
@@ -56,12 +51,9 @@ import { syncLegacyArtifact, warnLegacyArtifact } from "./lib/legacyArtifact";
|
|
|
56
51
|
// here) so that importing this module for its pure exports
|
|
57
52
|
// (definitionIdForPath, applyWidgetFormat, typeToJsonSchema — see
|
|
58
53
|
// generate-schema.test.ts) never reads argv or touches the filesystem.
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
// the test actually wanted to exercise. generateMeta() (below) and the
|
|
63
|
-
// final write are themselves only reached inside `if (isMainModule())`, so
|
|
64
|
-
// these vars only need real values in that same case.
|
|
54
|
+
// generateMeta() (below) and the final write are themselves only reached
|
|
55
|
+
// inside `if (isMainModule())`, so these vars only need real values in that
|
|
56
|
+
// same case.
|
|
65
57
|
// ---------------------------------------------------------------------------
|
|
66
58
|
const argv = process.argv.slice(2);
|
|
67
59
|
function arg(name: string, fallback: string): string {
|
|
@@ -70,7 +62,6 @@ function arg(name: string, fallback: string): string {
|
|
|
70
62
|
}
|
|
71
63
|
|
|
72
64
|
const NEW_DEFAULT_OUT_REL = ".deco/meta.gen.json";
|
|
73
|
-
const OLD_DEFAULT_OUT_REL = "src/server/admin/meta.gen.json";
|
|
74
65
|
|
|
75
66
|
let SITE_NAMESPACE = "site";
|
|
76
67
|
let SITE_NAME = "storefront";
|
|
@@ -90,8 +81,6 @@ let COMPOSE = false;
|
|
|
90
81
|
// Value written to the composed meta's `framework` field (only used with
|
|
91
82
|
// --compose). Defaults to composeMeta's historical "tanstack-start".
|
|
92
83
|
let FRAMEWORK = "tanstack-start";
|
|
93
|
-
let _hasLegacySchema = false;
|
|
94
|
-
let _oldSchemaPath = "";
|
|
95
84
|
|
|
96
85
|
if (isMainModule()) {
|
|
97
86
|
SITE_NAMESPACE = arg("namespace", SITE_NAMESPACE);
|
|
@@ -101,16 +90,10 @@ if (isMainModule()) {
|
|
|
101
90
|
LOADERS_REL = arg("loaders", LOADERS_REL);
|
|
102
91
|
APPS_REL = arg("apps", APPS_REL);
|
|
103
92
|
SKIP_APPS = argv.includes("--skip-apps");
|
|
104
|
-
const outFileExplicit = argv.includes("--out");
|
|
105
93
|
OUT_REL = arg("out", NEW_DEFAULT_OUT_REL);
|
|
106
94
|
PLATFORM = arg("platform", PLATFORM);
|
|
107
95
|
COMPOSE = argv.includes("--compose");
|
|
108
96
|
FRAMEWORK = arg("framework", FRAMEWORK);
|
|
109
|
-
_oldSchemaPath = path.resolve(process.cwd(), OLD_DEFAULT_OUT_REL);
|
|
110
|
-
_hasLegacySchema = !outFileExplicit && fs.existsSync(_oldSchemaPath);
|
|
111
|
-
if (_hasLegacySchema) {
|
|
112
|
-
warnLegacyArtifact(OLD_DEFAULT_OUT_REL, NEW_DEFAULT_OUT_REL);
|
|
113
|
-
}
|
|
114
97
|
}
|
|
115
98
|
|
|
116
99
|
// ---------------------------------------------------------------------------
|
|
@@ -1541,7 +1524,6 @@ if (isMainModule()) {
|
|
|
1541
1524
|
const outPath = path.resolve(process.cwd(), OUT_REL);
|
|
1542
1525
|
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
1543
1526
|
fs.writeFileSync(outPath, JSON.stringify(meta, null, 2));
|
|
1544
|
-
if (_hasLegacySchema) syncLegacyArtifact(_oldSchemaPath, outPath);
|
|
1545
1527
|
|
|
1546
1528
|
const defCount = Object.keys(meta.schema.definitions).length;
|
|
1547
1529
|
const secCount = Object.keys(meta.manifest.blocks.sections || {}).length;
|
|
@@ -115,48 +115,9 @@ describe("generate-sections default output path (.deco/)", () => {
|
|
|
115
115
|
const newDefault = path.join(tmpDir, ".deco", "sections.gen.ts");
|
|
116
116
|
expect(fs.existsSync(newDefault)).toBe(true);
|
|
117
117
|
expect(fs.readFileSync(newDefault, "utf-8")).toContain("site/sections/Hero.tsx");
|
|
118
|
-
// No legacy
|
|
118
|
+
// No legacy default path is written anymore, so no warning is expected.
|
|
119
119
|
expect(stderr).not.toContain("Generator default output moved");
|
|
120
120
|
}, 30_000);
|
|
121
|
-
|
|
122
|
-
it("warns once to stderr naming both paths when the OLD default file exists and no --out-file is passed, but still writes the NEW default", () => {
|
|
123
|
-
const oldDefaultDir = path.join(tmpDir, "src", "server", "cms");
|
|
124
|
-
fs.mkdirSync(oldDefaultDir, { recursive: true });
|
|
125
|
-
fs.writeFileSync(path.join(oldDefaultDir, "sections.gen.ts"), "// stale\n");
|
|
126
|
-
|
|
127
|
-
const { code, stderr } = runGenerator([], { cwd: tmpDir });
|
|
128
|
-
expect(code).toBe(0);
|
|
129
|
-
|
|
130
|
-
expect(stderr).toContain("src/server/cms/sections.gen.ts");
|
|
131
|
-
expect(stderr).toContain(".deco/sections.gen.ts");
|
|
132
|
-
expect(stderr).toContain("Update importers to use the new path");
|
|
133
|
-
|
|
134
|
-
const newDefault = path.join(tmpDir, ".deco", "sections.gen.ts");
|
|
135
|
-
expect(fs.existsSync(newDefault)).toBe(true);
|
|
136
|
-
expect(fs.readFileSync(newDefault, "utf-8")).toContain("site/sections/Hero.tsx");
|
|
137
|
-
|
|
138
|
-
// Old file is kept in sync as a re-export shim (NOT a verbatim copy — a
|
|
139
|
-
// byte copy would carry `.deco/`-relative import paths that break at the
|
|
140
|
-
// deeper legacy location). It re-exports the new file so mid-migration
|
|
141
|
-
// imports still resolve at any depth.
|
|
142
|
-
const oldDefault = path.join(tmpDir, "src", "server", "cms", "sections.gen.ts");
|
|
143
|
-
const oldContent = fs.readFileSync(oldDefault, "utf-8");
|
|
144
|
-
expect(oldContent).toContain('export * from "../../../.deco/sections.gen"');
|
|
145
|
-
expect(oldContent).not.toContain("site/sections/Hero.tsx");
|
|
146
|
-
}, 30_000);
|
|
147
|
-
|
|
148
|
-
it("does not warn when an explicit --out-file is passed, even if the OLD default file exists", () => {
|
|
149
|
-
const oldDefaultDir = path.join(tmpDir, "src", "server", "cms");
|
|
150
|
-
fs.mkdirSync(oldDefaultDir, { recursive: true });
|
|
151
|
-
fs.writeFileSync(path.join(oldDefaultDir, "sections.gen.ts"), "// stale\n");
|
|
152
|
-
|
|
153
|
-
const explicitOut = path.join(tmpDir, "custom", "sections.gen.ts");
|
|
154
|
-
const { code, stderr } = runGenerator(["--out-file", explicitOut], { cwd: tmpDir });
|
|
155
|
-
expect(code).toBe(0);
|
|
156
|
-
|
|
157
|
-
expect(stderr).not.toContain("Generator default output moved");
|
|
158
|
-
expect(fs.existsSync(explicitOut)).toBe(true);
|
|
159
|
-
}, 30_000);
|
|
160
121
|
});
|
|
161
122
|
|
|
162
123
|
describe("generate-sections --registry", () => {
|
|
@@ -28,15 +28,10 @@
|
|
|
28
28
|
* Built from every scanned section file, not just the ones
|
|
29
29
|
* carrying convention exports. Off by default so existing
|
|
30
30
|
* Vite sites regenerating sections.gen.ts in CI see zero diff.
|
|
31
|
-
*
|
|
32
|
-
* If no `--out-file` is passed and the OLD default (src/server/cms/sections.gen.ts)
|
|
33
|
-
* still exists on disk, a one-line legacy warning is printed to stderr and the
|
|
34
|
-
* NEW default is written anyway — see lib/legacyArtifact.ts.
|
|
35
31
|
*/
|
|
36
32
|
import fs from "node:fs";
|
|
37
33
|
import path from "node:path";
|
|
38
34
|
import { isExcludedCodegenFile } from "./lib/codegenExclusions";
|
|
39
|
-
import { syncLegacyArtifact, warnLegacyArtifact } from "./lib/legacyArtifact";
|
|
40
35
|
|
|
41
36
|
const args = process.argv.slice(2);
|
|
42
37
|
function arg(name: string, fallback: string): string {
|
|
@@ -45,15 +40,8 @@ function arg(name: string, fallback: string): string {
|
|
|
45
40
|
}
|
|
46
41
|
|
|
47
42
|
const sectionsDir = path.resolve(process.cwd(), arg("sections-dir", "src/sections"));
|
|
48
|
-
const OUT_FILE_EXPLICIT = args.includes("--out-file");
|
|
49
43
|
const NEW_DEFAULT_OUT_FILE = ".deco/sections.gen.ts";
|
|
50
|
-
const OLD_DEFAULT_OUT_FILE = "src/server/cms/sections.gen.ts";
|
|
51
44
|
const outFile = path.resolve(process.cwd(), arg("out-file", NEW_DEFAULT_OUT_FILE));
|
|
52
|
-
const oldSectionsPath = path.resolve(process.cwd(), OLD_DEFAULT_OUT_FILE);
|
|
53
|
-
const hasLegacy = !OUT_FILE_EXPLICIT && fs.existsSync(oldSectionsPath);
|
|
54
|
-
if (hasLegacy) {
|
|
55
|
-
warnLegacyArtifact(OLD_DEFAULT_OUT_FILE, NEW_DEFAULT_OUT_FILE);
|
|
56
|
-
}
|
|
57
45
|
const EMIT_REGISTRY = args.includes("--registry");
|
|
58
46
|
|
|
59
47
|
interface SectionMeta {
|
|
@@ -295,7 +283,6 @@ fs.writeFileSync(
|
|
|
295
283
|
outFile,
|
|
296
284
|
lines.join("\n").replace(/\n{3,}/g, "\n\n").replace(/\n*$/, "\n"),
|
|
297
285
|
);
|
|
298
|
-
if (hasLegacy) syncLegacyArtifact(oldSectionsPath, outFile);
|
|
299
286
|
|
|
300
287
|
console.log(
|
|
301
288
|
`Generated section metadata for ${entries.length} sections → ${path.relative(process.cwd(), outFile)}`,
|
|
@@ -199,7 +199,7 @@ export function report(ctx: MigrationContext): void {
|
|
|
199
199
|
lines.push("- [ ] `src/hooks/useCart.ts` — wire to actual server functions for your platform");
|
|
200
200
|
lines.push("- [ ] `src/worker-entry.ts` — verify CSP, proxy, and segment builder");
|
|
201
201
|
lines.push("- [ ] See the **CSS Migration** section above for DaisyUI v4→v5 / Tailwind v3→v4 findings specific to this site");
|
|
202
|
-
lines.push("- [ ] Run `npm run generate:blocks
|
|
202
|
+
lines.push("- [ ] Run `npm run generate` (unified: blocks, sections, loaders, schema) after migration");
|
|
203
203
|
lines.push("");
|
|
204
204
|
|
|
205
205
|
// Known Issues
|
|
@@ -250,9 +250,8 @@ export function report(ctx: MigrationContext): void {
|
|
|
250
250
|
lines.push("# 1. Install dependencies (bun is the canonical PM)");
|
|
251
251
|
lines.push("bun install");
|
|
252
252
|
lines.push("");
|
|
253
|
-
lines.push("# 2. Generate CMS blocks
|
|
254
|
-
lines.push("bun run generate
|
|
255
|
-
lines.push("bun run generate:schema");
|
|
253
|
+
lines.push("# 2. Generate CMS artifacts (blocks, sections, loaders, schema)");
|
|
254
|
+
lines.push("bun run generate");
|
|
256
255
|
lines.push("");
|
|
257
256
|
lines.push("# 3. Generate routes");
|
|
258
257
|
lines.push("bunx tsr generate");
|
|
@@ -20,7 +20,6 @@ const REQUIRED_FILES = [
|
|
|
20
20
|
// Deploy / preview / sync-secrets pipelines are owned by Cloudflare
|
|
21
21
|
// Workers Builds (D6.3) -- configured in the CF dashboard, not via
|
|
22
22
|
// GitHub workflow files in the site repo.
|
|
23
|
-
".github/workflows/regen-blocks.yml",
|
|
24
23
|
".github/workflows/lockfile-check.yml",
|
|
25
24
|
"knip.config.ts",
|
|
26
25
|
".prettierrc",
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generator default output paths flipped from `src/server/{cms,admin}/` to
|
|
6
|
-
* `.deco/` (framework artifacts live in the framework's folder, not mixed
|
|
7
|
-
* into app source). Sites that never pass an explicit `--out`/`--out-file`
|
|
8
|
-
* flag pick up the new default silently — except when the OLD default file
|
|
9
|
-
* is still sitting on disk, which almost always means something (an
|
|
10
|
-
* importer, a `.gitignore` entry, a stale CI cache check) still points at
|
|
11
|
-
* it. In that case we warn once, to stderr, and then write to the NEW
|
|
12
|
-
* default anyway: the artifact is regenerated code, so there's no reason to
|
|
13
|
-
* block the run — the warning is just a nudge to go clean up the stale file
|
|
14
|
-
* and its importers.
|
|
15
|
-
*
|
|
16
|
-
* An explicit flag means the caller made a deliberate choice about where
|
|
17
|
-
* output goes; it gets no warning and no guard.
|
|
18
|
-
*/
|
|
19
|
-
export function warnLegacyArtifact(oldPath: string, newPath: string): void {
|
|
20
|
-
console.warn(
|
|
21
|
-
`[deco] Generator default output moved: ${oldPath} -> ${newPath}. Update importers to use the new path, then delete the old file.`,
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Keeps the legacy `oldPath` in sync with the freshly-generated `newPath` so
|
|
27
|
-
* sites mid-migration whose imports still point at the old location keep
|
|
28
|
-
* working without a full migration first. Call this after generation
|
|
29
|
-
* completes, only when the old file was detected.
|
|
30
|
-
*
|
|
31
|
-
* For `.ts`/`.tsx` artifacts a verbatim copy would be broken: the generated
|
|
32
|
-
* file's import specifiers are relative to `newPath`'s directory (`.deco/`,
|
|
33
|
-
* one level deep), but `oldPath` lives deeper (`src/server/cms/`), so every
|
|
34
|
-
* `../src/...` specifier would resolve to a nonexistent path and crash the
|
|
35
|
-
* dev server on boot. Instead we write a re-export shim pointing at `newPath`
|
|
36
|
-
* — one specifier, correct at any depth, and self-documenting the deprecation.
|
|
37
|
-
* The generated `.gen.ts` files only have named exports, so `export *` forwards
|
|
38
|
-
* everything (including type exports). Non-TS artifacts (e.g. `.json` schema)
|
|
39
|
-
* have no import paths, so a byte copy is still correct.
|
|
40
|
-
*/
|
|
41
|
-
export function syncLegacyArtifact(oldPath: string, newPath: string): void {
|
|
42
|
-
fs.mkdirSync(path.dirname(oldPath), { recursive: true });
|
|
43
|
-
|
|
44
|
-
if (!/\.tsx?$/.test(oldPath)) {
|
|
45
|
-
fs.copyFileSync(newPath, oldPath);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const newRel = path.relative(process.cwd(), newPath).replace(/\\/g, "/");
|
|
50
|
-
let specifier = path
|
|
51
|
-
.relative(path.dirname(oldPath), newPath)
|
|
52
|
-
.replace(/\\/g, "/")
|
|
53
|
-
.replace(/\.tsx?$/, "");
|
|
54
|
-
if (!specifier.startsWith(".")) specifier = `./${specifier}`;
|
|
55
|
-
|
|
56
|
-
fs.writeFileSync(
|
|
57
|
-
oldPath,
|
|
58
|
-
`// AUTO-GENERATED — DO NOT EDIT.\n` +
|
|
59
|
-
`// Deprecated path: the generator now writes to "${newRel}".\n` +
|
|
60
|
-
`// This file only re-exports it so mid-migration imports keep working.\n` +
|
|
61
|
-
`// Update your imports to the new path, then delete this file.\n` +
|
|
62
|
-
`export * from "${specifier}";\n`,
|
|
63
|
-
);
|
|
64
|
-
}
|