wp-typia 0.23.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +2 -1
  2. package/bin/routing-metadata.generated.js +4 -0
  3. package/dist-bunli/.bunli/commands.gen.js +4103 -3086
  4. package/dist-bunli/{cli-hhp1d348.js → cli-1170yyve.js} +8 -7
  5. package/dist-bunli/{cli-qse6myha.js → cli-8hxf9qw6.js} +11 -3
  6. package/dist-bunli/{cli-8reep89s.js → cli-9fx0qgb7.js} +2 -2
  7. package/dist-bunli/{cli-add-21bvpfgw.js → cli-add-xjaaa01x.js} +1560 -1525
  8. package/dist-bunli/{cli-52ke0ptp.js → cli-am5x7tb4.js} +8 -2
  9. package/dist-bunli/cli-ccax7s0s.js +34 -0
  10. package/dist-bunli/{cli-diagnostics-5dvztm7q.js → cli-diagnostics-10drxh34.js} +1 -1
  11. package/dist-bunli/{cli-doctor-wy2yjsge.js → cli-doctor-19e8313m.js} +602 -459
  12. package/dist-bunli/{cli-2rqf6t0b.js → cli-e4bwd81c.js} +8 -11
  13. package/dist-bunli/{cli-9npd9was.js → cli-epsczb1c.js} +12 -10
  14. package/dist-bunli/{cli-agywa5n6.js → cli-fp16mntv.js} +8 -4
  15. package/dist-bunli/{cli-init-xnsbxncv.js → cli-init-2b4yn2cc.js} +14 -10
  16. package/dist-bunli/{cli-ts9thts5.js → cli-k5q5v8g6.js} +184 -162
  17. package/dist-bunli/{cli-c2acv5dv.js → cli-nvs5atj1.js} +2 -2
  18. package/dist-bunli/{cli-prompt-614tq57c.js → cli-prompt-ncyg68rn.js} +1 -1
  19. package/dist-bunli/{cli-bq2v559b.js → cli-rdcga1bd.js} +31 -13
  20. package/dist-bunli/{cli-scaffold-zhp2ym8z.js → cli-scaffold-4tjw4jk5.js} +27 -15
  21. package/dist-bunli/{cli-templates-hc71dfc2.js → cli-templates-g8t4fm11.js} +3 -2
  22. package/dist-bunli/{cli-p95wr1q8.js → cli-tq730sqt.js} +6 -3
  23. package/dist-bunli/{cli-1meywwsy.js → cli-y7w3pybs.js} +848 -246
  24. package/dist-bunli/{cli-z5qkx2pn.js → cli-ymecd15q.js} +37 -10
  25. package/dist-bunli/cli.js +4 -4
  26. package/dist-bunli/{command-list-aqrkx021.js → command-list-vme7dr5v.js} +81 -45
  27. package/dist-bunli/{create-template-validation-rtec5sng.js → create-template-validation-4fr851vg.js} +5 -4
  28. package/dist-bunli/{migrations-bx0yvc2v.js → migrations-pb5vvtdp.js} +9 -8
  29. package/dist-bunli/node-cli.js +399 -317
  30. package/dist-bunli/{workspace-project-csnnggz6.js → workspace-project-gmv2a71z.js} +4 -3
  31. package/package.json +2 -2
@@ -4,7 +4,7 @@ import {
4
4
  parseTemplateLocator,
5
5
  require_semver,
6
6
  validateExplicitCreateTemplateId
7
- } from "./cli-8reep89s.js";
7
+ } from "./cli-9fx0qgb7.js";
8
8
  import {
9
9
  getBuiltInSharedTemplateLayerDir,
10
10
  getBuiltInTemplateLayerDirs,
@@ -14,10 +14,10 @@ import {
14
14
  isOmittableBuiltInTemplateLayerDir,
15
15
  resolveBuiltInTemplateSource,
16
16
  resolveBuiltInTemplateSourceFromLayerDirs
17
- } from "./cli-c2acv5dv.js";
17
+ } from "./cli-nvs5atj1.js";
18
18
  import {
19
19
  getPackageVersions
20
- } from "./cli-agywa5n6.js";
20
+ } from "./cli-fp16mntv.js";
21
21
  import {
22
22
  BUILTIN_BLOCK_METADATA_VERSION,
23
23
  COMPOUND_CHILD_BLOCK_METADATA_DEFAULTS,
@@ -32,18 +32,20 @@ import {
32
32
  getTemplateById,
33
33
  isBuiltInTemplateId,
34
34
  normalizeTemplateLookupId
35
- } from "./cli-qse6myha.js";
35
+ } from "./cli-8hxf9qw6.js";
36
36
  import {
37
37
  seedProjectMigrations
38
- } from "./cli-9npd9was.js";
38
+ } from "./cli-epsczb1c.js";
39
39
  import {
40
40
  ensureMigrationDirectories,
41
41
  isPlainObject,
42
42
  stableJsonStringify,
43
43
  writeInitialMigrationScaffold,
44
44
  writeMigrationConfig
45
- } from "./cli-2rqf6t0b.js";
45
+ } from "./cli-e4bwd81c.js";
46
46
  import {
47
+ assertValidGeneratedSlug,
48
+ assertValidIntegrationEnvService,
47
49
  buildBlockCssClassName,
48
50
  buildFrontendCssClassName,
49
51
  getNodeErrorCode,
@@ -52,20 +54,25 @@ import {
52
54
  pathExists,
53
55
  readOptionalUtf8File,
54
56
  resolveScaffoldIdentifiers,
57
+ rollbackWorkspaceMutation,
58
+ snapshotWorkspaceFiles,
55
59
  toPascalCase,
56
60
  toSegmentPascalCase,
57
61
  toSnakeCase,
58
62
  toTitleCase,
59
63
  validateBlockSlug,
60
64
  validateNamespace
61
- } from "./cli-ts9thts5.js";
65
+ } from "./cli-k5q5v8g6.js";
62
66
  import {
63
67
  createManagedTempRoot
64
68
  } from "./cli-t73q5aqz.js";
65
69
  import {
66
70
  CLI_DIAGNOSTIC_CODES,
67
71
  createCliDiagnosticCodeError
68
- } from "./cli-p95wr1q8.js";
72
+ } from "./cli-tq730sqt.js";
73
+ import {
74
+ resolveWorkspaceProject
75
+ } from "./cli-1170yyve.js";
69
76
  import {
70
77
  PACKAGE_MANAGER_IDS,
71
78
  formatInstallCommand,
@@ -73,7 +80,12 @@ import {
73
80
  formatRunScript,
74
81
  getPackageManager,
75
82
  transformPackageManagerText
76
- } from "./cli-52ke0ptp.js";
83
+ } from "./cli-am5x7tb4.js";
84
+ import {
85
+ readJsonFile,
86
+ readJsonFileSync,
87
+ safeJsonParse
88
+ } from "./cli-ccax7s0s.js";
77
89
  import {
78
90
  __toESM
79
91
  } from "./cli-xnn9xjcy.js";
@@ -754,7 +766,9 @@ function getDevScript(packageManager, compoundPersistenceEnabled, templateId) {
754
766
  }
755
767
  async function mutatePackageJson(projectDir, mutate) {
756
768
  const packageJsonPath = path2.join(projectDir, "package.json");
757
- const packageJson = JSON.parse(await fsp2.readFile(packageJsonPath, "utf8"));
769
+ const packageJson = await readJsonFile(packageJsonPath, {
770
+ context: "local dev package manifest"
771
+ });
758
772
  mutate(packageJson);
759
773
  await fsp2.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
760
774
  `, "utf8");
@@ -2189,7 +2203,9 @@ function readGeneratedPackageJson(projectDir) {
2189
2203
  if (!fs2.existsSync(packageJsonPath)) {
2190
2204
  return null;
2191
2205
  }
2192
- return JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
2206
+ return readJsonFileSync(packageJsonPath, {
2207
+ context: "generated package manifest"
2208
+ });
2193
2209
  }
2194
2210
  function formatNonEmptyTargetDirectoryError(targetDir) {
2195
2211
  return `Target directory is not empty: ${targetDir}. Choose a new project directory, or empty this directory before rerunning the scaffold.`;
@@ -2231,7 +2247,9 @@ function isWorkspaceProject(projectDir) {
2231
2247
  }
2232
2248
  async function applyWorkspaceMigrationCapability(projectDir, packageManager) {
2233
2249
  const packageJsonPath = path4.join(projectDir, "package.json");
2234
- const packageJson = JSON.parse(await fsp3.readFile(packageJsonPath, "utf8"));
2250
+ const packageJson = await readJsonFile(packageJsonPath, {
2251
+ context: "workspace package manifest"
2252
+ });
2235
2253
  const wpTypiaPackageVersion = getPackageVersions().wpTypiaPackageVersion;
2236
2254
  const canonicalCliSpecifier = wpTypiaPackageVersion === "^0.0.0" ? "wp-typia" : `wp-typia@${wpTypiaPackageVersion.replace(/^[~^]/u, "")}`;
2237
2255
  const migrationCli = (args) => formatPackageExecCommand(packageManager, canonicalCliSpecifier, `migrate ${args}`);
@@ -2288,9 +2306,521 @@ async function withEphemeralScaffoldNodeModules(targetDir, callback) {
2288
2306
  }
2289
2307
  }
2290
2308
 
2309
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env.ts
2310
+ import { promises as fsp4 } from "fs";
2311
+ import path5 from "path";
2312
+
2313
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-mutation.ts
2314
+ var DEFAULT_PHP_SNIPPET_INSERTION_ANCHORS = [
2315
+ /add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
2316
+ /\?>\s*$/u
2317
+ ];
2318
+
2319
+ class WorkspaceMutationRollbackError extends Error {
2320
+ mutationError;
2321
+ rollbackError;
2322
+ constructor(mutationError, rollbackError) {
2323
+ super("Workspace mutation failed and rollback also failed.");
2324
+ this.name = "WorkspaceMutationRollbackError";
2325
+ this.mutationError = mutationError;
2326
+ this.rollbackError = rollbackError;
2327
+ }
2328
+ }
2329
+ async function executeWorkspaceMutationPlan({
2330
+ filePaths,
2331
+ run,
2332
+ snapshotDirs = [],
2333
+ targetPaths = []
2334
+ }) {
2335
+ const mutationSnapshot = {
2336
+ fileSources: await snapshotWorkspaceFiles(filePaths),
2337
+ snapshotDirs: [...snapshotDirs],
2338
+ targetPaths: [...targetPaths]
2339
+ };
2340
+ try {
2341
+ return await run();
2342
+ } catch (error) {
2343
+ try {
2344
+ await rollbackWorkspaceMutation(mutationSnapshot);
2345
+ } catch (rollbackError) {
2346
+ throw new WorkspaceMutationRollbackError(error, rollbackError);
2347
+ }
2348
+ throw error;
2349
+ }
2350
+ }
2351
+ function insertPhpSnippetBeforeWorkspaceAnchors(source, snippet) {
2352
+ for (const anchor of DEFAULT_PHP_SNIPPET_INSERTION_ANCHORS) {
2353
+ const candidate = source.replace(anchor, (match) => `${snippet}
2354
+ ${match}`);
2355
+ if (candidate !== source) {
2356
+ return candidate;
2357
+ }
2358
+ }
2359
+ return `${source.trimEnd()}
2360
+ ${snippet}
2361
+ `;
2362
+ }
2363
+ function appendPhpSnippetBeforeClosingTag(source, snippet) {
2364
+ const closingTagPattern = /\?>\s*$/u;
2365
+ if (closingTagPattern.test(source)) {
2366
+ return source.replace(closingTagPattern, `${snippet}
2367
+ ?>`);
2368
+ }
2369
+ return `${source.trimEnd()}
2370
+ ${snippet}
2371
+ `;
2372
+ }
2373
+
2374
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env.ts
2375
+ var WP_ENV_PACKAGE_VERSION = "^11.2.0";
2376
+ function buildWpEnvConfigSource() {
2377
+ return `${JSON.stringify({
2378
+ $schema: "https://schemas.wp.org/trunk/wp-env.json",
2379
+ core: null,
2380
+ port: 8888,
2381
+ testsEnvironment: false,
2382
+ plugins: ["."],
2383
+ config: {
2384
+ WP_DEBUG: true,
2385
+ WP_DEBUG_LOG: true,
2386
+ WP_DEBUG_DISPLAY: false,
2387
+ SCRIPT_DEBUG: true,
2388
+ WP_ENVIRONMENT_TYPE: "local"
2389
+ }
2390
+ }, null, 2)}
2391
+ `;
2392
+ }
2393
+ function buildDockerComposeSource() {
2394
+ return `services:
2395
+ integration-service:
2396
+ image: node:22-alpine
2397
+ working_dir: /workspace
2398
+ volumes:
2399
+ - .:/workspace
2400
+ command: >
2401
+ node -e "require('node:http').createServer((request, response) => {
2402
+ response.writeHead(request.url === '/health' ? 200 : 404, {
2403
+ 'content-type': 'application/json'
2404
+ });
2405
+ response.end(JSON.stringify({
2406
+ ok: request.url === '/health',
2407
+ service: 'wp-typia-integration-starter'
2408
+ }));
2409
+ }).listen(3000, '0.0.0.0')"
2410
+ ports:
2411
+ - "3000:3000"
2412
+ `;
2413
+ }
2414
+ function buildIntegrationSmokeScriptSource(integrationEnvSlug) {
2415
+ return `import fs from "node:fs";
2416
+ import path from "node:path";
2417
+ import { fileURLToPath } from "node:url";
2418
+
2419
+ const ROOT_DIR = path.resolve(
2420
+ fileURLToPath(new URL("../..", import.meta.url)),
2421
+ );
2422
+ const ENV_FILE = path.join(ROOT_DIR, ".env");
2423
+
2424
+ function parseEnvValue(value) {
2425
+ const trimmed = value.trim();
2426
+ if (
2427
+ (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
2428
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))
2429
+ ) {
2430
+ return trimmed.slice(1, -1);
2431
+ }
2432
+
2433
+ return trimmed;
2434
+ }
2435
+
2436
+ function readEnvFile(filePath) {
2437
+ if (!fs.existsSync(filePath)) {
2438
+ return {};
2439
+ }
2440
+
2441
+ return Object.fromEntries(
2442
+ fs
2443
+ .readFileSync(filePath, "utf8")
2444
+ .split(/\\r?\\n/u)
2445
+ .map((line) => line.trim())
2446
+ .filter((line) => line.length > 0 && !line.startsWith("#"))
2447
+ .map((line) => {
2448
+ const separatorIndex = line.indexOf("=");
2449
+ if (separatorIndex === -1) {
2450
+ return null;
2451
+ }
2452
+
2453
+ return [
2454
+ line.slice(0, separatorIndex).trim(),
2455
+ parseEnvValue(line.slice(separatorIndex + 1)),
2456
+ ];
2457
+ })
2458
+ .filter(Boolean),
2459
+ );
2460
+ }
2461
+
2462
+ const envFile = readEnvFile(ENV_FILE);
2463
+
2464
+ function getEnv(name, fallback) {
2465
+ return process.env[name] ?? envFile[name] ?? fallback;
2466
+ }
2467
+
2468
+ function resolveEndpointUrl(baseUrl, endpointPath) {
2469
+ const normalizedBaseUrl = new URL(baseUrl);
2470
+ if (!normalizedBaseUrl.pathname.endsWith("/")) {
2471
+ normalizedBaseUrl.pathname = \`\${normalizedBaseUrl.pathname}/\`;
2472
+ }
2473
+
2474
+ const relativePath = endpointPath.replace(/^\\/+/u, "");
2475
+ return new URL(relativePath, normalizedBaseUrl);
2476
+ }
2477
+
2478
+ async function assertJsonEndpoint(label, url) {
2479
+ const response = await fetch(url, {
2480
+ headers: {
2481
+ accept: "application/json",
2482
+ },
2483
+ });
2484
+
2485
+ if (!response.ok) {
2486
+ throw new Error(
2487
+ \`\${label} failed at \${url} with HTTP \${response.status}.\`,
2488
+ );
2489
+ }
2490
+
2491
+ const contentType = response.headers.get("content-type") ?? "";
2492
+ if (!contentType.includes("application/json")) {
2493
+ throw new Error(
2494
+ \`\${label} at \${url} did not return JSON (content-type: \${contentType || "missing"}).\`,
2495
+ );
2496
+ }
2497
+
2498
+ return response.json();
2499
+ }
2500
+
2501
+ const baseUrl = new URL(
2502
+ getEnv("WP_TYPIA_SMOKE_BASE_URL", "http://localhost:8888"),
2503
+ );
2504
+ const serviceUrl = getEnv("WP_TYPIA_SERVICE_URL", "").trim();
2505
+
2506
+ // Extend this starter with project-specific generated REST clients or schema
2507
+ // checks as the workspace grows. For example, read JSON schemas under
2508
+ // src/rest/<resource>/api-schemas or import TS clients through a tsx-powered
2509
+ // smoke runner when you need authenticated route coverage.
2510
+
2511
+ await assertJsonEndpoint(
2512
+ "WordPress REST index",
2513
+ resolveEndpointUrl(baseUrl, "wp-json/"),
2514
+ );
2515
+
2516
+ if (serviceUrl.length > 0) {
2517
+ await assertJsonEndpoint(
2518
+ "Local integration service healthcheck",
2519
+ resolveEndpointUrl(serviceUrl, "health"),
2520
+ );
2521
+ }
2522
+
2523
+ console.log("wp-typia integration smoke passed: ${integrationEnvSlug}");
2524
+ `;
2525
+ }
2526
+ function buildEnvExampleSource(service) {
2527
+ return [
2528
+ "# wp-typia integration smoke settings",
2529
+ "WP_TYPIA_SMOKE_BASE_URL=http://localhost:8888",
2530
+ "WP_TYPIA_SMOKE_USERNAME=admin",
2531
+ "WP_TYPIA_SMOKE_PASSWORD=password",
2532
+ ...service === "docker-compose" ? [
2533
+ "",
2534
+ "# Optional docker-compose integration service starter.",
2535
+ "WP_TYPIA_SERVICE_URL=http://localhost:3000"
2536
+ ] : [
2537
+ "",
2538
+ "# Set this when your smoke test needs a project-specific service.",
2539
+ "# WP_TYPIA_SERVICE_URL=http://localhost:3000"
2540
+ ],
2541
+ ""
2542
+ ].join(`
2543
+ `);
2544
+ }
2545
+ function buildIntegrationEnvReadmeSource({
2546
+ integrationEnvSlug,
2547
+ service,
2548
+ withReleaseZip,
2549
+ withWpEnv
2550
+ }) {
2551
+ const title = toTitleCase(integrationEnvSlug);
2552
+ const setupSteps = [
2553
+ "Copy `.env.example` to `.env` and adjust the URLs or credentials for your local project.",
2554
+ ...withWpEnv ? [
2555
+ "Run `npm run wp-env:start` to start the generated WordPress environment."
2556
+ ] : [
2557
+ "Point `WP_TYPIA_SMOKE_BASE_URL` at the WordPress environment you already run locally."
2558
+ ],
2559
+ ...service === "docker-compose" ? [
2560
+ "Run `npm run service:start` if you want the placeholder docker-compose service available at `WP_TYPIA_SERVICE_URL`."
2561
+ ] : [
2562
+ "Set `WP_TYPIA_SERVICE_URL` only when your integration smoke needs a local service dependency."
2563
+ ],
2564
+ `Run \`npm run smoke:${integrationEnvSlug}\` to execute the starter smoke check.`,
2565
+ ...withReleaseZip ? [
2566
+ "Run `npm run release:zip` after smoke checks pass to build a distributable plugin zip."
2567
+ ] : []
2568
+ ];
2569
+ return `# ${title} Integration Environment
2570
+
2571
+ This starter keeps local WordPress integration smoke checks opt-in and editable.
2572
+ It does not change default block scaffolds or require wp-env unless this add
2573
+ workflow was run with \`--wp-env\`.
2574
+
2575
+ ## Setup
2576
+
2577
+ ${setupSteps.map((step, index) => `${index + 1}. ${step}`).join(`
2578
+ `)}
2579
+
2580
+ ## Adapting the Starter
2581
+
2582
+ - Extend \`scripts/integration-smoke/${integrationEnvSlug}.mjs\` with the REST,
2583
+ editor, or service assertions that matter for this project.
2584
+ - Keep secrets in \`.env\`; \`.env.example\` should document only safe defaults.
2585
+ - If your project uses a real service stack, replace the placeholder
2586
+ \`docker-compose.integration.yml\` service with your database, queue, API, or
2587
+ emulator containers.
2588
+ - Keep the smoke script focused on high-signal integration checks so CI and
2589
+ local debugging stay fast.
2590
+ ${withReleaseZip ? "- Treat `release:zip:check` as a CI guard before packaging release artifacts.\n" : ""}
2591
+ `;
2592
+ }
2593
+ async function appendMissingLines(filePath, lines) {
2594
+ const current = await readOptionalUtf8File(filePath) ?? "";
2595
+ const missingLines = lines.filter((line) => !current.includes(`${line}
2596
+ `) && !current.endsWith(line));
2597
+ if (missingLines.length === 0) {
2598
+ return;
2599
+ }
2600
+ const separator = current.length === 0 || current.endsWith(`
2601
+ `) ? "" : `
2602
+ `;
2603
+ await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2604
+ await fsp4.writeFile(filePath, `${current}${separator}${missingLines.join(`
2605
+ `)}
2606
+ `, "utf8");
2607
+ }
2608
+ async function writeFileIfAbsent({
2609
+ filePath,
2610
+ source,
2611
+ warnings
2612
+ }) {
2613
+ if (await pathExists(filePath)) {
2614
+ warnings.push(`Preserved existing ${path5.basename(filePath)}; review it manually if you need different local integration settings.`);
2615
+ return;
2616
+ }
2617
+ await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2618
+ await fsp4.writeFile(filePath, source, "utf8");
2619
+ }
2620
+ async function writeNewScaffoldFile(filePath, source) {
2621
+ if (await pathExists(filePath)) {
2622
+ throw new Error(`An integration environment scaffold already exists at ${filePath}. Choose a different name.`);
2623
+ }
2624
+ await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2625
+ await fsp4.writeFile(filePath, source, "utf8");
2626
+ }
2627
+ function addScriptIfMissing({
2628
+ scriptName,
2629
+ scripts,
2630
+ scriptValue,
2631
+ warnings
2632
+ }) {
2633
+ if (scripts[scriptName] === undefined) {
2634
+ scripts[scriptName] = scriptValue;
2635
+ return;
2636
+ }
2637
+ if (scripts[scriptName] !== scriptValue) {
2638
+ warnings.push(`Preserved existing package script "${scriptName}"; add "${scriptValue}" manually if you want the generated integration command.`);
2639
+ }
2640
+ }
2641
+ async function mutatePackageJson2(projectDir, mutate) {
2642
+ const packageJsonPath = path5.join(projectDir, "package.json");
2643
+ const packageJson = await readJsonFile(packageJsonPath, {
2644
+ context: "integration env package manifest"
2645
+ });
2646
+ mutate(packageJson);
2647
+ await fsp4.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
2648
+ `, "utf8");
2649
+ }
2650
+ function addIntegrationEnvPackageJsonEntries({
2651
+ integrationEnvSlug,
2652
+ packageManager,
2653
+ packageJson,
2654
+ withReleaseZip,
2655
+ service,
2656
+ warnings,
2657
+ withWpEnv
2658
+ }) {
2659
+ const devDependencies = {
2660
+ ...packageJson.devDependencies ?? {}
2661
+ };
2662
+ if (withWpEnv && devDependencies["@wordpress/env"] === undefined) {
2663
+ devDependencies["@wordpress/env"] = WP_ENV_PACKAGE_VERSION;
2664
+ }
2665
+ packageJson.devDependencies = devDependencies;
2666
+ const scripts = {
2667
+ ...packageJson.scripts ?? {}
2668
+ };
2669
+ addScriptIfMissing({
2670
+ scriptName: `smoke:${integrationEnvSlug}`,
2671
+ scriptValue: `node scripts/integration-smoke/${integrationEnvSlug}.mjs`,
2672
+ scripts,
2673
+ warnings
2674
+ });
2675
+ addScriptIfMissing({
2676
+ scriptName: "smoke:integration",
2677
+ scriptValue: formatRunScript(packageManager, `smoke:${integrationEnvSlug}`),
2678
+ scripts,
2679
+ warnings
2680
+ });
2681
+ if (withWpEnv) {
2682
+ addScriptIfMissing({
2683
+ scriptName: "wp-env:start",
2684
+ scriptValue: "wp-env start",
2685
+ scripts,
2686
+ warnings
2687
+ });
2688
+ addScriptIfMissing({
2689
+ scriptName: "wp-env:stop",
2690
+ scriptValue: "wp-env stop",
2691
+ scripts,
2692
+ warnings
2693
+ });
2694
+ addScriptIfMissing({
2695
+ scriptName: "wp-env:reset",
2696
+ scriptValue: "wp-env destroy all && wp-env start",
2697
+ scripts,
2698
+ warnings
2699
+ });
2700
+ }
2701
+ if (withReleaseZip) {
2702
+ addScriptIfMissing({
2703
+ scriptName: "release:zip",
2704
+ scriptValue: `${formatRunScript(packageManager, "sync-rest:package")} && ${formatRunScript(packageManager, "build")} && wp-scripts plugin-zip`,
2705
+ scripts,
2706
+ warnings
2707
+ });
2708
+ addScriptIfMissing({
2709
+ scriptName: "release:zip:check",
2710
+ scriptValue: `${formatRunScript(packageManager, "sync-rest:package:check")} && ${formatRunScript(packageManager, "build")}`,
2711
+ scripts,
2712
+ warnings
2713
+ });
2714
+ addScriptIfMissing({
2715
+ scriptName: "qa:check",
2716
+ scriptValue: `${formatRunScript(packageManager, "wp-typia:doctor:workspace")} && ${formatRunScript(packageManager, "release:zip:check")}`,
2717
+ scripts,
2718
+ warnings
2719
+ });
2720
+ }
2721
+ if (service === "docker-compose") {
2722
+ addScriptIfMissing({
2723
+ scriptName: "service:start",
2724
+ scriptValue: "docker compose -f docker-compose.integration.yml up -d",
2725
+ scripts,
2726
+ warnings
2727
+ });
2728
+ addScriptIfMissing({
2729
+ scriptName: "service:stop",
2730
+ scriptValue: "docker compose -f docker-compose.integration.yml down",
2731
+ scripts,
2732
+ warnings
2733
+ });
2734
+ }
2735
+ packageJson.scripts = scripts;
2736
+ }
2737
+ async function runAddIntegrationEnvCommand({
2738
+ cwd = process.cwd(),
2739
+ integrationEnvName,
2740
+ service,
2741
+ withReleaseZip = false,
2742
+ withWpEnv = false
2743
+ }) {
2744
+ const workspace = resolveWorkspaceProject(cwd);
2745
+ const integrationEnvSlug = assertValidGeneratedSlug("Integration environment name", normalizeBlockSlug(integrationEnvName), "wp-typia add integration-env <name> [--wp-env] [--release-zip]");
2746
+ const serviceId = assertValidIntegrationEnvService(service);
2747
+ const warnings = [];
2748
+ const packageJsonPath = path5.join(workspace.projectDir, "package.json");
2749
+ const gitignorePath = path5.join(workspace.projectDir, ".gitignore");
2750
+ const envExamplePath = path5.join(workspace.projectDir, ".env.example");
2751
+ const wpEnvPath = path5.join(workspace.projectDir, ".wp-env.json");
2752
+ const dockerComposePath = path5.join(workspace.projectDir, "docker-compose.integration.yml");
2753
+ const smokeDir = path5.join(workspace.projectDir, "scripts", "integration-smoke");
2754
+ const docsDir = path5.join(workspace.projectDir, "docs", "integration-env");
2755
+ const smokeScriptPath = path5.join(smokeDir, `${integrationEnvSlug}.mjs`);
2756
+ const docsPath = path5.join(docsDir, `${integrationEnvSlug}.md`);
2757
+ const shouldRemoveSmokeDirOnRollback = !await pathExists(smokeDir);
2758
+ const shouldRemoveDocsDirOnRollback = !await pathExists(docsDir);
2759
+ await executeWorkspaceMutationPlan({
2760
+ filePaths: [
2761
+ packageJsonPath,
2762
+ gitignorePath,
2763
+ envExamplePath,
2764
+ ...withWpEnv ? [wpEnvPath] : [],
2765
+ ...serviceId === "docker-compose" ? [dockerComposePath] : []
2766
+ ],
2767
+ targetPaths: [
2768
+ smokeScriptPath,
2769
+ docsPath,
2770
+ ...shouldRemoveSmokeDirOnRollback ? [smokeDir] : [],
2771
+ ...shouldRemoveDocsDirOnRollback ? [docsDir] : []
2772
+ ],
2773
+ run: async () => {
2774
+ await writeNewScaffoldFile(smokeScriptPath, buildIntegrationSmokeScriptSource(integrationEnvSlug));
2775
+ await writeNewScaffoldFile(docsPath, buildIntegrationEnvReadmeSource({
2776
+ integrationEnvSlug,
2777
+ service: serviceId,
2778
+ withReleaseZip,
2779
+ withWpEnv
2780
+ }));
2781
+ await appendMissingLines(envExamplePath, [
2782
+ ...buildEnvExampleSource(serviceId).trimEnd().split(`
2783
+ `)
2784
+ ]);
2785
+ await appendMissingLines(gitignorePath, [".env", ".env.local"]);
2786
+ if (withWpEnv) {
2787
+ await writeFileIfAbsent({
2788
+ filePath: wpEnvPath,
2789
+ source: buildWpEnvConfigSource(),
2790
+ warnings
2791
+ });
2792
+ }
2793
+ if (serviceId === "docker-compose") {
2794
+ await writeFileIfAbsent({
2795
+ filePath: dockerComposePath,
2796
+ source: buildDockerComposeSource(),
2797
+ warnings
2798
+ });
2799
+ }
2800
+ await mutatePackageJson2(workspace.projectDir, (packageJson) => addIntegrationEnvPackageJsonEntries({
2801
+ integrationEnvSlug,
2802
+ packageManager: workspace.packageManager,
2803
+ packageJson,
2804
+ service: serviceId,
2805
+ withReleaseZip,
2806
+ warnings,
2807
+ withWpEnv
2808
+ }));
2809
+ }
2810
+ });
2811
+ return {
2812
+ integrationEnvSlug,
2813
+ projectDir: workspace.projectDir,
2814
+ service: serviceId,
2815
+ warnings: warnings.length > 0 ? warnings : undefined,
2816
+ withReleaseZip,
2817
+ withWpEnv
2818
+ };
2819
+ }
2820
+
2291
2821
  // ../wp-typia-project-tools/src/runtime/cli-validation.ts
2292
2822
  import fs3 from "fs";
2293
- import path5 from "path";
2823
+ import path6 from "path";
2294
2824
  function normalizeOptionalCliString(value) {
2295
2825
  if (typeof value !== "string") {
2296
2826
  return;
@@ -2299,14 +2829,14 @@ function normalizeOptionalCliString(value) {
2299
2829
  return trimmed.length > 0 ? trimmed : undefined;
2300
2830
  }
2301
2831
  function looksLikeLocalCliPath(value) {
2302
- return path5.isAbsolute(value) || value.startsWith("./") || value.startsWith("../") || value.startsWith(".\\") || value.startsWith("..\\");
2832
+ return path6.isAbsolute(value) || value.startsWith("./") || value.startsWith("../") || value.startsWith(".\\") || value.startsWith("..\\");
2303
2833
  }
2304
2834
  function resolveLocalCliPathOption(options) {
2305
2835
  const normalizedValue = normalizeOptionalCliString(options.value);
2306
2836
  if (!normalizedValue || !looksLikeLocalCliPath(normalizedValue)) {
2307
2837
  return normalizedValue;
2308
2838
  }
2309
- const resolvedPath = path5.resolve(options.cwd, normalizedValue);
2839
+ const resolvedPath = path6.resolve(options.cwd, normalizedValue);
2310
2840
  if (!fs3.existsSync(resolvedPath)) {
2311
2841
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
2312
2842
  }
@@ -2557,35 +3087,37 @@ async function collectScaffoldAnswers({
2557
3087
  }
2558
3088
 
2559
3089
  // ../wp-typia-project-tools/src/runtime/scaffold.ts
2560
- import { promises as fsp12 } from "fs";
2561
- import path17 from "path";
3090
+ import { promises as fsp13 } from "fs";
3091
+ import path18 from "path";
2562
3092
 
2563
3093
  // ../wp-typia-project-tools/src/runtime/scaffold-apply-utils.ts
2564
- import { promises as fsp6 } from "fs";
2565
- import path9 from "path";
3094
+ import { promises as fsp7 } from "fs";
3095
+ import path10 from "path";
2566
3096
  import { execSync as execSync3 } from "child_process";
2567
3097
  import { fileURLToPath } from "url";
2568
3098
 
2569
3099
  // ../wp-typia-project-tools/src/runtime/migration-ui-capability.ts
2570
- import { promises as fsp4 } from "fs";
2571
- import path6 from "path";
3100
+ import { promises as fsp5 } from "fs";
3101
+ import path7 from "path";
2572
3102
  var INITIAL_MIGRATION_VERSION = "v1";
2573
3103
  var BLOCK_METADATA_IMPORT_LINE = "import metadata from './block-metadata';";
2574
3104
  var LEGACY_BLOCK_JSON_IMPORT_LINE = "import metadata from './block.json';";
2575
- async function mutatePackageJson2(projectDir, mutate) {
2576
- const packageJsonPath = path6.join(projectDir, "package.json");
2577
- const packageJson = JSON.parse(await fsp4.readFile(packageJsonPath, "utf8"));
3105
+ async function mutatePackageJson3(projectDir, mutate) {
3106
+ const packageJsonPath = path7.join(projectDir, "package.json");
3107
+ const packageJson = await readJsonFile(packageJsonPath, {
3108
+ context: "migration UI package manifest"
3109
+ });
2578
3110
  mutate(packageJson);
2579
- await fsp4.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3111
+ await fsp5.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
2580
3112
  `, "utf8");
2581
3113
  }
2582
3114
  async function patchFile(filePath, transform) {
2583
- const source = await fsp4.readFile(filePath, "utf8");
3115
+ const source = await fsp5.readFile(filePath, "utf8");
2584
3116
  const nextSource = transform(source);
2585
3117
  if (nextSource === source) {
2586
3118
  throw new Error(`Unable to apply migration UI patch for ${filePath}`);
2587
3119
  }
2588
- await fsp4.writeFile(filePath, nextSource, "utf8");
3120
+ await fsp5.writeFile(filePath, nextSource, "utf8");
2589
3121
  }
2590
3122
  function injectAfter(source, needle, insertion) {
2591
3123
  if (source.includes(insertion)) {
@@ -2647,8 +3179,8 @@ function buildMigrationBlocks(templateId, variables) {
2647
3179
  ];
2648
3180
  }
2649
3181
  async function applySingleBlockPatches(projectDir, variables) {
2650
- const editPath = path6.join(projectDir, "src", "edit.tsx");
2651
- const indexPath = path6.join(projectDir, "src", "index.tsx");
3182
+ const editPath = path7.join(projectDir, "src", "edit.tsx");
3183
+ const indexPath = path7.join(projectDir, "src", "index.tsx");
2652
3184
  const deprecatedImport = `import { deprecated } from './migrations/generated/${variables.slugKebabCase}/deprecated';`;
2653
3185
  const deprecatedLine = " deprecated,";
2654
3186
  const dashboardImport = `import { MigrationDashboard } from './admin/migration-dashboard';`;
@@ -2669,10 +3201,10 @@ async function applySingleBlockPatches(projectDir, variables) {
2669
3201
  });
2670
3202
  }
2671
3203
  async function applyCompoundPatches(projectDir, variables) {
2672
- const parentEditPath = path6.join(projectDir, "src", "blocks", variables.slugKebabCase, "edit.tsx");
2673
- const parentIndexPath = path6.join(projectDir, "src", "blocks", variables.slugKebabCase, "index.tsx");
2674
- const childIndexPath = path6.join(projectDir, "src", "blocks", `${variables.slugKebabCase}-item`, "index.tsx");
2675
- const addChildScriptPath = path6.join(projectDir, "scripts", "add-compound-child.ts");
3204
+ const parentEditPath = path7.join(projectDir, "src", "blocks", variables.slugKebabCase, "edit.tsx");
3205
+ const parentIndexPath = path7.join(projectDir, "src", "blocks", variables.slugKebabCase, "index.tsx");
3206
+ const childIndexPath = path7.join(projectDir, "src", "blocks", `${variables.slugKebabCase}-item`, "index.tsx");
3207
+ const addChildScriptPath = path7.join(projectDir, "scripts", "add-compound-child.ts");
2676
3208
  await patchFile(parentIndexPath, (source) => {
2677
3209
  let nextSource = injectAfterBlockMetadataImport(source, `import { deprecated } from '../../migrations/generated/${variables.slugKebabCase}/deprecated';`);
2678
3210
  nextSource = injectBefore(nextSource, "\tedit: Edit,", "\tdeprecated,");
@@ -2742,9 +3274,9 @@ async function applyMigrationUiCapability({
2742
3274
  templateId,
2743
3275
  variables
2744
3276
  }) {
2745
- const commonTemplateDir = path6.join(SHARED_MIGRATION_UI_TEMPLATE_ROOT, "common");
3277
+ const commonTemplateDir = path7.join(SHARED_MIGRATION_UI_TEMPLATE_ROOT, "common");
2746
3278
  await copyInterpolatedDirectory(commonTemplateDir, projectDir, variables);
2747
- await mutatePackageJson2(projectDir, (packageJson) => {
3279
+ await mutatePackageJson3(projectDir, (packageJson) => {
2748
3280
  const wpTypiaPackageVersion = getPackageVersions().wpTypiaPackageVersion;
2749
3281
  const canonicalCliSpecifier = wpTypiaPackageVersion === "^0.0.0" ? "wp-typia" : `wp-typia@${wpTypiaPackageVersion.replace(/^[~^]/u, "")}`;
2750
3282
  const migrationCli = (args) => formatPackageExecCommand(packageManager, canonicalCliSpecifier, `migrate ${args}`);
@@ -2996,9 +3528,9 @@ function mergeTextLines(primaryContent, existingContent) {
2996
3528
  }
2997
3529
 
2998
3530
  // ../wp-typia-project-tools/src/runtime/scaffold-package-manager-files.ts
2999
- import { promises as fsp5 } from "fs";
3531
+ import { promises as fsp6 } from "fs";
3000
3532
  import { execSync as execSync2 } from "child_process";
3001
- import path7 from "path";
3533
+ import path8 from "path";
3002
3534
  var LOCKFILES = {
3003
3535
  bun: ["bun.lock", "bun.lockb"],
3004
3536
  npm: ["package-lock.json"],
@@ -3006,22 +3538,25 @@ var LOCKFILES = {
3006
3538
  yarn: ["yarn.lock"]
3007
3539
  };
3008
3540
  async function normalizePackageManagerFiles(targetDir, packageManagerId) {
3009
- const yarnRcPath = path7.join(targetDir, ".yarnrc.yml");
3541
+ const yarnRcPath = path8.join(targetDir, ".yarnrc.yml");
3010
3542
  if (packageManagerId === "yarn") {
3011
- await fsp5.writeFile(yarnRcPath, `nodeLinker: node-modules
3543
+ await fsp6.writeFile(yarnRcPath, `nodeLinker: node-modules
3012
3544
  `, "utf8");
3013
3545
  return;
3014
3546
  }
3015
- await fsp5.rm(yarnRcPath, { force: true });
3547
+ await fsp6.rm(yarnRcPath, { force: true });
3016
3548
  }
3017
3549
  async function normalizePackageJson(targetDir, packageManagerId) {
3018
- const packageJsonPath = path7.join(targetDir, "package.json");
3550
+ const packageJsonPath = path8.join(targetDir, "package.json");
3019
3551
  const packageJsonSource = await readOptionalUtf8File(packageJsonPath);
3020
3552
  if (packageJsonSource === null) {
3021
3553
  return;
3022
3554
  }
3023
3555
  const packageManager = getPackageManager(packageManagerId);
3024
- const packageJson = JSON.parse(packageJsonSource);
3556
+ const packageJson = safeJsonParse(packageJsonSource, {
3557
+ context: "generated package manifest",
3558
+ filePath: packageJsonPath
3559
+ });
3025
3560
  if (packageManagerId === "npm") {
3026
3561
  delete packageJson.packageManager;
3027
3562
  } else {
@@ -3034,7 +3569,7 @@ async function normalizePackageJson(targetDir, packageManagerId) {
3034
3569
  }
3035
3570
  }
3036
3571
  }
3037
- await fsp5.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3572
+ await fsp6.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3038
3573
  `, "utf8");
3039
3574
  }
3040
3575
  async function removeUnexpectedLockfiles(targetDir, packageManagerId) {
@@ -3044,7 +3579,7 @@ async function removeUnexpectedLockfiles(targetDir, packageManagerId) {
3044
3579
  if (keep.has(filename)) {
3045
3580
  return;
3046
3581
  }
3047
- await fsp5.rm(path7.join(targetDir, filename), { force: true });
3582
+ await fsp6.rm(path8.join(targetDir, filename), { force: true });
3048
3583
  }));
3049
3584
  }
3050
3585
  async function defaultInstallDependencies({
@@ -3057,14 +3592,15 @@ async function defaultInstallDependencies({
3057
3592
  });
3058
3593
  }
3059
3594
  // ../wp-typia-project-tools/src/runtime/scaffold-repository-reference.ts
3060
- import fs4 from "fs";
3061
3595
  import { createRequire } from "module";
3062
- import path8 from "path";
3596
+ import path9 from "path";
3063
3597
  var require2 = createRequire(import.meta.url);
3064
3598
  var DEFAULT_SCAFFOLD_REPOSITORY_REFERENCE = "imjlk/wp-typia";
3065
3599
  function readRepositoryPackageManifest(packageJsonPath) {
3066
3600
  try {
3067
- return JSON.parse(fs4.readFileSync(packageJsonPath, "utf8"));
3601
+ return readJsonFileSync(packageJsonPath, {
3602
+ context: "repository package manifest"
3603
+ });
3068
3604
  } catch (error) {
3069
3605
  if (getOptionalNodeErrorCode(error) === "ENOENT") {
3070
3606
  return null;
@@ -3122,9 +3658,9 @@ function parseRepositoryReference(value) {
3122
3658
  }
3123
3659
  function getDefaultRepositoryManifestPaths() {
3124
3660
  const candidatePaths = [
3125
- path8.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "..", "package.json"),
3126
- path8.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json"),
3127
- path8.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json"),
3661
+ path9.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "..", "package.json"),
3662
+ path9.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json"),
3663
+ path9.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json"),
3128
3664
  resolveInstalledPackageManifestPath("wp-typia"),
3129
3665
  resolveInstalledPackageManifestPath("@wp-typia/project-tools")
3130
3666
  ].filter((candidatePath) => Boolean(candidatePath));
@@ -3151,7 +3687,7 @@ async function reportScaffoldProgress(onProgress, event) {
3151
3687
  await onProgress?.(event);
3152
3688
  }
3153
3689
  var EPHEMERAL_NODE_MODULES_LINK_TYPE2 = process.platform === "win32" ? "junction" : "dir";
3154
- var __dirname2 = path9.dirname(fileURLToPath(import.meta.url));
3690
+ var __dirname2 = path10.dirname(fileURLToPath(import.meta.url));
3155
3691
  var LOCKFILES2 = {
3156
3692
  bun: ["bun.lock", "bun.lockb"],
3157
3693
  npm: ["package-lock.json"],
@@ -3159,11 +3695,11 @@ var LOCKFILES2 = {
3159
3695
  yarn: ["yarn.lock"]
3160
3696
  };
3161
3697
  async function ensureDirectory(targetDir, allowExisting = false) {
3162
- await fsp6.mkdir(targetDir, { recursive: true });
3698
+ await fsp7.mkdir(targetDir, { recursive: true });
3163
3699
  if (allowExisting) {
3164
3700
  return;
3165
3701
  }
3166
- const entries = await fsp6.readdir(targetDir);
3702
+ const entries = await fsp7.readdir(targetDir);
3167
3703
  if (entries.length > 0) {
3168
3704
  throw new Error(formatNonEmptyTargetDirectoryError(targetDir));
3169
3705
  }
@@ -3174,42 +3710,42 @@ async function writeStarterManifestFiles2(targetDir, templateId, variables, arti
3174
3710
  relativePath: `${artifact.relativeDir}/typia.manifest.json`
3175
3711
  })) : getStarterManifestFiles(templateId, variables);
3176
3712
  for (const { document, relativePath } of manifests) {
3177
- const destinationPath = path9.join(targetDir, relativePath);
3178
- await fsp6.mkdir(path9.dirname(destinationPath), { recursive: true });
3179
- await fsp6.writeFile(destinationPath, stringifyStarterManifest(document), "utf8");
3713
+ const destinationPath = path10.join(targetDir, relativePath);
3714
+ await fsp7.mkdir(path10.dirname(destinationPath), { recursive: true });
3715
+ await fsp7.writeFile(destinationPath, stringifyStarterManifest(document), "utf8");
3180
3716
  }
3181
3717
  }
3182
3718
  async function writeBuiltInStructuralArtifacts(targetDir, artifacts) {
3183
3719
  for (const artifact of artifacts) {
3184
- const destinationDir = path9.join(targetDir, artifact.relativeDir);
3185
- await fsp6.mkdir(destinationDir, { recursive: true });
3186
- await fsp6.writeFile(path9.join(destinationDir, "types.ts"), artifact.typesSource, "utf8");
3187
- await fsp6.writeFile(path9.join(destinationDir, "block.json"), stringifyBuiltInBlockJsonDocument(artifact.blockJsonDocument), "utf8");
3720
+ const destinationDir = path10.join(targetDir, artifact.relativeDir);
3721
+ await fsp7.mkdir(destinationDir, { recursive: true });
3722
+ await fsp7.writeFile(path10.join(destinationDir, "types.ts"), artifact.typesSource, "utf8");
3723
+ await fsp7.writeFile(path10.join(destinationDir, "block.json"), stringifyBuiltInBlockJsonDocument(artifact.blockJsonDocument), "utf8");
3188
3724
  }
3189
3725
  }
3190
3726
  async function writeBuiltInCodeArtifacts(targetDir, codeArtifacts) {
3191
3727
  for (const artifact of codeArtifacts) {
3192
- const destinationPath = path9.join(targetDir, artifact.relativePath);
3193
- await fsp6.mkdir(path9.dirname(destinationPath), { recursive: true });
3194
- await fsp6.writeFile(destinationPath, artifact.source, "utf8");
3728
+ const destinationPath = path10.join(targetDir, artifact.relativePath);
3729
+ await fsp7.mkdir(path10.dirname(destinationPath), { recursive: true });
3730
+ await fsp7.writeFile(destinationPath, artifact.source, "utf8");
3195
3731
  }
3196
3732
  }
3197
3733
  async function resolveScaffoldGeneratorNodeModulesPath2() {
3198
- const projectToolsPackageRoot = path9.resolve(__dirname2, "..", "..");
3734
+ const projectToolsPackageRoot = path10.resolve(__dirname2, "..", "..");
3199
3735
  const candidates = [
3200
- path9.join(projectToolsPackageRoot, "node_modules"),
3201
- path9.resolve(projectToolsPackageRoot, "..", ".."),
3202
- path9.resolve(projectToolsPackageRoot, "..", "..", "node_modules")
3736
+ path10.join(projectToolsPackageRoot, "node_modules"),
3737
+ path10.resolve(projectToolsPackageRoot, "..", ".."),
3738
+ path10.resolve(projectToolsPackageRoot, "..", "..", "node_modules")
3203
3739
  ];
3204
3740
  for (const candidate of candidates) {
3205
- if (await pathExists(path9.join(candidate, "typia", "package.json"))) {
3741
+ if (await pathExists(path10.join(candidate, "typia", "package.json"))) {
3206
3742
  return candidate;
3207
3743
  }
3208
3744
  }
3209
3745
  return null;
3210
3746
  }
3211
3747
  async function withEphemeralScaffoldNodeModules2(targetDir, callback) {
3212
- const targetNodeModulesPath = path9.join(targetDir, "node_modules");
3748
+ const targetNodeModulesPath = path10.join(targetDir, "node_modules");
3213
3749
  if (await pathExists(targetNodeModulesPath)) {
3214
3750
  await callback();
3215
3751
  return;
@@ -3218,11 +3754,11 @@ async function withEphemeralScaffoldNodeModules2(targetDir, callback) {
3218
3754
  if (!sourceNodeModulesPath) {
3219
3755
  throw new Error("Unable to resolve a node_modules directory with typia for scaffold-time REST artifact generation.");
3220
3756
  }
3221
- await fsp6.symlink(sourceNodeModulesPath, targetNodeModulesPath, EPHEMERAL_NODE_MODULES_LINK_TYPE2);
3757
+ await fsp7.symlink(sourceNodeModulesPath, targetNodeModulesPath, EPHEMERAL_NODE_MODULES_LINK_TYPE2);
3222
3758
  try {
3223
3759
  await callback();
3224
3760
  } finally {
3225
- await fsp6.rm(targetNodeModulesPath, { force: true, recursive: true });
3761
+ await fsp7.rm(targetNodeModulesPath, { force: true, recursive: true });
3226
3762
  }
3227
3763
  }
3228
3764
  async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables) {
@@ -3233,7 +3769,7 @@ async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables
3233
3769
  await withEphemeralScaffoldNodeModules2(targetDir, async () => {
3234
3770
  if (templateId === "persistence") {
3235
3771
  await syncPersistenceRestArtifacts({
3236
- apiTypesFile: path9.join("src", "api-types.ts"),
3772
+ apiTypesFile: path10.join("src", "api-types.ts"),
3237
3773
  outputDir: "src",
3238
3774
  projectDir: targetDir,
3239
3775
  variables
@@ -3241,27 +3777,27 @@ async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables
3241
3777
  return;
3242
3778
  }
3243
3779
  await syncPersistenceRestArtifacts({
3244
- apiTypesFile: path9.join("src", "blocks", variables.slugKebabCase, "api-types.ts"),
3245
- outputDir: path9.join("src", "blocks", variables.slugKebabCase),
3780
+ apiTypesFile: path10.join("src", "blocks", variables.slugKebabCase, "api-types.ts"),
3781
+ outputDir: path10.join("src", "blocks", variables.slugKebabCase),
3246
3782
  projectDir: targetDir,
3247
3783
  variables
3248
3784
  });
3249
3785
  });
3250
3786
  }
3251
3787
  async function normalizePackageManagerFiles2(targetDir, packageManagerId) {
3252
- const yarnRcPath = path9.join(targetDir, ".yarnrc.yml");
3788
+ const yarnRcPath = path10.join(targetDir, ".yarnrc.yml");
3253
3789
  if (packageManagerId === "yarn") {
3254
- await fsp6.writeFile(yarnRcPath, `nodeLinker: node-modules
3790
+ await fsp7.writeFile(yarnRcPath, `nodeLinker: node-modules
3255
3791
  `, "utf8");
3256
3792
  return;
3257
3793
  }
3258
- await fsp6.rm(yarnRcPath, { force: true });
3794
+ await fsp7.rm(yarnRcPath, { force: true });
3259
3795
  }
3260
3796
  async function removeQueryLoopPlaceholderFiles(projectDir, templateId) {
3261
3797
  if (templateId !== "query-loop") {
3262
3798
  return;
3263
3799
  }
3264
- await fsp6.rm(path9.join(projectDir, "src", "validator-toolkit.ts"), {
3800
+ await fsp7.rm(path10.join(projectDir, "src", "validator-toolkit.ts"), {
3265
3801
  force: true
3266
3802
  });
3267
3803
  }
@@ -3272,7 +3808,7 @@ async function removeUnexpectedLockfiles2(targetDir, packageManagerId) {
3272
3808
  if (keep.has(filename)) {
3273
3809
  return;
3274
3810
  }
3275
- await fsp6.rm(path9.join(targetDir, filename), { force: true });
3811
+ await fsp7.rm(path10.join(targetDir, filename), { force: true });
3276
3812
  }));
3277
3813
  }
3278
3814
  async function replaceTextRecursively(targetDir, packageManagerId, {
@@ -3295,21 +3831,21 @@ async function replaceTextRecursively(targetDir, packageManagerId, {
3295
3831
  manifestPaths: repositoryManifestPaths
3296
3832
  });
3297
3833
  async function visit(currentPath) {
3298
- const stats = await fsp6.stat(currentPath);
3834
+ const stats = await fsp7.stat(currentPath);
3299
3835
  if (stats.isDirectory()) {
3300
- const entries = await fsp6.readdir(currentPath);
3836
+ const entries = await fsp7.readdir(currentPath);
3301
3837
  for (const entry of entries) {
3302
- await visit(path9.join(currentPath, entry));
3838
+ await visit(path10.join(currentPath, entry));
3303
3839
  }
3304
3840
  return;
3305
3841
  }
3306
- if (path9.basename(currentPath) === "package.json" || !textExtensions.has(path9.extname(currentPath))) {
3842
+ if (path10.basename(currentPath) === "package.json" || !textExtensions.has(path10.extname(currentPath))) {
3307
3843
  return;
3308
3844
  }
3309
- const content = await fsp6.readFile(currentPath, "utf8");
3845
+ const content = await fsp7.readFile(currentPath, "utf8");
3310
3846
  const nextContent = replaceRepositoryReferencePlaceholders(transformPackageManagerText(content, packageManagerId), resolvedRepositoryReference);
3311
3847
  if (nextContent !== content) {
3312
- await fsp6.writeFile(currentPath, nextContent, "utf8");
3848
+ await fsp7.writeFile(currentPath, nextContent, "utf8");
3313
3849
  }
3314
3850
  }
3315
3851
  await visit(targetDir);
@@ -3381,17 +3917,17 @@ async function applyBuiltInScaffoldProjectFiles({
3381
3917
  phase: "finalize-project",
3382
3918
  title: "Finalizing scaffold output"
3383
3919
  });
3384
- const readmePath = path9.join(projectDir, "README.md");
3920
+ const readmePath = path10.join(projectDir, "README.md");
3385
3921
  if (!await pathExists(readmePath)) {
3386
- await fsp6.writeFile(readmePath, readmeContent ?? buildReadme(templateId, variables, packageManager, {
3922
+ await fsp7.writeFile(readmePath, readmeContent ?? buildReadme(templateId, variables, packageManager, {
3387
3923
  withMigrationUi,
3388
3924
  withTestPreset,
3389
3925
  withWpEnv
3390
3926
  }), "utf8");
3391
3927
  }
3392
- const gitignorePath = path9.join(projectDir, ".gitignore");
3928
+ const gitignorePath = path10.join(projectDir, ".gitignore");
3393
3929
  const existingGitignore = await readOptionalUtf8File(gitignorePath) ?? "";
3394
- await fsp6.writeFile(gitignorePath, mergeTextLines(gitignoreContent ?? buildGitignore(), existingGitignore), "utf8");
3930
+ await fsp7.writeFile(gitignorePath, mergeTextLines(gitignoreContent ?? buildGitignore(), existingGitignore), "utf8");
3395
3931
  await normalizePackageJson(projectDir, packageManager);
3396
3932
  await applyGeneratedProjectDxPackageJson({
3397
3933
  compoundPersistenceEnabled: isCompoundPersistenceEnabled(variables),
@@ -3422,31 +3958,31 @@ async function applyBuiltInScaffoldProjectFiles({
3422
3958
  }
3423
3959
 
3424
3960
  // ../wp-typia-project-tools/src/runtime/template-source-normalization.ts
3425
- import path13 from "path";
3961
+ import path14 from "path";
3426
3962
 
3427
3963
  // ../wp-typia-project-tools/src/runtime/template-layers.ts
3428
- import path10 from "path";
3429
- import { promises as fsp7 } from "fs";
3964
+ import path11 from "path";
3965
+ import { promises as fsp8 } from "fs";
3430
3966
  var TEMPLATE_LAYER_MANIFEST_FILENAME = "wp-typia.layers.json";
3431
3967
  var TEMPLATE_LAYER_MANIFEST_VERSION = 1;
3432
3968
  function resolveLayerPath(sourceRoot, relativePath) {
3433
- const targetPath = path10.resolve(sourceRoot, relativePath);
3434
- const relativeTarget = path10.relative(sourceRoot, targetPath);
3435
- if (relativeTarget.startsWith("..") || path10.isAbsolute(relativeTarget)) {
3969
+ const targetPath = path11.resolve(sourceRoot, relativePath);
3970
+ const relativeTarget = path11.relative(sourceRoot, targetPath);
3971
+ if (relativeTarget.startsWith("..") || path11.isAbsolute(relativeTarget)) {
3436
3972
  throw new Error(`Template layer path "${relativePath}" must stay within ${sourceRoot}.`);
3437
3973
  }
3438
3974
  return targetPath;
3439
3975
  }
3440
3976
  async function assertNoSymlinks(sourceDir) {
3441
- const stats = await fsp7.lstat(sourceDir);
3977
+ const stats = await fsp8.lstat(sourceDir);
3442
3978
  if (stats.isSymbolicLink()) {
3443
3979
  throw new Error(`Template layer packages may not include symbolic links: ${sourceDir}`);
3444
3980
  }
3445
3981
  if (!stats.isDirectory()) {
3446
3982
  return;
3447
3983
  }
3448
- for (const entry of await fsp7.readdir(sourceDir)) {
3449
- await assertNoSymlinks(path10.join(sourceDir, entry));
3984
+ for (const entry of await fsp8.readdir(sourceDir)) {
3985
+ await assertNoSymlinks(path11.join(sourceDir, entry));
3450
3986
  }
3451
3987
  }
3452
3988
  function parseLayerDefinition(layerId, value) {
@@ -3475,11 +4011,13 @@ function parseLayerDefinition(layerId, value) {
3475
4011
  };
3476
4012
  }
3477
4013
  async function loadExternalTemplateLayerManifest(sourceRoot) {
3478
- const manifestPath = path10.join(sourceRoot, TEMPLATE_LAYER_MANIFEST_FILENAME);
4014
+ const manifestPath = path11.join(sourceRoot, TEMPLATE_LAYER_MANIFEST_FILENAME);
3479
4015
  if (!await pathExists(manifestPath)) {
3480
4016
  return null;
3481
4017
  }
3482
- const raw = JSON.parse(await fsp7.readFile(manifestPath, "utf8"));
4018
+ const raw = await readJsonFile(manifestPath, {
4019
+ context: "template layer manifest"
4020
+ });
3483
4021
  if (!isPlainObject(raw)) {
3484
4022
  throw new Error(`${TEMPLATE_LAYER_MANIFEST_FILENAME} must export a JSON object.`);
3485
4023
  }
@@ -3573,7 +4111,7 @@ async function resolveExternalTemplateLayers({
3573
4111
  return;
3574
4112
  }
3575
4113
  const layerDir = resolveLayerPath(sourceRoot, definition.path);
3576
- const stats = await fsp7.stat(layerDir).catch(() => null);
4114
+ const stats = await fsp8.stat(layerDir).catch(() => null);
3577
4115
  if (!stats || !stats.isDirectory()) {
3578
4116
  throw new Error(`Layer "${layerId}" points to a missing directory: ${definition.path}`);
3579
4117
  }
@@ -3611,12 +4149,12 @@ async function assertExternalTemplateLayersDoNotWriteProtectedOutputs({
3611
4149
  }
3612
4150
 
3613
4151
  // ../wp-typia-project-tools/src/runtime/template-source-external.ts
3614
- import { promises as fsp8 } from "fs";
3615
- import path11 from "path";
4152
+ import { promises as fsp9 } from "fs";
4153
+ import path12 from "path";
3616
4154
  import { pathToFileURL } from "url";
3617
4155
 
3618
4156
  // ../wp-typia-project-tools/src/runtime/external-template-guards.ts
3619
- import fs5 from "fs";
4157
+ import fs4 from "fs";
3620
4158
  var TEMPLATE_SOURCE_TIMEOUT_CODE = "template-source-timeout";
3621
4159
  var TEMPLATE_SOURCE_TOO_LARGE_CODE = "template-source-too-large";
3622
4160
  var DEFAULT_EXTERNAL_TEMPLATE_TIMEOUT_MS = 20000;
@@ -3658,7 +4196,7 @@ function createExternalTemplateTooLargeError(label, maxBytes) {
3658
4196
  return createTemplateGuardError(TEMPLATE_SOURCE_TOO_LARGE_CODE, `${label} exceeded the external template size limit (${maxBytes} bytes).`);
3659
4197
  }
3660
4198
  function assertExternalTemplateFileSize(filePath, options) {
3661
- const stats = fs5.statSync(filePath);
4199
+ const stats = fs4.statSync(filePath);
3662
4200
  if (stats.size > options.maxBytes) {
3663
4201
  throw createExternalTemplateTooLargeError(options.label, options.maxBytes);
3664
4202
  }
@@ -3734,11 +4272,9 @@ async function readResponseBodyWithLimit(response, options) {
3734
4272
  }
3735
4273
  async function readJsonResponseWithLimit(response, options) {
3736
4274
  const buffer = await readResponseBodyWithLimit(response, options);
3737
- try {
3738
- return JSON.parse(buffer.toString("utf8"));
3739
- } catch (error) {
3740
- throw new Error(`Failed to parse ${options.label}: ${error instanceof Error ? error.message : String(error)}`);
3741
- }
4275
+ return safeJsonParse(buffer.toString("utf8"), {
4276
+ context: options.label
4277
+ });
3742
4278
  }
3743
4279
  async function readBufferResponseWithLimit(response, options) {
3744
4280
  return readResponseBodyWithLimit(response, options);
@@ -3756,16 +4292,16 @@ function getTemplateWarning(key) {
3756
4292
  return `Ignoring external template config key "${key}": ${TEMPLATE_WARNING_MESSAGE}`;
3757
4293
  }
3758
4294
  function resolveSourceSubpath(sourceDir, relativePath) {
3759
- const targetPath = path11.resolve(sourceDir, relativePath);
3760
- const relativeTarget = path11.relative(sourceDir, targetPath);
3761
- if (relativeTarget.startsWith("..") || path11.isAbsolute(relativeTarget)) {
4295
+ const targetPath = path12.resolve(sourceDir, relativePath);
4296
+ const relativeTarget = path12.relative(sourceDir, targetPath);
4297
+ if (relativeTarget.startsWith("..") || path12.isAbsolute(relativeTarget)) {
3762
4298
  throw new Error(`Template path "${relativePath}" must stay within ${sourceDir}.`);
3763
4299
  }
3764
4300
  return targetPath;
3765
4301
  }
3766
4302
  async function findExternalTemplateEntry(sourceDir) {
3767
4303
  for (const filename of EXTERNAL_TEMPLATE_ENTRY_CANDIDATES) {
3768
- const candidate = path11.join(sourceDir, filename);
4304
+ const candidate = path12.join(sourceDir, filename);
3769
4305
  if (await pathExists(candidate)) {
3770
4306
  return candidate;
3771
4307
  }
@@ -3781,7 +4317,7 @@ async function loadExternalTemplateConfig(sourceDir) {
3781
4317
  label: `External template config "${entryPath}"`,
3782
4318
  maxBytes: getExternalTemplateConfigMaxBytes()
3783
4319
  });
3784
- const entryStats = await fsp8.stat(entryPath);
4320
+ const entryStats = await fsp9.stat(entryPath);
3785
4321
  const moduleUrl = `${pathToFileURL(entryPath).href}?mtime=${entryStats.mtimeMs}`;
3786
4322
  const loadedModule = await withExternalTemplateTimeout(`loading external template config "${entryPath}"`, () => import(moduleUrl));
3787
4323
  const loadedConfig = loadedModule.default ?? loadedModule;
@@ -3888,21 +4424,21 @@ async function renderCreateBlockExternalTemplate(sourceDir, context, requestedVa
3888
4424
  const { folderName, formatHint, templatePath } = resolveConfiguredTemplatePath(config, variantConfig);
3889
4425
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-create-block-external-");
3890
4426
  try {
3891
- const renderedRoot = path11.join(tempRoot, "rendered");
4427
+ const renderedRoot = path12.join(tempRoot, "rendered");
3892
4428
  const blockDir = resolveSourceSubpath(renderedRoot, folderName);
3893
4429
  const view = await buildExternalTemplateView(context, config, selectedVariant, variantConfig);
3894
4430
  const blockTemplateDir = resolveSourceSubpath(sourceDir, templatePath);
3895
4431
  await copyRenderedDirectory(blockTemplateDir, blockDir, view, {
3896
4432
  filter: async (sourcePath, _destinationPath, entry) => {
3897
- const mustacheVariantPath = path11.join(path11.dirname(sourcePath), `${entry.name}.mustache`);
4433
+ const mustacheVariantPath = path12.join(path12.dirname(sourcePath), `${entry.name}.mustache`);
3898
4434
  return !(entry.isFile() && (entry.name === "package.json" || entry.name === "README.md") && await pathExists(mustacheVariantPath));
3899
4435
  }
3900
4436
  });
3901
4437
  const assetsPath = typeof variantConfig.assetsPath === "string" ? variantConfig.assetsPath : config.assetsPath;
3902
4438
  if (typeof assetsPath === "string" && assetsPath.trim().length > 0) {
3903
- await copyRawDirectory(resolveSourceSubpath(sourceDir, assetsPath), path11.join(tempRoot, "assets"));
4439
+ await copyRawDirectory(resolveSourceSubpath(sourceDir, assetsPath), path12.join(tempRoot, "assets"));
3904
4440
  }
3905
- const assetsDir = path11.join(tempRoot, "assets");
4441
+ const assetsDir = path12.join(tempRoot, "assets");
3906
4442
  return {
3907
4443
  assetsDir: await pathExists(assetsDir) ? assetsDir : undefined,
3908
4444
  blockDir,
@@ -3919,8 +4455,8 @@ async function renderCreateBlockExternalTemplate(sourceDir, context, requestedVa
3919
4455
  }
3920
4456
 
3921
4457
  // ../wp-typia-project-tools/src/runtime/template-source-remote.ts
3922
- import { promises as fsp9 } from "fs";
3923
- import path12 from "path";
4458
+ import { promises as fsp10 } from "fs";
4459
+ import path13 from "path";
3924
4460
  async function cleanupSeedRootPair(cleanup, seedCleanup) {
3925
4461
  let cleanupError;
3926
4462
  try {
@@ -3943,11 +4479,13 @@ function getDefaultCategoryFromBlockJson(blockJson) {
3943
4479
  async function readRemoteBlockJsonAsync(blockDir) {
3944
4480
  const sourceRoot = await getSeedSourceRoot(blockDir);
3945
4481
  for (const candidate of [
3946
- path12.join(blockDir, "block.json"),
3947
- path12.join(sourceRoot, "block.json")
4482
+ path13.join(blockDir, "block.json"),
4483
+ path13.join(sourceRoot, "block.json")
3948
4484
  ]) {
3949
4485
  if (await pathExists(candidate)) {
3950
- return JSON.parse(await fsp9.readFile(candidate, "utf8"));
4486
+ return readJsonFile(candidate, {
4487
+ context: "remote block metadata"
4488
+ });
3951
4489
  }
3952
4490
  }
3953
4491
  throw new Error(`Unable to locate block.json in ${blockDir}`);
@@ -3962,8 +4500,8 @@ async function getDefaultCategoryAsync(sourceDir) {
3962
4500
  }
3963
4501
  async function readTemplatePackageJsonAsync(sourceDir) {
3964
4502
  for (const candidate of [
3965
- path12.join(sourceDir, "package.json.mustache"),
3966
- path12.join(sourceDir, "package.json")
4503
+ path13.join(sourceDir, "package.json.mustache"),
4504
+ path13.join(sourceDir, "package.json")
3967
4505
  ]) {
3968
4506
  if (!await pathExists(candidate)) {
3969
4507
  continue;
@@ -3974,7 +4512,10 @@ async function readTemplatePackageJsonAsync(sourceDir) {
3974
4512
  maxBytes: getExternalTemplatePackageJsonMaxBytes()
3975
4513
  });
3976
4514
  return {
3977
- packageJson: JSON.parse(await fsp9.readFile(candidate, "utf8")),
4515
+ packageJson: safeJsonParse(await fsp10.readFile(candidate, "utf8"), {
4516
+ context: "template metadata file",
4517
+ filePath: candidate
4518
+ }),
3978
4519
  sourcePath: candidate
3979
4520
  };
3980
4521
  } catch (error) {
@@ -4000,16 +4541,16 @@ async function getTemplateProjectTypeAsync(sourceDir) {
4000
4541
  }
4001
4542
  async function normalizeWpTypiaTemplateSeed(seed) {
4002
4543
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
4003
- const normalizedDir = path12.join(tempRoot, "template");
4544
+ const normalizedDir = path13.join(tempRoot, "template");
4004
4545
  try {
4005
4546
  await copyRawDirectory(seed.blockDir, normalizedDir, {
4006
4547
  filter: async (sourcePath, _targetPath, entry) => {
4007
- const mustacheVariantPath = path12.join(path12.dirname(sourcePath), `${entry.name}.mustache`);
4548
+ const mustacheVariantPath = path13.join(path13.dirname(sourcePath), `${entry.name}.mustache`);
4008
4549
  return !(entry.isFile() && (entry.name === "package.json" || entry.name === "README.md") && await pathExists(mustacheVariantPath));
4009
4550
  }
4010
4551
  });
4011
4552
  if (seed.assetsDir && await pathExists(seed.assetsDir)) {
4012
- await fsp9.cp(seed.assetsDir, path12.join(normalizedDir, "assets"), {
4553
+ await fsp10.cp(seed.assetsDir, path13.join(normalizedDir, "assets"), {
4013
4554
  recursive: true,
4014
4555
  force: true
4015
4556
  });
@@ -4098,32 +4639,34 @@ function buildRemoteBlockJsonTemplate(blockJson) {
4098
4639
  }
4099
4640
  async function rewriteBlockJsonImports(directory) {
4100
4641
  const textExtensions = new Set([".js", ".jsx", ".ts", ".tsx"]);
4101
- const targetBlockJsonPath = path12.join(directory, "block.json");
4642
+ const targetBlockJsonPath = path13.join(directory, "block.json");
4102
4643
  async function visit(currentPath) {
4103
- const stats = await fsp9.stat(currentPath);
4644
+ const stats = await fsp10.stat(currentPath);
4104
4645
  if (stats.isDirectory()) {
4105
- const entries = await fsp9.readdir(currentPath);
4646
+ const entries = await fsp10.readdir(currentPath);
4106
4647
  for (const entry of entries) {
4107
- await visit(path12.join(currentPath, entry));
4648
+ await visit(path13.join(currentPath, entry));
4108
4649
  }
4109
4650
  return;
4110
4651
  }
4111
- if (!textExtensions.has(path12.extname(currentPath))) {
4652
+ if (!textExtensions.has(path13.extname(currentPath))) {
4112
4653
  return;
4113
4654
  }
4114
- const content = await fsp9.readFile(currentPath, "utf8");
4115
- const relativeSpecifier = path12.relative(path12.dirname(currentPath), targetBlockJsonPath).replace(/\\/g, "/");
4655
+ const content = await fsp10.readFile(currentPath, "utf8");
4656
+ const relativeSpecifier = path13.relative(path13.dirname(currentPath), targetBlockJsonPath).replace(/\\/g, "/");
4116
4657
  const normalizedSpecifier = relativeSpecifier.startsWith(".") ? relativeSpecifier : `./${relativeSpecifier}`;
4117
4658
  const next = content.replace(/(['"])\.{1,2}\/[^'"]*block\.json\1/g, `$1${normalizedSpecifier}$1`);
4118
4659
  if (next !== content) {
4119
- await fsp9.writeFile(currentPath, next, "utf8");
4660
+ await fsp10.writeFile(currentPath, next, "utf8");
4120
4661
  }
4121
4662
  }
4122
4663
  await visit(directory);
4123
4664
  }
4124
4665
  async function patchRemotePackageJson(templateDir, needsInteractivity) {
4125
- const packageJsonPath = path12.join(templateDir, "package.json.mustache");
4126
- const packageJson = JSON.parse(await fsp9.readFile(packageJsonPath, "utf8"));
4666
+ const packageJsonPath = path13.join(templateDir, "package.json.mustache");
4667
+ const packageJson = await readJsonFile(packageJsonPath, {
4668
+ context: "remote package template manifest"
4669
+ });
4127
4670
  const existingDependencies = { ...packageJson.dependencies ?? {} };
4128
4671
  const existingDevDependencies = { ...packageJson.devDependencies ?? {} };
4129
4672
  delete existingDependencies["@wp-typia/project-tools"];
@@ -4143,16 +4686,16 @@ async function patchRemotePackageJson(templateDir, needsInteractivity) {
4143
4686
  } else {
4144
4687
  delete packageJson.dependencies;
4145
4688
  }
4146
- await fsp9.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
4689
+ await fsp10.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
4147
4690
  `, "utf8");
4148
4691
  }
4149
4692
  async function getSeedSourceRoot(blockDir) {
4150
- return await pathExists(path12.join(blockDir, "src")) ? path12.join(blockDir, "src") : blockDir;
4693
+ return await pathExists(path13.join(blockDir, "src")) ? path13.join(blockDir, "src") : blockDir;
4151
4694
  }
4152
4695
  async function findSeedRenderPhp(seed) {
4153
4696
  for (const candidate of [
4154
- path12.join(seed.blockDir, "render.php"),
4155
- path12.join(seed.rootDir, "render.php")
4697
+ path13.join(seed.blockDir, "render.php"),
4698
+ path13.join(seed.rootDir, "render.php")
4156
4699
  ]) {
4157
4700
  if (await pathExists(candidate)) {
4158
4701
  return candidate;
@@ -4193,16 +4736,16 @@ async function removeSeedEntryConflicts(templateDir) {
4193
4736
  "view.ts",
4194
4737
  "view.tsx"
4195
4738
  ]) {
4196
- await fsp9.rm(path12.join(templateDir, "src", filename), { force: true });
4739
+ await fsp10.rm(path13.join(templateDir, "src", filename), { force: true });
4197
4740
  }
4198
4741
  }
4199
4742
  async function normalizeCreateBlockSubset(seed, context) {
4200
4743
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-remote-template-");
4201
4744
  try {
4202
- const templateDir = path12.join(tempRoot, "template");
4745
+ const templateDir = path13.join(tempRoot, "template");
4203
4746
  const blockJson = await readRemoteBlockJsonAsync(seed.blockDir);
4204
4747
  const sourceRoot = await getSeedSourceRoot(seed.blockDir);
4205
- await fsp9.mkdir(templateDir, { recursive: true });
4748
+ await fsp10.mkdir(templateDir, { recursive: true });
4206
4749
  for (const layerDir of getBuiltInTemplateLayerDirs("basic")) {
4207
4750
  if (!await pathExists(layerDir)) {
4208
4751
  if (isOmittableBuiltInTemplateLayerDir("basic", layerDir)) {
@@ -4210,29 +4753,29 @@ async function normalizeCreateBlockSubset(seed, context) {
4210
4753
  }
4211
4754
  throw new Error(`Built-in template layer is missing: ${layerDir}`);
4212
4755
  }
4213
- await fsp9.cp(layerDir, templateDir, {
4756
+ await fsp10.cp(layerDir, templateDir, {
4214
4757
  recursive: true,
4215
4758
  force: true
4216
4759
  });
4217
4760
  }
4218
4761
  await removeSeedEntryConflicts(templateDir);
4219
- await fsp9.cp(sourceRoot, path12.join(templateDir, "src"), {
4762
+ await fsp10.cp(sourceRoot, path13.join(templateDir, "src"), {
4220
4763
  recursive: true,
4221
4764
  force: true
4222
4765
  });
4223
4766
  const remoteRenderPath = await findSeedRenderPhp(seed);
4224
4767
  if (remoteRenderPath) {
4225
- await fsp9.copyFile(remoteRenderPath, path12.join(templateDir, "render.php"));
4768
+ await fsp10.copyFile(remoteRenderPath, path13.join(templateDir, "render.php"));
4226
4769
  }
4227
4770
  if (seed.assetsDir && await pathExists(seed.assetsDir)) {
4228
- await fsp9.cp(seed.assetsDir, path12.join(templateDir, "assets"), {
4771
+ await fsp10.cp(seed.assetsDir, path13.join(templateDir, "assets"), {
4229
4772
  recursive: true,
4230
4773
  force: true
4231
4774
  });
4232
4775
  }
4233
- await fsp9.writeFile(path12.join(templateDir, "src", "types.ts"), buildRemoteTypesSource(blockJson, context), "utf8");
4234
- await fsp9.writeFile(path12.join(templateDir, "src", "block.json"), buildRemoteBlockJsonTemplate(blockJson), "utf8");
4235
- await rewriteBlockJsonImports(path12.join(templateDir, "src"));
4776
+ await fsp10.writeFile(path13.join(templateDir, "src", "types.ts"), buildRemoteTypesSource(blockJson, context), "utf8");
4777
+ await fsp10.writeFile(path13.join(templateDir, "src", "block.json"), buildRemoteBlockJsonTemplate(blockJson), "utf8");
4778
+ await rewriteBlockJsonImports(path13.join(templateDir, "src"));
4236
4779
  const needsInteractivity = typeof blockJson.viewScriptModule === "string" || typeof blockJson.viewScript === "string" || (await Promise.all([
4237
4780
  "view.js",
4238
4781
  "view.jsx",
@@ -4240,7 +4783,7 @@ async function normalizeCreateBlockSubset(seed, context) {
4240
4783
  "view.tsx",
4241
4784
  "interactivity.js",
4242
4785
  "interactivity.ts"
4243
- ].map((filename) => pathExists(path12.join(templateDir, "src", filename))))).some(Boolean);
4786
+ ].map((filename) => pathExists(path13.join(templateDir, "src", filename))))).some(Boolean);
4244
4787
  await patchRemotePackageJson(templateDir, needsInteractivity);
4245
4788
  return {
4246
4789
  id: "remote:create-block-subset",
@@ -4270,7 +4813,8 @@ function getTemplateVariableContext(variables) {
4270
4813
  blockRuntimePackageVersion,
4271
4814
  blockTypesPackageVersion,
4272
4815
  projectToolsPackageVersion,
4273
- restPackageVersion
4816
+ restPackageVersion,
4817
+ wpTypiaPackageVersion
4274
4818
  } = getPackageVersions();
4275
4819
  return {
4276
4820
  ...variables,
@@ -4278,6 +4822,7 @@ function getTemplateVariableContext(variables) {
4278
4822
  blockRuntimePackageVersion: variables.blockRuntimePackageVersion ?? blockRuntimePackageVersion,
4279
4823
  blockTypesPackageVersion: variables.blockTypesPackageVersion ?? blockTypesPackageVersion,
4280
4824
  projectToolsPackageVersion: variables.projectToolsPackageVersion ?? projectToolsPackageVersion,
4825
+ wpTypiaPackageVersion: variables.wpTypiaPackageVersion ?? wpTypiaPackageVersion,
4281
4826
  description: variables.description,
4282
4827
  keyword: variables.keyword,
4283
4828
  namespace: variables.namespace,
@@ -4290,7 +4835,7 @@ function getTemplateVariableContext(variables) {
4290
4835
  };
4291
4836
  }
4292
4837
  async function detectTemplateSourceFormat(sourceDir) {
4293
- if (await pathExists(path13.join(sourceDir, "package.json.mustache"))) {
4838
+ if (await pathExists(path14.join(sourceDir, "package.json.mustache"))) {
4294
4839
  return "wp-typia";
4295
4840
  }
4296
4841
  if (await loadExternalTemplateLayerManifest(sourceDir)) {
@@ -4302,15 +4847,15 @@ async function detectTemplateSourceFormat(sourceDir) {
4302
4847
  if (await getTemplateProjectTypeAsync(sourceDir) !== null) {
4303
4848
  return "wp-typia";
4304
4849
  }
4305
- const sourceRoot = await pathExists(path13.join(sourceDir, "src")) ? path13.join(sourceDir, "src") : sourceDir;
4850
+ const sourceRoot = await pathExists(path14.join(sourceDir, "src")) ? path14.join(sourceDir, "src") : sourceDir;
4306
4851
  const blockJsonCandidates = [
4307
- path13.join(sourceDir, "block.json"),
4308
- path13.join(sourceRoot, "block.json")
4852
+ path14.join(sourceDir, "block.json"),
4853
+ path14.join(sourceRoot, "block.json")
4309
4854
  ];
4310
4855
  const hasBlockJson = (await Promise.all(blockJsonCandidates.map((candidate) => pathExists(candidate)))).some(Boolean);
4311
- const hasIndexFile = (await Promise.all(["index.js", "index.jsx", "index.ts", "index.tsx"].map((filename) => pathExists(path13.join(sourceRoot, filename))))).some(Boolean);
4312
- const hasEditFile = (await Promise.all(["edit.js", "edit.jsx", "edit.ts", "edit.tsx"].map((filename) => pathExists(path13.join(sourceRoot, filename))))).some(Boolean);
4313
- const hasSaveFile = (await Promise.all(["save.js", "save.jsx", "save.ts", "save.tsx"].map((filename) => pathExists(path13.join(sourceRoot, filename))))).some(Boolean);
4856
+ const hasIndexFile = (await Promise.all(["index.js", "index.jsx", "index.ts", "index.tsx"].map((filename) => pathExists(path14.join(sourceRoot, filename))))).some(Boolean);
4857
+ const hasEditFile = (await Promise.all(["edit.js", "edit.jsx", "edit.ts", "edit.tsx"].map((filename) => pathExists(path14.join(sourceRoot, filename))))).some(Boolean);
4858
+ const hasSaveFile = (await Promise.all(["save.js", "save.jsx", "save.ts", "save.tsx"].map((filename) => pathExists(path14.join(sourceRoot, filename))))).some(Boolean);
4314
4859
  if (hasBlockJson && hasIndexFile && hasEditFile && hasSaveFile) {
4315
4860
  return "create-block-subset";
4316
4861
  }
@@ -4319,10 +4864,10 @@ async function detectTemplateSourceFormat(sourceDir) {
4319
4864
 
4320
4865
  // ../wp-typia-project-tools/src/runtime/template-source-seeds.ts
4321
4866
  var import_semver = __toESM(require_semver(), 1);
4322
- import fs7 from "fs";
4323
- import { promises as fsp11 } from "fs";
4867
+ import fs6 from "fs";
4868
+ import { promises as fsp12 } from "fs";
4324
4869
  import { createRequire as createRequire2 } from "module";
4325
- import path16 from "path";
4870
+ import path17 from "path";
4326
4871
  import { spawnSync } from "child_process";
4327
4872
 
4328
4873
  // ../../node_modules/.bun/tar@7.5.13/node_modules/tar/dist/esm/index.min.js
@@ -6595,7 +7140,7 @@ var Vn = 512 * 1024;
6595
7140
  var $n = pr | ur | dr | mr;
6596
7141
  var lr = !fr && typeof ar == "number" ? ar | ur | dr | mr : null;
6597
7142
  var cs = lr !== null ? () => lr : Kn ? (s3) => s3 < Vn ? $n : "w" : () => "w";
6598
- var fs6 = (s3, t, e) => {
7143
+ var fs5 = (s3, t, e) => {
6599
7144
  try {
6600
7145
  return mi.lchownSync(s3, t, e);
6601
7146
  } catch (i) {
@@ -6644,7 +7189,7 @@ var ds = (s3, t, e, i) => {
6644
7189
  });
6645
7190
  };
6646
7191
  var qn = (s3, t, e, i) => {
6647
- t.isDirectory() && us(Ee.resolve(s3, t.name), e, i), fs6(Ee.resolve(s3, t.name), e, i);
7192
+ t.isDirectory() && us(Ee.resolve(s3, t.name), e, i), fs5(Ee.resolve(s3, t.name), e, i);
6648
7193
  };
6649
7194
  var us = (s3, t, e) => {
6650
7195
  let i;
@@ -6655,12 +7200,12 @@ var us = (s3, t, e) => {
6655
7200
  if (n?.code === "ENOENT")
6656
7201
  return;
6657
7202
  if (n?.code === "ENOTDIR" || n?.code === "ENOTSUP")
6658
- return fs6(s3, t, e);
7203
+ return fs5(s3, t, e);
6659
7204
  throw n;
6660
7205
  }
6661
7206
  for (let r of i)
6662
7207
  qn(s3, r, t, e);
6663
- return fs6(s3, t, e);
7208
+ return fs5(s3, t, e);
6664
7209
  };
6665
7210
  var we = class extends Error {
6666
7211
  path;
@@ -7474,8 +8019,8 @@ var So = (s3) => {
7474
8019
 
7475
8020
  // ../wp-typia-project-tools/src/runtime/template-source-cache.ts
7476
8021
  import { createHash, randomUUID } from "crypto";
7477
- import { promises as fsp10 } from "fs";
7478
- import path15 from "path";
8022
+ import { promises as fsp11 } from "fs";
8023
+ import path16 from "path";
7479
8024
 
7480
8025
  // ../wp-typia-project-tools/src/runtime/template-source-cache-markers.ts
7481
8026
  var CACHE_MARKER_FILE = "wp-typia-template-cache.json";
@@ -7595,7 +8140,7 @@ function formatExternalTemplateCachePruneMarker({
7595
8140
 
7596
8141
  // ../wp-typia-project-tools/src/runtime/template-source-cache-policy.ts
7597
8142
  import os2 from "os";
7598
- import path14 from "path";
8143
+ import path15 from "path";
7599
8144
  var EXTERNAL_TEMPLATE_CACHE_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE";
7600
8145
  var EXTERNAL_TEMPLATE_CACHE_DIR_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR";
7601
8146
  var EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_TTL_DAYS";
@@ -7613,9 +8158,9 @@ function isExternalTemplateCacheEnabled(env = process.env) {
7613
8158
  function getExternalTemplateCacheRoot(env = process.env) {
7614
8159
  const configuredCacheDir = env[EXTERNAL_TEMPLATE_CACHE_DIR_ENV]?.trim();
7615
8160
  if (configuredCacheDir) {
7616
- return path14.resolve(configuredCacheDir);
8161
+ return path15.resolve(configuredCacheDir);
7617
8162
  }
7618
- return path14.join(os2.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
8163
+ return path15.join(os2.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
7619
8164
  }
7620
8165
  function parseExternalTemplateCacheTtlDays(value) {
7621
8166
  if (typeof value !== "string" && typeof value !== "number") {
@@ -7693,7 +8238,7 @@ function createExternalTemplateCacheKey(keyParts) {
7693
8238
  }
7694
8239
  async function isDirectoryPath(directory) {
7695
8240
  try {
7696
- const stats = await fsp10.lstat(directory);
8241
+ const stats = await fsp11.lstat(directory);
7697
8242
  return stats.isDirectory() && !stats.isSymbolicLink();
7698
8243
  } catch {
7699
8244
  return false;
@@ -7701,7 +8246,7 @@ async function isDirectoryPath(directory) {
7701
8246
  }
7702
8247
  async function removeTemporaryCacheEntry(entryDir) {
7703
8248
  try {
7704
- await fsp10.rm(entryDir, { force: true, recursive: true });
8249
+ await fsp11.rm(entryDir, { force: true, recursive: true });
7705
8250
  } catch {}
7706
8251
  }
7707
8252
  function getCurrentUid() {
@@ -7709,7 +8254,7 @@ function getCurrentUid() {
7709
8254
  }
7710
8255
  async function isPrivateCacheDirectory(directory) {
7711
8256
  try {
7712
- const stats = await fsp10.lstat(directory);
8257
+ const stats = await fsp11.lstat(directory);
7713
8258
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
7714
8259
  return false;
7715
8260
  }
@@ -7727,11 +8272,11 @@ async function isPrivateCacheDirectory(directory) {
7727
8272
  }
7728
8273
  async function ensurePrivateCacheDirectory(directory) {
7729
8274
  try {
7730
- await fsp10.mkdir(directory, {
8275
+ await fsp11.mkdir(directory, {
7731
8276
  mode: PRIVATE_CACHE_DIRECTORY_MODE,
7732
8277
  recursive: true
7733
8278
  });
7734
- const stats = await fsp10.lstat(directory);
8279
+ const stats = await fsp11.lstat(directory);
7735
8280
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
7736
8281
  return false;
7737
8282
  }
@@ -7741,7 +8286,7 @@ async function ensurePrivateCacheDirectory(directory) {
7741
8286
  }
7742
8287
  if (process.platform !== "win32") {
7743
8288
  if ((stats.mode & 63) !== 0) {
7744
- await fsp10.chmod(directory, PRIVATE_CACHE_DIRECTORY_MODE);
8289
+ await fsp11.chmod(directory, PRIVATE_CACHE_DIRECTORY_MODE);
7745
8290
  }
7746
8291
  }
7747
8292
  return isPrivateCacheDirectory(directory);
@@ -7753,9 +8298,9 @@ function resolveCacheNamespaceDir(cacheRoot, namespace) {
7753
8298
  if (namespace === "." || namespace === ".." || !SAFE_CACHE_NAMESPACE_SEGMENT.test(namespace)) {
7754
8299
  return null;
7755
8300
  }
7756
- const namespaceDir = path15.join(cacheRoot, namespace);
7757
- const relativeNamespaceDir = path15.relative(cacheRoot, namespaceDir);
7758
- if (relativeNamespaceDir.length === 0 || relativeNamespaceDir.startsWith("..") || path15.isAbsolute(relativeNamespaceDir)) {
8301
+ const namespaceDir = path16.join(cacheRoot, namespace);
8302
+ const relativeNamespaceDir = path16.relative(cacheRoot, namespaceDir);
8303
+ if (relativeNamespaceDir.length === 0 || relativeNamespaceDir.startsWith("..") || path16.isAbsolute(relativeNamespaceDir)) {
7759
8304
  return null;
7760
8305
  }
7761
8306
  return namespaceDir;
@@ -7767,14 +8312,14 @@ function getCacheEntryPaths(descriptor) {
7767
8312
  if (!namespaceDir) {
7768
8313
  return null;
7769
8314
  }
7770
- const entryDir = path15.join(namespaceDir, cacheKey);
8315
+ const entryDir = path16.join(namespaceDir, cacheKey);
7771
8316
  return {
7772
8317
  cacheKey,
7773
8318
  cacheRoot,
7774
8319
  entryDir,
7775
- markerPath: path15.join(entryDir, CACHE_MARKER_FILE),
8320
+ markerPath: path16.join(entryDir, CACHE_MARKER_FILE),
7776
8321
  namespaceDir,
7777
- sourceDir: path15.join(entryDir, "source")
8322
+ sourceDir: path16.join(entryDir, "source")
7778
8323
  };
7779
8324
  }
7780
8325
  async function isReusableCacheEntry(entryDir, markerPath, sourceDir) {
@@ -7782,7 +8327,7 @@ async function isReusableCacheEntry(entryDir, markerPath, sourceDir) {
7782
8327
  }
7783
8328
  async function readCacheEntryMarker(markerPath) {
7784
8329
  try {
7785
- return parseExternalTemplateCacheEntryMarker(await fsp10.readFile(markerPath, "utf8"));
8330
+ return parseExternalTemplateCacheEntryMarker(await fsp11.readFile(markerPath, "utf8"));
7786
8331
  } catch {
7787
8332
  return null;
7788
8333
  }
@@ -7798,22 +8343,22 @@ async function isReusableFreshCacheEntry(entryDir, markerPath, sourceDir, nowMs,
7798
8343
  return marker !== null && isExternalTemplateCacheEntryFreshForTtl(marker.createdAtMs, nowMs, ttlMs);
7799
8344
  }
7800
8345
  function isPathInsideDirectory(directory, candidatePath) {
7801
- const relativePath = path15.relative(directory, candidatePath);
7802
- return relativePath.length > 0 && !relativePath.startsWith("..") && !path15.isAbsolute(relativePath);
8346
+ const relativePath = path16.relative(directory, candidatePath);
8347
+ return relativePath.length > 0 && !relativePath.startsWith("..") && !path16.isAbsolute(relativePath);
7803
8348
  }
7804
8349
  async function removeCacheEntryWithinRoot(cacheRoot, entryDir) {
7805
8350
  if (!isPathInsideDirectory(cacheRoot, entryDir)) {
7806
8351
  return false;
7807
8352
  }
7808
8353
  try {
7809
- await fsp10.rm(entryDir, { force: true, recursive: true });
8354
+ await fsp11.rm(entryDir, { force: true, recursive: true });
7810
8355
  return true;
7811
8356
  } catch {
7812
8357
  return false;
7813
8358
  }
7814
8359
  }
7815
8360
  function getCachePruneMarkerPath(cacheRoot) {
7816
- return path15.join(cacheRoot, CACHE_PRUNE_MARKER_FILE);
8361
+ return path16.join(cacheRoot, CACHE_PRUNE_MARKER_FILE);
7817
8362
  }
7818
8363
  async function shouldSkipExternalTemplateCachePrune({
7819
8364
  cacheRoot,
@@ -7827,7 +8372,7 @@ async function shouldSkipExternalTemplateCachePrune({
7827
8372
  }
7828
8373
  let markerText;
7829
8374
  try {
7830
- markerText = await fsp10.readFile(getCachePruneMarkerPath(cacheRoot), "utf8");
8375
+ markerText = await fsp11.readFile(getCachePruneMarkerPath(cacheRoot), "utf8");
7831
8376
  } catch {
7832
8377
  return false;
7833
8378
  }
@@ -7845,7 +8390,7 @@ async function writeExternalTemplateCachePruneMarker({
7845
8390
  ttlMs
7846
8391
  }) {
7847
8392
  try {
7848
- await fsp10.writeFile(getCachePruneMarkerPath(cacheRoot), formatExternalTemplateCachePruneMarker({
8393
+ await fsp11.writeFile(getCachePruneMarkerPath(cacheRoot), formatExternalTemplateCachePruneMarker({
7849
8394
  nowMs,
7850
8395
  pruneIntervalMs,
7851
8396
  ttlMs
@@ -7887,7 +8432,7 @@ async function pruneExternalTemplateCache(options = {}) {
7887
8432
  }
7888
8433
  let namespaceEntries;
7889
8434
  try {
7890
- namespaceEntries = await fsp10.readdir(cacheRoot, { withFileTypes: true });
8435
+ namespaceEntries = await fsp11.readdir(cacheRoot, { withFileTypes: true });
7891
8436
  } catch {
7892
8437
  return result;
7893
8438
  }
@@ -7903,7 +8448,7 @@ async function pruneExternalTemplateCache(options = {}) {
7903
8448
  }
7904
8449
  let cacheEntries;
7905
8450
  try {
7906
- cacheEntries = await fsp10.readdir(namespaceDir, { withFileTypes: true });
8451
+ cacheEntries = await fsp11.readdir(namespaceDir, { withFileTypes: true });
7907
8452
  } catch {
7908
8453
  result.skippedEntries += 1;
7909
8454
  continue;
@@ -7916,14 +8461,14 @@ async function pruneExternalTemplateCache(options = {}) {
7916
8461
  result.skippedEntries += 1;
7917
8462
  continue;
7918
8463
  }
7919
- const entryDir = path15.join(namespaceDir, cacheEntry.name);
8464
+ const entryDir = path16.join(namespaceDir, cacheEntry.name);
7920
8465
  result.scannedEntries += 1;
7921
8466
  if (!isPathInsideDirectory(cacheRoot, entryDir)) {
7922
8467
  result.skippedEntries += 1;
7923
8468
  continue;
7924
8469
  }
7925
- const markerPath = path15.join(entryDir, CACHE_MARKER_FILE);
7926
- const sourceDir = path15.join(entryDir, "source");
8470
+ const markerPath = path16.join(entryDir, CACHE_MARKER_FILE);
8471
+ const sourceDir = path16.join(entryDir, "source");
7927
8472
  const marker = await getReusableCacheEntryMarker(entryDir, markerPath, sourceDir);
7928
8473
  if (!marker) {
7929
8474
  result.skippedEntries += 1;
@@ -7963,7 +8508,7 @@ async function findReusableExternalTemplateSourceCache(descriptor) {
7963
8508
  await pruneExternalTemplateCache();
7964
8509
  let entries;
7965
8510
  try {
7966
- entries = await fsp10.readdir(namespaceDir, { withFileTypes: true });
8511
+ entries = await fsp11.readdir(namespaceDir, { withFileTypes: true });
7967
8512
  } catch {
7968
8513
  return null;
7969
8514
  }
@@ -7972,9 +8517,9 @@ async function findReusableExternalTemplateSourceCache(descriptor) {
7972
8517
  if (!entry.isDirectory()) {
7973
8518
  continue;
7974
8519
  }
7975
- const entryDir = path15.join(namespaceDir, entry.name);
7976
- const markerPath = path15.join(entryDir, CACHE_MARKER_FILE);
7977
- const sourceDir = path15.join(entryDir, "source");
8520
+ const entryDir = path16.join(namespaceDir, entry.name);
8521
+ const markerPath = path16.join(entryDir, CACHE_MARKER_FILE);
8522
+ const sourceDir = path16.join(entryDir, "source");
7978
8523
  const marker = await getReusableCacheEntryMarker(entryDir, markerPath, sourceDir);
7979
8524
  if (!marker || !isExternalTemplateCacheEntryFreshForTtl(marker.createdAtMs, nowMs, ttlMs) || !externalTemplateCacheMetadataMatches(marker.metadata, descriptor.metadata)) {
7980
8525
  continue;
@@ -8016,16 +8561,16 @@ async function resolveExternalTemplateSourceCache(descriptor, populateSourceDir)
8016
8561
  if (existingMarker) {
8017
8562
  await removeCacheEntryWithinRoot(cacheRoot, entryDir);
8018
8563
  }
8019
- const temporaryEntryDir = path15.join(namespaceDir, createTemporaryCacheEntryDirName(cacheKey));
8020
- const temporarySourceDir = path15.join(temporaryEntryDir, "source");
8564
+ const temporaryEntryDir = path16.join(namespaceDir, createTemporaryCacheEntryDirName(cacheKey));
8565
+ const temporarySourceDir = path16.join(temporaryEntryDir, "source");
8021
8566
  let populateFailed = false;
8022
8567
  try {
8023
- await fsp10.mkdir(temporarySourceDir, {
8568
+ await fsp11.mkdir(temporarySourceDir, {
8024
8569
  mode: PRIVATE_CACHE_DIRECTORY_MODE,
8025
8570
  recursive: true
8026
8571
  });
8027
8572
  if (process.platform !== "win32") {
8028
- await fsp10.chmod(temporaryEntryDir, PRIVATE_CACHE_DIRECTORY_MODE);
8573
+ await fsp11.chmod(temporaryEntryDir, PRIVATE_CACHE_DIRECTORY_MODE);
8029
8574
  }
8030
8575
  try {
8031
8576
  await populateSourceDir(temporarySourceDir);
@@ -8033,13 +8578,13 @@ async function resolveExternalTemplateSourceCache(descriptor, populateSourceDir)
8033
8578
  populateFailed = true;
8034
8579
  throw error;
8035
8580
  }
8036
- await fsp10.writeFile(path15.join(temporaryEntryDir, CACHE_MARKER_FILE), formatExternalTemplateCacheEntryMarker({
8581
+ await fsp11.writeFile(path16.join(temporaryEntryDir, CACHE_MARKER_FILE), formatExternalTemplateCacheEntryMarker({
8037
8582
  cacheKey,
8038
8583
  createdAt: new Date,
8039
8584
  metadata: descriptor.metadata,
8040
8585
  namespace: descriptor.namespace
8041
8586
  }), "utf8");
8042
- await fsp10.rename(temporaryEntryDir, entryDir);
8587
+ await fsp11.rename(temporaryEntryDir, entryDir);
8043
8588
  return {
8044
8589
  cacheHit: false,
8045
8590
  sourceDir
@@ -8110,9 +8655,9 @@ async function downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl,
8110
8655
  if (!tarballResponse.ok) {
8111
8656
  throw new Error(`Failed to download npm template tarball for ${locator.raw}: ${tarballResponse.status}`);
8112
8657
  }
8113
- const tarballPath = path16.join(path16.dirname(unpackDir), "template.tgz");
8114
- await fsp11.mkdir(unpackDir, { recursive: true });
8115
- await fsp11.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
8658
+ const tarballPath = path17.join(path17.dirname(unpackDir), "template.tgz");
8659
+ await fsp12.mkdir(unpackDir, { recursive: true });
8660
+ await fsp12.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
8116
8661
  label: `npm template tarball for ${locator.raw}@${resolvedVersion}`,
8117
8662
  maxBytes: getExternalTemplateTarballMaxBytes()
8118
8663
  }));
@@ -8121,7 +8666,7 @@ async function downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl,
8121
8666
  file: tarballPath,
8122
8667
  strip: 1
8123
8668
  });
8124
- await fsp11.rm(tarballPath, { force: true });
8669
+ await fsp12.rm(tarballPath, { force: true });
8125
8670
  await assertNoSymlinks2(unpackDir);
8126
8671
  }
8127
8672
  function selectRegistryVersion(metadata, locator) {
@@ -8216,7 +8761,7 @@ async function fetchNpmTemplateSource(locator) {
8216
8761
  }
8217
8762
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
8218
8763
  try {
8219
- const unpackDir = path16.join(tempRoot, "source");
8764
+ const unpackDir = path17.join(tempRoot, "source");
8220
8765
  await downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir);
8221
8766
  return {
8222
8767
  blockDir: unpackDir,
@@ -8232,20 +8777,22 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8232
8777
  if (locator.rawSpec !== "" && locator.rawSpec !== "*") {
8233
8778
  return null;
8234
8779
  }
8235
- const workspacePackagesRoot = path16.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
8236
- if (fs7.existsSync(workspacePackagesRoot)) {
8237
- for (const entry of fs7.readdirSync(workspacePackagesRoot, {
8780
+ const workspacePackagesRoot = path17.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
8781
+ if (fs6.existsSync(workspacePackagesRoot)) {
8782
+ for (const entry of fs6.readdirSync(workspacePackagesRoot, {
8238
8783
  withFileTypes: true
8239
8784
  })) {
8240
8785
  if (!entry.isDirectory()) {
8241
8786
  continue;
8242
8787
  }
8243
- const packageDir = path16.join(workspacePackagesRoot, entry.name);
8244
- const packageJsonPath = path16.join(packageDir, "package.json");
8245
- if (!fs7.existsSync(packageJsonPath)) {
8788
+ const packageDir = path17.join(workspacePackagesRoot, entry.name);
8789
+ const packageJsonPath = path17.join(packageDir, "package.json");
8790
+ if (!fs6.existsSync(packageJsonPath)) {
8246
8791
  continue;
8247
8792
  }
8248
- const manifest = JSON.parse(fs7.readFileSync(packageJsonPath, "utf8"));
8793
+ const manifest = readJsonFileSync(packageJsonPath, {
8794
+ context: "workspace template package manifest"
8795
+ });
8249
8796
  if (manifest.name === locator.name) {
8250
8797
  return {
8251
8798
  blockDir: packageDir,
@@ -8254,10 +8801,10 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8254
8801
  }
8255
8802
  }
8256
8803
  }
8257
- const workspaceRequire = createRequire2(path16.join(path16.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
8804
+ const workspaceRequire = createRequire2(path17.join(path17.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
8258
8805
  try {
8259
- const packageJsonPath = fs7.realpathSync(workspaceRequire.resolve(`${locator.name}/package.json`));
8260
- const sourceDir = path16.dirname(packageJsonPath);
8806
+ const packageJsonPath = fs6.realpathSync(workspaceRequire.resolve(`${locator.name}/package.json`));
8807
+ const sourceDir = path17.dirname(packageJsonPath);
8261
8808
  return {
8262
8809
  blockDir: sourceDir,
8263
8810
  rootDir: sourceDir
@@ -8266,11 +8813,11 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8266
8813
  const errorCode = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
8267
8814
  if (errorCode === "MODULE_NOT_FOUND" || errorCode === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
8268
8815
  for (const basePath of workspaceRequire.resolve.paths(locator.name) ?? []) {
8269
- const packageJsonPath = path16.join(basePath, locator.name, "package.json");
8270
- if (!fs7.existsSync(packageJsonPath)) {
8816
+ const packageJsonPath = path17.join(basePath, locator.name, "package.json");
8817
+ if (!fs6.existsSync(packageJsonPath)) {
8271
8818
  continue;
8272
8819
  }
8273
- const sourceDir = path16.dirname(fs7.realpathSync(packageJsonPath));
8820
+ const sourceDir = path17.dirname(fs6.realpathSync(packageJsonPath));
8274
8821
  return {
8275
8822
  blockDir: sourceDir,
8276
8823
  rootDir: sourceDir
@@ -8282,27 +8829,29 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8282
8829
  }
8283
8830
  }
8284
8831
  async function isOfficialWorkspaceTemplateSeedAsync(seed) {
8285
- const packageJsonPath = path16.join(seed.rootDir, "package.json");
8832
+ const packageJsonPath = path17.join(seed.rootDir, "package.json");
8286
8833
  if (!await pathExists(packageJsonPath)) {
8287
8834
  return false;
8288
8835
  }
8289
8836
  try {
8290
- const packageJson = JSON.parse(await fsp11.readFile(packageJsonPath, "utf8"));
8837
+ const packageJson = await readJsonFile(packageJsonPath, {
8838
+ context: "workspace template seed manifest"
8839
+ });
8291
8840
  return packageJson.name === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE;
8292
8841
  } catch {
8293
8842
  return false;
8294
8843
  }
8295
8844
  }
8296
8845
  async function assertNoSymlinks2(sourceDir) {
8297
- const stats = await fsp11.lstat(sourceDir);
8846
+ const stats = await fsp12.lstat(sourceDir);
8298
8847
  if (stats.isSymbolicLink()) {
8299
8848
  throw new Error(`Template sources may not include symbolic links: ${sourceDir}`);
8300
8849
  }
8301
8850
  if (!stats.isDirectory()) {
8302
8851
  return;
8303
8852
  }
8304
- for (const entry of await fsp11.readdir(sourceDir)) {
8305
- await assertNoSymlinks2(path16.join(sourceDir, entry));
8853
+ for (const entry of await fsp12.readdir(sourceDir)) {
8854
+ await assertNoSymlinks2(path17.join(sourceDir, entry));
8306
8855
  }
8307
8856
  }
8308
8857
  function runGitTemplateCommand(args, label, options = {}) {
@@ -8331,9 +8880,9 @@ function getGitHubTemplateRepositoryUrl(locator) {
8331
8880
  return `https://github.com/${locator.owner}/${locator.repo}.git`;
8332
8881
  }
8333
8882
  async function resolveGitHubTemplateDirectory(checkoutDir, locator) {
8334
- const sourceDir = path16.resolve(checkoutDir, locator.sourcePath);
8335
- const relativeSourceDir = path16.relative(checkoutDir, sourceDir);
8336
- if (relativeSourceDir.startsWith("..") || path16.isAbsolute(relativeSourceDir)) {
8883
+ const sourceDir = path17.resolve(checkoutDir, locator.sourcePath);
8884
+ const relativeSourceDir = path17.relative(checkoutDir, sourceDir);
8885
+ if (relativeSourceDir.startsWith("..") || path17.isAbsolute(relativeSourceDir)) {
8337
8886
  throw new Error("GitHub template path must stay within the cloned repository.");
8338
8887
  }
8339
8888
  if (!await pathExists(sourceDir)) {
@@ -8522,7 +9071,7 @@ async function resolveGitHubTemplateSource(locator) {
8522
9071
  }
8523
9072
  }
8524
9073
  const { path: remoteRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
8525
- const checkoutDir = path16.join(remoteRoot, "source");
9074
+ const checkoutDir = path17.join(remoteRoot, "source");
8526
9075
  try {
8527
9076
  cloneGitHubTemplateSource(locator, checkoutDir);
8528
9077
  const sourceDir = await resolveGitHubTemplateDirectory(checkoutDir, locator);
@@ -8539,7 +9088,7 @@ async function resolveGitHubTemplateSource(locator) {
8539
9088
  }
8540
9089
  async function resolveTemplateSeed(locator, cwd) {
8541
9090
  if (locator.kind === "path") {
8542
- const sourceDir = path16.resolve(cwd, locator.templatePath);
9091
+ const sourceDir = path17.resolve(cwd, locator.templatePath);
8543
9092
  if (!await pathExists(sourceDir)) {
8544
9093
  throw new Error(`Template path does not exist: ${sourceDir}`);
8545
9094
  }
@@ -9073,7 +9622,8 @@ function buildTemplateVariablesFromBlockSpec(spec) {
9073
9622
  blockRuntimePackageVersion,
9074
9623
  blockTypesPackageVersion,
9075
9624
  projectToolsPackageVersion,
9076
- restPackageVersion
9625
+ restPackageVersion,
9626
+ wpTypiaPackageVersion
9077
9627
  } = getPackageVersions();
9078
9628
  const slug = spec.block.slug;
9079
9629
  const slugSnakeCase = toSnakeCase(slug);
@@ -9129,6 +9679,7 @@ function buildTemplateVariablesFromBlockSpec(spec) {
9129
9679
  requiresPhp: compatibility.pluginHeader.requiresPhp,
9130
9680
  testedUpTo: compatibility.pluginHeader.testedUpTo,
9131
9681
  projectToolsPackageVersion,
9682
+ wpTypiaPackageVersion,
9132
9683
  cssClassName,
9133
9684
  dashCase: slug,
9134
9685
  dataStorageMode,
@@ -13642,7 +14193,8 @@ function getTemplateVariables(templateId, answers) {
13642
14193
  blockRuntimePackageVersion,
13643
14194
  blockTypesPackageVersion,
13644
14195
  projectToolsPackageVersion,
13645
- restPackageVersion
14196
+ restPackageVersion,
14197
+ wpTypiaPackageVersion
13646
14198
  } = getPackageVersions();
13647
14199
  const template = isBuiltInTemplateId(templateId) ? getTemplateById(templateId) : null;
13648
14200
  const metadataDefaults = isBuiltInTemplateId(templateId) ? getBuiltInTemplateMetadataDefaults(templateId) : null;
@@ -13698,6 +14250,7 @@ function getTemplateVariables(templateId, answers) {
13698
14250
  hasAlternatePlainTextRenderTarget: "false",
13699
14251
  hasAlternateRenderTargets: "false",
13700
14252
  projectToolsPackageVersion,
14253
+ wpTypiaPackageVersion,
13701
14254
  requiresAtLeast: compatibility.pluginHeader.requiresAtLeast,
13702
14255
  requiresPhp: compatibility.pluginHeader.requiresPhp,
13703
14256
  cssClassName,
@@ -13801,15 +14354,55 @@ function getTemplateVariables(templateId, answers) {
13801
14354
  // ../wp-typia-project-tools/src/runtime/scaffold.ts
13802
14355
  var DATA_STORAGE_MODES = ["post-meta", "custom-table"];
13803
14356
  var PERSISTENCE_POLICIES = ["authenticated", "public"];
14357
+ var CREATE_PROFILE_IDS = ["plugin-qa"];
13804
14358
  function isDataStorageMode(value) {
13805
14359
  return DATA_STORAGE_MODES.includes(value);
13806
14360
  }
13807
14361
  function isPersistencePolicy(value) {
13808
14362
  return PERSISTENCE_POLICIES.includes(value);
13809
14363
  }
14364
+ function isCreateProfileId(value) {
14365
+ return CREATE_PROFILE_IDS.includes(value);
14366
+ }
14367
+ function resolveCreateProfileId(profile) {
14368
+ if (profile === undefined || profile.trim().length === 0) {
14369
+ return;
14370
+ }
14371
+ const normalizedProfile = profile.trim();
14372
+ if (isCreateProfileId(normalizedProfile)) {
14373
+ return normalizedProfile;
14374
+ }
14375
+ throw new Error(`Unknown create profile "${profile}". Expected one of: ${CREATE_PROFILE_IDS.join(", ")}.`);
14376
+ }
13810
14377
  function normalizeTemplateSelection(templateId) {
13811
14378
  return normalizeTemplateLookupId(templateId);
13812
14379
  }
14380
+ function assertCreateProfileTemplateCompatibility({
14381
+ profile,
14382
+ templateId
14383
+ }) {
14384
+ if (!profile) {
14385
+ return;
14386
+ }
14387
+ if (profile === "plugin-qa" && templateId !== OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE) {
14388
+ throw new Error("`--profile plugin-qa` currently supports only the official workspace template. Use `--template workspace` or add QA files later with `wp-typia add integration-env <name> --wp-env --release-zip`.");
14389
+ }
14390
+ }
14391
+ async function applyCreateProfile({
14392
+ profile,
14393
+ projectDir
14394
+ }) {
14395
+ if (profile !== "plugin-qa") {
14396
+ return;
14397
+ }
14398
+ await runAddIntegrationEnvCommand({
14399
+ cwd: projectDir,
14400
+ integrationEnvName: "local-smoke",
14401
+ service: "none",
14402
+ withReleaseZip: true,
14403
+ withWpEnv: true
14404
+ });
14405
+ }
13813
14406
  async function reportScaffoldProgress2(onProgress, event) {
13814
14407
  await onProgress?.(event);
13815
14408
  }
@@ -13824,6 +14417,7 @@ async function scaffoldProject({
13824
14417
  externalLayerId,
13825
14418
  externalLayerSource,
13826
14419
  externalLayerSourceLabel,
14420
+ profile,
13827
14421
  repositoryReference,
13828
14422
  cwd = process.cwd(),
13829
14423
  allowExistingDir = false,
@@ -13838,6 +14432,10 @@ async function scaffoldProject({
13838
14432
  const resolvedTemplateId = normalizeTemplateSelection(templateId);
13839
14433
  const resolvedPackageManager = getPackageManager(packageManager).id;
13840
14434
  const isBuiltInTemplate = isBuiltInTemplateId(resolvedTemplateId);
14435
+ assertCreateProfileTemplateCompatibility({
14436
+ profile,
14437
+ templateId: resolvedTemplateId
14438
+ });
13841
14439
  assertExternalLayerCompositionOptions({
13842
14440
  externalLayerId,
13843
14441
  externalLayerSource
@@ -13946,17 +14544,17 @@ async function scaffoldProject({
13946
14544
  phase: "finalize-project",
13947
14545
  title: "Finalizing scaffold output"
13948
14546
  });
13949
- const readmePath = path17.join(projectDir, "README.md");
14547
+ const readmePath = path18.join(projectDir, "README.md");
13950
14548
  if (!await pathExists(readmePath)) {
13951
- await fsp12.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
14549
+ await fsp13.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
13952
14550
  withMigrationUi: isBuiltInTemplate || isWorkspace ? withMigrationUi : false,
13953
14551
  withTestPreset: isBuiltInTemplate ? withTestPreset : false,
13954
14552
  withWpEnv: isBuiltInTemplate ? withWpEnv : false
13955
14553
  }), "utf8");
13956
14554
  }
13957
- const gitignorePath = path17.join(projectDir, ".gitignore");
13958
- const existingGitignore = await pathExists(gitignorePath) ? await fsp12.readFile(gitignorePath, "utf8") : "";
13959
- await fsp12.writeFile(gitignorePath, mergeTextLines(buildGitignore(), existingGitignore), "utf8");
14555
+ const gitignorePath = path18.join(projectDir, ".gitignore");
14556
+ const existingGitignore = await pathExists(gitignorePath) ? await fsp13.readFile(gitignorePath, "utf8") : "";
14557
+ await fsp13.writeFile(gitignorePath, mergeTextLines(buildGitignore(), existingGitignore), "utf8");
13960
14558
  await normalizePackageJson(projectDir, resolvedPackageManager);
13961
14559
  if (isBuiltInTemplate) {
13962
14560
  const variableGroups = getScaffoldTemplateVariableGroups(variables);
@@ -13969,6 +14567,10 @@ async function scaffoldProject({
13969
14567
  withWpEnv
13970
14568
  });
13971
14569
  }
14570
+ await applyCreateProfile({
14571
+ profile,
14572
+ projectDir
14573
+ });
13972
14574
  await normalizePackageManagerFiles(projectDir, resolvedPackageManager);
13973
14575
  await removeUnexpectedLockfiles(projectDir, resolvedPackageManager);
13974
14576
  await replaceTextRecursively(projectDir, resolvedPackageManager, {
@@ -14036,6 +14638,6 @@ async function resolveOptionalInteractiveExternalLayerId({
14036
14638
  }
14037
14639
  }
14038
14640
 
14039
- export { syncPersistenceRestArtifacts, copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, getPrimaryDevelopmentScript, getOptionalOnboardingSteps, getOptionalOnboardingNote, getOptionalOnboardingShortNote, isCompoundPersistenceEnabled, formatNonEmptyTargetDirectoryError, resolveExternalTemplateLayers, resolveTemplateSeed, normalizeOptionalCliString, resolveLocalCliPathOption, assertExternalLayerCompositionOptions, assertBuiltInTemplateVariantAllowed, parseAlternateRenderTargets, parseCompoundInnerBlocksPreset, OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY, resolveScaffoldCompatibilityPolicy, createScaffoldCompatibilityConfig, renderScaffoldCompatibilityConfig, updatePluginHeaderCompatibility, getDefaultAnswers, resolveTemplateId, resolvePackageManagerId, collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, scaffoldProject, resolveOptionalInteractiveExternalLayerId };
14641
+ export { syncPersistenceRestArtifacts, copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, getPrimaryDevelopmentScript, getOptionalOnboardingSteps, getOptionalOnboardingNote, getOptionalOnboardingShortNote, isCompoundPersistenceEnabled, formatNonEmptyTargetDirectoryError, executeWorkspaceMutationPlan, insertPhpSnippetBeforeWorkspaceAnchors, appendPhpSnippetBeforeClosingTag, runAddIntegrationEnvCommand, resolveExternalTemplateLayers, resolveTemplateSeed, normalizeOptionalCliString, resolveLocalCliPathOption, assertExternalLayerCompositionOptions, assertBuiltInTemplateVariantAllowed, parseAlternateRenderTargets, parseCompoundInnerBlocksPreset, OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY, resolveScaffoldCompatibilityPolicy, createScaffoldCompatibilityConfig, renderScaffoldCompatibilityConfig, updatePluginHeaderCompatibility, getDefaultAnswers, resolveTemplateId, resolvePackageManagerId, collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, resolveCreateProfileId, scaffoldProject, resolveOptionalInteractiveExternalLayerId };
14040
14642
 
14041
- //# debugId=9368065E49298D9E64756E2164756E21
14643
+ //# debugId=5D116D118BFF7F2764756E2164756E21