wp-typia 0.19.0 → 0.20.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.
Files changed (42) hide show
  1. package/README.md +4 -2
  2. package/dist-bunli/.bunli/commands.gen.js +1843 -1216
  3. package/dist-bunli/.bunli/commands.gen.js.map +36 -33
  4. package/dist-bunli/cli-03j0axbt.js +163 -0
  5. package/dist-bunli/cli-03j0axbt.js.map +11 -0
  6. package/dist-bunli/{cli-7svz19s1.js → cli-2ybmc22r.js} +370 -86
  7. package/dist-bunli/{cli-7svz19s1.js.map → cli-2ybmc22r.js.map} +15 -14
  8. package/dist-bunli/cli-7yg38ht2.js +427 -0
  9. package/dist-bunli/cli-7yg38ht2.js.map +12 -0
  10. package/dist-bunli/{cli-yw0mq0wq.js → cli-93wd227r.js} +108 -3
  11. package/dist-bunli/cli-93wd227r.js.map +10 -0
  12. package/dist-bunli/{cli-kan7a6db.js → cli-a6dwqnhq.js} +24 -2
  13. package/dist-bunli/cli-a6dwqnhq.js.map +11 -0
  14. package/dist-bunli/{cli-add-j2c81sh1.js → cli-add-pq6wm87p.js} +16 -9
  15. package/dist-bunli/{cli-add-j2c81sh1.js.map → cli-add-pq6wm87p.js.map} +3 -3
  16. package/dist-bunli/{cli-diagnostics-c65hhyhx.js → cli-diagnostics-e5gxeprp.js} +8 -4
  17. package/dist-bunli/{cli-diagnostics-c65hhyhx.js.map → cli-diagnostics-e5gxeprp.js.map} +1 -1
  18. package/dist-bunli/{cli-doctor-hft0wr0e.js → cli-doctor-qk6fwpds.js} +14 -13
  19. package/dist-bunli/{cli-doctor-hft0wr0e.js.map → cli-doctor-qk6fwpds.js.map} +3 -3
  20. package/dist-bunli/{cli-572d6g4m.js → cli-hv2yedw2.js} +2 -157
  21. package/dist-bunli/{cli-572d6g4m.js.map → cli-hv2yedw2.js.map} +4 -6
  22. package/dist-bunli/{cli-scaffold-vcg6wem5.js → cli-scaffold-s3nhwe7x.js} +9 -7
  23. package/dist-bunli/cli-scaffold-s3nhwe7x.js.map +10 -0
  24. package/dist-bunli/cli-t73q5aqz.js +103 -0
  25. package/dist-bunli/cli-t73q5aqz.js.map +10 -0
  26. package/dist-bunli/{cli-templates-4qxszbmc.js → cli-templates-j65r4k9v.js} +1 -1
  27. package/dist-bunli/{cli-wtrvnce5.js → cli-w4r0rr8a.js} +8 -8
  28. package/dist-bunli/cli-w4r0rr8a.js.map +10 -0
  29. package/dist-bunli/cli.js +127 -2863
  30. package/dist-bunli/cli.js.map +5 -56
  31. package/dist-bunli/command-list-37n1za5q.js +2485 -0
  32. package/dist-bunli/command-list-37n1za5q.js.map +58 -0
  33. package/dist-bunli/node-cli.js +432 -323
  34. package/dist-bunli/node-cli.js.map +11 -10
  35. package/dist-bunli/{sync-x91y9jtv.js → sync-k2k8svyc.js} +3 -2
  36. package/dist-bunli/{sync-x91y9jtv.js.map → sync-k2k8svyc.js.map} +1 -1
  37. package/package.json +6 -3
  38. package/dist-bunli/cli-kan7a6db.js.map +0 -11
  39. package/dist-bunli/cli-scaffold-vcg6wem5.js.map +0 -10
  40. package/dist-bunli/cli-wtrvnce5.js.map +0 -10
  41. package/dist-bunli/cli-yw0mq0wq.js.map +0 -10
  42. /package/dist-bunli/{cli-templates-4qxszbmc.js.map → cli-templates-j65r4k9v.js.map} +0 -0
@@ -3,7 +3,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "wp-typia",
6
- version: "0.19.0",
6
+ version: "0.20.0",
7
7
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
8
8
  packageManager: "bun@1.3.11",
9
9
  type: "module",
@@ -19,14 +19,17 @@ var package_default = {
19
19
  scripts: {
20
20
  generate: "bun scripts/generate-bunli-metadata.ts",
21
21
  build: "bun run generate && bun scripts/build-bunli-runtime.ts",
22
+ "build:standalone": "bun scripts/build-standalone-runtime.ts --targets native --outdir ./dist-standalone",
23
+ "build:standalone:release": "bun scripts/build-standalone-runtime.ts --targets darwin-arm64,darwin-x64,linux-arm64,linux-x64,windows-x64 --outdir ./.cache/standalone/raw",
22
24
  "bunli:generate": "bun run generate",
23
25
  "bunli:build": "bun run build",
24
26
  "bunli:dev": "bun src/cli.ts",
25
27
  "bunli:test": "bun test tests/*.test.ts",
26
28
  dev: "bun run build && node bin/wp-typia.js",
29
+ "standalone:prepare-release-assets": "bun scripts/prepare-standalone-release-assets.ts --input-dir ./.cache/standalone/raw --outdir ./.cache/standalone/release-assets",
27
30
  test: "cd ../wp-typia-project-tools && bun run build && cd ../wp-typia && bun run build && bun test tests/*.test.ts",
28
31
  "test:coverage": "cd ../wp-typia-project-tools && bun run build && cd ../wp-typia && bun run build && bun test tests/*.test.ts --coverage --coverage-reporter=lcov --coverage-dir=coverage",
29
- clean: "rm -rf .bunli dist-bunli",
32
+ clean: "rm -rf .bunli .cache/standalone dist-bunli dist-standalone",
30
33
  prepack: "bun run build"
31
34
  },
32
35
  keywords: [
@@ -67,7 +70,7 @@ var package_default = {
67
70
  "@bunli/tui": "0.6.0",
68
71
  "@bunli/utils": "0.6.0",
69
72
  "@wp-typia/api-client": "^0.4.5",
70
- "@wp-typia/project-tools": "0.19.0",
73
+ "@wp-typia/project-tools": "0.19.1",
71
74
  "better-result": "^2.7.0",
72
75
  react: "^19.2.5",
73
76
  "react-dom": "^19.2.5",
@@ -91,8 +94,10 @@ var package_default = {
91
94
 
92
95
  // src/node-cli.ts
93
96
  import {
97
+ CLI_DIAGNOSTIC_CODES,
94
98
  createCliCommandError,
95
- formatCliDiagnosticError
99
+ formatCliDiagnosticError,
100
+ serializeCliDiagnosticError
96
101
  } from "@wp-typia/project-tools/cli-diagnostics";
97
102
 
98
103
  // src/command-option-metadata.ts
@@ -108,7 +113,7 @@ var CREATE_OPTION_METADATA = {
108
113
  },
109
114
  "dry-run": {
110
115
  argumentKind: "flag",
111
- description: "Preview scaffold output without writing files to the target directory.",
116
+ description: "Preview scaffold output for a logical <project-dir> without writing files to the target directory.",
112
117
  type: "boolean"
113
118
  },
114
119
  "external-layer-id": {
@@ -203,7 +208,7 @@ var ADD_OPTION_METADATA = {
203
208
  },
204
209
  "dry-run": {
205
210
  argumentKind: "flag",
206
- description: "Preview workspace file updates without writing them.",
211
+ description: "Preview workspace file updates and completion guidance without writing them.",
207
212
  type: "boolean"
208
213
  },
209
214
  "external-layer-id": {
@@ -313,6 +318,102 @@ function formatNodeFallbackOptionHelp(metadata) {
313
318
  return `- --${name}${short}: ${option.description}`;
314
319
  });
315
320
  }
321
+ function buildCommandOptionParser(...metadataMaps) {
322
+ const metadata = Object.assign({}, ...metadataMaps);
323
+ return {
324
+ booleanOptionNames: new Set(collectOptionNamesByType(metadata, "boolean")),
325
+ shortFlagMap: new Map(Object.entries(metadata).flatMap(([name, option]) => option.short ? [[option.short, { name, type: option.type }]] : [])),
326
+ stringOptionNames: new Set(collectOptionNamesByType(metadata, "string"))
327
+ };
328
+ }
329
+ function parseCommandArgvWithMetadata(argv, options) {
330
+ const flags = {};
331
+ const positionals = [];
332
+ const booleanOptionNames = new Set(options.parser.booleanOptionNames);
333
+ for (const optionName of options.extraBooleanOptionNames ?? []) {
334
+ booleanOptionNames.add(optionName);
335
+ }
336
+ for (let index = 0;index < argv.length; index += 1) {
337
+ const arg = argv[index];
338
+ if (!arg) {
339
+ continue;
340
+ }
341
+ if (arg === "--") {
342
+ positionals.push(...argv.slice(index + 1));
343
+ break;
344
+ }
345
+ if (arg.length === 2 && arg.startsWith("-")) {
346
+ const shortFlag = options.parser.shortFlagMap.get(arg.slice(1));
347
+ if (!shortFlag) {
348
+ throw new Error(`Unknown option \`${arg}\`.`);
349
+ }
350
+ if (shortFlag.type === "boolean") {
351
+ flags[shortFlag.name] = true;
352
+ continue;
353
+ }
354
+ const next = argv[index + 1];
355
+ if (!next || next.startsWith("-")) {
356
+ throw new Error(`\`${arg}\` requires a value.`);
357
+ }
358
+ flags[shortFlag.name] = next;
359
+ index += 1;
360
+ continue;
361
+ }
362
+ if (arg.startsWith("--")) {
363
+ const option = arg.slice(2);
364
+ const separatorIndex = option.indexOf("=");
365
+ const rawName = separatorIndex === -1 ? option : option.slice(0, separatorIndex);
366
+ const inlineValue = separatorIndex === -1 ? undefined : option.slice(separatorIndex + 1);
367
+ if (booleanOptionNames.has(rawName)) {
368
+ flags[rawName] = true;
369
+ continue;
370
+ }
371
+ if (!options.parser.stringOptionNames.has(rawName)) {
372
+ throw new Error(`Unknown option \`--${rawName}\`.`);
373
+ }
374
+ if (inlineValue !== undefined) {
375
+ if (!inlineValue) {
376
+ throw new Error(`\`--${rawName}\` requires a value.`);
377
+ }
378
+ flags[rawName] = inlineValue;
379
+ continue;
380
+ }
381
+ const next = argv[index + 1];
382
+ if (!next || next.startsWith("-")) {
383
+ throw new Error(`\`--${rawName}\` requires a value.`);
384
+ }
385
+ flags[rawName] = next;
386
+ index += 1;
387
+ continue;
388
+ }
389
+ if (arg.startsWith("-")) {
390
+ throw new Error(`Unknown option \`${arg}\`.`);
391
+ }
392
+ positionals.push(arg);
393
+ }
394
+ return {
395
+ flags,
396
+ positionals
397
+ };
398
+ }
399
+ function resolveCommandOptionValues(metadata, options) {
400
+ const resolved = {};
401
+ const optionNames = options.optionNames ?? Object.keys(metadata);
402
+ for (const optionName of optionNames) {
403
+ const name = String(optionName);
404
+ const descriptor = metadata[name];
405
+ if (!descriptor) {
406
+ continue;
407
+ }
408
+ const value = options.flags?.[name] ?? options.defaults?.[name];
409
+ if (descriptor.type === "boolean") {
410
+ resolved[name] = Boolean(value ?? false);
411
+ continue;
412
+ }
413
+ resolved[name] = typeof value === "string" ? value : undefined;
414
+ }
415
+ return resolved;
416
+ }
316
417
 
317
418
  // src/node-cli.ts
318
419
  import {
@@ -433,8 +534,8 @@ function extractWpTypiaConfigOverride(argv) {
433
534
  // src/runtime-bridge-add-dry-run.ts
434
535
  import fs2 from "node:fs";
435
536
  import { promises as fsp } from "node:fs";
436
- import os2 from "node:os";
437
537
  import path2 from "node:path";
538
+ import { createManagedTempRoot } from "@wp-typia/project-tools/temp-roots";
438
539
  var SKIPPED_COPY_ROOT_ENTRIES = new Set([".git", "node_modules"]);
439
540
  var SKIPPED_COMPARE_ROOT_ENTRIES = new Set([
440
541
  ".git",
@@ -540,7 +641,7 @@ async function simulateWorkspaceAddDryRun({
540
641
  const { resolveWorkspaceProject } = await import("@wp-typia/project-tools/workspace-project");
541
642
  const workspace = resolveWorkspaceProject(cwd);
542
643
  const relativeCwd = path2.relative(workspace.projectDir, path2.resolve(cwd));
543
- const tempRoot = await fsp.mkdtemp(path2.join(os2.tmpdir(), "wp-typia-add-plan-"));
644
+ const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-add-plan-");
544
645
  const simulatedProjectDir = path2.join(tempRoot, "workspace");
545
646
  try {
546
647
  await copyWorkspaceProject(workspace.projectDir, simulatedProjectDir);
@@ -553,11 +654,13 @@ async function simulateWorkspaceAddDryRun({
553
654
  result
554
655
  };
555
656
  } finally {
556
- await fsp.rm(tempRoot, { force: true, recursive: true });
657
+ await cleanup();
557
658
  }
558
659
  }
559
660
 
560
661
  // src/runtime-bridge-output.ts
662
+ import fs3 from "node:fs";
663
+ import path3 from "node:path";
561
664
  import { formatPackageExecCommand } from "@wp-typia/project-tools/package-managers";
562
665
  function printCompletionPayload(payload, options = {}) {
563
666
  const printLine = options.printLine ?? console.log;
@@ -636,6 +739,32 @@ function buildCreateDryRunPayload(flow) {
636
739
  warningLines: flow.result.warnings
637
740
  };
638
741
  }
742
+ function inferProjectPackageManager(projectDir) {
743
+ try {
744
+ const packageJsonPath = path3.join(projectDir, "package.json");
745
+ if (fs3.existsSync(packageJsonPath)) {
746
+ const manifest = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
747
+ if (manifest.packageManager?.startsWith("bun@"))
748
+ return "bun";
749
+ if (manifest.packageManager?.startsWith("pnpm@"))
750
+ return "pnpm";
751
+ if (manifest.packageManager?.startsWith("yarn@"))
752
+ return "yarn";
753
+ if (manifest.packageManager?.startsWith("npm@"))
754
+ return "npm";
755
+ }
756
+ } catch {}
757
+ if (fs3.existsSync(path3.join(projectDir, "bun.lock")) || fs3.existsSync(path3.join(projectDir, "bun.lockb"))) {
758
+ return "bun";
759
+ }
760
+ if (fs3.existsSync(path3.join(projectDir, "pnpm-lock.yaml"))) {
761
+ return "pnpm";
762
+ }
763
+ if (fs3.existsSync(path3.join(projectDir, "yarn.lock")) || fs3.existsSync(path3.join(projectDir, ".yarnrc.yml"))) {
764
+ return "yarn";
765
+ }
766
+ return "npm";
767
+ }
639
768
  function buildMigrationCompletionPayload(options) {
640
769
  const summaryLines = options.lines.filter((line) => line.trim().length > 0);
641
770
  return {
@@ -644,9 +773,20 @@ function buildMigrationCompletionPayload(options) {
644
773
  };
645
774
  }
646
775
  function buildAddCompletionPayload(options) {
776
+ const verificationLines = [
777
+ formatPackageExecCommand(options.packageManager ?? inferProjectPackageManager(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
778
+ ];
779
+ const verificationNote = "Run doctor via your package manager for a quick inventory and generated-artifact check after the add workflow.";
647
780
  switch (options.kind) {
648
781
  case "variation":
649
782
  return {
783
+ nextSteps: [
784
+ `Review src/blocks/${options.values.blockSlug}/variations/${options.values.variationSlug}.ts.`,
785
+ "Run your workspace build or dev command to pick up the new variation."
786
+ ],
787
+ optionalLines: verificationLines,
788
+ optionalNote: verificationNote,
789
+ optionalTitle: "Verify workspace health (optional):",
650
790
  summaryLines: [
651
791
  `Variation: ${options.values.variationSlug}`,
652
792
  `Target block: ${options.values.blockSlug}`,
@@ -656,6 +796,13 @@ function buildAddCompletionPayload(options) {
656
796
  };
657
797
  case "pattern":
658
798
  return {
799
+ nextSteps: [
800
+ `Review src/patterns/${options.values.patternSlug}.php.`,
801
+ "Run your workspace build or dev command to verify the new pattern registration."
802
+ ],
803
+ optionalLines: verificationLines,
804
+ optionalNote: verificationNote,
805
+ optionalTitle: "Verify workspace health (optional):",
659
806
  summaryLines: [
660
807
  `Pattern: ${options.values.patternSlug}`,
661
808
  `Project directory: ${options.projectDir}`
@@ -664,6 +811,13 @@ function buildAddCompletionPayload(options) {
664
811
  };
665
812
  case "binding-source":
666
813
  return {
814
+ nextSteps: [
815
+ `Review src/bindings/${options.values.bindingSourceSlug}/server.php and src/bindings/${options.values.bindingSourceSlug}/editor.ts.`,
816
+ "Run your workspace build or dev command to verify the binding source hooks and editor registration."
817
+ ],
818
+ optionalLines: verificationLines,
819
+ optionalNote: verificationNote,
820
+ optionalTitle: "Verify workspace health (optional):",
667
821
  summaryLines: [
668
822
  `Binding source: ${options.values.bindingSourceSlug}`,
669
823
  `Project directory: ${options.projectDir}`
@@ -672,6 +826,13 @@ function buildAddCompletionPayload(options) {
672
826
  };
673
827
  case "rest-resource":
674
828
  return {
829
+ nextSteps: [
830
+ `Review src/rest/${options.values.restResourceSlug}/ and inc/rest/${options.values.restResourceSlug}.php.`,
831
+ "Run your workspace build or dev command to verify the generated REST resource contract."
832
+ ],
833
+ optionalLines: verificationLines,
834
+ optionalNote: verificationNote,
835
+ optionalTitle: "Verify workspace health (optional):",
675
836
  summaryLines: [
676
837
  `REST resource: ${options.values.restResourceSlug}`,
677
838
  `Namespace: ${options.values.namespace}`,
@@ -682,6 +843,13 @@ function buildAddCompletionPayload(options) {
682
843
  };
683
844
  case "editor-plugin":
684
845
  return {
846
+ nextSteps: [
847
+ `Review src/editor-plugins/${options.values.editorPluginSlug}/.`,
848
+ "Run your workspace build or dev command to verify the new editor plugin registration."
849
+ ],
850
+ optionalLines: verificationLines,
851
+ optionalNote: verificationNote,
852
+ optionalTitle: "Verify workspace health (optional):",
685
853
  summaryLines: [
686
854
  `Editor plugin: ${options.values.editorPluginSlug}`,
687
855
  `Slot: ${options.values.slot}`,
@@ -691,6 +859,13 @@ function buildAddCompletionPayload(options) {
691
859
  };
692
860
  case "hooked-block":
693
861
  return {
862
+ nextSteps: [
863
+ `Review src/blocks/${options.values.blockSlug}/block.json for the new blockHooks entry.`,
864
+ "Run your workspace build or dev command to verify the updated hooked-block metadata."
865
+ ],
866
+ optionalLines: verificationLines,
867
+ optionalNote: verificationNote,
868
+ optionalTitle: "Verify workspace health (optional):",
694
869
  summaryLines: [
695
870
  `Block: ${options.values.blockSlug}`,
696
871
  `Anchor: ${options.values.anchorBlockName}`,
@@ -701,6 +876,13 @@ function buildAddCompletionPayload(options) {
701
876
  };
702
877
  default:
703
878
  return {
879
+ nextSteps: [
880
+ "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
881
+ "Run your workspace build or dev command to verify the new scaffolded block family."
882
+ ],
883
+ optionalLines: verificationLines,
884
+ optionalNote: verificationNote,
885
+ optionalTitle: "Verify workspace health (optional):",
704
886
  summaryLines: [
705
887
  `Blocks: ${options.values.blockSlugs}`,
706
888
  `Template family: ${options.values.templateId}`,
@@ -742,10 +924,19 @@ function toExternalLayerPromptOptions(options) {
742
924
  value: option.id
743
925
  }));
744
926
  }
927
+
928
+ // src/runtime-capabilities.ts
929
+ function isInteractiveTerminal({
930
+ stdin = process.stdin,
931
+ stdout = process.stdout,
932
+ term = process.env.TERM
933
+ } = {}) {
934
+ return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
935
+ }
745
936
  // src/runtime-bridge-sync.ts
746
937
  import { spawnSync } from "node:child_process";
747
- import fs3 from "node:fs";
748
- import path3 from "node:path";
938
+ import fs4 from "node:fs";
939
+ import path4 from "node:path";
749
940
  var SYNC_INSTALL_MARKERS = ["node_modules", ".pnp.cjs", ".pnp.loader.mjs"];
750
941
  var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
751
942
  function formatRunScript(packageManagerId, scriptName, extraArgs = "") {
@@ -774,7 +965,7 @@ function formatInstallCommand(packageManagerId) {
774
965
  }
775
966
  }
776
967
  function getSyncRootError(cwd) {
777
- return new Error(`No generated wp-typia project root was found at ${cwd}. Run \`wp-typia sync\` from a scaffolded project or official workspace root.`);
968
+ return new Error(`No generated wp-typia project root was found at ${cwd}. Run \`wp-typia sync\` from a scaffolded project or official workspace root that already contains generated sync scripts. If you expected this directory to work, cd into the scaffold root first or rerun the scaffold before syncing.`);
778
969
  }
779
970
  function inferSyncPackageManager(cwd, packageManagerField) {
780
971
  const field = String(packageManagerField ?? "");
@@ -786,26 +977,26 @@ function inferSyncPackageManager(cwd, packageManagerField) {
786
977
  return "pnpm";
787
978
  if (field.startsWith("yarn@"))
788
979
  return "yarn";
789
- if (fs3.existsSync(path3.join(cwd, "bun.lock")) || fs3.existsSync(path3.join(cwd, "bun.lockb"))) {
980
+ if (fs4.existsSync(path4.join(cwd, "bun.lock")) || fs4.existsSync(path4.join(cwd, "bun.lockb"))) {
790
981
  return "bun";
791
982
  }
792
- if (fs3.existsSync(path3.join(cwd, "pnpm-lock.yaml"))) {
983
+ if (fs4.existsSync(path4.join(cwd, "pnpm-lock.yaml"))) {
793
984
  return "pnpm";
794
985
  }
795
- if (fs3.existsSync(path3.join(cwd, "yarn.lock")) || fs3.existsSync(path3.join(cwd, ".pnp.cjs")) || fs3.existsSync(path3.join(cwd, ".pnp.loader.mjs")) || fs3.existsSync(path3.join(cwd, ".yarnrc.yml"))) {
986
+ if (fs4.existsSync(path4.join(cwd, "yarn.lock")) || fs4.existsSync(path4.join(cwd, ".pnp.cjs")) || fs4.existsSync(path4.join(cwd, ".pnp.loader.mjs")) || fs4.existsSync(path4.join(cwd, ".yarnrc.yml"))) {
796
987
  return "yarn";
797
988
  }
798
- if (fs3.existsSync(path3.join(cwd, "package-lock.json")) || fs3.existsSync(path3.join(cwd, "npm-shrinkwrap.json"))) {
989
+ if (fs4.existsSync(path4.join(cwd, "package-lock.json")) || fs4.existsSync(path4.join(cwd, "npm-shrinkwrap.json"))) {
799
990
  return "npm";
800
991
  }
801
992
  return "npm";
802
993
  }
803
994
  function resolveSyncProjectContext(cwd) {
804
- const packageJsonPath = path3.join(cwd, "package.json");
805
- if (!fs3.existsSync(packageJsonPath)) {
995
+ const packageJsonPath = path4.join(cwd, "package.json");
996
+ if (!fs4.existsSync(packageJsonPath)) {
806
997
  throw getSyncRootError(cwd);
807
998
  }
808
- const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
999
+ const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf8"));
809
1000
  const scripts = packageJson.scripts ?? {};
810
1001
  const syncScripts = {
811
1002
  sync: typeof scripts.sync === "string" ? scripts.sync : undefined,
@@ -823,12 +1014,12 @@ function resolveSyncProjectContext(cwd) {
823
1014
  };
824
1015
  }
825
1016
  function findInstalledDependencyMarkerDir(projectDir) {
826
- let currentDir = path3.resolve(projectDir);
1017
+ let currentDir = path4.resolve(projectDir);
827
1018
  while (true) {
828
- if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path3.join(currentDir, marker)))) {
1019
+ if (SYNC_INSTALL_MARKERS.some((marker) => fs4.existsSync(path4.join(currentDir, marker)))) {
829
1020
  return currentDir;
830
1021
  }
831
- const parentDir = path3.dirname(currentDir);
1022
+ const parentDir = path4.dirname(currentDir);
832
1023
  if (parentDir === currentDir) {
833
1024
  return null;
834
1025
  }
@@ -950,6 +1141,29 @@ function pushFlag(argv, name, value) {
950
1141
  }
951
1142
  argv.push(`--${name}`, String(value));
952
1143
  }
1144
+ async function executeWorkspaceAddWithOptionalDryRun(options) {
1145
+ const simulated = options.dryRun ? await simulateWorkspaceAddDryRun({
1146
+ cwd: options.cwd,
1147
+ execute: options.execute
1148
+ }) : null;
1149
+ const result = simulated?.result ?? await options.execute(options.cwd);
1150
+ const completion = options.buildCompletion(result);
1151
+ if (!options.dryRun) {
1152
+ return emitCompletion(completion, {
1153
+ emitOutput: options.emitOutput ?? true,
1154
+ printLine: options.printLine,
1155
+ warnLine: options.warnLine
1156
+ });
1157
+ }
1158
+ return emitCompletion(buildAddDryRunPayload({
1159
+ completion,
1160
+ fileOperations: simulated.fileOperations
1161
+ }), {
1162
+ emitOutput: options.emitOutput ?? true,
1163
+ printLine: options.printLine,
1164
+ warnLine: options.warnLine
1165
+ });
1166
+ }
953
1167
  var PACKAGE_MANAGER_PROMPT_OPTIONS = [
954
1168
  { label: "npm", value: "npm", hint: "Use npm" },
955
1169
  { label: "pnpm", value: "pnpm", hint: "Use pnpm" },
@@ -997,7 +1211,7 @@ async function executeCreateCommand({
997
1211
  loadCliScaffoldRuntime(),
998
1212
  loadCliTemplatesRuntime()
999
1213
  ]);
1000
- const shouldPrompt = interactive ?? (!Boolean(flags.yes) && Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY));
1214
+ const shouldPrompt = interactive ?? (!Boolean(flags.yes) && isInteractiveTerminal());
1001
1215
  const activePrompt = shouldPrompt ? prompt ?? createReadlinePrompt() : undefined;
1002
1216
  const shouldPromptForExternalLayerSelection = Boolean(activePrompt) && activePrompt !== prompt;
1003
1217
  const effectiveYes = Boolean(flags.yes) || Boolean(flags["dry-run"]) && !Boolean(activePrompt);
@@ -1074,15 +1288,14 @@ async function executeAddCommand({
1074
1288
  prompt,
1075
1289
  warnLine = console.warn
1076
1290
  }) {
1077
- if (!kind) {
1078
- const { formatAddHelpText } = await loadCliAddRuntime();
1079
- printLine(formatAddHelpText());
1080
- return;
1081
- }
1082
- const addRuntime = await loadCliAddRuntime();
1083
1291
  let activePrompt;
1084
1292
  const dryRun = Boolean(flags["dry-run"]);
1085
1293
  try {
1294
+ const addRuntime = await loadCliAddRuntime();
1295
+ if (!kind) {
1296
+ printLine(addRuntime.formatAddHelpText());
1297
+ throw new Error("`wp-typia add` requires <kind>. Usage: wp-typia add <block|variation|pattern|binding-source|rest-resource|editor-plugin|hooked-block> ...");
1298
+ }
1086
1299
  if (kind === "variation") {
1087
1300
  if (!name) {
1088
1301
  throw new Error("`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
@@ -1091,94 +1304,69 @@ async function executeAddCommand({
1091
1304
  if (!blockSlug) {
1092
1305
  throw new Error("`wp-typia add variation` requires --block <block-slug>.");
1093
1306
  }
1094
- const simulated2 = dryRun ? await simulateWorkspaceAddDryRun({
1307
+ return executeWorkspaceAddWithOptionalDryRun({
1308
+ buildCompletion: (result) => buildAddCompletionPayload({
1309
+ kind: "variation",
1310
+ projectDir: result.projectDir,
1311
+ values: {
1312
+ blockSlug: result.blockSlug,
1313
+ variationSlug: result.variationSlug
1314
+ }
1315
+ }),
1095
1316
  cwd,
1096
- execute: (simulatedCwd) => addRuntime.runAddVariationCommand({
1317
+ dryRun,
1318
+ emitOutput,
1319
+ execute: (targetCwd) => addRuntime.runAddVariationCommand({
1097
1320
  blockName: blockSlug,
1098
- cwd: simulatedCwd,
1321
+ cwd: targetCwd,
1099
1322
  variationName: name
1100
- })
1101
- }) : null;
1102
- const result2 = simulated2?.result ?? await addRuntime.runAddVariationCommand({
1103
- blockName: blockSlug,
1104
- cwd,
1105
- variationName: name
1106
- });
1107
- const completion2 = buildAddCompletionPayload({
1108
- kind: "variation",
1109
- projectDir: result2.projectDir,
1110
- values: {
1111
- blockSlug: result2.blockSlug,
1112
- variationSlug: result2.variationSlug
1113
- }
1323
+ }),
1324
+ printLine
1114
1325
  });
1115
- if (!dryRun) {
1116
- return emitCompletion(completion2, { emitOutput, printLine });
1117
- }
1118
- return emitCompletion(buildAddDryRunPayload({
1119
- completion: completion2,
1120
- fileOperations: simulated2.fileOperations
1121
- }), { emitOutput, printLine });
1122
1326
  }
1123
1327
  if (kind === "pattern") {
1124
1328
  if (!name) {
1125
1329
  throw new Error("`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.");
1126
1330
  }
1127
- const simulated2 = dryRun ? await simulateWorkspaceAddDryRun({
1331
+ return executeWorkspaceAddWithOptionalDryRun({
1332
+ buildCompletion: (result) => buildAddCompletionPayload({
1333
+ kind: "pattern",
1334
+ projectDir: result.projectDir,
1335
+ values: {
1336
+ patternSlug: result.patternSlug
1337
+ }
1338
+ }),
1128
1339
  cwd,
1129
- execute: (simulatedCwd) => addRuntime.runAddPatternCommand({
1130
- cwd: simulatedCwd,
1340
+ dryRun,
1341
+ emitOutput,
1342
+ execute: (targetCwd) => addRuntime.runAddPatternCommand({
1343
+ cwd: targetCwd,
1131
1344
  patternName: name
1132
- })
1133
- }) : null;
1134
- const result2 = simulated2?.result ?? await addRuntime.runAddPatternCommand({
1135
- cwd,
1136
- patternName: name
1137
- });
1138
- const completion2 = buildAddCompletionPayload({
1139
- kind: "pattern",
1140
- projectDir: result2.projectDir,
1141
- values: {
1142
- patternSlug: result2.patternSlug
1143
- }
1345
+ }),
1346
+ printLine
1144
1347
  });
1145
- if (!dryRun) {
1146
- return emitCompletion(completion2, { emitOutput, printLine });
1147
- }
1148
- return emitCompletion(buildAddDryRunPayload({
1149
- completion: completion2,
1150
- fileOperations: simulated2.fileOperations
1151
- }), { emitOutput, printLine });
1152
1348
  }
1153
1349
  if (kind === "binding-source") {
1154
1350
  if (!name) {
1155
1351
  throw new Error("`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name>.");
1156
1352
  }
1157
- const simulated2 = dryRun ? await simulateWorkspaceAddDryRun({
1353
+ return executeWorkspaceAddWithOptionalDryRun({
1354
+ buildCompletion: (result) => buildAddCompletionPayload({
1355
+ kind: "binding-source",
1356
+ projectDir: result.projectDir,
1357
+ values: {
1358
+ bindingSourceSlug: result.bindingSourceSlug
1359
+ }
1360
+ }),
1158
1361
  cwd,
1159
- execute: (simulatedCwd) => addRuntime.runAddBindingSourceCommand({
1362
+ dryRun,
1363
+ emitOutput,
1364
+ execute: (targetCwd) => addRuntime.runAddBindingSourceCommand({
1160
1365
  bindingSourceName: name,
1161
- cwd: simulatedCwd
1162
- })
1163
- }) : null;
1164
- const result2 = simulated2?.result ?? await addRuntime.runAddBindingSourceCommand({
1165
- bindingSourceName: name,
1166
- cwd
1167
- });
1168
- const completion2 = buildAddCompletionPayload({
1169
- kind: "binding-source",
1170
- projectDir: result2.projectDir,
1171
- values: {
1172
- bindingSourceSlug: result2.bindingSourceSlug
1173
- }
1366
+ cwd: targetCwd
1367
+ }),
1368
+ printLine
1174
1369
  });
1175
- if (!dryRun) {
1176
- return emitCompletion(completion2, { emitOutput, printLine });
1177
- }
1178
- return emitCompletion(buildAddDryRunPayload({
1179
- completion: completion2,
1180
- fileOperations: simulated2.fileOperations
1181
- }), { emitOutput, printLine });
1182
1370
  }
1183
1371
  if (kind === "rest-resource") {
1184
1372
  if (!name) {
@@ -1186,71 +1374,52 @@ async function executeAddCommand({
1186
1374
  }
1187
1375
  const methods = readOptionalStringFlag(flags, "methods");
1188
1376
  const namespace = readOptionalStringFlag(flags, "namespace");
1189
- const simulated2 = dryRun ? await simulateWorkspaceAddDryRun({
1377
+ return executeWorkspaceAddWithOptionalDryRun({
1378
+ buildCompletion: (result) => buildAddCompletionPayload({
1379
+ kind: "rest-resource",
1380
+ projectDir: result.projectDir,
1381
+ values: {
1382
+ methods: result.methods.join(", "),
1383
+ namespace: result.namespace,
1384
+ restResourceSlug: result.restResourceSlug
1385
+ }
1386
+ }),
1190
1387
  cwd,
1191
- execute: (simulatedCwd) => addRuntime.runAddRestResourceCommand({
1192
- cwd: simulatedCwd,
1388
+ dryRun,
1389
+ emitOutput,
1390
+ execute: (targetCwd) => addRuntime.runAddRestResourceCommand({
1391
+ cwd: targetCwd,
1193
1392
  methods,
1194
1393
  namespace,
1195
1394
  restResourceName: name
1196
- })
1197
- }) : null;
1198
- const result2 = simulated2?.result ?? await addRuntime.runAddRestResourceCommand({
1199
- cwd,
1200
- methods,
1201
- namespace,
1202
- restResourceName: name
1395
+ }),
1396
+ printLine
1203
1397
  });
1204
- const completion2 = buildAddCompletionPayload({
1205
- kind: "rest-resource",
1206
- projectDir: result2.projectDir,
1207
- values: {
1208
- methods: result2.methods.join(", "),
1209
- namespace: result2.namespace,
1210
- restResourceSlug: result2.restResourceSlug
1211
- }
1212
- });
1213
- if (!dryRun) {
1214
- return emitCompletion(completion2, { emitOutput, printLine });
1215
- }
1216
- return emitCompletion(buildAddDryRunPayload({
1217
- completion: completion2,
1218
- fileOperations: simulated2.fileOperations
1219
- }), { emitOutput, printLine });
1220
1398
  }
1221
1399
  if (kind === "editor-plugin") {
1222
1400
  if (!name) {
1223
1401
  throw new Error("`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <PluginSidebar>].");
1224
1402
  }
1225
1403
  const slot = readOptionalStringFlag(flags, "slot");
1226
- const simulated2 = dryRun ? await simulateWorkspaceAddDryRun({
1404
+ return executeWorkspaceAddWithOptionalDryRun({
1405
+ buildCompletion: (result) => buildAddCompletionPayload({
1406
+ kind: "editor-plugin",
1407
+ projectDir: result.projectDir,
1408
+ values: {
1409
+ editorPluginSlug: result.editorPluginSlug,
1410
+ slot: result.slot
1411
+ }
1412
+ }),
1227
1413
  cwd,
1228
- execute: (simulatedCwd) => addRuntime.runAddEditorPluginCommand({
1229
- cwd: simulatedCwd,
1414
+ dryRun,
1415
+ emitOutput,
1416
+ execute: (targetCwd) => addRuntime.runAddEditorPluginCommand({
1417
+ cwd: targetCwd,
1230
1418
  editorPluginName: name,
1231
1419
  slot
1232
- })
1233
- }) : null;
1234
- const result2 = simulated2?.result ?? await addRuntime.runAddEditorPluginCommand({
1235
- cwd,
1236
- editorPluginName: name,
1237
- slot
1420
+ }),
1421
+ printLine
1238
1422
  });
1239
- const completion2 = buildAddCompletionPayload({
1240
- kind: "editor-plugin",
1241
- projectDir: result2.projectDir,
1242
- values: {
1243
- editorPluginSlug: result2.editorPluginSlug,
1244
- slot: result2.slot
1245
- }
1246
- });
1247
- if (!dryRun) {
1248
- return emitCompletion(completion2, { emitOutput, printLine });
1249
- }
1250
- return emitCompletion(buildAddDryRunPayload({
1251
- completion: completion2,
1252
- fileOperations: simulated2.fileOperations
1253
- }), { emitOutput, printLine });
1254
1423
  }
1255
1424
  if (kind === "hooked-block") {
1256
1425
  if (!name) {
@@ -1264,37 +1433,27 @@ async function executeAddCommand({
1264
1433
  if (!position) {
1265
1434
  throw new Error("`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
1266
1435
  }
1267
- const simulated2 = dryRun ? await simulateWorkspaceAddDryRun({
1436
+ return executeWorkspaceAddWithOptionalDryRun({
1437
+ buildCompletion: (result) => buildAddCompletionPayload({
1438
+ kind: "hooked-block",
1439
+ projectDir: result.projectDir,
1440
+ values: {
1441
+ anchorBlockName: result.anchorBlockName,
1442
+ blockSlug: result.blockSlug,
1443
+ position: result.position
1444
+ }
1445
+ }),
1268
1446
  cwd,
1269
- execute: (simulatedCwd) => addRuntime.runAddHookedBlockCommand({
1447
+ dryRun,
1448
+ emitOutput,
1449
+ execute: (targetCwd) => addRuntime.runAddHookedBlockCommand({
1270
1450
  anchorBlockName,
1271
1451
  blockName: name,
1272
- cwd: simulatedCwd,
1452
+ cwd: targetCwd,
1273
1453
  position
1274
- })
1275
- }) : null;
1276
- const result2 = simulated2?.result ?? await addRuntime.runAddHookedBlockCommand({
1277
- anchorBlockName,
1278
- blockName: name,
1279
- cwd,
1280
- position
1454
+ }),
1455
+ printLine
1281
1456
  });
1282
- const completion2 = buildAddCompletionPayload({
1283
- kind: "hooked-block",
1284
- projectDir: result2.projectDir,
1285
- values: {
1286
- anchorBlockName: result2.anchorBlockName,
1287
- blockSlug: result2.blockSlug,
1288
- position: result2.position
1289
- }
1290
- });
1291
- if (!dryRun) {
1292
- return emitCompletion(completion2, { emitOutput, printLine });
1293
- }
1294
- return emitCompletion(buildAddDryRunPayload({
1295
- completion: completion2,
1296
- fileOperations: simulated2.fileOperations
1297
- }), { emitOutput, printLine });
1298
1457
  }
1299
1458
  if (kind !== "block") {
1300
1459
  throw new Error(`Unknown add kind "${kind}". Expected one of: block, variation, pattern, binding-source, rest-resource, editor-plugin, hooked-block.`);
@@ -1307,7 +1466,7 @@ async function executeAddCommand({
1307
1466
  }
1308
1467
  const externalLayerId = readOptionalStringFlag(flags, "external-layer-id");
1309
1468
  const externalLayerSource = readOptionalStringFlag(flags, "external-layer-source");
1310
- const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && (interactive ?? (Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY)));
1469
+ const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && (interactive ?? isInteractiveTerminal());
1311
1470
  const promptRuntime = shouldPromptForLayerSelection ? await loadCliPromptRuntime() : undefined;
1312
1471
  activePrompt = shouldPromptForLayerSelection ? prompt ?? promptRuntime?.createReadlinePrompt() : undefined;
1313
1472
  const selectPrompt = activePrompt;
@@ -1316,12 +1475,23 @@ async function executeAddCommand({
1316
1475
  const innerBlocksPreset = readOptionalStringFlag(flags, "inner-blocks-preset");
1317
1476
  const persistencePolicy = readOptionalStringFlag(flags, "persistence-policy");
1318
1477
  const resolvedTemplateId = readOptionalStringFlag(flags, "template");
1319
- const simulated = dryRun ? await simulateWorkspaceAddDryRun({
1478
+ return executeWorkspaceAddWithOptionalDryRun({
1479
+ buildCompletion: (result) => buildAddCompletionPayload({
1480
+ kind: "block",
1481
+ projectDir: result.projectDir,
1482
+ values: {
1483
+ blockSlugs: result.blockSlugs.join(", "),
1484
+ templateId: result.templateId
1485
+ },
1486
+ warnings: result.warnings
1487
+ }),
1320
1488
  cwd,
1321
- execute: (simulatedCwd) => addRuntime.runAddBlockCommand({
1489
+ dryRun,
1490
+ emitOutput,
1491
+ execute: (targetCwd) => addRuntime.runAddBlockCommand({
1322
1492
  alternateRenderTargets,
1323
1493
  blockName: name,
1324
- cwd: simulatedCwd,
1494
+ cwd: targetCwd,
1325
1495
  dataStorageMode,
1326
1496
  externalLayerId,
1327
1497
  externalLayerSource,
@@ -1329,36 +1499,10 @@ async function executeAddCommand({
1329
1499
  persistencePolicy,
1330
1500
  selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
1331
1501
  templateId: resolvedTemplateId
1332
- })
1333
- }) : null;
1334
- const result = simulated?.result ?? await addRuntime.runAddBlockCommand({
1335
- alternateRenderTargets,
1336
- blockName: name,
1337
- cwd,
1338
- dataStorageMode,
1339
- externalLayerId,
1340
- externalLayerSource,
1341
- innerBlocksPreset,
1342
- persistencePolicy,
1343
- selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
1344
- templateId: resolvedTemplateId
1345
- });
1346
- const completion = buildAddCompletionPayload({
1347
- kind: "block",
1348
- projectDir: result.projectDir,
1349
- values: {
1350
- blockSlugs: result.blockSlugs.join(", "),
1351
- templateId: result.templateId
1352
- },
1353
- warnings: result.warnings
1502
+ }),
1503
+ printLine,
1504
+ warnLine
1354
1505
  });
1355
- if (!dryRun) {
1356
- return emitCompletion(completion, { emitOutput, printLine, warnLine });
1357
- }
1358
- return emitCompletion(buildAddDryRunPayload({
1359
- completion,
1360
- fileOperations: simulated.fileOperations
1361
- }), { emitOutput, printLine, warnLine });
1362
1506
  } catch (error) {
1363
1507
  if (!shouldWrapCliCommandError({ emitOutput })) {
1364
1508
  throw error;
@@ -1464,7 +1608,7 @@ async function executeMigrateCommand({
1464
1608
  }
1465
1609
 
1466
1610
  // src/command-contract.ts
1467
- import path4 from "node:path";
1611
+ import path5 from "node:path";
1468
1612
  var WP_TYPIA_CANONICAL_CREATE_USAGE = "wp-typia create <project-dir>";
1469
1613
  var WP_TYPIA_POSITIONAL_ALIAS_USAGE = "wp-typia <project-dir>";
1470
1614
  var WP_TYPIA_CANONICAL_MIGRATE_USAGE = "wp-typia migrate <subcommand>";
@@ -1482,6 +1626,7 @@ var WP_TYPIA_RESERVED_TOP_LEVEL_COMMAND_NAMES = [
1482
1626
  "completions",
1483
1627
  "complete"
1484
1628
  ];
1629
+ var SHARED_OPTION_PARSER = buildCommandOptionParser(ADD_OPTION_METADATA, GLOBAL_OPTION_METADATA, CREATE_OPTION_METADATA, MIGRATE_OPTION_METADATA, TEMPLATES_OPTION_METADATA);
1485
1630
  var STRING_OPTION_NAMES_BY_COMMAND = {
1486
1631
  add: new Set(collectOptionNamesByType(ADD_OPTION_METADATA, "string")),
1487
1632
  create: new Set(collectOptionNamesByType(CREATE_OPTION_METADATA, "string")),
@@ -1489,13 +1634,7 @@ var STRING_OPTION_NAMES_BY_COMMAND = {
1489
1634
  templates: new Set(collectOptionNamesByType(TEMPLATES_OPTION_METADATA, "string"))
1490
1635
  };
1491
1636
  var GLOBAL_STRING_OPTION_NAMES = new Set(collectOptionNamesByType(GLOBAL_OPTION_METADATA, "string"));
1492
- var SHORT_OPTION_NAMES_WITH_VALUES = new Set(Object.values({
1493
- ...ADD_OPTION_METADATA,
1494
- ...GLOBAL_OPTION_METADATA,
1495
- ...CREATE_OPTION_METADATA,
1496
- ...MIGRATE_OPTION_METADATA,
1497
- ...TEMPLATES_OPTION_METADATA
1498
- }).filter((option) => option.type === "string").flatMap((option) => ("short" in option) && typeof option.short === "string" ? [option.short] : []));
1637
+ var SHORT_OPTION_NAMES_WITH_VALUES = new Set([...SHARED_OPTION_PARSER.shortFlagMap.entries()].filter(([, option]) => option.type === "string").map(([short]) => short));
1499
1638
  function isLongOptionValueConsumer(optionName) {
1500
1639
  if (GLOBAL_STRING_OPTION_NAMES.has(optionName)) {
1501
1640
  return true;
@@ -1649,7 +1788,7 @@ function looksLikeStructuredProjectInput(value) {
1649
1788
  return value.startsWith("@") && value.includes("/");
1650
1789
  }
1651
1790
  function assertPositionalAliasProjectDir(projectDir) {
1652
- const normalizedProjectDir = path4.normalize(projectDir).replace(/[\\/]+$/u, "") || path4.normalize(projectDir);
1791
+ const normalizedProjectDir = path5.normalize(projectDir).replace(/[\\/]+$/u, "") || path5.normalize(projectDir);
1653
1792
  if (normalizedProjectDir === "." || normalizedProjectDir === "..") {
1654
1793
  throw new Error(`The positional alias does not scaffold into \`${projectDir}\`. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` with an explicit child directory instead.`);
1655
1794
  }
@@ -1689,28 +1828,8 @@ function normalizeWpTypiaArgv(argv) {
1689
1828
  }
1690
1829
 
1691
1830
  // src/node-cli.ts
1692
- var STRING_FLAG_NAMES = new Set([
1693
- ...collectOptionNamesByType(GLOBAL_OPTION_METADATA, "string"),
1694
- ...collectOptionNamesByType(CREATE_OPTION_METADATA, "string"),
1695
- ...collectOptionNamesByType(ADD_OPTION_METADATA, "string"),
1696
- ...collectOptionNamesByType(MIGRATE_OPTION_METADATA, "string"),
1697
- ...collectOptionNamesByType(TEMPLATES_OPTION_METADATA, "string")
1698
- ]);
1699
- var BOOLEAN_FLAG_NAMES = new Set([
1700
- ...collectOptionNamesByType(CREATE_OPTION_METADATA, "boolean"),
1701
- ...collectOptionNamesByType(ADD_OPTION_METADATA, "boolean"),
1702
- ...collectOptionNamesByType(MIGRATE_OPTION_METADATA, "boolean"),
1703
- "check",
1704
- "help",
1705
- "version"
1706
- ]);
1707
- var SHORT_FLAG_MAP = new Map(Object.entries({
1708
- ...GLOBAL_OPTION_METADATA,
1709
- ...CREATE_OPTION_METADATA,
1710
- ...ADD_OPTION_METADATA,
1711
- ...MIGRATE_OPTION_METADATA,
1712
- ...TEMPLATES_OPTION_METADATA
1713
- }).flatMap(([name, option]) => ("short" in option) && typeof option.short === "string" ? [[option.short, { name, type: option.type }]] : []));
1831
+ var NODE_FALLBACK_OPTION_PARSER = buildCommandOptionParser(GLOBAL_OPTION_METADATA, CREATE_OPTION_METADATA, ADD_OPTION_METADATA, MIGRATE_OPTION_METADATA, TEMPLATES_OPTION_METADATA);
1832
+ var NODE_FALLBACK_BOOLEAN_OPTION_NAMES = ["check", "help", "version"];
1714
1833
  var NODE_FALLBACK_RUNTIME_SUMMARY_LINES = [
1715
1834
  "Runtime: Node fallback",
1716
1835
  "Human-readable fallback for common non-interactive create/add/migrate flows, doctor, sync, templates, --help, and --version when Bun is unavailable.",
@@ -1782,84 +1901,24 @@ async function applyNodeFallbackConfigDefaults(command, subcommand, flags, confi
1782
1901
  config = mergeWpTypiaUserConfig(config, overrideConfig);
1783
1902
  }
1784
1903
  if (command === "create") {
1785
- return {
1786
- ...getCreateDefaults(config),
1787
- ...flags
1788
- };
1904
+ return resolveCommandOptionValues(CREATE_OPTION_METADATA, {
1905
+ defaults: getCreateDefaults(config),
1906
+ flags
1907
+ });
1789
1908
  }
1790
1909
  if (command === "add" && subcommand === "block") {
1791
- return {
1792
- ...getAddBlockDefaults(config),
1793
- ...flags
1794
- };
1910
+ return resolveCommandOptionValues(ADD_OPTION_METADATA, {
1911
+ defaults: getAddBlockDefaults(config),
1912
+ flags
1913
+ });
1795
1914
  }
1796
1915
  return flags;
1797
1916
  }
1798
1917
  function parseArgv(argv) {
1799
- const flags = {};
1800
- const positionals = [];
1801
- for (let index = 0;index < argv.length; index += 1) {
1802
- const arg = argv[index];
1803
- if (!arg) {
1804
- continue;
1805
- }
1806
- if (arg === "--") {
1807
- positionals.push(...argv.slice(index + 1));
1808
- break;
1809
- }
1810
- if (arg.length === 2 && arg.startsWith("-")) {
1811
- const shortFlag = SHORT_FLAG_MAP.get(arg.slice(1));
1812
- if (!shortFlag) {
1813
- throw new Error(`Unknown option \`${arg}\`.`);
1814
- }
1815
- if (shortFlag.type === "boolean") {
1816
- flags[shortFlag.name] = true;
1817
- continue;
1818
- }
1819
- const next = argv[index + 1];
1820
- if (!next || next.startsWith("-")) {
1821
- throw new Error(`\`${arg}\` requires a value.`);
1822
- }
1823
- flags[shortFlag.name] = next;
1824
- index += 1;
1825
- continue;
1826
- }
1827
- if (arg.startsWith("--")) {
1828
- const option = arg.slice(2);
1829
- const separatorIndex = option.indexOf("=");
1830
- const rawName = separatorIndex === -1 ? option : option.slice(0, separatorIndex);
1831
- const inlineValue = separatorIndex === -1 ? undefined : option.slice(separatorIndex + 1);
1832
- if (BOOLEAN_FLAG_NAMES.has(rawName)) {
1833
- flags[rawName] = true;
1834
- continue;
1835
- }
1836
- if (!STRING_FLAG_NAMES.has(rawName)) {
1837
- throw new Error(`Unknown option \`--${rawName}\`.`);
1838
- }
1839
- if (inlineValue !== undefined) {
1840
- if (!inlineValue) {
1841
- throw new Error(`\`--${rawName}\` requires a value.`);
1842
- }
1843
- flags[rawName] = inlineValue;
1844
- continue;
1845
- }
1846
- const next = argv[index + 1];
1847
- if (!next || next.startsWith("-")) {
1848
- throw new Error(`\`--${rawName}\` requires a value.`);
1849
- }
1850
- flags[rawName] = next;
1851
- index += 1;
1852
- continue;
1853
- }
1854
- if (arg.startsWith("-")) {
1855
- throw new Error(`Unknown option \`${arg}\`.`);
1856
- }
1857
- positionals.push(arg);
1858
- }
1859
- return {
1860
- flags,
1861
- positionals
1862
- };
1918
+ return parseCommandArgvWithMetadata(argv, {
1919
+ extraBooleanOptionNames: NODE_FALLBACK_BOOLEAN_OPTION_NAMES,
1920
+ parser: NODE_FALLBACK_OPTION_PARSER
1921
+ });
1863
1922
  }
1864
1923
  function renderGeneralHelp() {
1865
1924
  printBlock2([
@@ -1941,22 +2000,37 @@ function renderTemplatesJson(flags, subcommand) {
1941
2000
  }
1942
2001
  const templateId = flags.id;
1943
2002
  if (!templateId) {
1944
- throw new Error("`wp-typia templates inspect` requires <template-id>.");
2003
+ throw createCliCommandError({
2004
+ code: CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT,
2005
+ command: "templates",
2006
+ detailLines: ["`wp-typia templates inspect` requires <template-id>."]
2007
+ });
1945
2008
  }
1946
2009
  const template = getTemplateById(templateId);
1947
2010
  if (!template) {
1948
- throw new Error(`Unknown template "${templateId}".`);
2011
+ throw createCliCommandError({
2012
+ code: CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT,
2013
+ command: "templates",
2014
+ detailLines: [`Unknown template "${templateId}".`]
2015
+ });
1949
2016
  }
1950
2017
  printLine(JSON.stringify({
1951
2018
  template
1952
2019
  }, null, 2));
1953
2020
  }
1954
2021
  function renderUnsupportedCommand(command) {
1955
- throw new Error([
1956
- `The Bun-free fallback runtime does not support \`${command}\` yet.`,
1957
- "Supported without Bun: `--version`, `--help`, non-interactive `create`/`add`/`migrate`, `doctor`, `sync`, `templates list`, and `templates inspect`.",
1958
- "Install Bun 1.3.11+ or use `bunx wp-typia ...` for the full Bunli-powered runtime."
1959
- ].join(" "));
2022
+ throw createCliCommandError({
2023
+ code: CLI_DIAGNOSTIC_CODES.UNSUPPORTED_COMMAND,
2024
+ command,
2025
+ detailLines: [
2026
+ [
2027
+ `The Bun-free fallback runtime does not support \`${command}\` yet.`,
2028
+ "Supported without Bun: `--version`, `--help`, non-interactive `create`/`add`/`migrate`, `doctor`, `sync`, `templates list`, and `templates inspect`.",
2029
+ "Install Bun 1.3.11+ or use `bunx wp-typia ...` for the full Bunli-powered runtime."
2030
+ ].join(" ")
2031
+ ],
2032
+ summary: "This command requires the Bun-powered runtime."
2033
+ });
1960
2034
  }
1961
2035
  async function renderDoctorJson() {
1962
2036
  const [{ getDoctorChecks }, { createCliCommandError: createCliCommandError2, getDoctorFailureDetailLines }] = await Promise.all([
@@ -2043,7 +2117,10 @@ async function runNodeCli(argv = process.argv.slice(2)) {
2043
2117
  if (!projectDir) {
2044
2118
  throw createCliCommandError({
2045
2119
  command: "create",
2046
- detailLines: ["`wp-typia create` requires <project-dir>."]
2120
+ detailLines: [
2121
+ "`wp-typia create` requires <project-dir>.",
2122
+ "`--dry-run` still needs a logical project directory name because wp-typia derives slugs, package names, and planned file paths from it."
2123
+ ]
2047
2124
  });
2048
2125
  }
2049
2126
  await executeCreateCommand({
@@ -2055,6 +2132,16 @@ async function runNodeCli(argv = process.argv.slice(2)) {
2055
2132
  return;
2056
2133
  }
2057
2134
  if (command === "add") {
2135
+ if (!positionals[1]) {
2136
+ const { formatAddHelpText } = await import("@wp-typia/project-tools/cli-add");
2137
+ printLine(formatAddHelpText());
2138
+ throw createCliCommandError({
2139
+ command: "add",
2140
+ detailLines: [
2141
+ "`wp-typia add` requires <kind>. Usage: wp-typia add <block|variation|pattern|binding-source|rest-resource|editor-plugin|hooked-block> ..."
2142
+ ]
2143
+ });
2144
+ }
2058
2145
  await executeAddCommand({
2059
2146
  cwd: process.cwd(),
2060
2147
  flags: mergedFlags,
@@ -2081,10 +2168,17 @@ async function runNodeCli(argv = process.argv.slice(2)) {
2081
2168
  return;
2082
2169
  }
2083
2170
  if (command === "sync") {
2084
- await executeSyncCommand({
2085
- check: Boolean(mergedFlags.check),
2086
- cwd: process.cwd()
2087
- });
2171
+ try {
2172
+ await executeSyncCommand({
2173
+ check: Boolean(mergedFlags.check),
2174
+ cwd: process.cwd()
2175
+ });
2176
+ } catch (error) {
2177
+ throw createCliCommandError({
2178
+ command: "sync",
2179
+ error
2180
+ });
2181
+ }
2088
2182
  return;
2089
2183
  }
2090
2184
  renderUnsupportedCommand(command ?? "(missing)");
@@ -2093,8 +2187,23 @@ async function runNodeCliEntrypoint(argv = process.argv.slice(2)) {
2093
2187
  try {
2094
2188
  await runNodeCli(argv);
2095
2189
  } catch (error) {
2190
+ let prefersStructuredErrorOutput = false;
2191
+ try {
2192
+ const normalizedArgv = normalizeWpTypiaArgv(argv);
2193
+ const { argv: argvWithoutConfigOverride } = extractWpTypiaConfigOverride(normalizedArgv);
2194
+ const { flags } = parseGlobalFlags(argvWithoutConfigOverride);
2195
+ prefersStructuredErrorOutput = flags.format === "json";
2196
+ } catch {}
2197
+ if (prefersStructuredErrorOutput) {
2198
+ console.error(JSON.stringify({
2199
+ ok: false,
2200
+ error: serializeCliDiagnosticError(error)
2201
+ }, null, 2));
2202
+ process.exitCode = 1;
2203
+ return;
2204
+ }
2096
2205
  console.error(`Error: ${await formatCliDiagnosticError(error)}`);
2097
- process.exit(1);
2206
+ process.exitCode = 1;
2098
2207
  }
2099
2208
  }
2100
2209
  export {
@@ -2104,4 +2213,4 @@ export {
2104
2213
  hasFlagBeforeTerminator
2105
2214
  };
2106
2215
 
2107
- //# debugId=7B916CF74AF5C70064756E2164756E21
2216
+ //# debugId=F7CDE5FD3282D0B964756E2164756E21