wp-typia 0.23.1 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,10 +14,11 @@ import {
14
14
  isOmittableBuiltInTemplateLayerDir,
15
15
  resolveBuiltInTemplateSource,
16
16
  resolveBuiltInTemplateSourceFromLayerDirs
17
- } from "./cli-nvs5atj1.js";
17
+ } from "./cli-sw06c521.js";
18
18
  import {
19
+ DEFAULT_WORDPRESS_ENV_VERSION,
19
20
  getPackageVersions
20
- } from "./cli-fp16mntv.js";
21
+ } from "./cli-y0a8nztv.js";
21
22
  import {
22
23
  BUILTIN_BLOCK_METADATA_VERSION,
23
24
  COMPOUND_CHILD_BLOCK_METADATA_DEFAULTS,
@@ -35,7 +36,7 @@ import {
35
36
  } from "./cli-8hxf9qw6.js";
36
37
  import {
37
38
  seedProjectMigrations
38
- } from "./cli-epsczb1c.js";
39
+ } from "./cli-0v407aag.js";
39
40
  import {
40
41
  ensureMigrationDirectories,
41
42
  isPlainObject,
@@ -62,7 +63,7 @@ import {
62
63
  toTitleCase,
63
64
  validateBlockSlug,
64
65
  validateNamespace
65
- } from "./cli-k5q5v8g6.js";
66
+ } from "./cli-v0nnagb3.js";
66
67
  import {
67
68
  createManagedTempRoot
68
69
  } from "./cli-t73q5aqz.js";
@@ -824,7 +825,7 @@ async function applyGeneratedProjectDxPackageJson({
824
825
  } : {}
825
826
  };
826
827
  if (withWpEnv || withTestPreset) {
827
- packageJson.devDependencies["@wordpress/env"] = "^11.2.0";
828
+ packageJson.devDependencies["@wordpress/env"] = DEFAULT_WORDPRESS_ENV_VERSION;
828
829
  }
829
830
  if (withTestPreset) {
830
831
  packageJson.devDependencies["@playwright/test"] = "^1.54.2";
@@ -2307,72 +2308,169 @@ async function withEphemeralScaffoldNodeModules(targetDir, callback) {
2307
2308
  }
2308
2309
 
2309
2310
  // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env.ts
2311
+ import path7 from "path";
2312
+
2313
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env-files.ts
2310
2314
  import { promises as fsp4 } from "fs";
2311
2315
  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;
2316
+ async function appendMissingLines(filePath, lines) {
2317
+ const current = await readOptionalUtf8File(filePath) ?? "";
2318
+ const existingLines = new Set(current.split(/\r?\n/u));
2319
+ const missingLines = lines.filter((line) => !existingLines.has(line));
2320
+ if (missingLines.length === 0) {
2321
+ return;
2327
2322
  }
2323
+ const separator = current.length === 0 || current.endsWith(`
2324
+ `) ? "" : `
2325
+ `;
2326
+ await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2327
+ await fsp4.writeFile(filePath, `${current}${separator}${missingLines.join(`
2328
+ `)}
2329
+ `, "utf8");
2328
2330
  }
2329
- async function executeWorkspaceMutationPlan({
2330
- filePaths,
2331
- run,
2332
- snapshotDirs = [],
2333
- targetPaths = []
2331
+ async function writeFileIfAbsent({
2332
+ filePath,
2333
+ source,
2334
+ warnings
2334
2335
  }) {
2335
- const mutationSnapshot = {
2336
- fileSources: await snapshotWorkspaceFiles(filePaths),
2337
- snapshotDirs: [...snapshotDirs],
2338
- targetPaths: [...targetPaths]
2339
- };
2336
+ await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2340
2337
  try {
2341
- return await run();
2338
+ await fsp4.writeFile(filePath, source, { encoding: "utf8", flag: "wx" });
2342
2339
  } catch (error) {
2343
- try {
2344
- await rollbackWorkspaceMutation(mutationSnapshot);
2345
- } catch (rollbackError) {
2346
- throw new WorkspaceMutationRollbackError(error, rollbackError);
2340
+ if (error.code === "EEXIST") {
2341
+ warnings.push(`Preserved existing ${path5.basename(filePath)}; review it manually if you need different local integration settings.`);
2342
+ return;
2347
2343
  }
2348
2344
  throw error;
2349
2345
  }
2350
2346
  }
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;
2347
+ async function writeNewScaffoldFile(filePath, source) {
2348
+ await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2349
+ try {
2350
+ await fsp4.writeFile(filePath, source, { encoding: "utf8", flag: "wx" });
2351
+ } catch (error) {
2352
+ if (error.code === "EEXIST") {
2353
+ throw new Error(`An integration environment scaffold already exists at ${filePath}. Choose a different name.`);
2357
2354
  }
2355
+ throw error;
2358
2356
  }
2359
- return `${source.trimEnd()}
2360
- ${snippet}
2361
- `;
2362
2357
  }
2363
- function appendPhpSnippetBeforeClosingTag(source, snippet) {
2364
- const closingTagPattern = /\?>\s*$/u;
2365
- if (closingTagPattern.test(source)) {
2366
- return source.replace(closingTagPattern, `${snippet}
2367
- ?>`);
2358
+
2359
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env-package-json.ts
2360
+ import { promises as fsp5 } from "fs";
2361
+ import path6 from "path";
2362
+ function addScriptIfMissing({
2363
+ scriptName,
2364
+ scripts,
2365
+ scriptValue,
2366
+ warnings
2367
+ }) {
2368
+ if (scripts[scriptName] === undefined) {
2369
+ scripts[scriptName] = scriptValue;
2370
+ return;
2368
2371
  }
2369
- return `${source.trimEnd()}
2370
- ${snippet}
2371
- `;
2372
+ if (scripts[scriptName] !== scriptValue) {
2373
+ warnings.push(`Preserved existing package script "${scriptName}"; add "${scriptValue}" manually if you want the generated integration command.`);
2374
+ }
2375
+ }
2376
+ async function mutateIntegrationEnvPackageJson(projectDir, mutate) {
2377
+ const packageJsonPath = path6.join(projectDir, "package.json");
2378
+ const packageJson = await readJsonFile(packageJsonPath, {
2379
+ context: "integration env package manifest"
2380
+ });
2381
+ mutate(packageJson);
2382
+ await fsp5.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
2383
+ `, "utf8");
2384
+ }
2385
+ function addIntegrationEnvPackageJsonEntries({
2386
+ integrationEnvSlug,
2387
+ packageManager,
2388
+ packageJson,
2389
+ withReleaseZip,
2390
+ service,
2391
+ warnings,
2392
+ withWpEnv
2393
+ }) {
2394
+ const devDependencies = {
2395
+ ...packageJson.devDependencies ?? {}
2396
+ };
2397
+ if (withWpEnv && devDependencies["@wordpress/env"] === undefined) {
2398
+ devDependencies["@wordpress/env"] = DEFAULT_WORDPRESS_ENV_VERSION;
2399
+ }
2400
+ packageJson.devDependencies = devDependencies;
2401
+ const scripts = {
2402
+ ...packageJson.scripts ?? {}
2403
+ };
2404
+ addScriptIfMissing({
2405
+ scriptName: `smoke:${integrationEnvSlug}`,
2406
+ scriptValue: `node scripts/integration-smoke/${integrationEnvSlug}.mjs`,
2407
+ scripts,
2408
+ warnings
2409
+ });
2410
+ addScriptIfMissing({
2411
+ scriptName: "smoke:integration",
2412
+ scriptValue: formatRunScript(packageManager, `smoke:${integrationEnvSlug}`),
2413
+ scripts,
2414
+ warnings
2415
+ });
2416
+ if (withWpEnv) {
2417
+ addScriptIfMissing({
2418
+ scriptName: "wp-env:start",
2419
+ scriptValue: "wp-env start",
2420
+ scripts,
2421
+ warnings
2422
+ });
2423
+ addScriptIfMissing({
2424
+ scriptName: "wp-env:stop",
2425
+ scriptValue: "wp-env stop",
2426
+ scripts,
2427
+ warnings
2428
+ });
2429
+ addScriptIfMissing({
2430
+ scriptName: "wp-env:reset",
2431
+ scriptValue: "wp-env destroy all && wp-env start",
2432
+ scripts,
2433
+ warnings
2434
+ });
2435
+ }
2436
+ if (withReleaseZip) {
2437
+ addScriptIfMissing({
2438
+ scriptName: "release:zip",
2439
+ scriptValue: `${formatRunScript(packageManager, "sync-rest:package")} && ${formatRunScript(packageManager, "build")} && wp-scripts plugin-zip`,
2440
+ scripts,
2441
+ warnings
2442
+ });
2443
+ addScriptIfMissing({
2444
+ scriptName: "release:zip:check",
2445
+ scriptValue: `${formatRunScript(packageManager, "sync-rest:package:check")} && ${formatRunScript(packageManager, "build")}`,
2446
+ scripts,
2447
+ warnings
2448
+ });
2449
+ addScriptIfMissing({
2450
+ scriptName: "qa:check",
2451
+ scriptValue: `${formatRunScript(packageManager, "wp-typia:doctor:workspace")} && ${formatRunScript(packageManager, "release:zip:check")}`,
2452
+ scripts,
2453
+ warnings
2454
+ });
2455
+ }
2456
+ if (service === "docker-compose") {
2457
+ addScriptIfMissing({
2458
+ scriptName: "service:start",
2459
+ scriptValue: "docker compose -f docker-compose.integration.yml up -d",
2460
+ scripts,
2461
+ warnings
2462
+ });
2463
+ addScriptIfMissing({
2464
+ scriptName: "service:stop",
2465
+ scriptValue: "docker compose -f docker-compose.integration.yml down",
2466
+ scripts,
2467
+ warnings
2468
+ });
2469
+ }
2470
+ packageJson.scripts = scripts;
2372
2471
  }
2373
2472
 
2374
- // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env.ts
2375
- var WP_ENV_PACKAGE_VERSION = "^11.2.0";
2473
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env-source-emitters.ts
2376
2474
  function buildWpEnvConfigSource() {
2377
2475
  return `${JSON.stringify({
2378
2476
  $schema: "https://schemas.wp.org/trunk/wp-env.json",
@@ -2465,6 +2563,11 @@ function getEnv(name, fallback) {
2465
2563
  return process.env[name] ?? envFile[name] ?? fallback;
2466
2564
  }
2467
2565
 
2566
+ function getPositiveIntegerEnv(name, fallback) {
2567
+ const value = Number.parseInt(getEnv(name, String(fallback)), 10);
2568
+ return Number.isFinite(value) && value > 0 ? value : fallback;
2569
+ }
2570
+
2468
2571
  function resolveEndpointUrl(baseUrl, endpointPath) {
2469
2572
  const normalizedBaseUrl = new URL(baseUrl);
2470
2573
  if (!normalizedBaseUrl.pathname.endsWith("/")) {
@@ -2476,10 +2579,15 @@ function resolveEndpointUrl(baseUrl, endpointPath) {
2476
2579
  }
2477
2580
 
2478
2581
  async function assertJsonEndpoint(label, url) {
2582
+ const requestTimeoutMs = getPositiveIntegerEnv(
2583
+ "WP_TYPIA_SMOKE_TIMEOUT_MS",
2584
+ 30_000,
2585
+ );
2479
2586
  const response = await fetch(url, {
2480
2587
  headers: {
2481
2588
  accept: "application/json",
2482
2589
  },
2590
+ signal: AbortSignal.timeout(requestTimeoutMs),
2483
2591
  });
2484
2592
 
2485
2593
  if (!response.ok) {
@@ -2529,6 +2637,7 @@ function buildEnvExampleSource(service) {
2529
2637
  "WP_TYPIA_SMOKE_BASE_URL=http://localhost:8888",
2530
2638
  "WP_TYPIA_SMOKE_USERNAME=admin",
2531
2639
  "WP_TYPIA_SMOKE_PASSWORD=password",
2640
+ "WP_TYPIA_SMOKE_TIMEOUT_MS=30000",
2532
2641
  ...service === "docker-compose" ? [
2533
2642
  "",
2534
2643
  "# Optional docker-compose integration service starter.",
@@ -2590,150 +2699,69 @@ ${setupSteps.map((step, index) => `${index + 1}. ${step}`).join(`
2590
2699
  ${withReleaseZip ? "- Treat `release:zip:check` as a CI guard before packaging release artifacts.\n" : ""}
2591
2700
  `;
2592
2701
  }
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;
2702
+
2703
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-mutation.ts
2704
+ var DEFAULT_PHP_SNIPPET_INSERTION_ANCHORS = [
2705
+ /add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
2706
+ /\?>\s*$/u
2707
+ ];
2708
+
2709
+ class WorkspaceMutationRollbackError extends Error {
2710
+ mutationError;
2711
+ rollbackError;
2712
+ constructor(mutationError, rollbackError) {
2713
+ super("Workspace mutation failed and rollback also failed.");
2714
+ this.name = "WorkspaceMutationRollbackError";
2715
+ this.mutationError = mutationError;
2716
+ this.rollbackError = rollbackError;
2599
2717
  }
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
2718
  }
2608
- async function writeFileIfAbsent({
2609
- filePath,
2610
- source,
2611
- warnings
2719
+ async function executeWorkspaceMutationPlan({
2720
+ filePaths,
2721
+ run,
2722
+ snapshotDirs = [],
2723
+ targetPaths = []
2612
2724
  }) {
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;
2725
+ const mutationSnapshot = {
2726
+ fileSources: await snapshotWorkspaceFiles(filePaths),
2727
+ snapshotDirs: [...snapshotDirs],
2728
+ targetPaths: [...targetPaths]
2729
+ };
2730
+ try {
2731
+ return await run();
2732
+ } catch (error) {
2733
+ try {
2734
+ await rollbackWorkspaceMutation(mutationSnapshot);
2735
+ } catch (rollbackError) {
2736
+ throw new WorkspaceMutationRollbackError(error, rollbackError);
2737
+ }
2738
+ throw error;
2616
2739
  }
2617
- await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2618
- await fsp4.writeFile(filePath, source, "utf8");
2619
2740
  }
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.`);
2741
+ function insertPhpSnippetBeforeWorkspaceAnchors(source, snippet) {
2742
+ for (const anchor of DEFAULT_PHP_SNIPPET_INSERTION_ANCHORS) {
2743
+ const candidate = source.replace(anchor, (match) => `${snippet}
2744
+ ${match}`);
2745
+ if (candidate !== source) {
2746
+ return candidate;
2747
+ }
2623
2748
  }
2624
- await fsp4.mkdir(path5.dirname(filePath), { recursive: true });
2625
- await fsp4.writeFile(filePath, source, "utf8");
2749
+ return `${source.trimEnd()}
2750
+ ${snippet}
2751
+ `;
2626
2752
  }
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
- });
2753
+ function appendPhpSnippetBeforeClosingTag(source, snippet) {
2754
+ const closingTagPattern = /\?>\s*$/u;
2755
+ if (closingTagPattern.test(source)) {
2756
+ return source.replace(closingTagPattern, `${snippet}
2757
+ ?>`);
2734
2758
  }
2735
- packageJson.scripts = scripts;
2759
+ return `${source.trimEnd()}
2760
+ ${snippet}
2761
+ `;
2736
2762
  }
2763
+
2764
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-integration-env.ts
2737
2765
  async function runAddIntegrationEnvCommand({
2738
2766
  cwd = process.cwd(),
2739
2767
  integrationEnvName,
@@ -2745,15 +2773,15 @@ async function runAddIntegrationEnvCommand({
2745
2773
  const integrationEnvSlug = assertValidGeneratedSlug("Integration environment name", normalizeBlockSlug(integrationEnvName), "wp-typia add integration-env <name> [--wp-env] [--release-zip]");
2746
2774
  const serviceId = assertValidIntegrationEnvService(service);
2747
2775
  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`);
2776
+ const packageJsonPath = path7.join(workspace.projectDir, "package.json");
2777
+ const gitignorePath = path7.join(workspace.projectDir, ".gitignore");
2778
+ const envExamplePath = path7.join(workspace.projectDir, ".env.example");
2779
+ const wpEnvPath = path7.join(workspace.projectDir, ".wp-env.json");
2780
+ const dockerComposePath = path7.join(workspace.projectDir, "docker-compose.integration.yml");
2781
+ const smokeDir = path7.join(workspace.projectDir, "scripts", "integration-smoke");
2782
+ const docsDir = path7.join(workspace.projectDir, "docs", "integration-env");
2783
+ const smokeScriptPath = path7.join(smokeDir, `${integrationEnvSlug}.mjs`);
2784
+ const docsPath = path7.join(docsDir, `${integrationEnvSlug}.md`);
2757
2785
  const shouldRemoveSmokeDirOnRollback = !await pathExists(smokeDir);
2758
2786
  const shouldRemoveDocsDirOnRollback = !await pathExists(docsDir);
2759
2787
  await executeWorkspaceMutationPlan({
@@ -2797,7 +2825,7 @@ async function runAddIntegrationEnvCommand({
2797
2825
  warnings
2798
2826
  });
2799
2827
  }
2800
- await mutatePackageJson2(workspace.projectDir, (packageJson) => addIntegrationEnvPackageJsonEntries({
2828
+ await mutateIntegrationEnvPackageJson(workspace.projectDir, (packageJson) => addIntegrationEnvPackageJsonEntries({
2801
2829
  integrationEnvSlug,
2802
2830
  packageManager: workspace.packageManager,
2803
2831
  packageJson,
@@ -2820,7 +2848,7 @@ async function runAddIntegrationEnvCommand({
2820
2848
 
2821
2849
  // ../wp-typia-project-tools/src/runtime/cli-validation.ts
2822
2850
  import fs3 from "fs";
2823
- import path6 from "path";
2851
+ import path8 from "path";
2824
2852
  function normalizeOptionalCliString(value) {
2825
2853
  if (typeof value !== "string") {
2826
2854
  return;
@@ -2829,14 +2857,14 @@ function normalizeOptionalCliString(value) {
2829
2857
  return trimmed.length > 0 ? trimmed : undefined;
2830
2858
  }
2831
2859
  function looksLikeLocalCliPath(value) {
2832
- return path6.isAbsolute(value) || value.startsWith("./") || value.startsWith("../") || value.startsWith(".\\") || value.startsWith("..\\");
2860
+ return path8.isAbsolute(value) || value.startsWith("./") || value.startsWith("../") || value.startsWith(".\\") || value.startsWith("..\\");
2833
2861
  }
2834
2862
  function resolveLocalCliPathOption(options) {
2835
2863
  const normalizedValue = normalizeOptionalCliString(options.value);
2836
2864
  if (!normalizedValue || !looksLikeLocalCliPath(normalizedValue)) {
2837
2865
  return normalizedValue;
2838
2866
  }
2839
- const resolvedPath = path6.resolve(options.cwd, normalizedValue);
2867
+ const resolvedPath = path8.resolve(options.cwd, normalizedValue);
2840
2868
  if (!fs3.existsSync(resolvedPath)) {
2841
2869
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
2842
2870
  }
@@ -3087,37 +3115,37 @@ async function collectScaffoldAnswers({
3087
3115
  }
3088
3116
 
3089
3117
  // ../wp-typia-project-tools/src/runtime/scaffold.ts
3090
- import { promises as fsp13 } from "fs";
3091
- import path18 from "path";
3118
+ import { promises as fsp14 } from "fs";
3119
+ import path20 from "path";
3092
3120
 
3093
3121
  // ../wp-typia-project-tools/src/runtime/scaffold-apply-utils.ts
3094
- import { promises as fsp7 } from "fs";
3095
- import path10 from "path";
3122
+ import { promises as fsp8 } from "fs";
3123
+ import path12 from "path";
3096
3124
  import { execSync as execSync3 } from "child_process";
3097
3125
  import { fileURLToPath } from "url";
3098
3126
 
3099
3127
  // ../wp-typia-project-tools/src/runtime/migration-ui-capability.ts
3100
- import { promises as fsp5 } from "fs";
3101
- import path7 from "path";
3128
+ import { promises as fsp6 } from "fs";
3129
+ import path9 from "path";
3102
3130
  var INITIAL_MIGRATION_VERSION = "v1";
3103
3131
  var BLOCK_METADATA_IMPORT_LINE = "import metadata from './block-metadata';";
3104
3132
  var LEGACY_BLOCK_JSON_IMPORT_LINE = "import metadata from './block.json';";
3105
- async function mutatePackageJson3(projectDir, mutate) {
3106
- const packageJsonPath = path7.join(projectDir, "package.json");
3133
+ async function mutatePackageJson2(projectDir, mutate) {
3134
+ const packageJsonPath = path9.join(projectDir, "package.json");
3107
3135
  const packageJson = await readJsonFile(packageJsonPath, {
3108
3136
  context: "migration UI package manifest"
3109
3137
  });
3110
3138
  mutate(packageJson);
3111
- await fsp5.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3139
+ await fsp6.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3112
3140
  `, "utf8");
3113
3141
  }
3114
3142
  async function patchFile(filePath, transform) {
3115
- const source = await fsp5.readFile(filePath, "utf8");
3143
+ const source = await fsp6.readFile(filePath, "utf8");
3116
3144
  const nextSource = transform(source);
3117
3145
  if (nextSource === source) {
3118
3146
  throw new Error(`Unable to apply migration UI patch for ${filePath}`);
3119
3147
  }
3120
- await fsp5.writeFile(filePath, nextSource, "utf8");
3148
+ await fsp6.writeFile(filePath, nextSource, "utf8");
3121
3149
  }
3122
3150
  function injectAfter(source, needle, insertion) {
3123
3151
  if (source.includes(insertion)) {
@@ -3179,8 +3207,8 @@ function buildMigrationBlocks(templateId, variables) {
3179
3207
  ];
3180
3208
  }
3181
3209
  async function applySingleBlockPatches(projectDir, variables) {
3182
- const editPath = path7.join(projectDir, "src", "edit.tsx");
3183
- const indexPath = path7.join(projectDir, "src", "index.tsx");
3210
+ const editPath = path9.join(projectDir, "src", "edit.tsx");
3211
+ const indexPath = path9.join(projectDir, "src", "index.tsx");
3184
3212
  const deprecatedImport = `import { deprecated } from './migrations/generated/${variables.slugKebabCase}/deprecated';`;
3185
3213
  const deprecatedLine = " deprecated,";
3186
3214
  const dashboardImport = `import { MigrationDashboard } from './admin/migration-dashboard';`;
@@ -3201,10 +3229,10 @@ async function applySingleBlockPatches(projectDir, variables) {
3201
3229
  });
3202
3230
  }
3203
3231
  async function applyCompoundPatches(projectDir, variables) {
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");
3232
+ const parentEditPath = path9.join(projectDir, "src", "blocks", variables.slugKebabCase, "edit.tsx");
3233
+ const parentIndexPath = path9.join(projectDir, "src", "blocks", variables.slugKebabCase, "index.tsx");
3234
+ const childIndexPath = path9.join(projectDir, "src", "blocks", `${variables.slugKebabCase}-item`, "index.tsx");
3235
+ const addChildScriptPath = path9.join(projectDir, "scripts", "add-compound-child.ts");
3208
3236
  await patchFile(parentIndexPath, (source) => {
3209
3237
  let nextSource = injectAfterBlockMetadataImport(source, `import { deprecated } from '../../migrations/generated/${variables.slugKebabCase}/deprecated';`);
3210
3238
  nextSource = injectBefore(nextSource, "\tedit: Edit,", "\tdeprecated,");
@@ -3274,9 +3302,9 @@ async function applyMigrationUiCapability({
3274
3302
  templateId,
3275
3303
  variables
3276
3304
  }) {
3277
- const commonTemplateDir = path7.join(SHARED_MIGRATION_UI_TEMPLATE_ROOT, "common");
3305
+ const commonTemplateDir = path9.join(SHARED_MIGRATION_UI_TEMPLATE_ROOT, "common");
3278
3306
  await copyInterpolatedDirectory(commonTemplateDir, projectDir, variables);
3279
- await mutatePackageJson3(projectDir, (packageJson) => {
3307
+ await mutatePackageJson2(projectDir, (packageJson) => {
3280
3308
  const wpTypiaPackageVersion = getPackageVersions().wpTypiaPackageVersion;
3281
3309
  const canonicalCliSpecifier = wpTypiaPackageVersion === "^0.0.0" ? "wp-typia" : `wp-typia@${wpTypiaPackageVersion.replace(/^[~^]/u, "")}`;
3282
3310
  const migrationCli = (args) => formatPackageExecCommand(packageManager, canonicalCliSpecifier, `migrate ${args}`);
@@ -3528,9 +3556,9 @@ function mergeTextLines(primaryContent, existingContent) {
3528
3556
  }
3529
3557
 
3530
3558
  // ../wp-typia-project-tools/src/runtime/scaffold-package-manager-files.ts
3531
- import { promises as fsp6 } from "fs";
3559
+ import { promises as fsp7 } from "fs";
3532
3560
  import { execSync as execSync2 } from "child_process";
3533
- import path8 from "path";
3561
+ import path10 from "path";
3534
3562
  var LOCKFILES = {
3535
3563
  bun: ["bun.lock", "bun.lockb"],
3536
3564
  npm: ["package-lock.json"],
@@ -3538,16 +3566,16 @@ var LOCKFILES = {
3538
3566
  yarn: ["yarn.lock"]
3539
3567
  };
3540
3568
  async function normalizePackageManagerFiles(targetDir, packageManagerId) {
3541
- const yarnRcPath = path8.join(targetDir, ".yarnrc.yml");
3569
+ const yarnRcPath = path10.join(targetDir, ".yarnrc.yml");
3542
3570
  if (packageManagerId === "yarn") {
3543
- await fsp6.writeFile(yarnRcPath, `nodeLinker: node-modules
3571
+ await fsp7.writeFile(yarnRcPath, `nodeLinker: node-modules
3544
3572
  `, "utf8");
3545
3573
  return;
3546
3574
  }
3547
- await fsp6.rm(yarnRcPath, { force: true });
3575
+ await fsp7.rm(yarnRcPath, { force: true });
3548
3576
  }
3549
3577
  async function normalizePackageJson(targetDir, packageManagerId) {
3550
- const packageJsonPath = path8.join(targetDir, "package.json");
3578
+ const packageJsonPath = path10.join(targetDir, "package.json");
3551
3579
  const packageJsonSource = await readOptionalUtf8File(packageJsonPath);
3552
3580
  if (packageJsonSource === null) {
3553
3581
  return;
@@ -3569,7 +3597,7 @@ async function normalizePackageJson(targetDir, packageManagerId) {
3569
3597
  }
3570
3598
  }
3571
3599
  }
3572
- await fsp6.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3600
+ await fsp7.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
3573
3601
  `, "utf8");
3574
3602
  }
3575
3603
  async function removeUnexpectedLockfiles(targetDir, packageManagerId) {
@@ -3579,7 +3607,7 @@ async function removeUnexpectedLockfiles(targetDir, packageManagerId) {
3579
3607
  if (keep.has(filename)) {
3580
3608
  return;
3581
3609
  }
3582
- await fsp6.rm(path8.join(targetDir, filename), { force: true });
3610
+ await fsp7.rm(path10.join(targetDir, filename), { force: true });
3583
3611
  }));
3584
3612
  }
3585
3613
  async function defaultInstallDependencies({
@@ -3593,7 +3621,7 @@ async function defaultInstallDependencies({
3593
3621
  }
3594
3622
  // ../wp-typia-project-tools/src/runtime/scaffold-repository-reference.ts
3595
3623
  import { createRequire } from "module";
3596
- import path9 from "path";
3624
+ import path11 from "path";
3597
3625
  var require2 = createRequire(import.meta.url);
3598
3626
  var DEFAULT_SCAFFOLD_REPOSITORY_REFERENCE = "imjlk/wp-typia";
3599
3627
  function readRepositoryPackageManifest(packageJsonPath) {
@@ -3658,9 +3686,9 @@ function parseRepositoryReference(value) {
3658
3686
  }
3659
3687
  function getDefaultRepositoryManifestPaths() {
3660
3688
  const candidatePaths = [
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"),
3689
+ path11.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "..", "package.json"),
3690
+ path11.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json"),
3691
+ path11.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json"),
3664
3692
  resolveInstalledPackageManifestPath("wp-typia"),
3665
3693
  resolveInstalledPackageManifestPath("@wp-typia/project-tools")
3666
3694
  ].filter((candidatePath) => Boolean(candidatePath));
@@ -3687,7 +3715,7 @@ async function reportScaffoldProgress(onProgress, event) {
3687
3715
  await onProgress?.(event);
3688
3716
  }
3689
3717
  var EPHEMERAL_NODE_MODULES_LINK_TYPE2 = process.platform === "win32" ? "junction" : "dir";
3690
- var __dirname2 = path10.dirname(fileURLToPath(import.meta.url));
3718
+ var __dirname2 = path12.dirname(fileURLToPath(import.meta.url));
3691
3719
  var LOCKFILES2 = {
3692
3720
  bun: ["bun.lock", "bun.lockb"],
3693
3721
  npm: ["package-lock.json"],
@@ -3695,11 +3723,11 @@ var LOCKFILES2 = {
3695
3723
  yarn: ["yarn.lock"]
3696
3724
  };
3697
3725
  async function ensureDirectory(targetDir, allowExisting = false) {
3698
- await fsp7.mkdir(targetDir, { recursive: true });
3726
+ await fsp8.mkdir(targetDir, { recursive: true });
3699
3727
  if (allowExisting) {
3700
3728
  return;
3701
3729
  }
3702
- const entries = await fsp7.readdir(targetDir);
3730
+ const entries = await fsp8.readdir(targetDir);
3703
3731
  if (entries.length > 0) {
3704
3732
  throw new Error(formatNonEmptyTargetDirectoryError(targetDir));
3705
3733
  }
@@ -3710,42 +3738,42 @@ async function writeStarterManifestFiles2(targetDir, templateId, variables, arti
3710
3738
  relativePath: `${artifact.relativeDir}/typia.manifest.json`
3711
3739
  })) : getStarterManifestFiles(templateId, variables);
3712
3740
  for (const { document, relativePath } of manifests) {
3713
- const destinationPath = path10.join(targetDir, relativePath);
3714
- await fsp7.mkdir(path10.dirname(destinationPath), { recursive: true });
3715
- await fsp7.writeFile(destinationPath, stringifyStarterManifest(document), "utf8");
3741
+ const destinationPath = path12.join(targetDir, relativePath);
3742
+ await fsp8.mkdir(path12.dirname(destinationPath), { recursive: true });
3743
+ await fsp8.writeFile(destinationPath, stringifyStarterManifest(document), "utf8");
3716
3744
  }
3717
3745
  }
3718
3746
  async function writeBuiltInStructuralArtifacts(targetDir, artifacts) {
3719
3747
  for (const artifact of artifacts) {
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");
3748
+ const destinationDir = path12.join(targetDir, artifact.relativeDir);
3749
+ await fsp8.mkdir(destinationDir, { recursive: true });
3750
+ await fsp8.writeFile(path12.join(destinationDir, "types.ts"), artifact.typesSource, "utf8");
3751
+ await fsp8.writeFile(path12.join(destinationDir, "block.json"), stringifyBuiltInBlockJsonDocument(artifact.blockJsonDocument), "utf8");
3724
3752
  }
3725
3753
  }
3726
3754
  async function writeBuiltInCodeArtifacts(targetDir, codeArtifacts) {
3727
3755
  for (const artifact of codeArtifacts) {
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");
3756
+ const destinationPath = path12.join(targetDir, artifact.relativePath);
3757
+ await fsp8.mkdir(path12.dirname(destinationPath), { recursive: true });
3758
+ await fsp8.writeFile(destinationPath, artifact.source, "utf8");
3731
3759
  }
3732
3760
  }
3733
3761
  async function resolveScaffoldGeneratorNodeModulesPath2() {
3734
- const projectToolsPackageRoot = path10.resolve(__dirname2, "..", "..");
3762
+ const projectToolsPackageRoot = path12.resolve(__dirname2, "..", "..");
3735
3763
  const candidates = [
3736
- path10.join(projectToolsPackageRoot, "node_modules"),
3737
- path10.resolve(projectToolsPackageRoot, "..", ".."),
3738
- path10.resolve(projectToolsPackageRoot, "..", "..", "node_modules")
3764
+ path12.join(projectToolsPackageRoot, "node_modules"),
3765
+ path12.resolve(projectToolsPackageRoot, "..", ".."),
3766
+ path12.resolve(projectToolsPackageRoot, "..", "..", "node_modules")
3739
3767
  ];
3740
3768
  for (const candidate of candidates) {
3741
- if (await pathExists(path10.join(candidate, "typia", "package.json"))) {
3769
+ if (await pathExists(path12.join(candidate, "typia", "package.json"))) {
3742
3770
  return candidate;
3743
3771
  }
3744
3772
  }
3745
3773
  return null;
3746
3774
  }
3747
3775
  async function withEphemeralScaffoldNodeModules2(targetDir, callback) {
3748
- const targetNodeModulesPath = path10.join(targetDir, "node_modules");
3776
+ const targetNodeModulesPath = path12.join(targetDir, "node_modules");
3749
3777
  if (await pathExists(targetNodeModulesPath)) {
3750
3778
  await callback();
3751
3779
  return;
@@ -3754,11 +3782,11 @@ async function withEphemeralScaffoldNodeModules2(targetDir, callback) {
3754
3782
  if (!sourceNodeModulesPath) {
3755
3783
  throw new Error("Unable to resolve a node_modules directory with typia for scaffold-time REST artifact generation.");
3756
3784
  }
3757
- await fsp7.symlink(sourceNodeModulesPath, targetNodeModulesPath, EPHEMERAL_NODE_MODULES_LINK_TYPE2);
3785
+ await fsp8.symlink(sourceNodeModulesPath, targetNodeModulesPath, EPHEMERAL_NODE_MODULES_LINK_TYPE2);
3758
3786
  try {
3759
3787
  await callback();
3760
3788
  } finally {
3761
- await fsp7.rm(targetNodeModulesPath, { force: true, recursive: true });
3789
+ await fsp8.rm(targetNodeModulesPath, { force: true, recursive: true });
3762
3790
  }
3763
3791
  }
3764
3792
  async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables) {
@@ -3769,7 +3797,7 @@ async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables
3769
3797
  await withEphemeralScaffoldNodeModules2(targetDir, async () => {
3770
3798
  if (templateId === "persistence") {
3771
3799
  await syncPersistenceRestArtifacts({
3772
- apiTypesFile: path10.join("src", "api-types.ts"),
3800
+ apiTypesFile: path12.join("src", "api-types.ts"),
3773
3801
  outputDir: "src",
3774
3802
  projectDir: targetDir,
3775
3803
  variables
@@ -3777,27 +3805,27 @@ async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables
3777
3805
  return;
3778
3806
  }
3779
3807
  await syncPersistenceRestArtifacts({
3780
- apiTypesFile: path10.join("src", "blocks", variables.slugKebabCase, "api-types.ts"),
3781
- outputDir: path10.join("src", "blocks", variables.slugKebabCase),
3808
+ apiTypesFile: path12.join("src", "blocks", variables.slugKebabCase, "api-types.ts"),
3809
+ outputDir: path12.join("src", "blocks", variables.slugKebabCase),
3782
3810
  projectDir: targetDir,
3783
3811
  variables
3784
3812
  });
3785
3813
  });
3786
3814
  }
3787
3815
  async function normalizePackageManagerFiles2(targetDir, packageManagerId) {
3788
- const yarnRcPath = path10.join(targetDir, ".yarnrc.yml");
3816
+ const yarnRcPath = path12.join(targetDir, ".yarnrc.yml");
3789
3817
  if (packageManagerId === "yarn") {
3790
- await fsp7.writeFile(yarnRcPath, `nodeLinker: node-modules
3818
+ await fsp8.writeFile(yarnRcPath, `nodeLinker: node-modules
3791
3819
  `, "utf8");
3792
3820
  return;
3793
3821
  }
3794
- await fsp7.rm(yarnRcPath, { force: true });
3822
+ await fsp8.rm(yarnRcPath, { force: true });
3795
3823
  }
3796
3824
  async function removeQueryLoopPlaceholderFiles(projectDir, templateId) {
3797
3825
  if (templateId !== "query-loop") {
3798
3826
  return;
3799
3827
  }
3800
- await fsp7.rm(path10.join(projectDir, "src", "validator-toolkit.ts"), {
3828
+ await fsp8.rm(path12.join(projectDir, "src", "validator-toolkit.ts"), {
3801
3829
  force: true
3802
3830
  });
3803
3831
  }
@@ -3808,7 +3836,7 @@ async function removeUnexpectedLockfiles2(targetDir, packageManagerId) {
3808
3836
  if (keep.has(filename)) {
3809
3837
  return;
3810
3838
  }
3811
- await fsp7.rm(path10.join(targetDir, filename), { force: true });
3839
+ await fsp8.rm(path12.join(targetDir, filename), { force: true });
3812
3840
  }));
3813
3841
  }
3814
3842
  async function replaceTextRecursively(targetDir, packageManagerId, {
@@ -3831,21 +3859,21 @@ async function replaceTextRecursively(targetDir, packageManagerId, {
3831
3859
  manifestPaths: repositoryManifestPaths
3832
3860
  });
3833
3861
  async function visit(currentPath) {
3834
- const stats = await fsp7.stat(currentPath);
3862
+ const stats = await fsp8.stat(currentPath);
3835
3863
  if (stats.isDirectory()) {
3836
- const entries = await fsp7.readdir(currentPath);
3864
+ const entries = await fsp8.readdir(currentPath);
3837
3865
  for (const entry of entries) {
3838
- await visit(path10.join(currentPath, entry));
3866
+ await visit(path12.join(currentPath, entry));
3839
3867
  }
3840
3868
  return;
3841
3869
  }
3842
- if (path10.basename(currentPath) === "package.json" || !textExtensions.has(path10.extname(currentPath))) {
3870
+ if (path12.basename(currentPath) === "package.json" || !textExtensions.has(path12.extname(currentPath))) {
3843
3871
  return;
3844
3872
  }
3845
- const content = await fsp7.readFile(currentPath, "utf8");
3873
+ const content = await fsp8.readFile(currentPath, "utf8");
3846
3874
  const nextContent = replaceRepositoryReferencePlaceholders(transformPackageManagerText(content, packageManagerId), resolvedRepositoryReference);
3847
3875
  if (nextContent !== content) {
3848
- await fsp7.writeFile(currentPath, nextContent, "utf8");
3876
+ await fsp8.writeFile(currentPath, nextContent, "utf8");
3849
3877
  }
3850
3878
  }
3851
3879
  await visit(targetDir);
@@ -3917,17 +3945,17 @@ async function applyBuiltInScaffoldProjectFiles({
3917
3945
  phase: "finalize-project",
3918
3946
  title: "Finalizing scaffold output"
3919
3947
  });
3920
- const readmePath = path10.join(projectDir, "README.md");
3948
+ const readmePath = path12.join(projectDir, "README.md");
3921
3949
  if (!await pathExists(readmePath)) {
3922
- await fsp7.writeFile(readmePath, readmeContent ?? buildReadme(templateId, variables, packageManager, {
3950
+ await fsp8.writeFile(readmePath, readmeContent ?? buildReadme(templateId, variables, packageManager, {
3923
3951
  withMigrationUi,
3924
3952
  withTestPreset,
3925
3953
  withWpEnv
3926
3954
  }), "utf8");
3927
3955
  }
3928
- const gitignorePath = path10.join(projectDir, ".gitignore");
3956
+ const gitignorePath = path12.join(projectDir, ".gitignore");
3929
3957
  const existingGitignore = await readOptionalUtf8File(gitignorePath) ?? "";
3930
- await fsp7.writeFile(gitignorePath, mergeTextLines(gitignoreContent ?? buildGitignore(), existingGitignore), "utf8");
3958
+ await fsp8.writeFile(gitignorePath, mergeTextLines(gitignoreContent ?? buildGitignore(), existingGitignore), "utf8");
3931
3959
  await normalizePackageJson(projectDir, packageManager);
3932
3960
  await applyGeneratedProjectDxPackageJson({
3933
3961
  compoundPersistenceEnabled: isCompoundPersistenceEnabled(variables),
@@ -3958,31 +3986,31 @@ async function applyBuiltInScaffoldProjectFiles({
3958
3986
  }
3959
3987
 
3960
3988
  // ../wp-typia-project-tools/src/runtime/template-source-normalization.ts
3961
- import path14 from "path";
3989
+ import path16 from "path";
3962
3990
 
3963
3991
  // ../wp-typia-project-tools/src/runtime/template-layers.ts
3964
- import path11 from "path";
3965
- import { promises as fsp8 } from "fs";
3992
+ import path13 from "path";
3993
+ import { promises as fsp9 } from "fs";
3966
3994
  var TEMPLATE_LAYER_MANIFEST_FILENAME = "wp-typia.layers.json";
3967
3995
  var TEMPLATE_LAYER_MANIFEST_VERSION = 1;
3968
3996
  function resolveLayerPath(sourceRoot, relativePath) {
3969
- const targetPath = path11.resolve(sourceRoot, relativePath);
3970
- const relativeTarget = path11.relative(sourceRoot, targetPath);
3971
- if (relativeTarget.startsWith("..") || path11.isAbsolute(relativeTarget)) {
3997
+ const targetPath = path13.resolve(sourceRoot, relativePath);
3998
+ const relativeTarget = path13.relative(sourceRoot, targetPath);
3999
+ if (relativeTarget.startsWith("..") || path13.isAbsolute(relativeTarget)) {
3972
4000
  throw new Error(`Template layer path "${relativePath}" must stay within ${sourceRoot}.`);
3973
4001
  }
3974
4002
  return targetPath;
3975
4003
  }
3976
4004
  async function assertNoSymlinks(sourceDir) {
3977
- const stats = await fsp8.lstat(sourceDir);
4005
+ const stats = await fsp9.lstat(sourceDir);
3978
4006
  if (stats.isSymbolicLink()) {
3979
4007
  throw new Error(`Template layer packages may not include symbolic links: ${sourceDir}`);
3980
4008
  }
3981
4009
  if (!stats.isDirectory()) {
3982
4010
  return;
3983
4011
  }
3984
- for (const entry of await fsp8.readdir(sourceDir)) {
3985
- await assertNoSymlinks(path11.join(sourceDir, entry));
4012
+ for (const entry of await fsp9.readdir(sourceDir)) {
4013
+ await assertNoSymlinks(path13.join(sourceDir, entry));
3986
4014
  }
3987
4015
  }
3988
4016
  function parseLayerDefinition(layerId, value) {
@@ -4011,7 +4039,7 @@ function parseLayerDefinition(layerId, value) {
4011
4039
  };
4012
4040
  }
4013
4041
  async function loadExternalTemplateLayerManifest(sourceRoot) {
4014
- const manifestPath = path11.join(sourceRoot, TEMPLATE_LAYER_MANIFEST_FILENAME);
4042
+ const manifestPath = path13.join(sourceRoot, TEMPLATE_LAYER_MANIFEST_FILENAME);
4015
4043
  if (!await pathExists(manifestPath)) {
4016
4044
  return null;
4017
4045
  }
@@ -4111,7 +4139,7 @@ async function resolveExternalTemplateLayers({
4111
4139
  return;
4112
4140
  }
4113
4141
  const layerDir = resolveLayerPath(sourceRoot, definition.path);
4114
- const stats = await fsp8.stat(layerDir).catch(() => null);
4142
+ const stats = await fsp9.stat(layerDir).catch(() => null);
4115
4143
  if (!stats || !stats.isDirectory()) {
4116
4144
  throw new Error(`Layer "${layerId}" points to a missing directory: ${definition.path}`);
4117
4145
  }
@@ -4149,8 +4177,8 @@ async function assertExternalTemplateLayersDoNotWriteProtectedOutputs({
4149
4177
  }
4150
4178
 
4151
4179
  // ../wp-typia-project-tools/src/runtime/template-source-external.ts
4152
- import { promises as fsp9 } from "fs";
4153
- import path12 from "path";
4180
+ import { promises as fsp10 } from "fs";
4181
+ import path14 from "path";
4154
4182
  import { pathToFileURL } from "url";
4155
4183
 
4156
4184
  // ../wp-typia-project-tools/src/runtime/external-template-guards.ts
@@ -4292,16 +4320,16 @@ function getTemplateWarning(key) {
4292
4320
  return `Ignoring external template config key "${key}": ${TEMPLATE_WARNING_MESSAGE}`;
4293
4321
  }
4294
4322
  function resolveSourceSubpath(sourceDir, relativePath) {
4295
- const targetPath = path12.resolve(sourceDir, relativePath);
4296
- const relativeTarget = path12.relative(sourceDir, targetPath);
4297
- if (relativeTarget.startsWith("..") || path12.isAbsolute(relativeTarget)) {
4323
+ const targetPath = path14.resolve(sourceDir, relativePath);
4324
+ const relativeTarget = path14.relative(sourceDir, targetPath);
4325
+ if (relativeTarget.startsWith("..") || path14.isAbsolute(relativeTarget)) {
4298
4326
  throw new Error(`Template path "${relativePath}" must stay within ${sourceDir}.`);
4299
4327
  }
4300
4328
  return targetPath;
4301
4329
  }
4302
4330
  async function findExternalTemplateEntry(sourceDir) {
4303
4331
  for (const filename of EXTERNAL_TEMPLATE_ENTRY_CANDIDATES) {
4304
- const candidate = path12.join(sourceDir, filename);
4332
+ const candidate = path14.join(sourceDir, filename);
4305
4333
  if (await pathExists(candidate)) {
4306
4334
  return candidate;
4307
4335
  }
@@ -4317,7 +4345,7 @@ async function loadExternalTemplateConfig(sourceDir) {
4317
4345
  label: `External template config "${entryPath}"`,
4318
4346
  maxBytes: getExternalTemplateConfigMaxBytes()
4319
4347
  });
4320
- const entryStats = await fsp9.stat(entryPath);
4348
+ const entryStats = await fsp10.stat(entryPath);
4321
4349
  const moduleUrl = `${pathToFileURL(entryPath).href}?mtime=${entryStats.mtimeMs}`;
4322
4350
  const loadedModule = await withExternalTemplateTimeout(`loading external template config "${entryPath}"`, () => import(moduleUrl));
4323
4351
  const loadedConfig = loadedModule.default ?? loadedModule;
@@ -4424,21 +4452,21 @@ async function renderCreateBlockExternalTemplate(sourceDir, context, requestedVa
4424
4452
  const { folderName, formatHint, templatePath } = resolveConfiguredTemplatePath(config, variantConfig);
4425
4453
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-create-block-external-");
4426
4454
  try {
4427
- const renderedRoot = path12.join(tempRoot, "rendered");
4455
+ const renderedRoot = path14.join(tempRoot, "rendered");
4428
4456
  const blockDir = resolveSourceSubpath(renderedRoot, folderName);
4429
4457
  const view = await buildExternalTemplateView(context, config, selectedVariant, variantConfig);
4430
4458
  const blockTemplateDir = resolveSourceSubpath(sourceDir, templatePath);
4431
4459
  await copyRenderedDirectory(blockTemplateDir, blockDir, view, {
4432
4460
  filter: async (sourcePath, _destinationPath, entry) => {
4433
- const mustacheVariantPath = path12.join(path12.dirname(sourcePath), `${entry.name}.mustache`);
4461
+ const mustacheVariantPath = path14.join(path14.dirname(sourcePath), `${entry.name}.mustache`);
4434
4462
  return !(entry.isFile() && (entry.name === "package.json" || entry.name === "README.md") && await pathExists(mustacheVariantPath));
4435
4463
  }
4436
4464
  });
4437
4465
  const assetsPath = typeof variantConfig.assetsPath === "string" ? variantConfig.assetsPath : config.assetsPath;
4438
4466
  if (typeof assetsPath === "string" && assetsPath.trim().length > 0) {
4439
- await copyRawDirectory(resolveSourceSubpath(sourceDir, assetsPath), path12.join(tempRoot, "assets"));
4467
+ await copyRawDirectory(resolveSourceSubpath(sourceDir, assetsPath), path14.join(tempRoot, "assets"));
4440
4468
  }
4441
- const assetsDir = path12.join(tempRoot, "assets");
4469
+ const assetsDir = path14.join(tempRoot, "assets");
4442
4470
  return {
4443
4471
  assetsDir: await pathExists(assetsDir) ? assetsDir : undefined,
4444
4472
  blockDir,
@@ -4455,8 +4483,8 @@ async function renderCreateBlockExternalTemplate(sourceDir, context, requestedVa
4455
4483
  }
4456
4484
 
4457
4485
  // ../wp-typia-project-tools/src/runtime/template-source-remote.ts
4458
- import { promises as fsp10 } from "fs";
4459
- import path13 from "path";
4486
+ import { promises as fsp11 } from "fs";
4487
+ import path15 from "path";
4460
4488
  async function cleanupSeedRootPair(cleanup, seedCleanup) {
4461
4489
  let cleanupError;
4462
4490
  try {
@@ -4479,8 +4507,8 @@ function getDefaultCategoryFromBlockJson(blockJson) {
4479
4507
  async function readRemoteBlockJsonAsync(blockDir) {
4480
4508
  const sourceRoot = await getSeedSourceRoot(blockDir);
4481
4509
  for (const candidate of [
4482
- path13.join(blockDir, "block.json"),
4483
- path13.join(sourceRoot, "block.json")
4510
+ path15.join(blockDir, "block.json"),
4511
+ path15.join(sourceRoot, "block.json")
4484
4512
  ]) {
4485
4513
  if (await pathExists(candidate)) {
4486
4514
  return readJsonFile(candidate, {
@@ -4500,8 +4528,8 @@ async function getDefaultCategoryAsync(sourceDir) {
4500
4528
  }
4501
4529
  async function readTemplatePackageJsonAsync(sourceDir) {
4502
4530
  for (const candidate of [
4503
- path13.join(sourceDir, "package.json.mustache"),
4504
- path13.join(sourceDir, "package.json")
4531
+ path15.join(sourceDir, "package.json.mustache"),
4532
+ path15.join(sourceDir, "package.json")
4505
4533
  ]) {
4506
4534
  if (!await pathExists(candidate)) {
4507
4535
  continue;
@@ -4512,7 +4540,7 @@ async function readTemplatePackageJsonAsync(sourceDir) {
4512
4540
  maxBytes: getExternalTemplatePackageJsonMaxBytes()
4513
4541
  });
4514
4542
  return {
4515
- packageJson: safeJsonParse(await fsp10.readFile(candidate, "utf8"), {
4543
+ packageJson: safeJsonParse(await fsp11.readFile(candidate, "utf8"), {
4516
4544
  context: "template metadata file",
4517
4545
  filePath: candidate
4518
4546
  }),
@@ -4541,16 +4569,16 @@ async function getTemplateProjectTypeAsync(sourceDir) {
4541
4569
  }
4542
4570
  async function normalizeWpTypiaTemplateSeed(seed) {
4543
4571
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
4544
- const normalizedDir = path13.join(tempRoot, "template");
4572
+ const normalizedDir = path15.join(tempRoot, "template");
4545
4573
  try {
4546
4574
  await copyRawDirectory(seed.blockDir, normalizedDir, {
4547
4575
  filter: async (sourcePath, _targetPath, entry) => {
4548
- const mustacheVariantPath = path13.join(path13.dirname(sourcePath), `${entry.name}.mustache`);
4576
+ const mustacheVariantPath = path15.join(path15.dirname(sourcePath), `${entry.name}.mustache`);
4549
4577
  return !(entry.isFile() && (entry.name === "package.json" || entry.name === "README.md") && await pathExists(mustacheVariantPath));
4550
4578
  }
4551
4579
  });
4552
4580
  if (seed.assetsDir && await pathExists(seed.assetsDir)) {
4553
- await fsp10.cp(seed.assetsDir, path13.join(normalizedDir, "assets"), {
4581
+ await fsp11.cp(seed.assetsDir, path15.join(normalizedDir, "assets"), {
4554
4582
  recursive: true,
4555
4583
  force: true
4556
4584
  });
@@ -4639,31 +4667,31 @@ function buildRemoteBlockJsonTemplate(blockJson) {
4639
4667
  }
4640
4668
  async function rewriteBlockJsonImports(directory) {
4641
4669
  const textExtensions = new Set([".js", ".jsx", ".ts", ".tsx"]);
4642
- const targetBlockJsonPath = path13.join(directory, "block.json");
4670
+ const targetBlockJsonPath = path15.join(directory, "block.json");
4643
4671
  async function visit(currentPath) {
4644
- const stats = await fsp10.stat(currentPath);
4672
+ const stats = await fsp11.stat(currentPath);
4645
4673
  if (stats.isDirectory()) {
4646
- const entries = await fsp10.readdir(currentPath);
4674
+ const entries = await fsp11.readdir(currentPath);
4647
4675
  for (const entry of entries) {
4648
- await visit(path13.join(currentPath, entry));
4676
+ await visit(path15.join(currentPath, entry));
4649
4677
  }
4650
4678
  return;
4651
4679
  }
4652
- if (!textExtensions.has(path13.extname(currentPath))) {
4680
+ if (!textExtensions.has(path15.extname(currentPath))) {
4653
4681
  return;
4654
4682
  }
4655
- const content = await fsp10.readFile(currentPath, "utf8");
4656
- const relativeSpecifier = path13.relative(path13.dirname(currentPath), targetBlockJsonPath).replace(/\\/g, "/");
4683
+ const content = await fsp11.readFile(currentPath, "utf8");
4684
+ const relativeSpecifier = path15.relative(path15.dirname(currentPath), targetBlockJsonPath).replace(/\\/g, "/");
4657
4685
  const normalizedSpecifier = relativeSpecifier.startsWith(".") ? relativeSpecifier : `./${relativeSpecifier}`;
4658
4686
  const next = content.replace(/(['"])\.{1,2}\/[^'"]*block\.json\1/g, `$1${normalizedSpecifier}$1`);
4659
4687
  if (next !== content) {
4660
- await fsp10.writeFile(currentPath, next, "utf8");
4688
+ await fsp11.writeFile(currentPath, next, "utf8");
4661
4689
  }
4662
4690
  }
4663
4691
  await visit(directory);
4664
4692
  }
4665
4693
  async function patchRemotePackageJson(templateDir, needsInteractivity) {
4666
- const packageJsonPath = path13.join(templateDir, "package.json.mustache");
4694
+ const packageJsonPath = path15.join(templateDir, "package.json.mustache");
4667
4695
  const packageJson = await readJsonFile(packageJsonPath, {
4668
4696
  context: "remote package template manifest"
4669
4697
  });
@@ -4686,16 +4714,16 @@ async function patchRemotePackageJson(templateDir, needsInteractivity) {
4686
4714
  } else {
4687
4715
  delete packageJson.dependencies;
4688
4716
  }
4689
- await fsp10.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
4717
+ await fsp11.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
4690
4718
  `, "utf8");
4691
4719
  }
4692
4720
  async function getSeedSourceRoot(blockDir) {
4693
- return await pathExists(path13.join(blockDir, "src")) ? path13.join(blockDir, "src") : blockDir;
4721
+ return await pathExists(path15.join(blockDir, "src")) ? path15.join(blockDir, "src") : blockDir;
4694
4722
  }
4695
4723
  async function findSeedRenderPhp(seed) {
4696
4724
  for (const candidate of [
4697
- path13.join(seed.blockDir, "render.php"),
4698
- path13.join(seed.rootDir, "render.php")
4725
+ path15.join(seed.blockDir, "render.php"),
4726
+ path15.join(seed.rootDir, "render.php")
4699
4727
  ]) {
4700
4728
  if (await pathExists(candidate)) {
4701
4729
  return candidate;
@@ -4736,16 +4764,16 @@ async function removeSeedEntryConflicts(templateDir) {
4736
4764
  "view.ts",
4737
4765
  "view.tsx"
4738
4766
  ]) {
4739
- await fsp10.rm(path13.join(templateDir, "src", filename), { force: true });
4767
+ await fsp11.rm(path15.join(templateDir, "src", filename), { force: true });
4740
4768
  }
4741
4769
  }
4742
4770
  async function normalizeCreateBlockSubset(seed, context) {
4743
4771
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-remote-template-");
4744
4772
  try {
4745
- const templateDir = path13.join(tempRoot, "template");
4773
+ const templateDir = path15.join(tempRoot, "template");
4746
4774
  const blockJson = await readRemoteBlockJsonAsync(seed.blockDir);
4747
4775
  const sourceRoot = await getSeedSourceRoot(seed.blockDir);
4748
- await fsp10.mkdir(templateDir, { recursive: true });
4776
+ await fsp11.mkdir(templateDir, { recursive: true });
4749
4777
  for (const layerDir of getBuiltInTemplateLayerDirs("basic")) {
4750
4778
  if (!await pathExists(layerDir)) {
4751
4779
  if (isOmittableBuiltInTemplateLayerDir("basic", layerDir)) {
@@ -4753,29 +4781,29 @@ async function normalizeCreateBlockSubset(seed, context) {
4753
4781
  }
4754
4782
  throw new Error(`Built-in template layer is missing: ${layerDir}`);
4755
4783
  }
4756
- await fsp10.cp(layerDir, templateDir, {
4784
+ await fsp11.cp(layerDir, templateDir, {
4757
4785
  recursive: true,
4758
4786
  force: true
4759
4787
  });
4760
4788
  }
4761
4789
  await removeSeedEntryConflicts(templateDir);
4762
- await fsp10.cp(sourceRoot, path13.join(templateDir, "src"), {
4790
+ await fsp11.cp(sourceRoot, path15.join(templateDir, "src"), {
4763
4791
  recursive: true,
4764
4792
  force: true
4765
4793
  });
4766
4794
  const remoteRenderPath = await findSeedRenderPhp(seed);
4767
4795
  if (remoteRenderPath) {
4768
- await fsp10.copyFile(remoteRenderPath, path13.join(templateDir, "render.php"));
4796
+ await fsp11.copyFile(remoteRenderPath, path15.join(templateDir, "render.php"));
4769
4797
  }
4770
4798
  if (seed.assetsDir && await pathExists(seed.assetsDir)) {
4771
- await fsp10.cp(seed.assetsDir, path13.join(templateDir, "assets"), {
4799
+ await fsp11.cp(seed.assetsDir, path15.join(templateDir, "assets"), {
4772
4800
  recursive: true,
4773
4801
  force: true
4774
4802
  });
4775
4803
  }
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"));
4804
+ await fsp11.writeFile(path15.join(templateDir, "src", "types.ts"), buildRemoteTypesSource(blockJson, context), "utf8");
4805
+ await fsp11.writeFile(path15.join(templateDir, "src", "block.json"), buildRemoteBlockJsonTemplate(blockJson), "utf8");
4806
+ await rewriteBlockJsonImports(path15.join(templateDir, "src"));
4779
4807
  const needsInteractivity = typeof blockJson.viewScriptModule === "string" || typeof blockJson.viewScript === "string" || (await Promise.all([
4780
4808
  "view.js",
4781
4809
  "view.jsx",
@@ -4783,7 +4811,7 @@ async function normalizeCreateBlockSubset(seed, context) {
4783
4811
  "view.tsx",
4784
4812
  "interactivity.js",
4785
4813
  "interactivity.ts"
4786
- ].map((filename) => pathExists(path13.join(templateDir, "src", filename))))).some(Boolean);
4814
+ ].map((filename) => pathExists(path15.join(templateDir, "src", filename))))).some(Boolean);
4787
4815
  await patchRemotePackageJson(templateDir, needsInteractivity);
4788
4816
  return {
4789
4817
  id: "remote:create-block-subset",
@@ -4835,7 +4863,7 @@ function getTemplateVariableContext(variables) {
4835
4863
  };
4836
4864
  }
4837
4865
  async function detectTemplateSourceFormat(sourceDir) {
4838
- if (await pathExists(path14.join(sourceDir, "package.json.mustache"))) {
4866
+ if (await pathExists(path16.join(sourceDir, "package.json.mustache"))) {
4839
4867
  return "wp-typia";
4840
4868
  }
4841
4869
  if (await loadExternalTemplateLayerManifest(sourceDir)) {
@@ -4847,15 +4875,15 @@ async function detectTemplateSourceFormat(sourceDir) {
4847
4875
  if (await getTemplateProjectTypeAsync(sourceDir) !== null) {
4848
4876
  return "wp-typia";
4849
4877
  }
4850
- const sourceRoot = await pathExists(path14.join(sourceDir, "src")) ? path14.join(sourceDir, "src") : sourceDir;
4878
+ const sourceRoot = await pathExists(path16.join(sourceDir, "src")) ? path16.join(sourceDir, "src") : sourceDir;
4851
4879
  const blockJsonCandidates = [
4852
- path14.join(sourceDir, "block.json"),
4853
- path14.join(sourceRoot, "block.json")
4880
+ path16.join(sourceDir, "block.json"),
4881
+ path16.join(sourceRoot, "block.json")
4854
4882
  ];
4855
4883
  const hasBlockJson = (await Promise.all(blockJsonCandidates.map((candidate) => pathExists(candidate)))).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);
4884
+ const hasIndexFile = (await Promise.all(["index.js", "index.jsx", "index.ts", "index.tsx"].map((filename) => pathExists(path16.join(sourceRoot, filename))))).some(Boolean);
4885
+ const hasEditFile = (await Promise.all(["edit.js", "edit.jsx", "edit.ts", "edit.tsx"].map((filename) => pathExists(path16.join(sourceRoot, filename))))).some(Boolean);
4886
+ const hasSaveFile = (await Promise.all(["save.js", "save.jsx", "save.ts", "save.tsx"].map((filename) => pathExists(path16.join(sourceRoot, filename))))).some(Boolean);
4859
4887
  if (hasBlockJson && hasIndexFile && hasEditFile && hasSaveFile) {
4860
4888
  return "create-block-subset";
4861
4889
  }
@@ -4865,9 +4893,9 @@ async function detectTemplateSourceFormat(sourceDir) {
4865
4893
  // ../wp-typia-project-tools/src/runtime/template-source-seeds.ts
4866
4894
  var import_semver = __toESM(require_semver(), 1);
4867
4895
  import fs6 from "fs";
4868
- import { promises as fsp12 } from "fs";
4896
+ import { promises as fsp13 } from "fs";
4869
4897
  import { createRequire as createRequire2 } from "module";
4870
- import path17 from "path";
4898
+ import path19 from "path";
4871
4899
  import { spawnSync } from "child_process";
4872
4900
 
4873
4901
  // ../../node_modules/.bun/tar@7.5.13/node_modules/tar/dist/esm/index.min.js
@@ -8019,8 +8047,8 @@ var So = (s3) => {
8019
8047
 
8020
8048
  // ../wp-typia-project-tools/src/runtime/template-source-cache.ts
8021
8049
  import { createHash, randomUUID } from "crypto";
8022
- import { promises as fsp11 } from "fs";
8023
- import path16 from "path";
8050
+ import { promises as fsp12 } from "fs";
8051
+ import path18 from "path";
8024
8052
 
8025
8053
  // ../wp-typia-project-tools/src/runtime/template-source-cache-markers.ts
8026
8054
  var CACHE_MARKER_FILE = "wp-typia-template-cache.json";
@@ -8140,7 +8168,7 @@ function formatExternalTemplateCachePruneMarker({
8140
8168
 
8141
8169
  // ../wp-typia-project-tools/src/runtime/template-source-cache-policy.ts
8142
8170
  import os2 from "os";
8143
- import path15 from "path";
8171
+ import path17 from "path";
8144
8172
  var EXTERNAL_TEMPLATE_CACHE_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE";
8145
8173
  var EXTERNAL_TEMPLATE_CACHE_DIR_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR";
8146
8174
  var EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_TTL_DAYS";
@@ -8158,9 +8186,9 @@ function isExternalTemplateCacheEnabled(env = process.env) {
8158
8186
  function getExternalTemplateCacheRoot(env = process.env) {
8159
8187
  const configuredCacheDir = env[EXTERNAL_TEMPLATE_CACHE_DIR_ENV]?.trim();
8160
8188
  if (configuredCacheDir) {
8161
- return path15.resolve(configuredCacheDir);
8189
+ return path17.resolve(configuredCacheDir);
8162
8190
  }
8163
- return path15.join(os2.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
8191
+ return path17.join(os2.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
8164
8192
  }
8165
8193
  function parseExternalTemplateCacheTtlDays(value) {
8166
8194
  if (typeof value !== "string" && typeof value !== "number") {
@@ -8238,7 +8266,7 @@ function createExternalTemplateCacheKey(keyParts) {
8238
8266
  }
8239
8267
  async function isDirectoryPath(directory) {
8240
8268
  try {
8241
- const stats = await fsp11.lstat(directory);
8269
+ const stats = await fsp12.lstat(directory);
8242
8270
  return stats.isDirectory() && !stats.isSymbolicLink();
8243
8271
  } catch {
8244
8272
  return false;
@@ -8246,7 +8274,7 @@ async function isDirectoryPath(directory) {
8246
8274
  }
8247
8275
  async function removeTemporaryCacheEntry(entryDir) {
8248
8276
  try {
8249
- await fsp11.rm(entryDir, { force: true, recursive: true });
8277
+ await fsp12.rm(entryDir, { force: true, recursive: true });
8250
8278
  } catch {}
8251
8279
  }
8252
8280
  function getCurrentUid() {
@@ -8254,7 +8282,7 @@ function getCurrentUid() {
8254
8282
  }
8255
8283
  async function isPrivateCacheDirectory(directory) {
8256
8284
  try {
8257
- const stats = await fsp11.lstat(directory);
8285
+ const stats = await fsp12.lstat(directory);
8258
8286
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
8259
8287
  return false;
8260
8288
  }
@@ -8272,11 +8300,11 @@ async function isPrivateCacheDirectory(directory) {
8272
8300
  }
8273
8301
  async function ensurePrivateCacheDirectory(directory) {
8274
8302
  try {
8275
- await fsp11.mkdir(directory, {
8303
+ await fsp12.mkdir(directory, {
8276
8304
  mode: PRIVATE_CACHE_DIRECTORY_MODE,
8277
8305
  recursive: true
8278
8306
  });
8279
- const stats = await fsp11.lstat(directory);
8307
+ const stats = await fsp12.lstat(directory);
8280
8308
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
8281
8309
  return false;
8282
8310
  }
@@ -8286,7 +8314,7 @@ async function ensurePrivateCacheDirectory(directory) {
8286
8314
  }
8287
8315
  if (process.platform !== "win32") {
8288
8316
  if ((stats.mode & 63) !== 0) {
8289
- await fsp11.chmod(directory, PRIVATE_CACHE_DIRECTORY_MODE);
8317
+ await fsp12.chmod(directory, PRIVATE_CACHE_DIRECTORY_MODE);
8290
8318
  }
8291
8319
  }
8292
8320
  return isPrivateCacheDirectory(directory);
@@ -8298,9 +8326,9 @@ function resolveCacheNamespaceDir(cacheRoot, namespace) {
8298
8326
  if (namespace === "." || namespace === ".." || !SAFE_CACHE_NAMESPACE_SEGMENT.test(namespace)) {
8299
8327
  return null;
8300
8328
  }
8301
- const namespaceDir = path16.join(cacheRoot, namespace);
8302
- const relativeNamespaceDir = path16.relative(cacheRoot, namespaceDir);
8303
- if (relativeNamespaceDir.length === 0 || relativeNamespaceDir.startsWith("..") || path16.isAbsolute(relativeNamespaceDir)) {
8329
+ const namespaceDir = path18.join(cacheRoot, namespace);
8330
+ const relativeNamespaceDir = path18.relative(cacheRoot, namespaceDir);
8331
+ if (relativeNamespaceDir.length === 0 || relativeNamespaceDir.startsWith("..") || path18.isAbsolute(relativeNamespaceDir)) {
8304
8332
  return null;
8305
8333
  }
8306
8334
  return namespaceDir;
@@ -8312,14 +8340,14 @@ function getCacheEntryPaths(descriptor) {
8312
8340
  if (!namespaceDir) {
8313
8341
  return null;
8314
8342
  }
8315
- const entryDir = path16.join(namespaceDir, cacheKey);
8343
+ const entryDir = path18.join(namespaceDir, cacheKey);
8316
8344
  return {
8317
8345
  cacheKey,
8318
8346
  cacheRoot,
8319
8347
  entryDir,
8320
- markerPath: path16.join(entryDir, CACHE_MARKER_FILE),
8348
+ markerPath: path18.join(entryDir, CACHE_MARKER_FILE),
8321
8349
  namespaceDir,
8322
- sourceDir: path16.join(entryDir, "source")
8350
+ sourceDir: path18.join(entryDir, "source")
8323
8351
  };
8324
8352
  }
8325
8353
  async function isReusableCacheEntry(entryDir, markerPath, sourceDir) {
@@ -8327,7 +8355,7 @@ async function isReusableCacheEntry(entryDir, markerPath, sourceDir) {
8327
8355
  }
8328
8356
  async function readCacheEntryMarker(markerPath) {
8329
8357
  try {
8330
- return parseExternalTemplateCacheEntryMarker(await fsp11.readFile(markerPath, "utf8"));
8358
+ return parseExternalTemplateCacheEntryMarker(await fsp12.readFile(markerPath, "utf8"));
8331
8359
  } catch {
8332
8360
  return null;
8333
8361
  }
@@ -8343,22 +8371,22 @@ async function isReusableFreshCacheEntry(entryDir, markerPath, sourceDir, nowMs,
8343
8371
  return marker !== null && isExternalTemplateCacheEntryFreshForTtl(marker.createdAtMs, nowMs, ttlMs);
8344
8372
  }
8345
8373
  function isPathInsideDirectory(directory, candidatePath) {
8346
- const relativePath = path16.relative(directory, candidatePath);
8347
- return relativePath.length > 0 && !relativePath.startsWith("..") && !path16.isAbsolute(relativePath);
8374
+ const relativePath = path18.relative(directory, candidatePath);
8375
+ return relativePath.length > 0 && !relativePath.startsWith("..") && !path18.isAbsolute(relativePath);
8348
8376
  }
8349
8377
  async function removeCacheEntryWithinRoot(cacheRoot, entryDir) {
8350
8378
  if (!isPathInsideDirectory(cacheRoot, entryDir)) {
8351
8379
  return false;
8352
8380
  }
8353
8381
  try {
8354
- await fsp11.rm(entryDir, { force: true, recursive: true });
8382
+ await fsp12.rm(entryDir, { force: true, recursive: true });
8355
8383
  return true;
8356
8384
  } catch {
8357
8385
  return false;
8358
8386
  }
8359
8387
  }
8360
8388
  function getCachePruneMarkerPath(cacheRoot) {
8361
- return path16.join(cacheRoot, CACHE_PRUNE_MARKER_FILE);
8389
+ return path18.join(cacheRoot, CACHE_PRUNE_MARKER_FILE);
8362
8390
  }
8363
8391
  async function shouldSkipExternalTemplateCachePrune({
8364
8392
  cacheRoot,
@@ -8372,7 +8400,7 @@ async function shouldSkipExternalTemplateCachePrune({
8372
8400
  }
8373
8401
  let markerText;
8374
8402
  try {
8375
- markerText = await fsp11.readFile(getCachePruneMarkerPath(cacheRoot), "utf8");
8403
+ markerText = await fsp12.readFile(getCachePruneMarkerPath(cacheRoot), "utf8");
8376
8404
  } catch {
8377
8405
  return false;
8378
8406
  }
@@ -8390,7 +8418,7 @@ async function writeExternalTemplateCachePruneMarker({
8390
8418
  ttlMs
8391
8419
  }) {
8392
8420
  try {
8393
- await fsp11.writeFile(getCachePruneMarkerPath(cacheRoot), formatExternalTemplateCachePruneMarker({
8421
+ await fsp12.writeFile(getCachePruneMarkerPath(cacheRoot), formatExternalTemplateCachePruneMarker({
8394
8422
  nowMs,
8395
8423
  pruneIntervalMs,
8396
8424
  ttlMs
@@ -8432,7 +8460,7 @@ async function pruneExternalTemplateCache(options = {}) {
8432
8460
  }
8433
8461
  let namespaceEntries;
8434
8462
  try {
8435
- namespaceEntries = await fsp11.readdir(cacheRoot, { withFileTypes: true });
8463
+ namespaceEntries = await fsp12.readdir(cacheRoot, { withFileTypes: true });
8436
8464
  } catch {
8437
8465
  return result;
8438
8466
  }
@@ -8448,7 +8476,7 @@ async function pruneExternalTemplateCache(options = {}) {
8448
8476
  }
8449
8477
  let cacheEntries;
8450
8478
  try {
8451
- cacheEntries = await fsp11.readdir(namespaceDir, { withFileTypes: true });
8479
+ cacheEntries = await fsp12.readdir(namespaceDir, { withFileTypes: true });
8452
8480
  } catch {
8453
8481
  result.skippedEntries += 1;
8454
8482
  continue;
@@ -8461,14 +8489,14 @@ async function pruneExternalTemplateCache(options = {}) {
8461
8489
  result.skippedEntries += 1;
8462
8490
  continue;
8463
8491
  }
8464
- const entryDir = path16.join(namespaceDir, cacheEntry.name);
8492
+ const entryDir = path18.join(namespaceDir, cacheEntry.name);
8465
8493
  result.scannedEntries += 1;
8466
8494
  if (!isPathInsideDirectory(cacheRoot, entryDir)) {
8467
8495
  result.skippedEntries += 1;
8468
8496
  continue;
8469
8497
  }
8470
- const markerPath = path16.join(entryDir, CACHE_MARKER_FILE);
8471
- const sourceDir = path16.join(entryDir, "source");
8498
+ const markerPath = path18.join(entryDir, CACHE_MARKER_FILE);
8499
+ const sourceDir = path18.join(entryDir, "source");
8472
8500
  const marker = await getReusableCacheEntryMarker(entryDir, markerPath, sourceDir);
8473
8501
  if (!marker) {
8474
8502
  result.skippedEntries += 1;
@@ -8508,7 +8536,7 @@ async function findReusableExternalTemplateSourceCache(descriptor) {
8508
8536
  await pruneExternalTemplateCache();
8509
8537
  let entries;
8510
8538
  try {
8511
- entries = await fsp11.readdir(namespaceDir, { withFileTypes: true });
8539
+ entries = await fsp12.readdir(namespaceDir, { withFileTypes: true });
8512
8540
  } catch {
8513
8541
  return null;
8514
8542
  }
@@ -8517,9 +8545,9 @@ async function findReusableExternalTemplateSourceCache(descriptor) {
8517
8545
  if (!entry.isDirectory()) {
8518
8546
  continue;
8519
8547
  }
8520
- const entryDir = path16.join(namespaceDir, entry.name);
8521
- const markerPath = path16.join(entryDir, CACHE_MARKER_FILE);
8522
- const sourceDir = path16.join(entryDir, "source");
8548
+ const entryDir = path18.join(namespaceDir, entry.name);
8549
+ const markerPath = path18.join(entryDir, CACHE_MARKER_FILE);
8550
+ const sourceDir = path18.join(entryDir, "source");
8523
8551
  const marker = await getReusableCacheEntryMarker(entryDir, markerPath, sourceDir);
8524
8552
  if (!marker || !isExternalTemplateCacheEntryFreshForTtl(marker.createdAtMs, nowMs, ttlMs) || !externalTemplateCacheMetadataMatches(marker.metadata, descriptor.metadata)) {
8525
8553
  continue;
@@ -8561,16 +8589,16 @@ async function resolveExternalTemplateSourceCache(descriptor, populateSourceDir)
8561
8589
  if (existingMarker) {
8562
8590
  await removeCacheEntryWithinRoot(cacheRoot, entryDir);
8563
8591
  }
8564
- const temporaryEntryDir = path16.join(namespaceDir, createTemporaryCacheEntryDirName(cacheKey));
8565
- const temporarySourceDir = path16.join(temporaryEntryDir, "source");
8592
+ const temporaryEntryDir = path18.join(namespaceDir, createTemporaryCacheEntryDirName(cacheKey));
8593
+ const temporarySourceDir = path18.join(temporaryEntryDir, "source");
8566
8594
  let populateFailed = false;
8567
8595
  try {
8568
- await fsp11.mkdir(temporarySourceDir, {
8596
+ await fsp12.mkdir(temporarySourceDir, {
8569
8597
  mode: PRIVATE_CACHE_DIRECTORY_MODE,
8570
8598
  recursive: true
8571
8599
  });
8572
8600
  if (process.platform !== "win32") {
8573
- await fsp11.chmod(temporaryEntryDir, PRIVATE_CACHE_DIRECTORY_MODE);
8601
+ await fsp12.chmod(temporaryEntryDir, PRIVATE_CACHE_DIRECTORY_MODE);
8574
8602
  }
8575
8603
  try {
8576
8604
  await populateSourceDir(temporarySourceDir);
@@ -8578,13 +8606,13 @@ async function resolveExternalTemplateSourceCache(descriptor, populateSourceDir)
8578
8606
  populateFailed = true;
8579
8607
  throw error;
8580
8608
  }
8581
- await fsp11.writeFile(path16.join(temporaryEntryDir, CACHE_MARKER_FILE), formatExternalTemplateCacheEntryMarker({
8609
+ await fsp12.writeFile(path18.join(temporaryEntryDir, CACHE_MARKER_FILE), formatExternalTemplateCacheEntryMarker({
8582
8610
  cacheKey,
8583
8611
  createdAt: new Date,
8584
8612
  metadata: descriptor.metadata,
8585
8613
  namespace: descriptor.namespace
8586
8614
  }), "utf8");
8587
- await fsp11.rename(temporaryEntryDir, entryDir);
8615
+ await fsp12.rename(temporaryEntryDir, entryDir);
8588
8616
  return {
8589
8617
  cacheHit: false,
8590
8618
  sourceDir
@@ -8655,9 +8683,9 @@ async function downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl,
8655
8683
  if (!tarballResponse.ok) {
8656
8684
  throw new Error(`Failed to download npm template tarball for ${locator.raw}: ${tarballResponse.status}`);
8657
8685
  }
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, {
8686
+ const tarballPath = path19.join(path19.dirname(unpackDir), "template.tgz");
8687
+ await fsp13.mkdir(unpackDir, { recursive: true });
8688
+ await fsp13.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
8661
8689
  label: `npm template tarball for ${locator.raw}@${resolvedVersion}`,
8662
8690
  maxBytes: getExternalTemplateTarballMaxBytes()
8663
8691
  }));
@@ -8666,7 +8694,7 @@ async function downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl,
8666
8694
  file: tarballPath,
8667
8695
  strip: 1
8668
8696
  });
8669
- await fsp12.rm(tarballPath, { force: true });
8697
+ await fsp13.rm(tarballPath, { force: true });
8670
8698
  await assertNoSymlinks2(unpackDir);
8671
8699
  }
8672
8700
  function selectRegistryVersion(metadata, locator) {
@@ -8761,7 +8789,7 @@ async function fetchNpmTemplateSource(locator) {
8761
8789
  }
8762
8790
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
8763
8791
  try {
8764
- const unpackDir = path17.join(tempRoot, "source");
8792
+ const unpackDir = path19.join(tempRoot, "source");
8765
8793
  await downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir);
8766
8794
  return {
8767
8795
  blockDir: unpackDir,
@@ -8777,7 +8805,7 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8777
8805
  if (locator.rawSpec !== "" && locator.rawSpec !== "*") {
8778
8806
  return null;
8779
8807
  }
8780
- const workspacePackagesRoot = path17.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
8808
+ const workspacePackagesRoot = path19.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
8781
8809
  if (fs6.existsSync(workspacePackagesRoot)) {
8782
8810
  for (const entry of fs6.readdirSync(workspacePackagesRoot, {
8783
8811
  withFileTypes: true
@@ -8785,8 +8813,8 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8785
8813
  if (!entry.isDirectory()) {
8786
8814
  continue;
8787
8815
  }
8788
- const packageDir = path17.join(workspacePackagesRoot, entry.name);
8789
- const packageJsonPath = path17.join(packageDir, "package.json");
8816
+ const packageDir = path19.join(workspacePackagesRoot, entry.name);
8817
+ const packageJsonPath = path19.join(packageDir, "package.json");
8790
8818
  if (!fs6.existsSync(packageJsonPath)) {
8791
8819
  continue;
8792
8820
  }
@@ -8801,10 +8829,10 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8801
8829
  }
8802
8830
  }
8803
8831
  }
8804
- const workspaceRequire = createRequire2(path17.join(path17.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
8832
+ const workspaceRequire = createRequire2(path19.join(path19.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
8805
8833
  try {
8806
8834
  const packageJsonPath = fs6.realpathSync(workspaceRequire.resolve(`${locator.name}/package.json`));
8807
- const sourceDir = path17.dirname(packageJsonPath);
8835
+ const sourceDir = path19.dirname(packageJsonPath);
8808
8836
  return {
8809
8837
  blockDir: sourceDir,
8810
8838
  rootDir: sourceDir
@@ -8813,11 +8841,11 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8813
8841
  const errorCode = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
8814
8842
  if (errorCode === "MODULE_NOT_FOUND" || errorCode === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
8815
8843
  for (const basePath of workspaceRequire.resolve.paths(locator.name) ?? []) {
8816
- const packageJsonPath = path17.join(basePath, locator.name, "package.json");
8844
+ const packageJsonPath = path19.join(basePath, locator.name, "package.json");
8817
8845
  if (!fs6.existsSync(packageJsonPath)) {
8818
8846
  continue;
8819
8847
  }
8820
- const sourceDir = path17.dirname(fs6.realpathSync(packageJsonPath));
8848
+ const sourceDir = path19.dirname(fs6.realpathSync(packageJsonPath));
8821
8849
  return {
8822
8850
  blockDir: sourceDir,
8823
8851
  rootDir: sourceDir
@@ -8829,7 +8857,7 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
8829
8857
  }
8830
8858
  }
8831
8859
  async function isOfficialWorkspaceTemplateSeedAsync(seed) {
8832
- const packageJsonPath = path17.join(seed.rootDir, "package.json");
8860
+ const packageJsonPath = path19.join(seed.rootDir, "package.json");
8833
8861
  if (!await pathExists(packageJsonPath)) {
8834
8862
  return false;
8835
8863
  }
@@ -8843,15 +8871,15 @@ async function isOfficialWorkspaceTemplateSeedAsync(seed) {
8843
8871
  }
8844
8872
  }
8845
8873
  async function assertNoSymlinks2(sourceDir) {
8846
- const stats = await fsp12.lstat(sourceDir);
8874
+ const stats = await fsp13.lstat(sourceDir);
8847
8875
  if (stats.isSymbolicLink()) {
8848
8876
  throw new Error(`Template sources may not include symbolic links: ${sourceDir}`);
8849
8877
  }
8850
8878
  if (!stats.isDirectory()) {
8851
8879
  return;
8852
8880
  }
8853
- for (const entry of await fsp12.readdir(sourceDir)) {
8854
- await assertNoSymlinks2(path17.join(sourceDir, entry));
8881
+ for (const entry of await fsp13.readdir(sourceDir)) {
8882
+ await assertNoSymlinks2(path19.join(sourceDir, entry));
8855
8883
  }
8856
8884
  }
8857
8885
  function runGitTemplateCommand(args, label, options = {}) {
@@ -8880,9 +8908,9 @@ function getGitHubTemplateRepositoryUrl(locator) {
8880
8908
  return `https://github.com/${locator.owner}/${locator.repo}.git`;
8881
8909
  }
8882
8910
  async function resolveGitHubTemplateDirectory(checkoutDir, locator) {
8883
- const sourceDir = path17.resolve(checkoutDir, locator.sourcePath);
8884
- const relativeSourceDir = path17.relative(checkoutDir, sourceDir);
8885
- if (relativeSourceDir.startsWith("..") || path17.isAbsolute(relativeSourceDir)) {
8911
+ const sourceDir = path19.resolve(checkoutDir, locator.sourcePath);
8912
+ const relativeSourceDir = path19.relative(checkoutDir, sourceDir);
8913
+ if (relativeSourceDir.startsWith("..") || path19.isAbsolute(relativeSourceDir)) {
8886
8914
  throw new Error("GitHub template path must stay within the cloned repository.");
8887
8915
  }
8888
8916
  if (!await pathExists(sourceDir)) {
@@ -9071,7 +9099,7 @@ async function resolveGitHubTemplateSource(locator) {
9071
9099
  }
9072
9100
  }
9073
9101
  const { path: remoteRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
9074
- const checkoutDir = path17.join(remoteRoot, "source");
9102
+ const checkoutDir = path19.join(remoteRoot, "source");
9075
9103
  try {
9076
9104
  cloneGitHubTemplateSource(locator, checkoutDir);
9077
9105
  const sourceDir = await resolveGitHubTemplateDirectory(checkoutDir, locator);
@@ -9088,7 +9116,7 @@ async function resolveGitHubTemplateSource(locator) {
9088
9116
  }
9089
9117
  async function resolveTemplateSeed(locator, cwd) {
9090
9118
  if (locator.kind === "path") {
9091
- const sourceDir = path17.resolve(cwd, locator.templatePath);
9119
+ const sourceDir = path19.resolve(cwd, locator.templatePath);
9092
9120
  if (!await pathExists(sourceDir)) {
9093
9121
  throw new Error(`Template path does not exist: ${sourceDir}`);
9094
9122
  }
@@ -9977,7 +10005,7 @@ function toPhpSingleQuotedString(value) {
9977
10005
  return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
9978
10006
  }
9979
10007
 
9980
- // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-family-artifacts.ts
10008
+ // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-basic-artifacts.ts
9981
10009
  var BASIC_STYLE_TEMPLATE = `/**
9982
10010
  * {{title}} Block Styles
9983
10011
  */
@@ -10048,60 +10076,531 @@ if ( ! defined( 'ABSPATH' ) ) {
10048
10076
  <?php esc_html_e( 'Server render placeholder.', '{{textDomain}}' ); ?>
10049
10077
  </div>
10050
10078
  `;
10051
- var INTERACTIVITY_STYLE_TEMPLATE = `.{{cssClassName}} {
10052
- position: relative;
10053
- padding: 1rem;
10054
- border: 1px solid #dcdcde;
10055
- border-radius: 0.75rem;
10056
- background: #fff;
10079
+ function buildBasicArtifacts(variables) {
10080
+ return [
10081
+ renderArtifact("src/editor.scss", BASIC_EDITOR_STYLE_TEMPLATE, variables),
10082
+ renderArtifact("src/style.scss", BASIC_STYLE_TEMPLATE, variables),
10083
+ renderArtifact("src/render.php", BASIC_RENDER_TEMPLATE, variables)
10084
+ ];
10085
+ }
10086
+ // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-compound-templates.ts
10087
+ var COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE = `<?php
10088
+ /**
10089
+ * Alternate render target helpers for the {{title}} compound parent block.
10090
+ *
10091
+ * @package {{pascalCase}}
10092
+ */
10057
10093
 
10058
- &__content {
10059
- display: grid;
10060
- gap: 0.75rem;
10061
- }
10094
+ if ( ! defined( 'ABSPATH' ) ) {
10095
+ exit;
10096
+ }
10062
10097
 
10063
- &__counter {
10064
- display: inline-flex;
10065
- gap: 0.35rem;
10066
- align-items: center;
10067
- font-size: 0.9rem;
10068
- font-weight: 600;
10069
- }
10098
+ if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_build_render_context' ) ) {
10099
+ function {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block ) {
10100
+ $validator_path = __DIR__ . '/typia-validator.php';
10101
+ if ( ! file_exists( $validator_path ) ) {
10102
+ return null;
10103
+ }
10070
10104
 
10071
- &__progress {
10072
- width: 100%;
10073
- height: 0.5rem;
10074
- overflow: hidden;
10075
- background: #f0f0f1;
10076
- border-radius: 999px;
10077
- }
10105
+ $validator = require $validator_path;
10106
+ if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
10107
+ return null;
10108
+ }
10078
10109
 
10079
- &__progress-bar {
10080
- height: 100%;
10081
- background: #3858e9;
10082
- transition: width 0.2s ease;
10083
- }
10110
+ $normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
10111
+ $validation = $validator->validate( $normalized );
10112
+ $resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
10113
+ $heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};
10114
+ $intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
10115
+ $button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
10116
+ $show_count = ! empty( $normalized['showCount'] );
10117
+ $show_dividers = ! empty( $normalized['showDividers'] );
10118
+ $post_id = is_object( $block ) && isset( $block->context['postId'] )
10119
+ ? (int) $block->context['postId']
10120
+ : (int) get_queried_object_id();
10121
+ $storage_mode = '{{dataStorageMode}}';
10122
+ $persistence_policy = '{{persistencePolicy}}';
10084
10123
 
10085
- &__animation {
10086
- min-height: 1.5rem;
10087
- font-size: 0.85rem;
10088
- color: #3858e9;
10089
- opacity: 0;
10090
- transition: opacity 0.2s ease;
10124
+ $notice_message = 'authenticated' === $persistence_policy
10125
+ ? __( 'Sign in to persist this counter.', '{{textDomain}}' )
10126
+ : __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
10091
10127
 
10092
- &.is-active {
10093
- opacity: 1;
10094
- }
10095
- }
10128
+ if ( empty( $validation['valid'] ) || '' === $resource_key ) {
10129
+ return null;
10130
+ }
10096
10131
 
10097
- &__completion {
10098
- font-weight: 700;
10099
- color: #06752d;
10100
- }
10132
+ {{phpPrefix}}_record_rendered_block_instance(
10133
+ (int) $post_id,
10134
+ '{{namespace}}/{{slugKebabCase}}',
10135
+ $resource_key
10136
+ );
10101
10137
 
10102
- &__reset {
10103
- align-self: start;
10104
- padding: 0.4rem 0.7rem;
10138
+ $web_context = array(
10139
+ 'bootstrapReady' => false,
10140
+ 'buttonLabel' => $button_label,
10141
+ 'canWrite' => false,
10142
+ 'client' => array(
10143
+ 'writeExpiry' => 0,
10144
+ 'writeNonce' => '',
10145
+ 'writeToken' => '',
10146
+ ),
10147
+ 'count' => 0,
10148
+ 'error' => '',
10149
+ 'isBootstrapping' => false,
10150
+ 'isLoading' => false,
10151
+ 'isSaving' => false,
10152
+ 'persistencePolicy' => $persistence_policy,
10153
+ 'postId' => (int) $post_id,
10154
+ 'resourceKey' => $resource_key,
10155
+ 'showCount' => $show_count,
10156
+ 'storage' => $storage_mode,
10157
+ );
10158
+
10159
+ $allowed_inner_html = wp_kses_allowed_html( 'post' );
10160
+
10161
+ foreach ( $allowed_inner_html as &$allowed_attributes ) {
10162
+ if ( ! is_array( $allowed_attributes ) ) {
10163
+ continue;
10164
+ }
10165
+
10166
+ $allowed_attributes['data-wp-bind--disabled'] = true;
10167
+ $allowed_attributes['data-wp-bind--hidden'] = true;
10168
+ $allowed_attributes['data-wp-bind--value'] = true;
10169
+ $allowed_attributes['data-wp-class'] = true;
10170
+ $allowed_attributes['data-wp-class--active'] = true;
10171
+ $allowed_attributes['data-wp-context'] = true;
10172
+ $allowed_attributes['data-wp-init'] = true;
10173
+ $allowed_attributes['data-wp-interactive'] = true;
10174
+ $allowed_attributes['data-wp-on--click'] = true;
10175
+ $allowed_attributes['data-wp-on--mouseenter'] = true;
10176
+ $allowed_attributes['data-wp-on--mouseleave'] = true;
10177
+ $allowed_attributes['data-wp-run--mounted'] = true;
10178
+ $allowed_attributes['data-wp-style--width'] = true;
10179
+ $allowed_attributes['data-wp-text'] = true;
10180
+ }
10181
+ unset( $allowed_attributes );
10182
+
10183
+ return array(
10184
+ 'buttonLabel' => $button_label,
10185
+ 'frontendClassName' => '{{cssClassName}}',
10186
+ 'heading' => $heading,
10187
+ 'intro' => $intro,
10188
+ 'isVisible' => true,
10189
+ 'normalized' => $normalized,
10190
+ 'noticeMessage' => $notice_message,
10191
+ 'postId' => (int) $post_id,
10192
+ 'resourceKey' => $resource_key,
10193
+ 'sanitizedContent' => wp_kses( $content, $allowed_inner_html ),
10194
+ 'showCount' => $show_count,
10195
+ 'showDividers' => $show_dividers,
10196
+ 'title' => {{titleJson}},
10197
+ 'webContext' => $web_context,
10198
+ );
10199
+ }
10200
+ }
10201
+
10202
+ if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_render_target' ) ) {
10203
+ function {{phpPrefix}}_{{slugSnakeCase}}_render_target( string $target, $attributes, $content = '', $block = null ): string {
10204
+ $context = {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block );
10205
+ if ( null === $context ) {
10206
+ return '';
10207
+ }
10208
+
10209
+ $target_context = apply_filters(
10210
+ '{{phpPrefix}}_{{slugSnakeCase}}_render_target_context',
10211
+ $context,
10212
+ $target,
10213
+ $attributes,
10214
+ $block
10215
+ );
10216
+
10217
+ $markup = '';
10218
+ switch ( $target ) {
10219
+ case 'email':
10220
+ $parts = array(
10221
+ '<div class="' . esc_attr( $target_context['frontendClassName'] ) . '-email">',
10222
+ '<h3>' . esc_html( $target_context['heading'] ) . '</h3>',
10223
+ );
10224
+ if ( '' !== $target_context['intro'] ) {
10225
+ $parts[] = '<p>' . esc_html( $target_context['intro'] ) . '</p>';
10226
+ }
10227
+ if ( ! empty( $target_context['showCount'] ) ) {
10228
+ $parts[] = '<p><strong>' . esc_html__( 'Count', '{{textDomain}}' ) . ':</strong> ' . esc_html( (string) $target_context['webContext']['count'] ) . '</p>';
10229
+ }
10230
+ $parts[] = wp_kses_post( $target_context['sanitizedContent'] );
10231
+ $parts[] = '<p>' . esc_html( $target_context['noticeMessage'] ) . '</p>';
10232
+ $parts[] = '</div>';
10233
+ $markup = implode( '', $parts );
10234
+ break;
10235
+ case 'mjml':
10236
+ $markup = '<mjml><mj-body><mj-section><mj-column><mj-text font-weight="700">' . esc_html( $target_context['heading'] ) . '</mj-text>';
10237
+ if ( '' !== $target_context['intro'] ) {
10238
+ $markup .= '<mj-text>' . esc_html( $target_context['intro'] ) . '</mj-text>';
10239
+ }
10240
+ if ( ! empty( $target_context['showCount'] ) ) {
10241
+ $markup .= '<mj-text>' . esc_html__( 'Count', '{{textDomain}}' ) . ': ' . esc_html( (string) $target_context['webContext']['count'] ) . '</mj-text>';
10242
+ }
10243
+ $markup .= '<mj-text>' . esc_html( wp_strip_all_tags( $target_context['sanitizedContent'] ) ) . '</mj-text>';
10244
+ $markup .= '<mj-text>' . esc_html( $target_context['noticeMessage'] ) . '</mj-text></mj-column></mj-section></mj-body></mjml>';
10245
+ break;
10246
+ case 'plain-text':
10247
+ $markup = implode(
10248
+ "\\n",
10249
+ array_filter(
10250
+ array(
10251
+ $target_context['heading'],
10252
+ $target_context['intro'],
10253
+ wp_strip_all_tags( $target_context['sanitizedContent'] ),
10254
+ ! empty( $target_context['showCount'] )
10255
+ ? sprintf( '%s: %s', __( 'Count', '{{textDomain}}' ), (string) $target_context['webContext']['count'] )
10256
+ : null,
10257
+ $target_context['noticeMessage'],
10258
+ ),
10259
+ static fn( $value ) => is_string( $value ) && '' !== $value
10260
+ )
10261
+ );
10262
+ break;
10263
+ case 'web':
10264
+ default:
10265
+ $wrapper_attributes = get_block_wrapper_attributes(
10266
+ array(
10267
+ 'class' => '{{cssClassName}}',
10268
+ 'data-show-dividers' => $target_context['showDividers'] ? 'true' : 'false',
10269
+ 'data-wp-context' => wp_json_encode( $target_context['webContext'] ),
10270
+ 'data-wp-init' => 'callbacks.init',
10271
+ 'data-wp-interactive' => '{{slugKebabCase}}',
10272
+ 'data-wp-run--mounted' => 'callbacks.mounted',
10273
+ )
10274
+ );
10275
+ ob_start();
10276
+ ?>
10277
+ <div <?php echo $wrapper_attributes; ?>>
10278
+ <h3 class="{{cssClassName}}__heading"><?php echo esc_html( $target_context['heading'] ); ?></h3>
10279
+ <?php if ( '' !== $target_context['intro'] ) : ?>
10280
+ <p class="{{cssClassName}}__intro"><?php echo esc_html( $target_context['intro'] ); ?></p>
10281
+ <?php endif; ?>
10282
+ <p
10283
+ class="{{cssClassName}}__notice"
10284
+ data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
10285
+ hidden
10286
+ >
10287
+ <?php echo esc_html( $target_context['noticeMessage'] ); ?>
10288
+ </p>
10289
+ <p
10290
+ class="{{cssClassName}}__error"
10291
+ role="status"
10292
+ aria-live="polite"
10293
+ aria-atomic="true"
10294
+ data-wp-bind--hidden="!context.error"
10295
+ data-wp-text="context.error"
10296
+ hidden
10297
+ ></p>
10298
+ <?php if ( ! empty( $target_context['showCount'] ) ) : ?>
10299
+ <div class="{{cssClassName}}__counter">
10300
+ <span
10301
+ class="{{cssClassName}}__count"
10302
+ role="status"
10303
+ aria-live="polite"
10304
+ aria-atomic="true"
10305
+ data-wp-text="context.count"
10306
+ >0</span>
10307
+ <button
10308
+ type="button"
10309
+ disabled
10310
+ data-wp-bind--disabled="!context.canWrite"
10311
+ data-wp-on--click="actions.increment"
10312
+ >
10313
+ <?php echo esc_html( $target_context['buttonLabel'] ); ?>
10314
+ </button>
10315
+ </div>
10316
+ <?php endif; ?>
10317
+ <div class="{{cssClassName}}__items">
10318
+ <?php echo wp_kses_post( $target_context['sanitizedContent'] ); ?>
10319
+ </div>
10320
+ </div>
10321
+ <?php
10322
+ $markup = (string) ob_get_clean();
10323
+ break;
10324
+ }
10325
+
10326
+ return apply_filters(
10327
+ '{{phpPrefix}}_{{slugSnakeCase}}_render_target_markup',
10328
+ $markup,
10329
+ $target,
10330
+ $target_context
10331
+ );
10332
+ }
10333
+ }
10334
+ `;
10335
+ var COMPOUND_STYLE_TEMPLATE = `.{{cssClassName}} {
10336
+ border: 1px solid #dcdcde;
10337
+ border-radius: 12px;
10338
+ padding: 1.25rem;
10339
+ background: #fff;
10340
+ }
10341
+
10342
+ .{{cssClassName}}__heading {
10343
+ margin: 0 0 0.5rem;
10344
+ font-size: 1.2rem;
10345
+ }
10346
+
10347
+ .{{cssClassName}}__intro {
10348
+ margin: 0 0 1rem;
10349
+ color: #50575e;
10350
+ }
10351
+
10352
+ .{{cssClassName}}__items {
10353
+ display: grid;
10354
+ gap: 0.75rem;
10355
+ }
10356
+
10357
+ .{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}} {
10358
+ border-top: 1px solid #dcdcde;
10359
+ padding-top: 0.75rem;
10360
+ }
10361
+
10362
+ .{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}}:first-child {
10363
+ border-top: 0;
10364
+ padding-top: 0;
10365
+ }
10366
+ `;
10367
+ var COMPOUND_PERSISTENCE_RENDER_TEMPLATE = `<?php
10368
+ /**
10369
+ * Dynamic render entry for the {{title}} compound parent block.
10370
+ *
10371
+ * @package {{pascalCase}}
10372
+ */
10373
+
10374
+ if ( ! defined( 'ABSPATH' ) ) {
10375
+ exit;
10376
+ }
10377
+
10378
+ $validator_path = __DIR__ . '/typia-validator.php';
10379
+ if ( ! file_exists( $validator_path ) ) {
10380
+ return '';
10381
+ }
10382
+
10383
+ $validator = require $validator_path;
10384
+ if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
10385
+ return '';
10386
+ }
10387
+
10388
+ $normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
10389
+ $validation = $validator->validate( $normalized );
10390
+ $resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
10391
+ $heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};
10392
+ $intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
10393
+ $button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
10394
+ $show_count = ! empty( $normalized['showCount'] );
10395
+ $show_dividers = ! empty( $normalized['showDividers'] );
10396
+ $post_id = is_object( $block ) && isset( $block->context['postId'] )
10397
+ ? (int) $block->context['postId']
10398
+ : (int) get_queried_object_id();
10399
+ $storage_mode = '{{dataStorageMode}}';
10400
+ $persistence_policy = '{{persistencePolicy}}';
10401
+
10402
+ $notice_message = 'authenticated' === $persistence_policy
10403
+ ? __( 'Sign in to persist this counter.', '{{textDomain}}' )
10404
+ : __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
10405
+
10406
+ if ( empty( $validation['valid'] ) || '' === $resource_key ) {
10407
+ return '';
10408
+ }
10409
+
10410
+ {{phpPrefix}}_record_rendered_block_instance(
10411
+ (int) $post_id,
10412
+ '{{namespace}}/{{slugKebabCase}}',
10413
+ $resource_key
10414
+ );
10415
+
10416
+ $context = array(
10417
+ 'bootstrapReady' => false,
10418
+ 'buttonLabel' => $button_label,
10419
+ 'canWrite' => false,
10420
+ 'client' => array(
10421
+ 'writeExpiry' => 0,
10422
+ 'writeNonce' => '',
10423
+ 'writeToken' => '',
10424
+ ),
10425
+ 'count' => 0,
10426
+ 'error' => '',
10427
+ 'isBootstrapping' => false,
10428
+ 'isLoading' => false,
10429
+ 'isSaving' => false,
10430
+ 'persistencePolicy' => $persistence_policy,
10431
+ 'postId' => (int) $post_id,
10432
+ 'resourceKey' => $resource_key,
10433
+ 'showCount' => $show_count,
10434
+ 'storage' => $storage_mode,
10435
+ );
10436
+
10437
+ $allowed_inner_html = wp_kses_allowed_html( 'post' );
10438
+
10439
+ foreach ( $allowed_inner_html as &$allowed_attributes ) {
10440
+ if ( ! is_array( $allowed_attributes ) ) {
10441
+ continue;
10442
+ }
10443
+
10444
+ $allowed_attributes['data-wp-bind--disabled'] = true;
10445
+ $allowed_attributes['data-wp-bind--hidden'] = true;
10446
+ $allowed_attributes['data-wp-bind--value'] = true;
10447
+ $allowed_attributes['data-wp-class'] = true;
10448
+ $allowed_attributes['data-wp-class--active'] = true;
10449
+ $allowed_attributes['data-wp-context'] = true;
10450
+ $allowed_attributes['data-wp-init'] = true;
10451
+ $allowed_attributes['data-wp-interactive'] = true;
10452
+ $allowed_attributes['data-wp-on--click'] = true;
10453
+ $allowed_attributes['data-wp-on--mouseenter'] = true;
10454
+ $allowed_attributes['data-wp-on--mouseleave'] = true;
10455
+ $allowed_attributes['data-wp-run--mounted'] = true;
10456
+ $allowed_attributes['data-wp-style--width'] = true;
10457
+ $allowed_attributes['data-wp-text'] = true;
10458
+ }
10459
+ unset( $allowed_attributes );
10460
+
10461
+ $sanitized_content = wp_kses( $content, $allowed_inner_html );
10462
+
10463
+ $wrapper_attributes = get_block_wrapper_attributes(
10464
+ array(
10465
+ 'class' => '{{cssClassName}}',
10466
+ 'data-show-dividers' => $show_dividers ? 'true' : 'false',
10467
+ 'data-wp-context' => wp_json_encode( $context ),
10468
+ 'data-wp-init' => 'callbacks.init',
10469
+ 'data-wp-interactive' => '{{slugKebabCase}}',
10470
+ 'data-wp-run--mounted' => 'callbacks.mounted',
10471
+ )
10472
+ );
10473
+ ?>
10474
+
10475
+ <div <?php echo $wrapper_attributes; ?>>
10476
+ <h3 class="{{cssClassName}}__heading"><?php echo esc_html( $heading ); ?></h3>
10477
+ <?php if ( '' !== $intro ) : ?>
10478
+ <p class="{{cssClassName}}__intro"><?php echo esc_html( $intro ); ?></p>
10479
+ <?php endif; ?>
10480
+ <p
10481
+ class="{{cssClassName}}__notice"
10482
+ data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
10483
+ hidden
10484
+ >
10485
+ <?php echo esc_html( $notice_message ); ?>
10486
+ </p>
10487
+ <p
10488
+ class="{{cssClassName}}__error"
10489
+ role="status"
10490
+ aria-live="polite"
10491
+ aria-atomic="true"
10492
+ data-wp-bind--hidden="!context.error"
10493
+ data-wp-text="context.error"
10494
+ hidden
10495
+ ></p>
10496
+ <?php if ( $show_count ) : ?>
10497
+ <div class="{{cssClassName}}__counter">
10498
+ <span
10499
+ class="{{cssClassName}}__count"
10500
+ role="status"
10501
+ aria-live="polite"
10502
+ aria-atomic="true"
10503
+ data-wp-text="context.count"
10504
+ >0</span>
10505
+ <button
10506
+ type="button"
10507
+ disabled
10508
+ data-wp-bind--disabled="!context.canWrite"
10509
+ data-wp-on--click="actions.increment"
10510
+ >
10511
+ <?php echo esc_html( $button_label ); ?>
10512
+ </button>
10513
+ </div>
10514
+ <?php endif; ?>
10515
+ <div class="{{cssClassName}}__items">
10516
+ <?php echo $sanitized_content; ?>
10517
+ </div>
10518
+ </div>
10519
+ `;
10520
+
10521
+ // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-compound-artifacts.ts
10522
+ function buildCompoundArtifacts(variables) {
10523
+ const alternateRenderTargets = getScaffoldAlternateRenderTargets(variables);
10524
+ const artifacts = [
10525
+ renderArtifact(`src/blocks/${variables.slugKebabCase}/style.scss`, COMPOUND_STYLE_TEMPLATE, variables)
10526
+ ];
10527
+ if (isCompoundPersistenceEnabled(variables)) {
10528
+ const renderView = {
10529
+ ...variables,
10530
+ titlePhpLiteral: toPhpSingleQuotedString(variables.title)
10531
+ };
10532
+ if (alternateRenderTargets.enabled) {
10533
+ artifacts.push(renderArtifact(`src/blocks/${variables.slugKebabCase}/render-targets.php`, COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE, renderView), buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render.php`, "web", variables));
10534
+ if (alternateRenderTargets.hasEmail) {
10535
+ artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-email.php`, "email", variables));
10536
+ }
10537
+ if (alternateRenderTargets.hasMjml) {
10538
+ artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-mjml.php`, "mjml", variables));
10539
+ }
10540
+ if (alternateRenderTargets.hasPlainText) {
10541
+ artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-text.php`, "plain-text", variables));
10542
+ }
10543
+ return artifacts;
10544
+ }
10545
+ artifacts.push(renderArtifact(`src/blocks/${variables.slugKebabCase}/render.php`, COMPOUND_PERSISTENCE_RENDER_TEMPLATE, renderView));
10546
+ }
10547
+ return artifacts;
10548
+ }
10549
+ // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-interactivity-artifacts.ts
10550
+ var INTERACTIVITY_STYLE_TEMPLATE = `.{{cssClassName}} {
10551
+ position: relative;
10552
+ padding: 1rem;
10553
+ border: 1px solid #dcdcde;
10554
+ border-radius: 0.75rem;
10555
+ background: #fff;
10556
+
10557
+ &__content {
10558
+ display: grid;
10559
+ gap: 0.75rem;
10560
+ }
10561
+
10562
+ &__counter {
10563
+ display: inline-flex;
10564
+ gap: 0.35rem;
10565
+ align-items: center;
10566
+ font-size: 0.9rem;
10567
+ font-weight: 600;
10568
+ }
10569
+
10570
+ &__progress {
10571
+ width: 100%;
10572
+ height: 0.5rem;
10573
+ overflow: hidden;
10574
+ background: #f0f0f1;
10575
+ border-radius: 999px;
10576
+ }
10577
+
10578
+ &__progress-bar {
10579
+ height: 100%;
10580
+ background: #3858e9;
10581
+ transition: width 0.2s ease;
10582
+ }
10583
+
10584
+ &__animation {
10585
+ min-height: 1.5rem;
10586
+ font-size: 0.85rem;
10587
+ color: #3858e9;
10588
+ opacity: 0;
10589
+ transition: opacity 0.2s ease;
10590
+
10591
+ &.is-active {
10592
+ opacity: 1;
10593
+ }
10594
+ }
10595
+
10596
+ &__completion {
10597
+ font-weight: 700;
10598
+ color: #06752d;
10599
+ }
10600
+
10601
+ &__reset {
10602
+ align-self: start;
10603
+ padding: 0.4rem 0.7rem;
10105
10604
  border: 1px solid #dcdcde;
10106
10605
  border-radius: 999px;
10107
10606
  background: transparent;
@@ -10117,7 +10616,14 @@ var INTERACTIVITY_EDITOR_STYLE_TEMPLATE = `/**
10117
10616
  outline: 1px dashed #ddd;
10118
10617
  outline-offset: -1px;
10119
10618
  }
10120
- `;
10619
+ `;
10620
+ function buildInteractivityArtifacts(variables) {
10621
+ return [
10622
+ renderArtifact("src/editor.scss", INTERACTIVITY_EDITOR_STYLE_TEMPLATE, variables),
10623
+ renderArtifact("src/style.scss", INTERACTIVITY_STYLE_TEMPLATE, variables)
10624
+ ];
10625
+ }
10626
+ // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-persistence-templates.ts
10121
10627
  var PERSISTENCE_STYLE_TEMPLATE = `.{{cssClassName}} {
10122
10628
  border: 1px solid #dcdcde;
10123
10629
  border-radius: 12px;
@@ -10451,280 +10957,32 @@ if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_render_target' ) ) {
10451
10957
  </p>
10452
10958
  <p
10453
10959
  class="{{frontendCssClassName}}__error"
10454
- role="status"
10455
- aria-live="polite"
10456
- aria-atomic="true"
10457
- data-wp-bind--hidden="!context.error"
10458
- data-wp-text="context.error"
10459
- hidden
10460
- ></p>
10461
- <?php if ( ! empty( $target_context['showCount'] ) ) : ?>
10462
- <span
10463
- class="{{frontendCssClassName}}__count"
10464
- role="status"
10465
- aria-live="polite"
10466
- aria-atomic="true"
10467
- data-wp-text="context.count"
10468
- >
10469
- 0
10470
- </span>
10471
- <?php endif; ?>
10472
- <button
10473
- type="button"
10474
- disabled
10475
- data-wp-bind--disabled="!context.canWrite"
10476
- data-wp-on--click="actions.increment"
10477
- >
10478
- <?php echo esc_html( $target_context['buttonLabel'] ); ?>
10479
- </button>
10480
- </div>
10481
- </div>
10482
- <?php
10483
- $markup = (string) ob_get_clean();
10484
- break;
10485
- }
10486
-
10487
- return apply_filters(
10488
- '{{phpPrefix}}_{{slugSnakeCase}}_render_target_markup',
10489
- $markup,
10490
- $target,
10491
- $target_context
10492
- );
10493
- }
10494
- }
10495
- `;
10496
- var COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE = `<?php
10497
- /**
10498
- * Alternate render target helpers for the {{title}} compound parent block.
10499
- *
10500
- * @package {{pascalCase}}
10501
- */
10502
-
10503
- if ( ! defined( 'ABSPATH' ) ) {
10504
- exit;
10505
- }
10506
-
10507
- if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_build_render_context' ) ) {
10508
- function {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block ) {
10509
- $validator_path = __DIR__ . '/typia-validator.php';
10510
- if ( ! file_exists( $validator_path ) ) {
10511
- return null;
10512
- }
10513
-
10514
- $validator = require $validator_path;
10515
- if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
10516
- return null;
10517
- }
10518
-
10519
- $normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
10520
- $validation = $validator->validate( $normalized );
10521
- $resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
10522
- $heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};
10523
- $intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
10524
- $button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
10525
- $show_count = ! empty( $normalized['showCount'] );
10526
- $show_dividers = ! empty( $normalized['showDividers'] );
10527
- $post_id = is_object( $block ) && isset( $block->context['postId'] )
10528
- ? (int) $block->context['postId']
10529
- : (int) get_queried_object_id();
10530
- $storage_mode = '{{dataStorageMode}}';
10531
- $persistence_policy = '{{persistencePolicy}}';
10532
-
10533
- $notice_message = 'authenticated' === $persistence_policy
10534
- ? __( 'Sign in to persist this counter.', '{{textDomain}}' )
10535
- : __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
10536
-
10537
- if ( empty( $validation['valid'] ) || '' === $resource_key ) {
10538
- return null;
10539
- }
10540
-
10541
- {{phpPrefix}}_record_rendered_block_instance(
10542
- (int) $post_id,
10543
- '{{namespace}}/{{slugKebabCase}}',
10544
- $resource_key
10545
- );
10546
-
10547
- $web_context = array(
10548
- 'bootstrapReady' => false,
10549
- 'buttonLabel' => $button_label,
10550
- 'canWrite' => false,
10551
- 'client' => array(
10552
- 'writeExpiry' => 0,
10553
- 'writeNonce' => '',
10554
- 'writeToken' => '',
10555
- ),
10556
- 'count' => 0,
10557
- 'error' => '',
10558
- 'isBootstrapping' => false,
10559
- 'isLoading' => false,
10560
- 'isSaving' => false,
10561
- 'persistencePolicy' => $persistence_policy,
10562
- 'postId' => (int) $post_id,
10563
- 'resourceKey' => $resource_key,
10564
- 'showCount' => $show_count,
10565
- 'storage' => $storage_mode,
10566
- );
10567
-
10568
- $allowed_inner_html = wp_kses_allowed_html( 'post' );
10569
-
10570
- foreach ( $allowed_inner_html as &$allowed_attributes ) {
10571
- if ( ! is_array( $allowed_attributes ) ) {
10572
- continue;
10573
- }
10574
-
10575
- $allowed_attributes['data-wp-bind--disabled'] = true;
10576
- $allowed_attributes['data-wp-bind--hidden'] = true;
10577
- $allowed_attributes['data-wp-bind--value'] = true;
10578
- $allowed_attributes['data-wp-class'] = true;
10579
- $allowed_attributes['data-wp-class--active'] = true;
10580
- $allowed_attributes['data-wp-context'] = true;
10581
- $allowed_attributes['data-wp-init'] = true;
10582
- $allowed_attributes['data-wp-interactive'] = true;
10583
- $allowed_attributes['data-wp-on--click'] = true;
10584
- $allowed_attributes['data-wp-on--mouseenter'] = true;
10585
- $allowed_attributes['data-wp-on--mouseleave'] = true;
10586
- $allowed_attributes['data-wp-run--mounted'] = true;
10587
- $allowed_attributes['data-wp-style--width'] = true;
10588
- $allowed_attributes['data-wp-text'] = true;
10589
- }
10590
- unset( $allowed_attributes );
10591
-
10592
- return array(
10593
- 'buttonLabel' => $button_label,
10594
- 'frontendClassName' => '{{cssClassName}}',
10595
- 'heading' => $heading,
10596
- 'intro' => $intro,
10597
- 'isVisible' => true,
10598
- 'normalized' => $normalized,
10599
- 'noticeMessage' => $notice_message,
10600
- 'postId' => (int) $post_id,
10601
- 'resourceKey' => $resource_key,
10602
- 'sanitizedContent' => wp_kses( $content, $allowed_inner_html ),
10603
- 'showCount' => $show_count,
10604
- 'showDividers' => $show_dividers,
10605
- 'title' => {{titleJson}},
10606
- 'webContext' => $web_context,
10607
- );
10608
- }
10609
- }
10610
-
10611
- if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_render_target' ) ) {
10612
- function {{phpPrefix}}_{{slugSnakeCase}}_render_target( string $target, $attributes, $content = '', $block = null ): string {
10613
- $context = {{phpPrefix}}_{{slugSnakeCase}}_build_render_context( $attributes, $content, $block );
10614
- if ( null === $context ) {
10615
- return '';
10616
- }
10617
-
10618
- $target_context = apply_filters(
10619
- '{{phpPrefix}}_{{slugSnakeCase}}_render_target_context',
10620
- $context,
10621
- $target,
10622
- $attributes,
10623
- $block
10624
- );
10625
-
10626
- $markup = '';
10627
- switch ( $target ) {
10628
- case 'email':
10629
- $parts = array(
10630
- '<div class="' . esc_attr( $target_context['frontendClassName'] ) . '-email">',
10631
- '<h3>' . esc_html( $target_context['heading'] ) . '</h3>',
10632
- );
10633
- if ( '' !== $target_context['intro'] ) {
10634
- $parts[] = '<p>' . esc_html( $target_context['intro'] ) . '</p>';
10635
- }
10636
- if ( ! empty( $target_context['showCount'] ) ) {
10637
- $parts[] = '<p><strong>' . esc_html__( 'Count', '{{textDomain}}' ) . ':</strong> ' . esc_html( (string) $target_context['webContext']['count'] ) . '</p>';
10638
- }
10639
- $parts[] = wp_kses_post( $target_context['sanitizedContent'] );
10640
- $parts[] = '<p>' . esc_html( $target_context['noticeMessage'] ) . '</p>';
10641
- $parts[] = '</div>';
10642
- $markup = implode( '', $parts );
10643
- break;
10644
- case 'mjml':
10645
- $markup = '<mjml><mj-body><mj-section><mj-column><mj-text font-weight="700">' . esc_html( $target_context['heading'] ) . '</mj-text>';
10646
- if ( '' !== $target_context['intro'] ) {
10647
- $markup .= '<mj-text>' . esc_html( $target_context['intro'] ) . '</mj-text>';
10648
- }
10649
- if ( ! empty( $target_context['showCount'] ) ) {
10650
- $markup .= '<mj-text>' . esc_html__( 'Count', '{{textDomain}}' ) . ': ' . esc_html( (string) $target_context['webContext']['count'] ) . '</mj-text>';
10651
- }
10652
- $markup .= '<mj-text>' . esc_html( wp_strip_all_tags( $target_context['sanitizedContent'] ) ) . '</mj-text>';
10653
- $markup .= '<mj-text>' . esc_html( $target_context['noticeMessage'] ) . '</mj-text></mj-column></mj-section></mj-body></mjml>';
10654
- break;
10655
- case 'plain-text':
10656
- $markup = implode(
10657
- "\\n",
10658
- array_filter(
10659
- array(
10660
- $target_context['heading'],
10661
- $target_context['intro'],
10662
- wp_strip_all_tags( $target_context['sanitizedContent'] ),
10663
- ! empty( $target_context['showCount'] )
10664
- ? sprintf( '%s: %s', __( 'Count', '{{textDomain}}' ), (string) $target_context['webContext']['count'] )
10665
- : null,
10666
- $target_context['noticeMessage'],
10667
- ),
10668
- static fn( $value ) => is_string( $value ) && '' !== $value
10669
- )
10670
- );
10671
- break;
10672
- case 'web':
10673
- default:
10674
- $wrapper_attributes = get_block_wrapper_attributes(
10675
- array(
10676
- 'class' => '{{cssClassName}}',
10677
- 'data-show-dividers' => $target_context['showDividers'] ? 'true' : 'false',
10678
- 'data-wp-context' => wp_json_encode( $target_context['webContext'] ),
10679
- 'data-wp-init' => 'callbacks.init',
10680
- 'data-wp-interactive' => '{{slugKebabCase}}',
10681
- 'data-wp-run--mounted' => 'callbacks.mounted',
10682
- )
10683
- );
10684
- ob_start();
10685
- ?>
10686
- <div <?php echo $wrapper_attributes; ?>>
10687
- <h3 class="{{cssClassName}}__heading"><?php echo esc_html( $target_context['heading'] ); ?></h3>
10688
- <?php if ( '' !== $target_context['intro'] ) : ?>
10689
- <p class="{{cssClassName}}__intro"><?php echo esc_html( $target_context['intro'] ); ?></p>
10690
- <?php endif; ?>
10691
- <p
10692
- class="{{cssClassName}}__notice"
10693
- data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
10694
- hidden
10695
- >
10696
- <?php echo esc_html( $target_context['noticeMessage'] ); ?>
10697
- </p>
10698
- <p
10699
- class="{{cssClassName}}__error"
10700
- role="status"
10701
- aria-live="polite"
10702
- aria-atomic="true"
10703
- data-wp-bind--hidden="!context.error"
10704
- data-wp-text="context.error"
10705
- hidden
10706
- ></p>
10707
- <?php if ( ! empty( $target_context['showCount'] ) ) : ?>
10708
- <div class="{{cssClassName}}__counter">
10960
+ role="status"
10961
+ aria-live="polite"
10962
+ aria-atomic="true"
10963
+ data-wp-bind--hidden="!context.error"
10964
+ data-wp-text="context.error"
10965
+ hidden
10966
+ ></p>
10967
+ <?php if ( ! empty( $target_context['showCount'] ) ) : ?>
10709
10968
  <span
10710
- class="{{cssClassName}}__count"
10969
+ class="{{frontendCssClassName}}__count"
10711
10970
  role="status"
10712
10971
  aria-live="polite"
10713
10972
  aria-atomic="true"
10714
10973
  data-wp-text="context.count"
10715
- >0</span>
10716
- <button
10717
- type="button"
10718
- disabled
10719
- data-wp-bind--disabled="!context.canWrite"
10720
- data-wp-on--click="actions.increment"
10721
10974
  >
10722
- <?php echo esc_html( $target_context['buttonLabel'] ); ?>
10723
- </button>
10724
- </div>
10725
- <?php endif; ?>
10726
- <div class="{{cssClassName}}__items">
10727
- <?php echo wp_kses_post( $target_context['sanitizedContent'] ); ?>
10975
+ 0
10976
+ </span>
10977
+ <?php endif; ?>
10978
+ <button
10979
+ type="button"
10980
+ disabled
10981
+ data-wp-bind--disabled="!context.canWrite"
10982
+ data-wp-on--click="actions.increment"
10983
+ >
10984
+ <?php echo esc_html( $target_context['buttonLabel'] ); ?>
10985
+ </button>
10728
10986
  </div>
10729
10987
  </div>
10730
10988
  <?php
@@ -10741,51 +10999,8 @@ if ( ! function_exists( '{{phpPrefix}}_{{slugSnakeCase}}_render_target' ) ) {
10741
10999
  }
10742
11000
  }
10743
11001
  `;
10744
- var COMPOUND_STYLE_TEMPLATE = `.{{cssClassName}} {
10745
- border: 1px solid #dcdcde;
10746
- border-radius: 12px;
10747
- padding: 1.25rem;
10748
- background: #fff;
10749
- }
10750
-
10751
- .{{cssClassName}}__heading {
10752
- margin: 0 0 0.5rem;
10753
- font-size: 1.2rem;
10754
- }
10755
-
10756
- .{{cssClassName}}__intro {
10757
- margin: 0 0 1rem;
10758
- color: #50575e;
10759
- }
10760
-
10761
- .{{cssClassName}}__items {
10762
- display: grid;
10763
- gap: 0.75rem;
10764
- }
10765
-
10766
- .{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}} {
10767
- border-top: 1px solid #dcdcde;
10768
- padding-top: 0.75rem;
10769
- }
10770
11002
 
10771
- .{{cssClassName}}[data-show-dividers='true'] .{{compoundChildCssClassName}}:first-child {
10772
- border-top: 0;
10773
- padding-top: 0;
10774
- }
10775
- `;
10776
- function buildBasicArtifacts(variables) {
10777
- return [
10778
- renderArtifact("src/editor.scss", BASIC_EDITOR_STYLE_TEMPLATE, variables),
10779
- renderArtifact("src/style.scss", BASIC_STYLE_TEMPLATE, variables),
10780
- renderArtifact("src/render.php", BASIC_RENDER_TEMPLATE, variables)
10781
- ];
10782
- }
10783
- function buildInteractivityArtifacts(variables) {
10784
- return [
10785
- renderArtifact("src/editor.scss", INTERACTIVITY_EDITOR_STYLE_TEMPLATE, variables),
10786
- renderArtifact("src/style.scss", INTERACTIVITY_STYLE_TEMPLATE, variables)
10787
- ];
10788
- }
11003
+ // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-persistence-artifacts.ts
10789
11004
  function buildPersistenceArtifacts(variables) {
10790
11005
  const alternateRenderTargets = getScaffoldAlternateRenderTargets(variables);
10791
11006
  if (!alternateRenderTargets.enabled) {
@@ -10810,187 +11025,6 @@ function buildPersistenceArtifacts(variables) {
10810
11025
  }
10811
11026
  return artifacts;
10812
11027
  }
10813
- function buildCompoundArtifacts(variables) {
10814
- const alternateRenderTargets = getScaffoldAlternateRenderTargets(variables);
10815
- const artifacts = [
10816
- renderArtifact(`src/blocks/${variables.slugKebabCase}/style.scss`, COMPOUND_STYLE_TEMPLATE, variables)
10817
- ];
10818
- if (isCompoundPersistenceEnabled(variables)) {
10819
- const renderView = {
10820
- ...variables,
10821
- titlePhpLiteral: toPhpSingleQuotedString(variables.title)
10822
- };
10823
- if (alternateRenderTargets.enabled) {
10824
- artifacts.push(renderArtifact(`src/blocks/${variables.slugKebabCase}/render-targets.php`, COMPOUND_PERSISTENCE_RENDER_TARGETS_TEMPLATE, renderView), buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render.php`, "web", variables));
10825
- if (alternateRenderTargets.hasEmail) {
10826
- artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-email.php`, "email", variables));
10827
- }
10828
- if (alternateRenderTargets.hasMjml) {
10829
- artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-mjml.php`, "mjml", variables));
10830
- }
10831
- if (alternateRenderTargets.hasPlainText) {
10832
- artifacts.push(buildAlternateRenderEntryArtifact(`src/blocks/${variables.slugKebabCase}/render-text.php`, "plain-text", variables));
10833
- }
10834
- return artifacts;
10835
- }
10836
- const renderSource = `<?php
10837
- /**
10838
- * Dynamic render entry for the {{title}} compound parent block.
10839
- *
10840
- * @package {{pascalCase}}
10841
- */
10842
-
10843
- if ( ! defined( 'ABSPATH' ) ) {
10844
- exit;
10845
- }
10846
-
10847
- $validator_path = __DIR__ . '/typia-validator.php';
10848
- if ( ! file_exists( $validator_path ) ) {
10849
- return '';
10850
- }
10851
-
10852
- $validator = require $validator_path;
10853
- if ( ! is_object( $validator ) || ! method_exists( $validator, 'apply_defaults' ) || ! method_exists( $validator, 'validate' ) ) {
10854
- return '';
10855
- }
10856
-
10857
- $normalized = $validator->apply_defaults( is_array( $attributes ) ? $attributes : array() );
10858
- $validation = $validator->validate( $normalized );
10859
- $resource_key = isset( $normalized['resourceKey'] ) ? (string) $normalized['resourceKey'] : '';
10860
- $heading = isset( $normalized['heading'] ) ? (string) $normalized['heading'] : {{titlePhpLiteral}};
10861
- $intro = isset( $normalized['intro'] ) ? (string) $normalized['intro'] : '';
10862
- $button_label = isset( $normalized['buttonLabel'] ) ? (string) $normalized['buttonLabel'] : 'Persist Count';
10863
- $show_count = ! empty( $normalized['showCount'] );
10864
- $show_dividers = ! empty( $normalized['showDividers'] );
10865
- $post_id = is_object( $block ) && isset( $block->context['postId'] )
10866
- ? (int) $block->context['postId']
10867
- : (int) get_queried_object_id();
10868
- $storage_mode = '{{dataStorageMode}}';
10869
- $persistence_policy = '{{persistencePolicy}}';
10870
-
10871
- $notice_message = 'authenticated' === $persistence_policy
10872
- ? __( 'Sign in to persist this counter.', '{{textDomain}}' )
10873
- : __( 'Public writes are temporarily unavailable.', '{{textDomain}}' );
10874
-
10875
- if ( empty( $validation['valid'] ) || '' === $resource_key ) {
10876
- return '';
10877
- }
10878
-
10879
- {{phpPrefix}}_record_rendered_block_instance(
10880
- (int) $post_id,
10881
- '{{namespace}}/{{slugKebabCase}}',
10882
- $resource_key
10883
- );
10884
-
10885
- $context = array(
10886
- 'bootstrapReady' => false,
10887
- 'buttonLabel' => $button_label,
10888
- 'canWrite' => false,
10889
- 'client' => array(
10890
- 'writeExpiry' => 0,
10891
- 'writeNonce' => '',
10892
- 'writeToken' => '',
10893
- ),
10894
- 'count' => 0,
10895
- 'error' => '',
10896
- 'isBootstrapping' => false,
10897
- 'isLoading' => false,
10898
- 'isSaving' => false,
10899
- 'persistencePolicy' => $persistence_policy,
10900
- 'postId' => (int) $post_id,
10901
- 'resourceKey' => $resource_key,
10902
- 'showCount' => $show_count,
10903
- 'storage' => $storage_mode,
10904
- );
10905
-
10906
- $allowed_inner_html = wp_kses_allowed_html( 'post' );
10907
-
10908
- foreach ( $allowed_inner_html as &$allowed_attributes ) {
10909
- if ( ! is_array( $allowed_attributes ) ) {
10910
- continue;
10911
- }
10912
-
10913
- $allowed_attributes['data-wp-bind--disabled'] = true;
10914
- $allowed_attributes['data-wp-bind--hidden'] = true;
10915
- $allowed_attributes['data-wp-bind--value'] = true;
10916
- $allowed_attributes['data-wp-class'] = true;
10917
- $allowed_attributes['data-wp-class--active'] = true;
10918
- $allowed_attributes['data-wp-context'] = true;
10919
- $allowed_attributes['data-wp-init'] = true;
10920
- $allowed_attributes['data-wp-interactive'] = true;
10921
- $allowed_attributes['data-wp-on--click'] = true;
10922
- $allowed_attributes['data-wp-on--mouseenter'] = true;
10923
- $allowed_attributes['data-wp-on--mouseleave'] = true;
10924
- $allowed_attributes['data-wp-run--mounted'] = true;
10925
- $allowed_attributes['data-wp-style--width'] = true;
10926
- $allowed_attributes['data-wp-text'] = true;
10927
- }
10928
- unset( $allowed_attributes );
10929
-
10930
- $sanitized_content = wp_kses( $content, $allowed_inner_html );
10931
-
10932
- $wrapper_attributes = get_block_wrapper_attributes(
10933
- array(
10934
- 'class' => '{{cssClassName}}',
10935
- 'data-show-dividers' => $show_dividers ? 'true' : 'false',
10936
- 'data-wp-context' => wp_json_encode( $context ),
10937
- 'data-wp-init' => 'callbacks.init',
10938
- 'data-wp-interactive' => '{{slugKebabCase}}',
10939
- 'data-wp-run--mounted' => 'callbacks.mounted',
10940
- )
10941
- );
10942
- ?>
10943
-
10944
- <div <?php echo $wrapper_attributes; ?>>
10945
- <h3 class="{{cssClassName}}__heading"><?php echo esc_html( $heading ); ?></h3>
10946
- <?php if ( '' !== $intro ) : ?>
10947
- <p class="{{cssClassName}}__intro"><?php echo esc_html( $intro ); ?></p>
10948
- <?php endif; ?>
10949
- <p
10950
- class="{{cssClassName}}__notice"
10951
- data-wp-bind--hidden="!context.bootstrapReady || context.canWrite"
10952
- hidden
10953
- >
10954
- <?php echo esc_html( $notice_message ); ?>
10955
- </p>
10956
- <p
10957
- class="{{cssClassName}}__error"
10958
- role="status"
10959
- aria-live="polite"
10960
- aria-atomic="true"
10961
- data-wp-bind--hidden="!context.error"
10962
- data-wp-text="context.error"
10963
- hidden
10964
- ></p>
10965
- <?php if ( $show_count ) : ?>
10966
- <div class="{{cssClassName}}__counter">
10967
- <span
10968
- class="{{cssClassName}}__count"
10969
- role="status"
10970
- aria-live="polite"
10971
- aria-atomic="true"
10972
- data-wp-text="context.count"
10973
- >0</span>
10974
- <button
10975
- type="button"
10976
- disabled
10977
- data-wp-bind--disabled="!context.canWrite"
10978
- data-wp-on--click="actions.increment"
10979
- >
10980
- <?php echo esc_html( $button_label ); ?>
10981
- </button>
10982
- </div>
10983
- <?php endif; ?>
10984
- <div class="{{cssClassName}}__items">
10985
- <?php echo $sanitized_content; ?>
10986
- </div>
10987
- </div>
10988
- `;
10989
- artifacts.push(renderArtifact(`src/blocks/${variables.slugKebabCase}/render.php`, renderSource, renderView));
10990
- }
10991
- return artifacts;
10992
- }
10993
-
10994
11028
  // ../wp-typia-project-tools/src/runtime/built-in-block-non-ts-artifacts.ts
10995
11029
  function buildBuiltInNonTsArtifacts({
10996
11030
  templateId,
@@ -14544,17 +14578,17 @@ async function scaffoldProject({
14544
14578
  phase: "finalize-project",
14545
14579
  title: "Finalizing scaffold output"
14546
14580
  });
14547
- const readmePath = path18.join(projectDir, "README.md");
14581
+ const readmePath = path20.join(projectDir, "README.md");
14548
14582
  if (!await pathExists(readmePath)) {
14549
- await fsp13.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
14583
+ await fsp14.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
14550
14584
  withMigrationUi: isBuiltInTemplate || isWorkspace ? withMigrationUi : false,
14551
14585
  withTestPreset: isBuiltInTemplate ? withTestPreset : false,
14552
14586
  withWpEnv: isBuiltInTemplate ? withWpEnv : false
14553
14587
  }), "utf8");
14554
14588
  }
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");
14589
+ const gitignorePath = path20.join(projectDir, ".gitignore");
14590
+ const existingGitignore = await pathExists(gitignorePath) ? await fsp14.readFile(gitignorePath, "utf8") : "";
14591
+ await fsp14.writeFile(gitignorePath, mergeTextLines(buildGitignore(), existingGitignore), "utf8");
14558
14592
  await normalizePackageJson(projectDir, resolvedPackageManager);
14559
14593
  if (isBuiltInTemplate) {
14560
14594
  const variableGroups = getScaffoldTemplateVariableGroups(variables);
@@ -14640,4 +14674,4 @@ async function resolveOptionalInteractiveExternalLayerId({
14640
14674
 
14641
14675
  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 };
14642
14676
 
14643
- //# debugId=5D116D118BFF7F2764756E2164756E21
14677
+ //# debugId=5D6C751C245E365E64756E2164756E21