wp-typia 0.24.4 → 0.24.6
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/README.md +8 -6
- package/bin/wp-typia.js +24 -103
- package/{dist-bunli/node-cli.js → dist/cli.js} +5086 -3693
- package/package.json +9 -36
- package/bin/routing-metadata.generated.d.ts +0 -8
- package/bin/routing-metadata.generated.js +0 -93
- package/bin/runtime-routing.d.ts +0 -34
- package/bin/runtime-routing.js +0 -124
- package/dist-bunli/.bunli/commands.gen.js +0 -304441
- package/dist-bunli/.bunli/highlights-eq9cgrbb.scm +0 -604
- package/dist-bunli/.bunli/highlights-ghv9g403.scm +0 -205
- package/dist-bunli/.bunli/highlights-hk7bwhj4.scm +0 -284
- package/dist-bunli/.bunli/highlights-r812a2qc.scm +0 -150
- package/dist-bunli/.bunli/highlights-x6tmsnaa.scm +0 -115
- package/dist-bunli/.bunli/injections-73j83es3.scm +0 -27
- package/dist-bunli/.bunli/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
- package/dist-bunli/.bunli/tree-sitter-markdown-411r6y9b.wasm +0 -0
- package/dist-bunli/.bunli/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
- package/dist-bunli/.bunli/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/dist-bunli/.bunli/tree-sitter-zig-e78zbjpm.wasm +0 -0
- package/dist-bunli/agents-91fpdyyt.js +0 -12
- package/dist-bunli/chunk-bdqvmfwv-f5qmzmxg.js +0 -16825
- package/dist-bunli/cli-03j0axbt.js +0 -163
- package/dist-bunli/cli-1170yyve.js +0 -106
- package/dist-bunli/cli-368d4cgy.js +0 -1235
- package/dist-bunli/cli-377p86mf.js +0 -191
- package/dist-bunli/cli-6v0pcxw6.js +0 -314
- package/dist-bunli/cli-84c7wff4.js +0 -198
- package/dist-bunli/cli-8hxf9qw6.js +0 -198
- package/dist-bunli/cli-9fx0qgb7.js +0 -3680
- package/dist-bunli/cli-ac2ebaf8.js +0 -3
- package/dist-bunli/cli-add-qjd3ba8j.js +0 -10671
- package/dist-bunli/cli-am5x7tb4.js +0 -192
- package/dist-bunli/cli-bajwv85z.js +0 -24
- package/dist-bunli/cli-ccax7s0s.js +0 -34
- package/dist-bunli/cli-cvxvcw7c.js +0 -46
- package/dist-bunli/cli-diagnostics-10drxh34.js +0 -34
- package/dist-bunli/cli-doctor-6fyxq940.js +0 -1446
- package/dist-bunli/cli-e4bwd81c.js +0 -1260
- package/dist-bunli/cli-fv4h3ydt.js +0 -173823
- package/dist-bunli/cli-hv2yedw2.js +0 -74591
- package/dist-bunli/cli-init-7avk42dh.js +0 -880
- package/dist-bunli/cli-kfm9mm68.js +0 -14679
- package/dist-bunli/cli-prompt-ncyg68rn.js +0 -12
- package/dist-bunli/cli-rdcga1bd.js +0 -135
- package/dist-bunli/cli-scaffold-0bb6pr3w.js +0 -538
- package/dist-bunli/cli-t73q5aqz.js +0 -103
- package/dist-bunli/cli-templates-g8t4fm11.js +0 -167
- package/dist-bunli/cli-tj7ajdvf.js +0 -2612
- package/dist-bunli/cli-tq730sqt.js +0 -344
- package/dist-bunli/cli-xnn9xjcy.js +0 -68
- package/dist-bunli/cli-z48frc8t.js +0 -229
- package/dist-bunli/cli.js +0 -2523
- package/dist-bunli/command-list-y3g7e9rb.js +0 -4013
- package/dist-bunli/create-template-validation-4fr851vg.js +0 -16
- package/dist-bunli/migrations-3vngdy51.js +0 -47
- package/dist-bunli/sync-k2k8svyc.js +0 -13
- package/dist-bunli/workspace-project-gmv2a71z.js +0 -22
|
@@ -1,1260 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
formatRunScript,
|
|
4
|
-
inferPackageManagerId,
|
|
5
|
-
parsePackageManagerField
|
|
6
|
-
} from "./cli-am5x7tb4.js";
|
|
7
|
-
import {
|
|
8
|
-
readJsonFileSync
|
|
9
|
-
} from "./cli-ccax7s0s.js";
|
|
10
|
-
|
|
11
|
-
// ../wp-typia-project-tools/src/runtime/migration-utils.ts
|
|
12
|
-
import fs from "fs";
|
|
13
|
-
import path from "path";
|
|
14
|
-
import { execSync } from "child_process";
|
|
15
|
-
|
|
16
|
-
// ../wp-typia-project-tools/src/runtime/object-utils.ts
|
|
17
|
-
import { isPlainObject as isSharedPlainObject } from "@wp-typia/api-client/runtime-primitives";
|
|
18
|
-
function isPlainObject(value) {
|
|
19
|
-
return isSharedPlainObject(value);
|
|
20
|
-
}
|
|
21
|
-
function toStableJsonValue(value) {
|
|
22
|
-
if (Array.isArray(value)) {
|
|
23
|
-
return value.map((entry) => toStableJsonValue(entry));
|
|
24
|
-
}
|
|
25
|
-
if (isPlainObject(value)) {
|
|
26
|
-
return Object.fromEntries(Object.keys(value).sort((left, right) => left < right ? -1 : left > right ? 1 : 0).map((key) => [key, toStableJsonValue(value[key])]));
|
|
27
|
-
}
|
|
28
|
-
return value;
|
|
29
|
-
}
|
|
30
|
-
function stableJsonStringify(value) {
|
|
31
|
-
return JSON.stringify(toStableJsonValue(value));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ../wp-typia-project-tools/src/runtime/migration-utils.ts
|
|
35
|
-
var MIGRATION_VERSION_LABEL_PATTERN = /^v([1-9]\d*)$/;
|
|
36
|
-
var LEGACY_SEMVER_MIGRATION_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
37
|
-
function getValueAtPath(input, pathLabel) {
|
|
38
|
-
return String(pathLabel).split(".").reduce((value, segment) => isPlainObject(value) ? value[segment] : undefined, input);
|
|
39
|
-
}
|
|
40
|
-
function setValueAtPath(input, pathLabel, value) {
|
|
41
|
-
const segments = String(pathLabel).split(".");
|
|
42
|
-
let target = input;
|
|
43
|
-
while (segments.length > 1) {
|
|
44
|
-
const segment = segments.shift();
|
|
45
|
-
if (!segment) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
if (!isPlainObject(target[segment])) {
|
|
49
|
-
target[segment] = {};
|
|
50
|
-
}
|
|
51
|
-
target = target[segment];
|
|
52
|
-
}
|
|
53
|
-
target[segments[0]] = value;
|
|
54
|
-
return input;
|
|
55
|
-
}
|
|
56
|
-
function deleteValueAtPath(input, pathLabel) {
|
|
57
|
-
const segments = String(pathLabel).split(".");
|
|
58
|
-
let target = input;
|
|
59
|
-
while (segments.length > 1) {
|
|
60
|
-
const segment = segments.shift();
|
|
61
|
-
if (!segment || !isPlainObject(target[segment])) {
|
|
62
|
-
return input;
|
|
63
|
-
}
|
|
64
|
-
target = target[segment];
|
|
65
|
-
}
|
|
66
|
-
delete target[segments[0]];
|
|
67
|
-
return input;
|
|
68
|
-
}
|
|
69
|
-
function createFixtureScalarValue(pathLabel) {
|
|
70
|
-
const normalized = String(pathLabel).toLowerCase();
|
|
71
|
-
if (normalized.includes("id")) {
|
|
72
|
-
return "00000000-0000-4000-8000-000000000000";
|
|
73
|
-
}
|
|
74
|
-
if (normalized.includes("count") || normalized.includes("number")) {
|
|
75
|
-
return 1;
|
|
76
|
-
}
|
|
77
|
-
if (normalized.includes("visible") || normalized.startsWith("is")) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
return `legacy:${pathLabel}`;
|
|
81
|
-
}
|
|
82
|
-
function createTransformFixtureValue(attribute, pathLabel) {
|
|
83
|
-
switch (attribute?.ts?.kind) {
|
|
84
|
-
case "number":
|
|
85
|
-
return "42";
|
|
86
|
-
case "boolean":
|
|
87
|
-
return "1";
|
|
88
|
-
case "union":
|
|
89
|
-
return { kind: "unknown" };
|
|
90
|
-
default:
|
|
91
|
-
return createFixtureScalarValue(pathLabel);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function readJson(filePath) {
|
|
95
|
-
return readJsonFileSync(filePath, {
|
|
96
|
-
context: "migration JSON file"
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
function renderPhpValue(value, indentLevel) {
|
|
100
|
-
const indent = "\t".repeat(indentLevel);
|
|
101
|
-
const nestedIndent = "\t".repeat(indentLevel + 1);
|
|
102
|
-
if (value === null) {
|
|
103
|
-
return "null";
|
|
104
|
-
}
|
|
105
|
-
if (typeof value === "string") {
|
|
106
|
-
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
107
|
-
}
|
|
108
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
109
|
-
return String(value);
|
|
110
|
-
}
|
|
111
|
-
if (Array.isArray(value)) {
|
|
112
|
-
if (value.length === 0) {
|
|
113
|
-
return "[]";
|
|
114
|
-
}
|
|
115
|
-
const items = value.map((item) => `${nestedIndent}${renderPhpValue(item, indentLevel + 1)}`);
|
|
116
|
-
return `[
|
|
117
|
-
${items.join(`,
|
|
118
|
-
`)}
|
|
119
|
-
${indent}]`;
|
|
120
|
-
}
|
|
121
|
-
if (typeof value === "object") {
|
|
122
|
-
const entries = Object.entries(value);
|
|
123
|
-
if (entries.length === 0) {
|
|
124
|
-
return "[]";
|
|
125
|
-
}
|
|
126
|
-
const items = entries.map(([key, item]) => `${nestedIndent}'${String(key).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}' => ${renderPhpValue(item, indentLevel + 1)}`);
|
|
127
|
-
return `[
|
|
128
|
-
${items.join(`,
|
|
129
|
-
`)}
|
|
130
|
-
${indent}]`;
|
|
131
|
-
}
|
|
132
|
-
throw new Error(`Unable to encode PHP migration registry value for ${String(value)}`);
|
|
133
|
-
}
|
|
134
|
-
function copyFile(sourcePath, targetPath) {
|
|
135
|
-
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
136
|
-
fs.copyFileSync(sourcePath, targetPath);
|
|
137
|
-
}
|
|
138
|
-
function sanitizeSaveSnapshotSource(source) {
|
|
139
|
-
return source.replace(/^import\s+\{[^}]+\}\s+from\s+['"]\.\/types['"];?\n?/gm, "").replace(/^interface\s+SaveProps\s*\{[\s\S]*?\}\n?/m, "").replace(/: SaveProps/g, ": { attributes: any }").replace(/attributes:\s*[A-Za-z0-9_<>{}\[\]|&,\s]+;/g, "attributes: any;").replace(/\(\{\s*attributes\s*\}:\s*\{\s*attributes:\s*any\s*\}\)/g, "({ attributes }: { attributes: any })").replace(/\n{3,}/g, `
|
|
140
|
-
|
|
141
|
-
`).trimEnd().concat(`
|
|
142
|
-
`);
|
|
143
|
-
}
|
|
144
|
-
function sanitizeSnapshotBlockJson(blockJson) {
|
|
145
|
-
const snapshot = { ...blockJson };
|
|
146
|
-
for (const key of [
|
|
147
|
-
"editorScript",
|
|
148
|
-
"script",
|
|
149
|
-
"scriptModule",
|
|
150
|
-
"viewScript",
|
|
151
|
-
"viewScriptModule",
|
|
152
|
-
"style",
|
|
153
|
-
"editorStyle",
|
|
154
|
-
"render"
|
|
155
|
-
]) {
|
|
156
|
-
delete snapshot[key];
|
|
157
|
-
}
|
|
158
|
-
return snapshot;
|
|
159
|
-
}
|
|
160
|
-
function runProjectScriptIfPresent(projectDir, scriptName) {
|
|
161
|
-
const packageJson = readJson(path.join(projectDir, "package.json"));
|
|
162
|
-
if (!packageJson.scripts?.[scriptName]) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
const packageManagerId = detectPackageManagerId(projectDir);
|
|
166
|
-
execSync(formatRunScript(packageManagerId, scriptName), {
|
|
167
|
-
cwd: projectDir,
|
|
168
|
-
stdio: "inherit"
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
function detectPackageManagerId(projectDir) {
|
|
172
|
-
const packageJson = readJson(path.join(projectDir, "package.json"));
|
|
173
|
-
return parsePackageManagerField(packageJson.packageManager) ?? inferPackageManagerId(projectDir);
|
|
174
|
-
}
|
|
175
|
-
function getLocalTsxBinary(projectDir) {
|
|
176
|
-
const filename = process.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
177
|
-
const binaryPath = path.join(projectDir, "node_modules", ".bin", filename);
|
|
178
|
-
if (!fs.existsSync(binaryPath)) {
|
|
179
|
-
throw new Error("Local tsx binary was not found. Install project dependencies before running migration verification.");
|
|
180
|
-
}
|
|
181
|
-
return binaryPath;
|
|
182
|
-
}
|
|
183
|
-
function isInteractiveTerminal() {
|
|
184
|
-
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
185
|
-
}
|
|
186
|
-
function resolveTargetMigrationVersion(currentMigrationVersion, value) {
|
|
187
|
-
return value === "current" ? currentMigrationVersion : value;
|
|
188
|
-
}
|
|
189
|
-
function isMigrationVersionLabel(value) {
|
|
190
|
-
return MIGRATION_VERSION_LABEL_PATTERN.test(value);
|
|
191
|
-
}
|
|
192
|
-
function isLegacySemverMigrationVersion(value) {
|
|
193
|
-
return LEGACY_SEMVER_MIGRATION_VERSION_PATTERN.test(value);
|
|
194
|
-
}
|
|
195
|
-
function assertMigrationVersionLabel(value, label) {
|
|
196
|
-
if (!isMigrationVersionLabel(value)) {
|
|
197
|
-
throw new Error(`Invalid ${label}: ${value}. Expected vN with N >= 1.`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
function parseMigrationVersionNumber(value) {
|
|
201
|
-
const match = value.match(MIGRATION_VERSION_LABEL_PATTERN);
|
|
202
|
-
if (!match) {
|
|
203
|
-
throw new Error(`Invalid migration version label: ${value}. Expected vN with N >= 1.`);
|
|
204
|
-
}
|
|
205
|
-
return Number.parseInt(match[1], 10);
|
|
206
|
-
}
|
|
207
|
-
function compareMigrationVersionLabels(left, right) {
|
|
208
|
-
return parseMigrationVersionNumber(left) - parseMigrationVersionNumber(right);
|
|
209
|
-
}
|
|
210
|
-
function formatLegacyMigrationWorkspaceResetGuidance(reason) {
|
|
211
|
-
return [
|
|
212
|
-
reason ? `${reason} ` : "",
|
|
213
|
-
"Back up `src/migrations/` if needed, remove or reset the existing migration workspace, ",
|
|
214
|
-
"then rerun `wp-typia migrate init --current-migration-version v1`."
|
|
215
|
-
].join("");
|
|
216
|
-
}
|
|
217
|
-
function escapeForCode(value) {
|
|
218
|
-
return String(value).replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
219
|
-
}
|
|
220
|
-
function renderObjectKey(key) {
|
|
221
|
-
return JSON.stringify(String(key));
|
|
222
|
-
}
|
|
223
|
-
function isNumber(value) {
|
|
224
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// ../wp-typia-project-tools/src/runtime/migration-constants.ts
|
|
228
|
-
import path2 from "path";
|
|
229
|
-
var ROOT_BLOCK_JSON = "block.json";
|
|
230
|
-
var ROOT_MANIFEST = "typia.manifest.json";
|
|
231
|
-
var ROOT_PHP_MIGRATION_REGISTRY = "typia-migration-registry.php";
|
|
232
|
-
var SRC_BLOCK_JSON = path2.join("src", "block.json");
|
|
233
|
-
var SRC_MANIFEST = path2.join("src", "typia.manifest.json");
|
|
234
|
-
var ROOT_SAVE_FILE = path2.join("src", "save.tsx");
|
|
235
|
-
var ROOT_TYPES_FILE = path2.join("src", "types.ts");
|
|
236
|
-
var MIGRATIONS_DIR = path2.join("src", "migrations");
|
|
237
|
-
var CONFIG_FILE = path2.join(MIGRATIONS_DIR, "config.ts");
|
|
238
|
-
var GENERATED_DIR = path2.join(MIGRATIONS_DIR, "generated");
|
|
239
|
-
var FIXTURES_DIR = path2.join(MIGRATIONS_DIR, "fixtures");
|
|
240
|
-
var RULES_DIR = path2.join(MIGRATIONS_DIR, "rules");
|
|
241
|
-
var SNAPSHOT_DIR = path2.join(MIGRATIONS_DIR, "versions");
|
|
242
|
-
var SUPPORTED_PROJECT_FILES = ["package.json", ROOT_BLOCK_JSON, ROOT_SAVE_FILE, ROOT_TYPES_FILE];
|
|
243
|
-
var MIGRATION_TODO_PREFIX = "TODO MIGRATION:";
|
|
244
|
-
|
|
245
|
-
// ../wp-typia-project-tools/src/runtime/migration-project-layout-discovery.ts
|
|
246
|
-
import fs2 from "fs";
|
|
247
|
-
import path3 from "path";
|
|
248
|
-
|
|
249
|
-
// ../wp-typia-project-tools/src/runtime/migration-project-config-source.ts
|
|
250
|
-
function normalizeRelativePath(value) {
|
|
251
|
-
return value.replace(/\\/g, "/");
|
|
252
|
-
}
|
|
253
|
-
function stripCommentsAndStrings(source) {
|
|
254
|
-
let result = "";
|
|
255
|
-
let index = 0;
|
|
256
|
-
let mode = "code";
|
|
257
|
-
while (index < source.length) {
|
|
258
|
-
const current = source[index];
|
|
259
|
-
const next = source[index + 1];
|
|
260
|
-
if (mode === "code") {
|
|
261
|
-
if (current === "/" && next === "/") {
|
|
262
|
-
result += " ";
|
|
263
|
-
index += 2;
|
|
264
|
-
mode = "line-comment";
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
if (current === "/" && next === "*") {
|
|
268
|
-
result += " ";
|
|
269
|
-
index += 2;
|
|
270
|
-
mode = "block-comment";
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
if (current === "'") {
|
|
274
|
-
result += current;
|
|
275
|
-
index += 1;
|
|
276
|
-
mode = "single-quote";
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
if (current === '"') {
|
|
280
|
-
result += current;
|
|
281
|
-
index += 1;
|
|
282
|
-
mode = "double-quote";
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
if (current === "`") {
|
|
286
|
-
result += current;
|
|
287
|
-
index += 1;
|
|
288
|
-
mode = "template";
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
result += current;
|
|
292
|
-
index += 1;
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
if (mode === "line-comment") {
|
|
296
|
-
result += current === `
|
|
297
|
-
` ? `
|
|
298
|
-
` : " ";
|
|
299
|
-
index += 1;
|
|
300
|
-
if (current === `
|
|
301
|
-
`) {
|
|
302
|
-
mode = "code";
|
|
303
|
-
}
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
if (mode === "block-comment") {
|
|
307
|
-
if (current === "*" && next === "/") {
|
|
308
|
-
result += " ";
|
|
309
|
-
index += 2;
|
|
310
|
-
mode = "code";
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
result += current === `
|
|
314
|
-
` ? `
|
|
315
|
-
` : " ";
|
|
316
|
-
index += 1;
|
|
317
|
-
continue;
|
|
318
|
-
}
|
|
319
|
-
if (current === "\\") {
|
|
320
|
-
result += index + 1 < source.length ? " " : " ";
|
|
321
|
-
index += Math.min(2, source.length - index);
|
|
322
|
-
continue;
|
|
323
|
-
}
|
|
324
|
-
const closingQuote = mode === "single-quote" ? "'" : mode === "double-quote" ? '"' : "`";
|
|
325
|
-
if (current === closingQuote) {
|
|
326
|
-
result += current;
|
|
327
|
-
index += 1;
|
|
328
|
-
mode = "code";
|
|
329
|
-
continue;
|
|
330
|
-
}
|
|
331
|
-
result += current === `
|
|
332
|
-
` ? `
|
|
333
|
-
` : " ";
|
|
334
|
-
index += 1;
|
|
335
|
-
}
|
|
336
|
-
return result;
|
|
337
|
-
}
|
|
338
|
-
function findMigrationConfigBodyRange(source) {
|
|
339
|
-
const sanitizedSource = stripCommentsAndStrings(source);
|
|
340
|
-
const configAssignment = /\bmigrationConfig\s*=\s*\{/u.exec(sanitizedSource);
|
|
341
|
-
if (!configAssignment) {
|
|
342
|
-
return null;
|
|
343
|
-
}
|
|
344
|
-
const braceStart = configAssignment.index + configAssignment[0].length - 1;
|
|
345
|
-
let braceDepth = 0;
|
|
346
|
-
for (let index = braceStart;index < sanitizedSource.length; index += 1) {
|
|
347
|
-
const current = sanitizedSource[index];
|
|
348
|
-
if (current === "{") {
|
|
349
|
-
braceDepth += 1;
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
if (current === "}") {
|
|
353
|
-
braceDepth -= 1;
|
|
354
|
-
if (braceDepth === 0) {
|
|
355
|
-
return {
|
|
356
|
-
end: index,
|
|
357
|
-
start: braceStart + 1
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
function createTopLevelConfigView(source) {
|
|
365
|
-
const range = findMigrationConfigBodyRange(source);
|
|
366
|
-
if (!range) {
|
|
367
|
-
return null;
|
|
368
|
-
}
|
|
369
|
-
const bodySource = source.slice(range.start, range.end);
|
|
370
|
-
const sanitizedBody = stripCommentsAndStrings(bodySource);
|
|
371
|
-
let view = "";
|
|
372
|
-
let braceDepth = 0;
|
|
373
|
-
let bracketDepth = 0;
|
|
374
|
-
let parenDepth = 0;
|
|
375
|
-
for (let index = 0;index < sanitizedBody.length; index += 1) {
|
|
376
|
-
const current = sanitizedBody[index];
|
|
377
|
-
if (current === "{") {
|
|
378
|
-
braceDepth += 1;
|
|
379
|
-
} else if (current === "}") {
|
|
380
|
-
braceDepth = Math.max(0, braceDepth - 1);
|
|
381
|
-
} else if (current === "[") {
|
|
382
|
-
bracketDepth += 1;
|
|
383
|
-
} else if (current === "]") {
|
|
384
|
-
bracketDepth = Math.max(0, bracketDepth - 1);
|
|
385
|
-
} else if (current === "(") {
|
|
386
|
-
parenDepth += 1;
|
|
387
|
-
} else if (current === ")") {
|
|
388
|
-
parenDepth = Math.max(0, parenDepth - 1);
|
|
389
|
-
}
|
|
390
|
-
const nested = braceDepth > 0 || bracketDepth > 0 || parenDepth > 0;
|
|
391
|
-
view += nested && current !== "{" && current !== "}" && current !== "[" && current !== "]" && current !== "(" && current !== ")" ? current === `
|
|
392
|
-
` ? `
|
|
393
|
-
` : " " : current;
|
|
394
|
-
}
|
|
395
|
-
return view;
|
|
396
|
-
}
|
|
397
|
-
function findTopLevelConfigPropertyValueStart(source, key) {
|
|
398
|
-
const range = findMigrationConfigBodyRange(source);
|
|
399
|
-
if (!range) {
|
|
400
|
-
return null;
|
|
401
|
-
}
|
|
402
|
-
const bodySource = source.slice(range.start, range.end);
|
|
403
|
-
const topLevelView = createTopLevelConfigView(source);
|
|
404
|
-
if (!topLevelView) {
|
|
405
|
-
return null;
|
|
406
|
-
}
|
|
407
|
-
const pattern = new RegExp(`\\b${key}\\s*:\\s*`, "u");
|
|
408
|
-
const match = pattern.exec(topLevelView);
|
|
409
|
-
if (!match) {
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
let start = match.index + match[0].length;
|
|
413
|
-
while (start < bodySource.length && /\s/u.test(bodySource[start])) {
|
|
414
|
-
start += 1;
|
|
415
|
-
}
|
|
416
|
-
return { bodySource, start };
|
|
417
|
-
}
|
|
418
|
-
function hasLegacyConfigKeys(source) {
|
|
419
|
-
const topLevelView = createTopLevelConfigView(source);
|
|
420
|
-
if (!topLevelView) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
return /\bcurrentVersion\s*:/u.test(topLevelView) || /\bsupportedVersions\s*:/u.test(topLevelView);
|
|
424
|
-
}
|
|
425
|
-
function readQuotedString(source, startIndex) {
|
|
426
|
-
const quote = source[startIndex];
|
|
427
|
-
if (quote !== '"' && quote !== "'") {
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
430
|
-
let value = "";
|
|
431
|
-
let index = startIndex + 1;
|
|
432
|
-
while (index < source.length) {
|
|
433
|
-
const current = source[index];
|
|
434
|
-
if (current === "\\") {
|
|
435
|
-
if (index + 1 < source.length) {
|
|
436
|
-
value += source.slice(index, index + 2);
|
|
437
|
-
index += 2;
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
value += current;
|
|
441
|
-
index += 1;
|
|
442
|
-
continue;
|
|
443
|
-
}
|
|
444
|
-
if (current === quote) {
|
|
445
|
-
return value;
|
|
446
|
-
}
|
|
447
|
-
value += current;
|
|
448
|
-
index += 1;
|
|
449
|
-
}
|
|
450
|
-
return null;
|
|
451
|
-
}
|
|
452
|
-
function readStringArrayLiteral(source, startIndex) {
|
|
453
|
-
if (source[startIndex] !== "[") {
|
|
454
|
-
return null;
|
|
455
|
-
}
|
|
456
|
-
let bracketDepth = 0;
|
|
457
|
-
let index = startIndex;
|
|
458
|
-
let quote = null;
|
|
459
|
-
while (index < source.length) {
|
|
460
|
-
const current = source[index];
|
|
461
|
-
if (quote) {
|
|
462
|
-
if (current === "\\") {
|
|
463
|
-
index += 2;
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
if (current === quote) {
|
|
467
|
-
quote = null;
|
|
468
|
-
}
|
|
469
|
-
index += 1;
|
|
470
|
-
continue;
|
|
471
|
-
}
|
|
472
|
-
if (current === '"' || current === "'") {
|
|
473
|
-
quote = current;
|
|
474
|
-
index += 1;
|
|
475
|
-
continue;
|
|
476
|
-
}
|
|
477
|
-
if (current === "[") {
|
|
478
|
-
bracketDepth += 1;
|
|
479
|
-
} else if (current === "]") {
|
|
480
|
-
bracketDepth -= 1;
|
|
481
|
-
if (bracketDepth === 0) {
|
|
482
|
-
const body = source.slice(startIndex + 1, index);
|
|
483
|
-
return [...body.matchAll(/["']([^"']+)["']/gu)].map((match) => match[1]);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
index += 1;
|
|
487
|
-
}
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
|
-
function readArrayLiteralBody(source, startIndex) {
|
|
491
|
-
if (source[startIndex] !== "[") {
|
|
492
|
-
return null;
|
|
493
|
-
}
|
|
494
|
-
let bracketDepth = 0;
|
|
495
|
-
let index = startIndex;
|
|
496
|
-
let quote = null;
|
|
497
|
-
while (index < source.length) {
|
|
498
|
-
const current = source[index];
|
|
499
|
-
if (quote) {
|
|
500
|
-
if (current === "\\") {
|
|
501
|
-
index += 2;
|
|
502
|
-
continue;
|
|
503
|
-
}
|
|
504
|
-
if (current === quote) {
|
|
505
|
-
quote = null;
|
|
506
|
-
}
|
|
507
|
-
index += 1;
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
if (current === '"' || current === "'") {
|
|
511
|
-
quote = current;
|
|
512
|
-
index += 1;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
if (current === "[") {
|
|
516
|
-
bracketDepth += 1;
|
|
517
|
-
} else if (current === "]") {
|
|
518
|
-
bracketDepth -= 1;
|
|
519
|
-
if (bracketDepth === 0) {
|
|
520
|
-
return source.slice(startIndex + 1, index);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
index += 1;
|
|
524
|
-
}
|
|
525
|
-
return null;
|
|
526
|
-
}
|
|
527
|
-
function extractObjectLiteralBodies(source) {
|
|
528
|
-
const results = [];
|
|
529
|
-
let braceDepth = 0;
|
|
530
|
-
let objectStart = -1;
|
|
531
|
-
let quote = null;
|
|
532
|
-
for (let index = 0;index < source.length; index += 1) {
|
|
533
|
-
const current = source[index];
|
|
534
|
-
if (quote) {
|
|
535
|
-
if (current === "\\") {
|
|
536
|
-
index += 1;
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
if (current === quote) {
|
|
540
|
-
quote = null;
|
|
541
|
-
}
|
|
542
|
-
continue;
|
|
543
|
-
}
|
|
544
|
-
if (current === '"' || current === "'") {
|
|
545
|
-
quote = current;
|
|
546
|
-
continue;
|
|
547
|
-
}
|
|
548
|
-
if (current === "{") {
|
|
549
|
-
if (braceDepth === 0) {
|
|
550
|
-
objectStart = index + 1;
|
|
551
|
-
}
|
|
552
|
-
braceDepth += 1;
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
if (current === "}") {
|
|
556
|
-
braceDepth -= 1;
|
|
557
|
-
if (braceDepth === 0 && objectStart >= 0) {
|
|
558
|
-
results.push(source.slice(objectStart, index));
|
|
559
|
-
objectStart = -1;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
return results;
|
|
564
|
-
}
|
|
565
|
-
function createLegacyMigrationWorkspaceResetError(reason) {
|
|
566
|
-
return new Error(`Detected a legacy semver-based migration workspace. ${formatLegacyMigrationWorkspaceResetGuidance(reason)}`);
|
|
567
|
-
}
|
|
568
|
-
function parseMigrationBlocks(source) {
|
|
569
|
-
const blocksArrayBody = matchRootConfigArrayBody(source, "blocks");
|
|
570
|
-
if (!blocksArrayBody) {
|
|
571
|
-
return [];
|
|
572
|
-
}
|
|
573
|
-
const blockLiterals = extractObjectLiteralBodies(blocksArrayBody);
|
|
574
|
-
return blockLiterals.map((body) => {
|
|
575
|
-
const key = matchConfigValue(body, "key");
|
|
576
|
-
const blockName = matchConfigValue(body, "blockName");
|
|
577
|
-
const blockJsonFile = matchConfigValue(body, "blockJsonFile");
|
|
578
|
-
const manifestFile = matchConfigValue(body, "manifestFile");
|
|
579
|
-
const saveFile = matchConfigValue(body, "saveFile");
|
|
580
|
-
const typesFile = matchConfigValue(body, "typesFile");
|
|
581
|
-
if (!key || !blockName || !blockJsonFile || !manifestFile || !saveFile || !typesFile) {
|
|
582
|
-
return null;
|
|
583
|
-
}
|
|
584
|
-
return {
|
|
585
|
-
blockJsonFile,
|
|
586
|
-
blockName,
|
|
587
|
-
key,
|
|
588
|
-
manifestFile,
|
|
589
|
-
saveFile,
|
|
590
|
-
typesFile
|
|
591
|
-
};
|
|
592
|
-
}).filter((block) => block !== null);
|
|
593
|
-
}
|
|
594
|
-
function matchConfigValue(source, key) {
|
|
595
|
-
const pattern = new RegExp(`${key}:\\s*["']([^"']+)["']`, "u");
|
|
596
|
-
return source.match(pattern)?.[1] ?? null;
|
|
597
|
-
}
|
|
598
|
-
function matchRootConfigValue(source, key) {
|
|
599
|
-
const match = findTopLevelConfigPropertyValueStart(source, key);
|
|
600
|
-
if (!match) {
|
|
601
|
-
return null;
|
|
602
|
-
}
|
|
603
|
-
return readQuotedString(match.bodySource, match.start);
|
|
604
|
-
}
|
|
605
|
-
function matchRootConfigStringArrayValue(source, key) {
|
|
606
|
-
const match = findTopLevelConfigPropertyValueStart(source, key);
|
|
607
|
-
if (!match) {
|
|
608
|
-
return null;
|
|
609
|
-
}
|
|
610
|
-
return readStringArrayLiteral(match.bodySource, match.start);
|
|
611
|
-
}
|
|
612
|
-
function matchRootConfigArrayBody(source, key) {
|
|
613
|
-
const match = findTopLevelConfigPropertyValueStart(source, key);
|
|
614
|
-
if (!match) {
|
|
615
|
-
return null;
|
|
616
|
-
}
|
|
617
|
-
return readArrayLiteralBody(match.bodySource, match.start);
|
|
618
|
-
}
|
|
619
|
-
function parseMigrationConfig(source) {
|
|
620
|
-
if (hasLegacyConfigKeys(source)) {
|
|
621
|
-
throw createLegacyMigrationWorkspaceResetError("Detected legacy config keys `currentVersion` / `supportedVersions` in `src/migrations/config.ts`.");
|
|
622
|
-
}
|
|
623
|
-
const blockName = matchRootConfigValue(source, "blockName");
|
|
624
|
-
const currentMigrationVersion = matchRootConfigValue(source, "currentMigrationVersion");
|
|
625
|
-
const snapshotDir = matchRootConfigValue(source, "snapshotDir");
|
|
626
|
-
const supportedMigrationVersions = matchRootConfigStringArrayValue(source, "supportedMigrationVersions");
|
|
627
|
-
const blocksArrayBody = matchRootConfigArrayBody(source, "blocks");
|
|
628
|
-
const blocks = blocksArrayBody === null ? [] : parseMigrationBlocks(source);
|
|
629
|
-
if (!currentMigrationVersion || !snapshotDir || !supportedMigrationVersions) {
|
|
630
|
-
throw new Error("Unable to parse migration config. Regenerate with `wp-typia migrate init --current-migration-version v1`.");
|
|
631
|
-
}
|
|
632
|
-
if (blocksArrayBody !== null && blocks.length === 0 && blocksArrayBody.trim().length > 0) {
|
|
633
|
-
throw new Error("Migration config defines `blocks`, but the array entries could not be parsed. Regenerate the config or fix the malformed block targets in `src/migrations/config.ts`.");
|
|
634
|
-
}
|
|
635
|
-
if (!blockName && blocks.length === 0 && blocksArrayBody === null) {
|
|
636
|
-
throw new Error("Migration config must define `blockName` or `blocks`.");
|
|
637
|
-
}
|
|
638
|
-
if (!isMigrationVersionLabel(currentMigrationVersion)) {
|
|
639
|
-
if (isLegacySemverMigrationVersion(currentMigrationVersion)) {
|
|
640
|
-
throw createLegacyMigrationWorkspaceResetError(`Detected legacy semver migration version label \`${currentMigrationVersion}\` in \`src/migrations/config.ts\`.`);
|
|
641
|
-
}
|
|
642
|
-
throw new Error(`Invalid current migration version: ${currentMigrationVersion}. Expected vN with N >= 1.`);
|
|
643
|
-
}
|
|
644
|
-
for (const version of supportedMigrationVersions) {
|
|
645
|
-
if (!isMigrationVersionLabel(version)) {
|
|
646
|
-
if (isLegacySemverMigrationVersion(version)) {
|
|
647
|
-
throw createLegacyMigrationWorkspaceResetError(`Detected legacy semver migration version label \`${version}\` in \`src/migrations/config.ts\`.`);
|
|
648
|
-
}
|
|
649
|
-
throw new Error(`Invalid supported migration version: ${version}. Expected vN with N >= 1.`);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
supportedMigrationVersions.sort(compareMigrationVersionLabels);
|
|
653
|
-
return {
|
|
654
|
-
blockName: blockName ?? undefined,
|
|
655
|
-
blocks: blocksArrayBody === null ? undefined : blocks,
|
|
656
|
-
currentMigrationVersion,
|
|
657
|
-
snapshotDir,
|
|
658
|
-
supportedMigrationVersions
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
// ../wp-typia-project-tools/src/runtime/migration-project-layout-discovery.ts
|
|
663
|
-
var DEFAULT_BLOCK_KEY = "default";
|
|
664
|
-
var SINGLE_BLOCK_LAYOUT_NOT_FOUND = "No supported single-block migration layout was found.";
|
|
665
|
-
var SINGLE_BLOCK_LAYOUT_CANDIDATES = [
|
|
666
|
-
{
|
|
667
|
-
blockJsonFile: SRC_BLOCK_JSON,
|
|
668
|
-
manifestFile: SRC_MANIFEST
|
|
669
|
-
},
|
|
670
|
-
{
|
|
671
|
-
blockJsonFile: ROOT_BLOCK_JSON,
|
|
672
|
-
manifestFile: ROOT_MANIFEST
|
|
673
|
-
}
|
|
674
|
-
];
|
|
675
|
-
var LEGACY_ROOT_SINGLE_BLOCK_LAYOUT = SINGLE_BLOCK_LAYOUT_CANDIDATES[1];
|
|
676
|
-
function readSingleBlockTarget(projectDir, {
|
|
677
|
-
blockJsonFile,
|
|
678
|
-
manifestFile
|
|
679
|
-
}) {
|
|
680
|
-
const requiredFiles = [blockJsonFile, ROOT_SAVE_FILE, ROOT_TYPES_FILE];
|
|
681
|
-
if (requiredFiles.some((relativePath) => !fs2.existsSync(path3.join(projectDir, relativePath)))) {
|
|
682
|
-
return null;
|
|
683
|
-
}
|
|
684
|
-
const blockName = readJson(path3.join(projectDir, blockJsonFile))?.name;
|
|
685
|
-
if (typeof blockName !== "string" || blockName.length === 0) {
|
|
686
|
-
throw new Error(`Unable to resolve block name from ${normalizeRelativePath(blockJsonFile)}`);
|
|
687
|
-
}
|
|
688
|
-
return {
|
|
689
|
-
blockJsonFile: normalizeRelativePath(blockJsonFile),
|
|
690
|
-
blockName,
|
|
691
|
-
key: DEFAULT_BLOCK_KEY,
|
|
692
|
-
manifestFile: normalizeRelativePath(manifestFile),
|
|
693
|
-
saveFile: ROOT_SAVE_FILE,
|
|
694
|
-
typesFile: ROOT_TYPES_FILE
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
function collectSingleBlockCandidates(projectDir) {
|
|
698
|
-
return SINGLE_BLOCK_LAYOUT_CANDIDATES.filter(({ blockJsonFile }) => hasSingleBlockLayoutFiles(projectDir, blockJsonFile));
|
|
699
|
-
}
|
|
700
|
-
function hasSingleBlockLayoutFiles(projectDir, blockJsonFile) {
|
|
701
|
-
return [blockJsonFile, ROOT_SAVE_FILE, ROOT_TYPES_FILE].every((relativePath) => fs2.existsSync(path3.join(projectDir, relativePath)));
|
|
702
|
-
}
|
|
703
|
-
function orderSingleBlockCandidates(projectDir, candidates) {
|
|
704
|
-
const candidatesWithManifest = candidates.filter(({ manifestFile }) => fs2.existsSync(path3.join(projectDir, manifestFile)));
|
|
705
|
-
return [
|
|
706
|
-
...candidatesWithManifest,
|
|
707
|
-
...candidates.filter((candidate) => !candidatesWithManifest.includes(candidate))
|
|
708
|
-
];
|
|
709
|
-
}
|
|
710
|
-
function createImplicitLegacyBlock(projectDir, blockName) {
|
|
711
|
-
if (blockName) {
|
|
712
|
-
try {
|
|
713
|
-
const rootTarget = readSingleBlockTarget(projectDir, LEGACY_ROOT_SINGLE_BLOCK_LAYOUT);
|
|
714
|
-
const srcTarget = readSingleBlockTarget(projectDir, SINGLE_BLOCK_LAYOUT_CANDIDATES[0]);
|
|
715
|
-
const hasSrcManifest = fs2.existsSync(path3.join(projectDir, SRC_MANIFEST));
|
|
716
|
-
if (rootTarget?.blockName === blockName && (!srcTarget || srcTarget.blockName !== blockName || !hasSrcManifest)) {
|
|
717
|
-
return {
|
|
718
|
-
...rootTarget,
|
|
719
|
-
key: DEFAULT_BLOCK_KEY
|
|
720
|
-
};
|
|
721
|
-
}
|
|
722
|
-
} catch {}
|
|
723
|
-
}
|
|
724
|
-
const discovered = discoverSingleBlockTarget(projectDir, blockName);
|
|
725
|
-
return {
|
|
726
|
-
...discovered,
|
|
727
|
-
key: DEFAULT_BLOCK_KEY
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
function createMalformedMultiBlockTargetError(directory, reason) {
|
|
731
|
-
return new Error("Unable to auto-detect a supported migration retrofit layout. " + `Detected ${path3.join("src", "blocks", directory, "block.json")} but ${reason}. ` + "Create `src/migrations/config.ts` manually if your project uses a custom layout.");
|
|
732
|
-
}
|
|
733
|
-
function getRequiredProjectFiles(projectDir, blocks) {
|
|
734
|
-
if (Array.isArray(blocks) && blocks.length > 0) {
|
|
735
|
-
return [
|
|
736
|
-
"package.json",
|
|
737
|
-
...blocks.flatMap((block) => [block.blockJsonFile, block.saveFile, block.typesFile])
|
|
738
|
-
];
|
|
739
|
-
}
|
|
740
|
-
const configPath = path3.join(projectDir, CONFIG_FILE);
|
|
741
|
-
if (fs2.existsSync(configPath)) {
|
|
742
|
-
const config = parseMigrationConfig(fs2.readFileSync(configPath, "utf8"));
|
|
743
|
-
const configuredBlocks = config.blocks ?? [createImplicitLegacyBlock(projectDir, config.blockName)];
|
|
744
|
-
return [
|
|
745
|
-
"package.json",
|
|
746
|
-
...configuredBlocks.flatMap((block) => [block.blockJsonFile, block.saveFile, block.typesFile])
|
|
747
|
-
];
|
|
748
|
-
}
|
|
749
|
-
const discoveredLayout = discoverMigrationLayout(projectDir);
|
|
750
|
-
if (discoveredLayout?.mode === "multi") {
|
|
751
|
-
return [
|
|
752
|
-
"package.json",
|
|
753
|
-
...discoveredLayout.blocks.flatMap((block) => [block.blockJsonFile, block.saveFile, block.typesFile])
|
|
754
|
-
];
|
|
755
|
-
}
|
|
756
|
-
if (discoveredLayout?.mode === "single") {
|
|
757
|
-
return [
|
|
758
|
-
"package.json",
|
|
759
|
-
discoveredLayout.block.blockJsonFile,
|
|
760
|
-
discoveredLayout.block.saveFile,
|
|
761
|
-
discoveredLayout.block.typesFile
|
|
762
|
-
];
|
|
763
|
-
}
|
|
764
|
-
return SUPPORTED_PROJECT_FILES;
|
|
765
|
-
}
|
|
766
|
-
function ensureAdvancedMigrationProject(projectDir, blocks) {
|
|
767
|
-
const missing = getRequiredProjectFiles(projectDir, blocks).filter((relativePath) => !fs2.existsSync(path3.join(projectDir, relativePath)));
|
|
768
|
-
if (missing.length > 0) {
|
|
769
|
-
throw new Error(`This directory is not a supported migration-capable project. Missing: ${missing.join(", ")}`);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
function createBlockTarget(projectDir, {
|
|
773
|
-
blockJsonFile,
|
|
774
|
-
key,
|
|
775
|
-
manifestFile,
|
|
776
|
-
saveFile,
|
|
777
|
-
typesFile
|
|
778
|
-
}) {
|
|
779
|
-
const requiredFiles = [blockJsonFile, saveFile, typesFile];
|
|
780
|
-
if (requiredFiles.some((relativePath) => !fs2.existsSync(path3.join(projectDir, relativePath)))) {
|
|
781
|
-
return null;
|
|
782
|
-
}
|
|
783
|
-
const blockName = readJson(path3.join(projectDir, blockJsonFile))?.name;
|
|
784
|
-
if (typeof blockName !== "string" || blockName.length === 0) {
|
|
785
|
-
return null;
|
|
786
|
-
}
|
|
787
|
-
return {
|
|
788
|
-
blockJsonFile: normalizeRelativePath(blockJsonFile),
|
|
789
|
-
blockName,
|
|
790
|
-
key,
|
|
791
|
-
manifestFile: normalizeRelativePath(manifestFile),
|
|
792
|
-
saveFile: normalizeRelativePath(saveFile),
|
|
793
|
-
typesFile: normalizeRelativePath(typesFile)
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
function discoverSingleBlockTarget(projectDir, preferredBlockName) {
|
|
797
|
-
const candidates = collectSingleBlockCandidates(projectDir);
|
|
798
|
-
if (candidates.length === 0) {
|
|
799
|
-
throw new Error(SINGLE_BLOCK_LAYOUT_NOT_FOUND);
|
|
800
|
-
}
|
|
801
|
-
const readCandidate = (candidate) => readSingleBlockTarget(projectDir, candidate);
|
|
802
|
-
const orderedCandidates = orderSingleBlockCandidates(projectDir, candidates);
|
|
803
|
-
if (preferredBlockName) {
|
|
804
|
-
const validTargets = [];
|
|
805
|
-
let firstReadError2 = null;
|
|
806
|
-
for (const candidate of orderedCandidates) {
|
|
807
|
-
try {
|
|
808
|
-
const target = readCandidate(candidate);
|
|
809
|
-
if (!target) {
|
|
810
|
-
continue;
|
|
811
|
-
}
|
|
812
|
-
if (target.blockName === preferredBlockName) {
|
|
813
|
-
return target;
|
|
814
|
-
}
|
|
815
|
-
validTargets.push(target);
|
|
816
|
-
} catch (error) {
|
|
817
|
-
if (!firstReadError2 && error instanceof Error) {
|
|
818
|
-
firstReadError2 = error;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
if (validTargets.length > 0) {
|
|
823
|
-
throw new Error(`Configured migration blockName ${preferredBlockName} does not match the detected single-block layout(s): ${validTargets.map((target) => target.blockName).join(", ")}.`);
|
|
824
|
-
}
|
|
825
|
-
if (firstReadError2) {
|
|
826
|
-
throw firstReadError2;
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
let firstReadError;
|
|
830
|
-
let sawReadError = false;
|
|
831
|
-
for (const candidate of orderedCandidates) {
|
|
832
|
-
try {
|
|
833
|
-
const target = readCandidate(candidate);
|
|
834
|
-
if (target) {
|
|
835
|
-
return target;
|
|
836
|
-
}
|
|
837
|
-
} catch (error) {
|
|
838
|
-
if (!sawReadError) {
|
|
839
|
-
firstReadError = error;
|
|
840
|
-
sawReadError = true;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
if (sawReadError) {
|
|
845
|
-
throw firstReadError;
|
|
846
|
-
}
|
|
847
|
-
throw new Error(SINGLE_BLOCK_LAYOUT_NOT_FOUND);
|
|
848
|
-
}
|
|
849
|
-
function discoverMigrationLayout(projectDir) {
|
|
850
|
-
const blocksRoot = path3.join(projectDir, "src", "blocks");
|
|
851
|
-
let firstMultiBlockError = null;
|
|
852
|
-
if (fs2.existsSync(blocksRoot) && fs2.statSync(blocksRoot).isDirectory()) {
|
|
853
|
-
const blockDirectories = fs2.readdirSync(blocksRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
854
|
-
const candidateDirectories = blockDirectories.filter((directory) => fs2.existsSync(path3.join(blocksRoot, directory, "block.json")));
|
|
855
|
-
if (candidateDirectories.length > 0) {
|
|
856
|
-
const blocks = candidateDirectories.flatMap((directory) => {
|
|
857
|
-
const saveFile = path3.join("src", "blocks", directory, "save.tsx");
|
|
858
|
-
const typesFile = path3.join("src", "blocks", directory, "types.ts");
|
|
859
|
-
const missingFiles = [saveFile, typesFile].filter((relativePath) => !fs2.existsSync(path3.join(projectDir, relativePath)));
|
|
860
|
-
if (missingFiles.length > 0) {
|
|
861
|
-
firstMultiBlockError ??= createMalformedMultiBlockTargetError(directory, `the block target is missing ${missingFiles.join(", ")}`);
|
|
862
|
-
return [];
|
|
863
|
-
}
|
|
864
|
-
let block = null;
|
|
865
|
-
try {
|
|
866
|
-
block = createBlockTarget(projectDir, {
|
|
867
|
-
blockJsonFile: path3.join("src", "blocks", directory, "block.json"),
|
|
868
|
-
key: directory,
|
|
869
|
-
manifestFile: path3.join("src", "blocks", directory, "typia.manifest.json"),
|
|
870
|
-
saveFile,
|
|
871
|
-
typesFile
|
|
872
|
-
});
|
|
873
|
-
} catch (error) {
|
|
874
|
-
firstMultiBlockError ??= error instanceof Error ? createMalformedMultiBlockTargetError(directory, `could not be parsed (${error.message})`) : createMalformedMultiBlockTargetError(directory, "could not be parsed");
|
|
875
|
-
return [];
|
|
876
|
-
}
|
|
877
|
-
if (!block) {
|
|
878
|
-
firstMultiBlockError ??= createMalformedMultiBlockTargetError(directory, "it does not expose a valid block name");
|
|
879
|
-
return [];
|
|
880
|
-
}
|
|
881
|
-
return [block];
|
|
882
|
-
});
|
|
883
|
-
if (blocks.length > 0) {
|
|
884
|
-
return {
|
|
885
|
-
blocks: blocks.sort((left, right) => left.key.localeCompare(right.key)),
|
|
886
|
-
mode: "multi"
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
try {
|
|
892
|
-
return {
|
|
893
|
-
block: discoverSingleBlockTarget(projectDir),
|
|
894
|
-
mode: "single"
|
|
895
|
-
};
|
|
896
|
-
} catch (error) {
|
|
897
|
-
if (error instanceof Error && error.message === SINGLE_BLOCK_LAYOUT_NOT_FOUND) {
|
|
898
|
-
if (firstMultiBlockError) {
|
|
899
|
-
throw firstMultiBlockError;
|
|
900
|
-
}
|
|
901
|
-
return null;
|
|
902
|
-
}
|
|
903
|
-
throw error;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
function discoverMigrationInitLayout(projectDir) {
|
|
907
|
-
const discoveredLayout = discoverMigrationLayout(projectDir);
|
|
908
|
-
if (discoveredLayout) {
|
|
909
|
-
return discoveredLayout;
|
|
910
|
-
}
|
|
911
|
-
throw new Error("Unable to auto-detect a supported migration retrofit layout. " + "Expected either `src/blocks/*/block.json` with matching `types.ts` and `save.tsx`, " + "or a single-block layout using `src/block.json` (or legacy root `block.json`) with `src/types.ts` and `src/save.tsx`. " + "Create `src/migrations/config.ts` manually if your project uses a custom layout.");
|
|
912
|
-
}
|
|
913
|
-
function resolveMigrationBlocks(projectDir, config) {
|
|
914
|
-
if (Array.isArray(config.blocks)) {
|
|
915
|
-
if (config.blocks.length === 0) {
|
|
916
|
-
return [];
|
|
917
|
-
}
|
|
918
|
-
return config.blocks.map((block) => {
|
|
919
|
-
const blockJsonPath = path3.join(projectDir, block.blockJsonFile);
|
|
920
|
-
const manifestPath = path3.join(projectDir, block.manifestFile);
|
|
921
|
-
return {
|
|
922
|
-
...block,
|
|
923
|
-
currentBlockJson: readJson(blockJsonPath),
|
|
924
|
-
currentManifest: readJson(manifestPath),
|
|
925
|
-
layout: "multi"
|
|
926
|
-
};
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
return [createImplicitLegacyBlock(projectDir, config.blockName)].map((block) => {
|
|
930
|
-
const blockJsonPath = path3.join(projectDir, block.blockJsonFile);
|
|
931
|
-
const manifestPath = path3.join(projectDir, block.manifestFile);
|
|
932
|
-
return {
|
|
933
|
-
...block,
|
|
934
|
-
currentBlockJson: readJson(blockJsonPath),
|
|
935
|
-
currentManifest: readJson(manifestPath),
|
|
936
|
-
layout: "legacy"
|
|
937
|
-
};
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
function readProjectBlockName(projectDir) {
|
|
941
|
-
return discoverSingleBlockTarget(projectDir).blockName;
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
// ../wp-typia-project-tools/src/runtime/migration-project-layout-paths.ts
|
|
945
|
-
import fs3 from "fs";
|
|
946
|
-
import path4 from "path";
|
|
947
|
-
function toImportPath(fromDir, targetPath, stripExtension = false) {
|
|
948
|
-
let relativePath = normalizeRelativePath(path4.relative(fromDir, targetPath));
|
|
949
|
-
if (!relativePath.startsWith(".")) {
|
|
950
|
-
relativePath = `./${relativePath}`;
|
|
951
|
-
}
|
|
952
|
-
if (stripExtension) {
|
|
953
|
-
relativePath = relativePath.replace(/\.[^.]+$/u, "");
|
|
954
|
-
}
|
|
955
|
-
return relativePath;
|
|
956
|
-
}
|
|
957
|
-
function getProjectPaths(projectDir) {
|
|
958
|
-
return {
|
|
959
|
-
configFile: path4.join(projectDir, CONFIG_FILE),
|
|
960
|
-
fixturesDir: path4.join(projectDir, FIXTURES_DIR),
|
|
961
|
-
generatedDir: path4.join(projectDir, GENERATED_DIR),
|
|
962
|
-
rulesDir: path4.join(projectDir, RULES_DIR),
|
|
963
|
-
snapshotDir: path4.join(projectDir, SNAPSHOT_DIR)
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
function getSnapshotRoot(projectDir, block, version) {
|
|
967
|
-
if ("layout" in block && block.layout === "legacy") {
|
|
968
|
-
return path4.join(projectDir, SNAPSHOT_DIR, version);
|
|
969
|
-
}
|
|
970
|
-
return path4.join(projectDir, SNAPSHOT_DIR, version, block.key);
|
|
971
|
-
}
|
|
972
|
-
function getSnapshotBlockJsonPath(projectDir, block, version) {
|
|
973
|
-
return path4.join(getSnapshotRoot(projectDir, block, version), ROOT_BLOCK_JSON);
|
|
974
|
-
}
|
|
975
|
-
function getSnapshotManifestPath(projectDir, block, version) {
|
|
976
|
-
return path4.join(getSnapshotRoot(projectDir, block, version), ROOT_MANIFEST);
|
|
977
|
-
}
|
|
978
|
-
function getAvailableSnapshotVersionsForBlock(projectDir, supportedMigrationVersions, block) {
|
|
979
|
-
return supportedMigrationVersions.filter((version) => fs3.existsSync(getSnapshotManifestPath(projectDir, block, version))).sort(compareMigrationVersionLabels);
|
|
980
|
-
}
|
|
981
|
-
function createMissingBlockSnapshotMessage(blockName, fromVersion, availableSnapshotVersions) {
|
|
982
|
-
return availableSnapshotVersions.length === 0 ? `Snapshot manifest for ${blockName} @ ${fromVersion} does not exist. ` + `No snapshots exist yet for ${blockName}. Run \`wp-typia migrate snapshot --migration-version ${fromVersion}\` first.` : `Snapshot manifest for ${blockName} @ ${fromVersion} does not exist. ` + `Available snapshot versions for ${blockName}: ${availableSnapshotVersions.join(", ")}. ` + `Run \`wp-typia migrate snapshot --migration-version ${fromVersion}\` first if you want to preserve that release.`;
|
|
983
|
-
}
|
|
984
|
-
function getSnapshotSavePath(projectDir, block, version) {
|
|
985
|
-
return path4.join(getSnapshotRoot(projectDir, block, version), "save.tsx");
|
|
986
|
-
}
|
|
987
|
-
function getGeneratedDirForBlock(paths, block) {
|
|
988
|
-
if ("layout" in block && block.layout === "legacy") {
|
|
989
|
-
return paths.generatedDir;
|
|
990
|
-
}
|
|
991
|
-
return path4.join(paths.generatedDir, block.key);
|
|
992
|
-
}
|
|
993
|
-
function getRuleFilePath(paths, block, fromVersion, toVersion) {
|
|
994
|
-
if ("layout" in block && block.layout === "legacy") {
|
|
995
|
-
return path4.join(paths.rulesDir, `${fromVersion}-to-${toVersion}.ts`);
|
|
996
|
-
}
|
|
997
|
-
return path4.join(paths.rulesDir, block.key, `${fromVersion}-to-${toVersion}.ts`);
|
|
998
|
-
}
|
|
999
|
-
function getFixtureFilePath(paths, block, fromVersion, toVersion) {
|
|
1000
|
-
if ("layout" in block && block.layout === "legacy") {
|
|
1001
|
-
return path4.join(paths.fixturesDir, `${fromVersion}-to-${toVersion}.json`);
|
|
1002
|
-
}
|
|
1003
|
-
return path4.join(paths.fixturesDir, block.key, `${fromVersion}-to-${toVersion}.json`);
|
|
1004
|
-
}
|
|
1005
|
-
function getValidatorsImportPath(projectDir, block, fromDir) {
|
|
1006
|
-
const validatorPath = path4.join(projectDir, block.typesFile.replace(/types\.ts$/u, "validators.ts"));
|
|
1007
|
-
return toImportPath(fromDir, validatorPath, true);
|
|
1008
|
-
}
|
|
1009
|
-
function ensureMigrationDirectories(projectDir, blocks) {
|
|
1010
|
-
const paths = getProjectPaths(projectDir);
|
|
1011
|
-
fs3.mkdirSync(paths.fixturesDir, { recursive: true });
|
|
1012
|
-
fs3.mkdirSync(paths.generatedDir, { recursive: true });
|
|
1013
|
-
fs3.mkdirSync(paths.rulesDir, { recursive: true });
|
|
1014
|
-
fs3.mkdirSync(paths.snapshotDir, { recursive: true });
|
|
1015
|
-
if (!Array.isArray(blocks) || blocks.length === 0) {
|
|
1016
|
-
return;
|
|
1017
|
-
}
|
|
1018
|
-
for (const block of blocks) {
|
|
1019
|
-
fs3.mkdirSync(path4.join(paths.fixturesDir, block.key), { recursive: true });
|
|
1020
|
-
fs3.mkdirSync(path4.join(paths.generatedDir, block.key), { recursive: true });
|
|
1021
|
-
fs3.mkdirSync(path4.join(paths.rulesDir, block.key), { recursive: true });
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
function discoverMigrationEntries(state) {
|
|
1025
|
-
const entries = [];
|
|
1026
|
-
const currentVersion = state.config.currentMigrationVersion;
|
|
1027
|
-
for (const block of state.blocks) {
|
|
1028
|
-
const generatedDir = getGeneratedDirForBlock(state.paths, block);
|
|
1029
|
-
for (const version of state.config.supportedMigrationVersions) {
|
|
1030
|
-
if (version === currentVersion) {
|
|
1031
|
-
continue;
|
|
1032
|
-
}
|
|
1033
|
-
const manifestPath = getSnapshotManifestPath(state.projectDir, block, version);
|
|
1034
|
-
const blockJsonPath = getSnapshotBlockJsonPath(state.projectDir, block, version);
|
|
1035
|
-
const savePath = getSnapshotSavePath(state.projectDir, block, version);
|
|
1036
|
-
const rulePath = getRuleFilePath(state.paths, block, version, currentVersion);
|
|
1037
|
-
if (!fs3.existsSync(manifestPath) || !fs3.existsSync(blockJsonPath) || !fs3.existsSync(savePath) || !fs3.existsSync(rulePath)) {
|
|
1038
|
-
continue;
|
|
1039
|
-
}
|
|
1040
|
-
entries.push({
|
|
1041
|
-
block,
|
|
1042
|
-
blockJsonImport: toImportPath(generatedDir, blockJsonPath),
|
|
1043
|
-
fixtureImport: toImportPath(generatedDir, getFixtureFilePath(state.paths, block, version, currentVersion)),
|
|
1044
|
-
fromVersion: version,
|
|
1045
|
-
generatedDir,
|
|
1046
|
-
manifestImport: toImportPath(generatedDir, manifestPath),
|
|
1047
|
-
ruleImport: toImportPath(generatedDir, rulePath, true),
|
|
1048
|
-
rulePath,
|
|
1049
|
-
saveImport: toImportPath(generatedDir, savePath, true),
|
|
1050
|
-
toVersion: currentVersion,
|
|
1051
|
-
validatorImport: getValidatorsImportPath(state.projectDir, block, generatedDir)
|
|
1052
|
-
});
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
return entries.sort((left, right) => {
|
|
1056
|
-
const versionDelta = compareMigrationVersionLabels(right.fromVersion, left.fromVersion);
|
|
1057
|
-
if (versionDelta !== 0) {
|
|
1058
|
-
return versionDelta;
|
|
1059
|
-
}
|
|
1060
|
-
return left.block.key.localeCompare(right.block.key);
|
|
1061
|
-
});
|
|
1062
|
-
}
|
|
1063
|
-
function assertRuleHasNoTodos(projectDir, block, fromMigrationVersion, toMigrationVersion) {
|
|
1064
|
-
const rulePath = getRuleFilePath(getProjectPaths(projectDir), block, fromMigrationVersion, toMigrationVersion);
|
|
1065
|
-
if (!fs3.existsSync(rulePath)) {
|
|
1066
|
-
throw new Error(`Missing migration rule: ${path4.relative(projectDir, rulePath)}`);
|
|
1067
|
-
}
|
|
1068
|
-
const source = fs3.readFileSync(rulePath, "utf8");
|
|
1069
|
-
if (source.includes(MIGRATION_TODO_PREFIX)) {
|
|
1070
|
-
throw new Error(`Migration rule still contains ${MIGRATION_TODO_PREFIX} markers: ${path4.relative(projectDir, rulePath)}`);
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
function readRuleMetadata(rulePath) {
|
|
1074
|
-
const source = fs3.readFileSync(rulePath, "utf8");
|
|
1075
|
-
const unresolvedBlock = source.match(/export const unresolved = \[([\s\S]*?)\] as const;/);
|
|
1076
|
-
const renameMapBlock = source.match(/export const renameMap: RenameMap = \{([\s\S]*?)\};/);
|
|
1077
|
-
const transformsBlock = source.match(/export const transforms: TransformMap = \{([\s\S]*?)\};/);
|
|
1078
|
-
const unresolved = unresolvedBlock ? [...unresolvedBlock[1].matchAll(/"([^"]+)"/g)].map((match) => match[1]) : [];
|
|
1079
|
-
const renameMap = renameMapBlock ? [...renameMapBlock[1].matchAll(/^\s*"([^"]+)":\s*"([^"]+)"/gm)].map((match) => ({
|
|
1080
|
-
currentPath: match[1],
|
|
1081
|
-
legacyPath: match[2]
|
|
1082
|
-
})) : [];
|
|
1083
|
-
const transforms = transformsBlock ? [...transformsBlock[1].matchAll(/^\s*"([^"]+)":\s*\(/gm)].map((match) => match[1]) : [];
|
|
1084
|
-
return { renameMap, transforms, unresolved };
|
|
1085
|
-
}
|
|
1086
|
-
// ../wp-typia-project-tools/src/runtime/migration-project-workspace.ts
|
|
1087
|
-
import fs4 from "fs";
|
|
1088
|
-
import path5 from "path";
|
|
1089
|
-
var LEGACY_VERSIONED_EDGE_FILE_PATTERN = /^(\d+\.\d+\.\d+)-to-(\d+\.\d+\.\d+)\.(?:ts|json)$/;
|
|
1090
|
-
function createEmptyMigrationProjectBlockJson() {
|
|
1091
|
-
return {};
|
|
1092
|
-
}
|
|
1093
|
-
function createEmptyMigrationProjectManifest() {
|
|
1094
|
-
return {
|
|
1095
|
-
attributes: {},
|
|
1096
|
-
manifestVersion: 2,
|
|
1097
|
-
sourceType: null
|
|
1098
|
-
};
|
|
1099
|
-
}
|
|
1100
|
-
function writeInitialMigrationScaffold(projectDir, currentMigrationVersion, blocks) {
|
|
1101
|
-
const paths = getProjectPaths(projectDir);
|
|
1102
|
-
const readmeFiles = [
|
|
1103
|
-
[path5.join(paths.snapshotDir, "README.md"), `# Migration Version Snapshots
|
|
1104
|
-
|
|
1105
|
-
Snapshots for ${currentMigrationVersion} and future migration versions live here.
|
|
1106
|
-
`],
|
|
1107
|
-
[path5.join(paths.rulesDir, "README.md"), `# Migration Rules
|
|
1108
|
-
|
|
1109
|
-
Scaffold direct legacy-to-current migration rules in this directory.
|
|
1110
|
-
`],
|
|
1111
|
-
[path5.join(paths.fixturesDir, "README.md"), `# Migration Fixtures
|
|
1112
|
-
|
|
1113
|
-
Generated fixtures are used by verify to assert migrations.
|
|
1114
|
-
`]
|
|
1115
|
-
];
|
|
1116
|
-
for (const [targetPath, content] of readmeFiles) {
|
|
1117
|
-
if (!fs4.existsSync(targetPath)) {
|
|
1118
|
-
fs4.writeFileSync(targetPath, content, "utf8");
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
if (!Array.isArray(blocks) || blocks.length === 0) {
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
for (const block of blocks) {
|
|
1125
|
-
const scopedReadmes = [
|
|
1126
|
-
[path5.join(paths.rulesDir, block.key, "README.md"), `# ${block.blockName} Migration Rules
|
|
1127
|
-
|
|
1128
|
-
Scaffold direct legacy-to-current migration rules for ${block.blockName} in this directory.
|
|
1129
|
-
`],
|
|
1130
|
-
[path5.join(paths.fixturesDir, block.key, "README.md"), `# ${block.blockName} Migration Fixtures
|
|
1131
|
-
|
|
1132
|
-
Generated fixtures for ${block.blockName} are stored in this directory.
|
|
1133
|
-
`]
|
|
1134
|
-
];
|
|
1135
|
-
for (const [targetPath, content] of scopedReadmes) {
|
|
1136
|
-
if (!fs4.existsSync(targetPath)) {
|
|
1137
|
-
fs4.mkdirSync(path5.dirname(targetPath), { recursive: true });
|
|
1138
|
-
fs4.writeFileSync(targetPath, content, "utf8");
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
function findLegacySemverMigrationArtifacts(projectDir) {
|
|
1144
|
-
const paths = getProjectPaths(projectDir);
|
|
1145
|
-
const matches = [];
|
|
1146
|
-
if (fs4.existsSync(paths.snapshotDir)) {
|
|
1147
|
-
for (const entry of fs4.readdirSync(paths.snapshotDir, { withFileTypes: true })) {
|
|
1148
|
-
if (entry.isDirectory() && isLegacySemverMigrationVersion(entry.name)) {
|
|
1149
|
-
matches.push(normalizeRelativePath(path5.join(SNAPSHOT_DIR, entry.name)));
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
const scanEdgeDir = (directory, relativeRoot) => {
|
|
1154
|
-
if (!fs4.existsSync(directory)) {
|
|
1155
|
-
return;
|
|
1156
|
-
}
|
|
1157
|
-
const walk = (currentDir, currentRelativeDir) => {
|
|
1158
|
-
for (const entry of fs4.readdirSync(currentDir, { withFileTypes: true })) {
|
|
1159
|
-
if (entry.isDirectory()) {
|
|
1160
|
-
walk(path5.join(currentDir, entry.name), path5.join(currentRelativeDir, entry.name));
|
|
1161
|
-
continue;
|
|
1162
|
-
}
|
|
1163
|
-
if (LEGACY_VERSIONED_EDGE_FILE_PATTERN.test(entry.name)) {
|
|
1164
|
-
matches.push(normalizeRelativePath(path5.join(currentRelativeDir, entry.name)));
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
};
|
|
1168
|
-
walk(directory, relativeRoot);
|
|
1169
|
-
};
|
|
1170
|
-
scanEdgeDir(paths.rulesDir, RULES_DIR);
|
|
1171
|
-
scanEdgeDir(paths.fixturesDir, FIXTURES_DIR);
|
|
1172
|
-
return matches;
|
|
1173
|
-
}
|
|
1174
|
-
function assertNoLegacySemverMigrationWorkspace(projectDir) {
|
|
1175
|
-
const paths = getProjectPaths(projectDir);
|
|
1176
|
-
if (fs4.existsSync(paths.configFile)) {
|
|
1177
|
-
const source = fs4.readFileSync(paths.configFile, "utf8");
|
|
1178
|
-
if (hasLegacyConfigKeys(source)) {
|
|
1179
|
-
throw createLegacyMigrationWorkspaceResetError("Detected legacy config keys `currentVersion` / `supportedVersions` in `src/migrations/config.ts`.");
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
const artifactMatches = findLegacySemverMigrationArtifacts(projectDir);
|
|
1183
|
-
if (artifactMatches.length > 0) {
|
|
1184
|
-
throw createLegacyMigrationWorkspaceResetError(`Detected legacy semver-named migration artifacts: ${artifactMatches.join(", ")}.`);
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
function loadMigrationProject(projectDir, {
|
|
1188
|
-
allowMissingConfig = false,
|
|
1189
|
-
allowSyncTypes = true
|
|
1190
|
-
} = {}) {
|
|
1191
|
-
assertNoLegacySemverMigrationWorkspace(projectDir);
|
|
1192
|
-
ensureAdvancedMigrationProject(projectDir);
|
|
1193
|
-
const paths = getProjectPaths(projectDir);
|
|
1194
|
-
const config = allowMissingConfig && !fs4.existsSync(paths.configFile) ? {
|
|
1195
|
-
blocks: [createImplicitLegacyBlock(projectDir)],
|
|
1196
|
-
currentMigrationVersion: "v1",
|
|
1197
|
-
snapshotDir: SNAPSHOT_DIR.replace(/\\/g, "/"),
|
|
1198
|
-
supportedMigrationVersions: []
|
|
1199
|
-
} : parseMigrationConfig(fs4.readFileSync(paths.configFile, "utf8"));
|
|
1200
|
-
const configuredBlocks = config.blocks === undefined ? [createImplicitLegacyBlock(projectDir, config.blockName)] : config.blocks;
|
|
1201
|
-
const missingManifestFiles = configuredBlocks.filter((block) => !fs4.existsSync(path5.join(projectDir, block.manifestFile))).map((block) => block.manifestFile);
|
|
1202
|
-
if (missingManifestFiles.length > 0) {
|
|
1203
|
-
if (!allowSyncTypes) {
|
|
1204
|
-
throw new Error("Migration planning is read-only and cannot run `sync-types` automatically. " + `Missing current manifest file(s): ${missingManifestFiles.join(", ")}. ` + "Run your project's `sync-types` script in the project root first, then rerun the planning command.");
|
|
1205
|
-
}
|
|
1206
|
-
runProjectScriptIfPresent(projectDir, "sync-types");
|
|
1207
|
-
const remainingManifestFiles = configuredBlocks.filter((block) => !fs4.existsSync(path5.join(projectDir, block.manifestFile))).map((block) => block.manifestFile);
|
|
1208
|
-
if (remainingManifestFiles.length > 0) {
|
|
1209
|
-
throw new Error(`Missing current manifest file(s): ${remainingManifestFiles.join(", ")}. ` + "Run your project's `sync-types` script in the project root first, then retry.");
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
const blocks = resolveMigrationBlocks(projectDir, config);
|
|
1213
|
-
return {
|
|
1214
|
-
blocks,
|
|
1215
|
-
config,
|
|
1216
|
-
currentBlockJson: blocks[0]?.currentBlockJson ?? (config.blocks !== undefined ? createEmptyMigrationProjectBlockJson() : readJson(path5.join(projectDir, ROOT_BLOCK_JSON))),
|
|
1217
|
-
currentManifest: blocks[0]?.currentManifest ?? (config.blocks !== undefined ? createEmptyMigrationProjectManifest() : readJson(path5.join(projectDir, ROOT_MANIFEST))),
|
|
1218
|
-
paths,
|
|
1219
|
-
projectDir
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1222
|
-
function writeMigrationConfig(projectDir, config) {
|
|
1223
|
-
const paths = getProjectPaths(projectDir);
|
|
1224
|
-
fs4.mkdirSync(path5.dirname(paths.configFile), { recursive: true });
|
|
1225
|
-
if (!Array.isArray(config.blocks)) {
|
|
1226
|
-
fs4.writeFileSync(paths.configFile, `export const migrationConfig = {
|
|
1227
|
-
blockName: '${config.blockName ?? readProjectBlockName(projectDir)}',
|
|
1228
|
-
currentMigrationVersion: '${config.currentMigrationVersion}',
|
|
1229
|
-
supportedMigrationVersions: [ ${config.supportedMigrationVersions.map((version) => `'${version}'`).join(", ")} ],
|
|
1230
|
-
snapshotDir: '${config.snapshotDir}',
|
|
1231
|
-
} as const;
|
|
1232
|
-
|
|
1233
|
-
export default migrationConfig;
|
|
1234
|
-
`, "utf8");
|
|
1235
|
-
return;
|
|
1236
|
-
}
|
|
1237
|
-
const blocksSource = config.blocks.map((block) => ` {
|
|
1238
|
-
key: '${block.key}',
|
|
1239
|
-
blockName: '${block.blockName}',
|
|
1240
|
-
blockJsonFile: '${normalizeRelativePath(block.blockJsonFile)}',
|
|
1241
|
-
manifestFile: '${normalizeRelativePath(block.manifestFile)}',
|
|
1242
|
-
saveFile: '${normalizeRelativePath(block.saveFile)}',
|
|
1243
|
-
typesFile: '${normalizeRelativePath(block.typesFile)}',
|
|
1244
|
-
},`).join(`
|
|
1245
|
-
`);
|
|
1246
|
-
fs4.writeFileSync(paths.configFile, `export const migrationConfig = {
|
|
1247
|
-
currentMigrationVersion: '${config.currentMigrationVersion}',
|
|
1248
|
-
supportedMigrationVersions: [ ${config.supportedMigrationVersions.map((version) => `'${version}'`).join(", ")} ],
|
|
1249
|
-
snapshotDir: '${config.snapshotDir}',
|
|
1250
|
-
blocks: [
|
|
1251
|
-
${blocksSource}
|
|
1252
|
-
],
|
|
1253
|
-
} as const;
|
|
1254
|
-
|
|
1255
|
-
export default migrationConfig;
|
|
1256
|
-
`, "utf8");
|
|
1257
|
-
}
|
|
1258
|
-
export { isPlainObject, stableJsonStringify, getValueAtPath, setValueAtPath, deleteValueAtPath, createFixtureScalarValue, createTransformFixtureValue, readJson, renderPhpValue, copyFile, sanitizeSaveSnapshotSource, sanitizeSnapshotBlockJson, runProjectScriptIfPresent, detectPackageManagerId, getLocalTsxBinary, isInteractiveTerminal, resolveTargetMigrationVersion, assertMigrationVersionLabel, compareMigrationVersionLabels, formatLegacyMigrationWorkspaceResetGuidance, escapeForCode, renderObjectKey, isNumber, parseMigrationConfig, ROOT_PHP_MIGRATION_REGISTRY, SNAPSHOT_DIR, MIGRATION_TODO_PREFIX, ensureAdvancedMigrationProject, discoverMigrationInitLayout, getProjectPaths, getSnapshotRoot, getSnapshotBlockJsonPath, getSnapshotManifestPath, getAvailableSnapshotVersionsForBlock, createMissingBlockSnapshotMessage, getSnapshotSavePath, getGeneratedDirForBlock, getRuleFilePath, getFixtureFilePath, ensureMigrationDirectories, discoverMigrationEntries, assertRuleHasNoTodos, readRuleMetadata, writeInitialMigrationScaffold, assertNoLegacySemverMigrationWorkspace, loadMigrationProject, writeMigrationConfig };
|
|
1259
|
-
|
|
1260
|
-
//# debugId=595C3CACBE984E6464756E2164756E21
|