wp-typia 0.22.9 → 0.23.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.
@@ -11,13 +11,15 @@ import {
11
11
  WP_TYPIA_TOP_LEVEL_COMMAND_NAMES,
12
12
  buildCommandOptions,
13
13
  emitCliDiagnosticFailure,
14
+ formatAddKindList,
15
+ formatAddKindUsagePlaceholder,
14
16
  getAddBlockDefaults,
15
17
  getCreateDefaults,
16
18
  getMcpSchemaSources,
17
19
  package_default,
18
20
  prefersStructuredCliOutput,
19
21
  resolveCommandOptionValues
20
- } from "./cli-y934dq2k.js";
22
+ } from "./cli-z5qkx2pn.js";
21
23
  import {
22
24
  Result,
23
25
  TaggedError,
@@ -36,7 +38,7 @@ import {
36
38
  } from "./cli-t73q5aqz.js";
37
39
  import {
38
40
  ADD_KIND_IDS
39
- } from "./cli-fys8vm2t.js";
41
+ } from "./cli-43mx1vfb.js";
40
42
  import {
41
43
  CLI_DIAGNOSTIC_CODES,
42
44
  createCliDiagnosticCodeError
@@ -57,6 +59,26 @@ import {
57
59
  // src/commands/add.ts
58
60
  var import_react34 = __toESM(require_react(), 1);
59
61
 
62
+ // src/commands/output-adapters.ts
63
+ var defaultPrintLine = (line) => {
64
+ process.stdout.write(`${line}
65
+ `);
66
+ };
67
+ var defaultWarnLine = (line) => {
68
+ process.stderr.write(`${line}
69
+ `);
70
+ };
71
+ function resolveCommandPrintLine(args) {
72
+ return args.printLine ?? defaultPrintLine;
73
+ }
74
+ function resolveCommandOutputAdapters(args) {
75
+ const adapters = args;
76
+ return {
77
+ printLine: adapters.printLine ?? defaultPrintLine,
78
+ warnLine: adapters.warnLine ?? defaultWarnLine
79
+ };
80
+ }
81
+
60
82
  // src/render-loader.ts
61
83
  import fs from "fs";
62
84
  import { fileURLToPath } from "url";
@@ -97,6 +119,11 @@ var NAME_SOURCE_VISIBLE_FIELDS = [
97
119
  "name",
98
120
  "source"
99
121
  ];
122
+ var NAME_TYPE_VISIBLE_FIELDS = [
123
+ "kind",
124
+ "name",
125
+ "type"
126
+ ];
100
127
  var NAME_BLOCK_ATTRIBUTE_VISIBLE_FIELDS = [
101
128
  "kind",
102
129
  "name",
@@ -136,6 +163,12 @@ var NAME_NAMESPACE_VISIBLE_FIELDS = [
136
163
  "name",
137
164
  "namespace"
138
165
  ];
166
+ var NAME_POST_TYPE_TYPE_VISIBLE_FIELDS = [
167
+ "kind",
168
+ "name",
169
+ "post-type",
170
+ "type"
171
+ ];
139
172
  function requireAddKindName(context, message) {
140
173
  if (!context.name) {
141
174
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
@@ -182,6 +215,7 @@ function assertAddBlockTemplateId(context, templateId) {
182
215
  }
183
216
 
184
217
  // src/add-kinds/ability.ts
218
+ var ABILITY_MISSING_NAME_MESSAGE = "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.";
185
219
  var abilityAddKindEntry = defineAddKindRegistryEntry({
186
220
  completion: {
187
221
  nextSteps: (values) => [
@@ -206,7 +240,7 @@ var abilityAddKindEntry = defineAddKindRegistryEntry({
206
240
  abilitySlug: result.abilitySlug
207
241
  }),
208
242
  getWarnings: (result) => result.warnings,
209
- missingNameMessage: "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.",
243
+ missingNameMessage: ABILITY_MISSING_NAME_MESSAGE,
210
244
  warnLine: context.warnLine
211
245
  });
212
246
  },
@@ -240,6 +274,9 @@ function readOptionalLooseStringFlag(flags, name) {
240
274
  function readOptionalStrictStringFlag(flags, name) {
241
275
  return readOptionalCliStringFlagValue(flags, name, "strict");
242
276
  }
277
+ function readOptionalDashedOrCamelStringFlag(flags, dashedName, camelName) {
278
+ return readOptionalStrictStringFlag(flags, dashedName) ?? readOptionalStrictStringFlag(flags, camelName);
279
+ }
243
280
  function requireStrictStringFlag(flags, name, message) {
244
281
  const value = readOptionalStrictStringFlag(flags, name);
245
282
  if (!value) {
@@ -257,6 +294,7 @@ function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message
257
294
  }
258
295
 
259
296
  // src/add-kinds/admin-view.ts
297
+ var ADMIN_VIEW_MISSING_NAME_MESSAGE = "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].";
260
298
  var adminViewAddKindEntry = defineAddKindRegistryEntry({
261
299
  completion: {
262
300
  nextSteps: (values) => [
@@ -273,7 +311,7 @@ var adminViewAddKindEntry = defineAddKindRegistryEntry({
273
311
  description: "Add an opt-in DataViews-powered admin screen",
274
312
  nameLabel: "Admin view name",
275
313
  async prepareExecution(context) {
276
- const name = requireAddKindName(context, "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].");
314
+ const name = requireAddKindName(context, ADMIN_VIEW_MISSING_NAME_MESSAGE);
277
315
  const source = readOptionalStrictStringFlag(context.flags, "source");
278
316
  return createNamedExecutionPlan(context, {
279
317
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
@@ -285,8 +323,9 @@ var adminViewAddKindEntry = defineAddKindRegistryEntry({
285
323
  adminViewSlug: result.adminViewSlug,
286
324
  ...result.source ? { source: result.source } : {}
287
325
  }),
288
- missingNameMessage: "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].",
289
- name
326
+ missingNameMessage: ADMIN_VIEW_MISSING_NAME_MESSAGE,
327
+ name,
328
+ warnLine: context.warnLine
290
329
  });
291
330
  },
292
331
  sortOrder: 10,
@@ -296,6 +335,7 @@ var adminViewAddKindEntry = defineAddKindRegistryEntry({
296
335
  });
297
336
 
298
337
  // src/add-kinds/ai-feature.ts
338
+ var AI_FEATURE_MISSING_NAME_MESSAGE = "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].";
299
339
  var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
300
340
  completion: {
301
341
  nextSteps: (values) => [
@@ -312,7 +352,7 @@ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
312
352
  description: "Add a server-owned WordPress AI feature endpoint",
313
353
  nameLabel: "AI feature name",
314
354
  async prepareExecution(context) {
315
- const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
355
+ const name = requireAddKindName(context, AI_FEATURE_MISSING_NAME_MESSAGE);
316
356
  const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
317
357
  return createNamedExecutionPlan(context, {
318
358
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
@@ -325,7 +365,7 @@ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
325
365
  namespace: result.namespace
326
366
  }),
327
367
  getWarnings: (result) => result.warnings,
328
- missingNameMessage: "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].",
368
+ missingNameMessage: AI_FEATURE_MISSING_NAME_MESSAGE,
329
369
  name,
330
370
  warnLine: context.warnLine
331
371
  });
@@ -337,6 +377,7 @@ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
337
377
  });
338
378
 
339
379
  // src/add-kinds/binding-source.ts
380
+ var BINDING_SOURCE_MISSING_NAME_MESSAGE = "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].";
340
381
  var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
341
382
  completion: {
342
383
  nextSteps: (values) => [
@@ -356,7 +397,7 @@ var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
356
397
  description: "Add a shared block bindings source",
357
398
  nameLabel: "Binding source name",
358
399
  async prepareExecution(context) {
359
- const name = requireAddKindName(context, "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].");
400
+ const name = requireAddKindName(context, BINDING_SOURCE_MISSING_NAME_MESSAGE);
360
401
  const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
361
402
  return createNamedExecutionPlan(context, {
362
403
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
@@ -370,8 +411,9 @@ var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
370
411
  ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
371
412
  bindingSourceSlug: result.bindingSourceSlug
372
413
  }),
373
- missingNameMessage: "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].",
374
- name
414
+ missingNameMessage: BINDING_SOURCE_MISSING_NAME_MESSAGE,
415
+ name,
416
+ warnLine: context.warnLine
375
417
  });
376
418
  },
377
419
  sortOrder: 70,
@@ -397,6 +439,7 @@ function toExternalLayerPromptOptions(options) {
397
439
  }
398
440
 
399
441
  // src/add-kinds/block.ts
442
+ var BLOCK_MISSING_NAME_MESSAGE = "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]";
400
443
  var blockAddKindEntry = defineAddKindRegistryEntry({
401
444
  completion: {
402
445
  nextSteps: () => [
@@ -414,7 +457,7 @@ var blockAddKindEntry = defineAddKindRegistryEntry({
414
457
  hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
415
458
  nameLabel: "Block name",
416
459
  async prepareExecution(context) {
417
- const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
460
+ const name = requireAddKindName(context, BLOCK_MISSING_NAME_MESSAGE);
418
461
  const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
419
462
  const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
420
463
  const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
@@ -452,7 +495,7 @@ var blockAddKindEntry = defineAddKindRegistryEntry({
452
495
  templateId: result.templateId
453
496
  }),
454
497
  getWarnings: (result) => result.warnings,
455
- missingNameMessage: "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]",
498
+ missingNameMessage: BLOCK_MISSING_NAME_MESSAGE,
456
499
  name,
457
500
  warnLine: context.warnLine
458
501
  });
@@ -474,7 +517,52 @@ var blockAddKindEntry = defineAddKindRegistryEntry({
474
517
  })
475
518
  });
476
519
 
520
+ // src/add-kinds/contract.ts
521
+ var CONTRACT_MISSING_NAME_MESSAGE = "`wp-typia add contract` requires <name>. Usage: wp-typia add contract <name> [--type <ExportedTypeName>].";
522
+ var contractAddKindEntry = defineAddKindRegistryEntry({
523
+ completion: {
524
+ nextSteps: (values) => [
525
+ `Edit ${values.typesFile} when the standalone wire shape changes.`,
526
+ "Run `wp-typia sync-rest` or `wp-typia sync` to refresh the generated schema artifact."
527
+ ],
528
+ summaryLines: (values, projectDir) => [
529
+ `Contract: ${values.contractSlug}`,
530
+ `Source type: ${values.sourceTypeName}`,
531
+ `Schema: ${values.schemaFile}`,
532
+ `Project directory: ${projectDir}`
533
+ ],
534
+ title: "Added standalone contract"
535
+ },
536
+ description: "Add a standalone TypeScript schema contract",
537
+ nameLabel: "Contract name",
538
+ async prepareExecution(context) {
539
+ const name = requireAddKindName(context, CONTRACT_MISSING_NAME_MESSAGE);
540
+ const typeName = readOptionalStrictStringFlag(context.flags, "type");
541
+ return createNamedExecutionPlan(context, {
542
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddContractCommand({
543
+ contractName: name2,
544
+ cwd,
545
+ typeName
546
+ }),
547
+ getValues: (result) => ({
548
+ contractSlug: result.contractSlug,
549
+ schemaFile: result.schemaFile,
550
+ sourceTypeName: result.sourceTypeName,
551
+ typesFile: result.typesFile
552
+ }),
553
+ missingNameMessage: CONTRACT_MISSING_NAME_MESSAGE,
554
+ name,
555
+ warnLine: context.warnLine
556
+ });
557
+ },
558
+ sortOrder: 75,
559
+ supportsDryRun: true,
560
+ usage: "wp-typia add contract <name> [--type <ExportedTypeName>] [--dry-run]",
561
+ visibleFieldNames: () => NAME_TYPE_VISIBLE_FIELDS
562
+ });
563
+
477
564
  // src/add-kinds/editor-plugin.ts
565
+ var EDITOR_PLUGIN_MISSING_NAME_MESSAGE = "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].";
478
566
  var editorPluginAddKindEntry = defineAddKindRegistryEntry({
479
567
  completion: {
480
568
  nextSteps: (values) => [
@@ -491,7 +579,7 @@ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
491
579
  description: "Add a slot-aware document editor extension shell",
492
580
  nameLabel: "Editor plugin name",
493
581
  async prepareExecution(context) {
494
- const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].");
582
+ const name = requireAddKindName(context, EDITOR_PLUGIN_MISSING_NAME_MESSAGE);
495
583
  const slot = readOptionalStrictStringFlag(context.flags, "slot");
496
584
  return createNamedExecutionPlan(context, {
497
585
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
@@ -503,8 +591,9 @@ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
503
591
  editorPluginSlug: result.editorPluginSlug,
504
592
  slot: result.slot
505
593
  }),
506
- missingNameMessage: "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].",
507
- name
594
+ missingNameMessage: EDITOR_PLUGIN_MISSING_NAME_MESSAGE,
595
+ name,
596
+ warnLine: context.warnLine
508
597
  });
509
598
  },
510
599
  sortOrder: 120,
@@ -514,6 +603,7 @@ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
514
603
  });
515
604
 
516
605
  // src/add-kinds/hooked-block.ts
606
+ var HOOKED_BLOCK_MISSING_NAME_MESSAGE = "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.";
517
607
  var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
518
608
  completion: {
519
609
  nextSteps: (values) => [
@@ -531,7 +621,7 @@ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
531
621
  description: "Add block.json hook metadata to an existing block",
532
622
  nameLabel: "Target block",
533
623
  async prepareExecution(context) {
534
- const name = requireAddKindName(context, "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.");
624
+ const name = requireAddKindName(context, HOOKED_BLOCK_MISSING_NAME_MESSAGE);
535
625
  const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
536
626
  const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
537
627
  return createNamedExecutionPlan(context, {
@@ -546,8 +636,9 @@ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
546
636
  blockSlug: result.blockSlug,
547
637
  position: result.position
548
638
  }),
549
- missingNameMessage: "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.",
550
- name
639
+ missingNameMessage: HOOKED_BLOCK_MISSING_NAME_MESSAGE,
640
+ name,
641
+ warnLine: context.warnLine
551
642
  });
552
643
  },
553
644
  sortOrder: 110,
@@ -556,7 +647,53 @@ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
556
647
  visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
557
648
  });
558
649
 
650
+ // src/add-kinds/integration-env.ts
651
+ var INTEGRATION_ENV_MISSING_NAME_MESSAGE = "`wp-typia add integration-env` requires <name>. Usage: wp-typia add integration-env <name> [--wp-env] [--service <none|docker-compose>].";
652
+ var integrationEnvAddKindEntry = defineAddKindRegistryEntry({
653
+ completion: {
654
+ nextSteps: (values) => [
655
+ `Review scripts/integration-smoke/${values.integrationEnvSlug}.mjs and docs/integration-env/${values.integrationEnvSlug}.md.`,
656
+ "Copy `.env.example` to `.env`, adjust local URLs or credentials, then run the generated smoke script.",
657
+ ...values.withWpEnv === "true" ? ["Run `npm run wp-env:start` before the smoke check when using the generated wp-env preset."] : []
658
+ ],
659
+ summaryLines: (values, projectDir) => [
660
+ `Integration env: ${values.integrationEnvSlug}`,
661
+ `wp-env preset: ${values.withWpEnv}`,
662
+ `Service starter: ${values.service}`,
663
+ `Project directory: ${projectDir}`
664
+ ],
665
+ title: "Added integration environment starter"
666
+ },
667
+ description: "Add an opt-in local WordPress integration smoke environment starter",
668
+ nameLabel: "Integration env name",
669
+ async prepareExecution(context) {
670
+ const service = readOptionalStrictStringFlag(context.flags, "service");
671
+ const withWpEnv = Boolean(context.flags["wp-env"]);
672
+ return createNamedExecutionPlan(context, {
673
+ execute: ({ cwd, name }) => context.addRuntime.runAddIntegrationEnvCommand({
674
+ cwd,
675
+ integrationEnvName: name,
676
+ service,
677
+ withWpEnv
678
+ }),
679
+ getValues: (result) => ({
680
+ integrationEnvSlug: result.integrationEnvSlug,
681
+ service: result.service,
682
+ withWpEnv: String(result.withWpEnv)
683
+ }),
684
+ getWarnings: (result) => result.warnings,
685
+ missingNameMessage: INTEGRATION_ENV_MISSING_NAME_MESSAGE,
686
+ warnLine: context.warnLine
687
+ });
688
+ },
689
+ sortOrder: 25,
690
+ supportsDryRun: true,
691
+ usage: "wp-typia add integration-env <name> [--wp-env] [--service <none|docker-compose>] [--dry-run]",
692
+ visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
693
+ });
694
+
559
695
  // src/add-kinds/pattern.ts
696
+ var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.";
560
697
  var patternAddKindEntry = defineAddKindRegistryEntry({
561
698
  completion: {
562
699
  nextSteps: (values) => [
@@ -580,7 +717,8 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
580
717
  getValues: (result) => ({
581
718
  patternSlug: result.patternSlug
582
719
  }),
583
- missingNameMessage: "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>."
720
+ missingNameMessage: PATTERN_MISSING_NAME_MESSAGE,
721
+ warnLine: context.warnLine
584
722
  });
585
723
  },
586
724
  sortOrder: 60,
@@ -589,50 +727,182 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
589
727
  visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
590
728
  });
591
729
 
730
+ // src/add-kinds/post-meta.ts
731
+ var POST_META_MISSING_NAME_MESSAGE = "`wp-typia add post-meta` requires <name>. Usage: wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>].";
732
+ var POST_META_MISSING_POST_TYPE_MESSAGE = "`wp-typia add post-meta` requires --post-type <post-type>. Usage: wp-typia add post-meta <name> --post-type <post-type>.";
733
+ var postMetaAddKindEntry = defineAddKindRegistryEntry({
734
+ completion: {
735
+ nextSteps: (values) => [
736
+ `Edit ${values.typesFile} when the post meta shape changes.`,
737
+ "Run `wp-typia sync-rest --check` to verify the generated meta schema is current.",
738
+ `Smoke test ${values.metaKey} on the ${values.postType} post type in WordPress.`
739
+ ],
740
+ summaryLines: (values, projectDir) => [
741
+ `Post meta contract: ${values.postMetaSlug}`,
742
+ `Post type: ${values.postType}`,
743
+ `Meta key: ${values.metaKey}`,
744
+ `REST/editor exposure: ${values.showInRest}`,
745
+ `Schema: ${values.schemaFile}`,
746
+ `PHP: ${values.phpFile}`,
747
+ `Project directory: ${projectDir}`
748
+ ],
749
+ title: "Added post meta contract"
750
+ },
751
+ description: "Add a typed WordPress post meta contract",
752
+ hiddenBooleanSubmitFields: ["hide-from-rest"],
753
+ hiddenStringSubmitFields: ["meta-key"],
754
+ nameLabel: "Post meta name",
755
+ async prepareExecution(context) {
756
+ const name = requireAddKindName(context, POST_META_MISSING_NAME_MESSAGE);
757
+ const hideFromRest = Boolean(context.flags["hide-from-rest"] ?? context.flags.hideFromRest);
758
+ const metaKey = readOptionalDashedOrCamelStringFlag(context.flags, "meta-key", "metaKey");
759
+ const postType = readOptionalDashedOrCamelStringFlag(context.flags, "post-type", "postType") ?? requireStrictStringFlag(context.flags, "post-type", POST_META_MISSING_POST_TYPE_MESSAGE);
760
+ const typeName = readOptionalStrictStringFlag(context.flags, "type");
761
+ return createNamedExecutionPlan(context, {
762
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddPostMetaCommand({
763
+ cwd,
764
+ hideFromRest,
765
+ metaKey,
766
+ postMetaName: name2,
767
+ postType,
768
+ typeName
769
+ }),
770
+ getValues: (result) => ({
771
+ metaKey: result.metaKey,
772
+ phpFile: result.phpFile,
773
+ postMetaSlug: result.postMetaSlug,
774
+ postType: result.postType,
775
+ schemaFile: result.schemaFile,
776
+ showInRest: result.showInRest ? "enabled" : "disabled",
777
+ sourceTypeName: result.sourceTypeName,
778
+ typesFile: result.typesFile
779
+ }),
780
+ missingNameMessage: POST_META_MISSING_NAME_MESSAGE,
781
+ name,
782
+ warnLine: context.warnLine
783
+ });
784
+ },
785
+ sortOrder: 85,
786
+ supportsDryRun: true,
787
+ usage: "wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>] [--hide-from-rest] [--dry-run]",
788
+ visibleFieldNames: () => NAME_POST_TYPE_TYPE_VISIBLE_FIELDS
789
+ });
790
+
592
791
  // src/add-kinds/rest-resource.ts
792
+ var REST_RESOURCE_MISSING_NAME_MESSAGE = "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] or wp-typia add rest-resource <name> --manual [--method GET] [--path /external].";
793
+ function readOptionalDashedOrCamelStringFlag2(flags, dashedName, camelName) {
794
+ return readOptionalStrictStringFlag(flags, dashedName) ?? readOptionalStrictStringFlag(flags, camelName);
795
+ }
593
796
  var restResourceAddKindEntry = defineAddKindRegistryEntry({
594
797
  completion: {
595
- nextSteps: (values) => [
798
+ nextSteps: (values) => values.mode === "manual" ? [
799
+ `Review src/rest/${values.restResourceSlug}/ and edit the manual contract types to match the external route owner.`,
800
+ "Run sync-rest --check after changing the contract types to verify schemas, OpenAPI, and client artifacts."
801
+ ] : [
596
802
  `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
597
803
  "Run your workspace build or dev command to verify the generated REST resource contract."
598
804
  ],
599
805
  summaryLines: (values, projectDir) => [
600
806
  `REST resource: ${values.restResourceSlug}`,
807
+ `Mode: ${values.mode}`,
601
808
  `Namespace: ${values.namespace}`,
602
- `Methods: ${values.methods}`,
809
+ ...values.mode === "manual" ? [
810
+ `Route: ${values.method} /${values.namespace}${values.pathPattern}`,
811
+ `Auth: ${values.auth}`,
812
+ ...values.secretFieldName ? [
813
+ `Secret field: ${values.secretFieldName} -> ${values.secretStateFieldName}`
814
+ ] : []
815
+ ] : [
816
+ `Methods: ${values.methods}`,
817
+ ...values.routePattern ? [`Item route: /${values.namespace}${values.routePattern}`] : [],
818
+ ...values.permissionCallback ? [`Permission callback: ${values.permissionCallback}`] : [],
819
+ ...values.controllerClass ? [`Controller class: ${values.controllerClass}`] : []
820
+ ],
603
821
  `Project directory: ${projectDir}`
604
822
  ],
605
- title: "Added plugin-level REST resource"
823
+ title: "Added REST resource contract"
606
824
  },
607
- description: "Add a plugin-level typed REST resource",
825
+ description: "Add a generated or type-only REST resource contract",
826
+ hiddenBooleanSubmitFields: ["manual"],
827
+ hiddenStringSubmitFields: [
828
+ "auth",
829
+ "body-type",
830
+ "controller-class",
831
+ "controller-extends",
832
+ "method",
833
+ "path",
834
+ "permission-callback",
835
+ "query-type",
836
+ "response-type",
837
+ "route-pattern",
838
+ "secret-field",
839
+ "secret-state-field"
840
+ ],
608
841
  nameLabel: "REST resource name",
609
842
  async prepareExecution(context) {
610
- const name = requireAddKindName(context, "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>].");
843
+ const name = requireAddKindName(context, REST_RESOURCE_MISSING_NAME_MESSAGE);
844
+ const auth = readOptionalStrictStringFlag(context.flags, "auth");
845
+ const bodyTypeName = readOptionalStrictStringFlag(context.flags, "body-type");
846
+ const controllerClass = readOptionalDashedOrCamelStringFlag2(context.flags, "controller-class", "controllerClass");
847
+ const controllerExtends = readOptionalDashedOrCamelStringFlag2(context.flags, "controller-extends", "controllerExtends");
848
+ const manual = Boolean(context.flags.manual);
849
+ const method = readOptionalStrictStringFlag(context.flags, "method");
611
850
  const methods = readOptionalStrictStringFlag(context.flags, "methods");
612
851
  const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
852
+ const permissionCallback = readOptionalDashedOrCamelStringFlag2(context.flags, "permission-callback", "permissionCallback");
853
+ const pathPattern = readOptionalStrictStringFlag(context.flags, "path");
854
+ const queryTypeName = readOptionalStrictStringFlag(context.flags, "query-type");
855
+ const responseTypeName = readOptionalStrictStringFlag(context.flags, "response-type");
856
+ const routePattern = readOptionalDashedOrCamelStringFlag2(context.flags, "route-pattern", "routePattern");
857
+ const secretFieldName = readOptionalDashedOrCamelStringFlag2(context.flags, "secret-field", "secretField");
858
+ const secretStateFieldName = readOptionalDashedOrCamelStringFlag2(context.flags, "secret-state-field", "secretStateField");
613
859
  return createNamedExecutionPlan(context, {
614
860
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
861
+ auth,
862
+ bodyTypeName,
863
+ controllerClass,
864
+ controllerExtends,
615
865
  cwd,
866
+ manual,
867
+ method,
616
868
  methods,
617
869
  namespace,
618
- restResourceName: name2
870
+ permissionCallback,
871
+ pathPattern,
872
+ queryTypeName,
873
+ restResourceName: name2,
874
+ responseTypeName,
875
+ routePattern,
876
+ secretFieldName,
877
+ secretStateFieldName
619
878
  }),
620
879
  getValues: (result) => ({
880
+ auth: result.auth ?? "",
881
+ controllerClass: result.controllerClass ?? "",
882
+ method: result.method ?? "",
621
883
  methods: result.methods.join(", "),
884
+ mode: result.mode,
622
885
  namespace: result.namespace,
623
- restResourceSlug: result.restResourceSlug
886
+ pathPattern: result.pathPattern ?? "",
887
+ permissionCallback: result.permissionCallback ?? "",
888
+ restResourceSlug: result.restResourceSlug,
889
+ routePattern: result.routePattern ?? "",
890
+ secretFieldName: result.secretFieldName ?? "",
891
+ secretStateFieldName: result.secretStateFieldName ?? ""
624
892
  }),
625
- missingNameMessage: "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>].",
626
- name
893
+ missingNameMessage: REST_RESOURCE_MISSING_NAME_MESSAGE,
894
+ name,
895
+ warnLine: context.warnLine
627
896
  });
628
897
  },
629
898
  sortOrder: 80,
630
899
  supportsDryRun: true,
631
- usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
900
+ usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--manual --method <GET|POST|PUT|PATCH|DELETE> --auth <public|authenticated|public-write-protected> --path <route-pattern> --query-type <Type> --body-type <Type> --response-type <Type> --secret-field <field> --secret-state-field <field>] [--dry-run]",
632
901
  visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
633
902
  });
634
903
 
635
904
  // src/add-kinds/style.ts
905
+ var STYLE_MISSING_NAME_MESSAGE = "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.";
636
906
  var styleAddKindEntry = defineAddKindRegistryEntry({
637
907
  completion: {
638
908
  nextSteps: (values) => [
@@ -649,7 +919,7 @@ var styleAddKindEntry = defineAddKindRegistryEntry({
649
919
  description: "Add a Block Styles registration to an existing block",
650
920
  nameLabel: "Style name",
651
921
  async prepareExecution(context) {
652
- const name = requireAddKindName(context, "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.");
922
+ const name = requireAddKindName(context, STYLE_MISSING_NAME_MESSAGE);
653
923
  const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
654
924
  return createNamedExecutionPlan(context, {
655
925
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
@@ -661,8 +931,9 @@ var styleAddKindEntry = defineAddKindRegistryEntry({
661
931
  blockSlug: result.blockSlug,
662
932
  styleSlug: result.styleSlug
663
933
  }),
664
- missingNameMessage: "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.",
665
- name
934
+ missingNameMessage: STYLE_MISSING_NAME_MESSAGE,
935
+ name,
936
+ warnLine: context.warnLine
666
937
  });
667
938
  },
668
939
  sortOrder: 40,
@@ -672,6 +943,7 @@ var styleAddKindEntry = defineAddKindRegistryEntry({
672
943
  });
673
944
 
674
945
  // src/add-kinds/transform.ts
946
+ var TRANSFORM_MISSING_NAME_MESSAGE = "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.";
675
947
  var transformAddKindEntry = defineAddKindRegistryEntry({
676
948
  completion: {
677
949
  nextSteps: (values) => [
@@ -689,7 +961,7 @@ var transformAddKindEntry = defineAddKindRegistryEntry({
689
961
  description: "Add a block-to-block transform into a workspace block",
690
962
  nameLabel: "Transform name",
691
963
  async prepareExecution(context) {
692
- const name = requireAddKindName(context, "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.");
964
+ const name = requireAddKindName(context, TRANSFORM_MISSING_NAME_MESSAGE);
693
965
  const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
694
966
  const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
695
967
  return createNamedExecutionPlan(context, {
@@ -705,8 +977,9 @@ var transformAddKindEntry = defineAddKindRegistryEntry({
705
977
  toBlockName: result.toBlockName,
706
978
  transformSlug: result.transformSlug
707
979
  }),
708
- missingNameMessage: "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.",
709
- name
980
+ missingNameMessage: TRANSFORM_MISSING_NAME_MESSAGE,
981
+ name,
982
+ warnLine: context.warnLine
710
983
  });
711
984
  },
712
985
  sortOrder: 50,
@@ -716,6 +989,7 @@ var transformAddKindEntry = defineAddKindRegistryEntry({
716
989
  });
717
990
 
718
991
  // src/add-kinds/variation.ts
992
+ var VARIATION_MISSING_NAME_MESSAGE = "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>";
719
993
  var variationAddKindEntry = defineAddKindRegistryEntry({
720
994
  completion: {
721
995
  nextSteps: (values) => [
@@ -732,7 +1006,7 @@ var variationAddKindEntry = defineAddKindRegistryEntry({
732
1006
  description: "Add a variation to an existing block",
733
1007
  nameLabel: "Variation name",
734
1008
  async prepareExecution(context) {
735
- const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
1009
+ const name = requireAddKindName(context, VARIATION_MISSING_NAME_MESSAGE);
736
1010
  const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
737
1011
  return createNamedExecutionPlan(context, {
738
1012
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
@@ -744,8 +1018,9 @@ var variationAddKindEntry = defineAddKindRegistryEntry({
744
1018
  blockSlug: result.blockSlug,
745
1019
  variationSlug: result.variationSlug
746
1020
  }),
747
- missingNameMessage: "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>",
748
- name
1021
+ missingNameMessage: VARIATION_MISSING_NAME_MESSAGE,
1022
+ name,
1023
+ warnLine: context.warnLine
749
1024
  });
750
1025
  },
751
1026
  sortOrder: 30,
@@ -758,12 +1033,15 @@ var variationAddKindEntry = defineAddKindRegistryEntry({
758
1033
  var ADD_KIND_REGISTRY = {
759
1034
  "admin-view": adminViewAddKindEntry,
760
1035
  block: blockAddKindEntry,
1036
+ "integration-env": integrationEnvAddKindEntry,
761
1037
  variation: variationAddKindEntry,
762
1038
  style: styleAddKindEntry,
763
1039
  transform: transformAddKindEntry,
764
1040
  pattern: patternAddKindEntry,
765
1041
  "binding-source": bindingSourceAddKindEntry,
1042
+ contract: contractAddKindEntry,
766
1043
  "rest-resource": restResourceAddKindEntry,
1044
+ "post-meta": postMetaAddKindEntry,
767
1045
  ability: abilityAddKindEntry,
768
1046
  "ai-feature": aiFeatureAddKindEntry,
769
1047
  "hooked-block": hookedBlockAddKindEntry,
@@ -783,12 +1061,6 @@ function buildAddKindCompletionDetails(kind, options) {
783
1061
  title: descriptor.title
784
1062
  };
785
1063
  }
786
- function formatAddKindList() {
787
- return ADD_KIND_IDS.join(", ");
788
- }
789
- function formatAddKindUsagePlaceholder() {
790
- return `<${ADD_KIND_IDS.join("|")}>`;
791
- }
792
1064
  function supportsAddKindDryRun(kind) {
793
1065
  return ADD_KIND_REGISTRY[kind].supportsDryRun;
794
1066
  }
@@ -835,6 +1107,55 @@ async function copyWorkspaceProject(sourceDir, targetDir) {
835
1107
  recursive: true
836
1108
  });
837
1109
  }
1110
+ function formatInstallMarkerError(error) {
1111
+ if (error instanceof Error) {
1112
+ return error.message;
1113
+ }
1114
+ return String(error);
1115
+ }
1116
+ function formatInstallMarkerFailures(failures) {
1117
+ return failures.map((failure) => `${failure.operation}: ${failure.reason}`).join("; ");
1118
+ }
1119
+ function ensureWorkspaceInstallMarker({
1120
+ fsAdapter = fs2,
1121
+ sourceMarker,
1122
+ targetMarker
1123
+ }) {
1124
+ const failures = [];
1125
+ try {
1126
+ fsAdapter.symlinkSync(sourceMarker, targetMarker);
1127
+ return;
1128
+ } catch (error) {
1129
+ failures.push({
1130
+ operation: "symlink",
1131
+ reason: formatInstallMarkerError(error)
1132
+ });
1133
+ }
1134
+ try {
1135
+ fsAdapter.linkSync(sourceMarker, targetMarker);
1136
+ return;
1137
+ } catch (error) {
1138
+ failures.push({
1139
+ operation: "hard link",
1140
+ reason: formatInstallMarkerError(error)
1141
+ });
1142
+ }
1143
+ try {
1144
+ fsAdapter.copyFileSync(sourceMarker, targetMarker);
1145
+ return;
1146
+ } catch (error) {
1147
+ failures.push({
1148
+ operation: "copy",
1149
+ reason: formatInstallMarkerError(error)
1150
+ });
1151
+ }
1152
+ throw new Error([
1153
+ "Failed to prepare dry-run install marker.",
1154
+ `Source: ${sourceMarker}`,
1155
+ `Target: ${targetMarker}`,
1156
+ `Fallback failures: ${formatInstallMarkerFailures(failures)}`
1157
+ ].join(" "));
1158
+ }
838
1159
  function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
839
1160
  const sourceNodeModules = path.join(sourceDir, "node_modules");
840
1161
  if (fs2.existsSync(sourceNodeModules)) {
@@ -846,15 +1167,7 @@ function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
846
1167
  continue;
847
1168
  }
848
1169
  const targetMarker = path.join(targetDir, marker);
849
- try {
850
- fs2.symlinkSync(sourceMarker, targetMarker);
851
- } catch {
852
- try {
853
- fs2.linkSync(sourceMarker, targetMarker);
854
- } catch {
855
- fs2.copyFileSync(sourceMarker, targetMarker);
856
- }
857
- }
1170
+ ensureWorkspaceInstallMarker({ sourceMarker, targetMarker });
858
1171
  }
859
1172
  }
860
1173
  async function listWorkspaceFiles(rootDir) {
@@ -937,6 +1250,11 @@ async function simulateWorkspaceAddDryRun({
937
1250
  }
938
1251
  }
939
1252
 
1253
+ // src/string-utils.ts
1254
+ function escapeRegExp(source) {
1255
+ return source.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
1256
+ }
1257
+
940
1258
  // src/output-markers.ts
941
1259
  var UNICODE_OUTPUT_MARKERS = {
942
1260
  dryRun: "\uD83E\uDDEA",
@@ -952,9 +1270,6 @@ var ASCII_OUTPUT_MARKERS = {
952
1270
  };
953
1271
  var ASCII_ENV_TRUTHY_VALUES = new Set(["1", "on", "true", "yes"]);
954
1272
  var ASCII_ENV_FALSY_VALUES = new Set(["0", "off", "false", "no"]);
955
- function escapeRegExp(source) {
956
- return source.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
957
- }
958
1273
  function readAsciiPreferenceFromEnv(env) {
959
1274
  const rawValue = env.WP_TYPIA_ASCII;
960
1275
  if (typeof rawValue !== "string") {
@@ -1015,47 +1330,38 @@ function stripLeadingOutputMarker(text, kind) {
1015
1330
  return text.replace(new RegExp(`^(?:${markerPattern})\\s*`, "u"), "");
1016
1331
  }
1017
1332
 
1018
- // src/print-block.ts
1019
- function printBlock(printLine, lines) {
1020
- for (const line of lines) {
1021
- printLine(line);
1022
- }
1333
+ // src/runtime-output/init.ts
1334
+ function buildInitCompletionPayload(plan, markerOptions) {
1335
+ const changeLines = [
1336
+ ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
1337
+ ...plan.packageChanges.packageManagerField ? [
1338
+ `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
1339
+ ] : [],
1340
+ ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
1341
+ ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
1342
+ ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
1343
+ ];
1344
+ const modeLine = plan.commandMode === "apply" ? plan.status === "already-initialized" ? "Mode: apply requested; no files were written because the retrofit surface already existed." : "Mode: apply; package.json and retrofit helper files were written." : "Mode: preview only; no files were written.";
1345
+ const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
1346
+ const title = plan.status === "already-initialized" ? formatOutputMarker("success", `wp-typia init: ${plan.projectName} is already initialized`, markerOptions) : plan.commandMode === "apply" ? formatOutputMarker("success", `Applied retrofit init for ${plan.projectName}`, markerOptions) : formatOutputMarker("dryRun", `Retrofit init plan for ${plan.projectName}`, markerOptions);
1347
+ return {
1348
+ nextSteps: plan.nextSteps,
1349
+ optionalLines: changeLines,
1350
+ optionalNote: plan.summary,
1351
+ optionalTitle,
1352
+ summaryLines: [
1353
+ `Project directory: ${plan.projectDir}`,
1354
+ `Detected layout: ${plan.detectedLayout.description}`,
1355
+ ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
1356
+ `Package manager: ${plan.packageManager}`,
1357
+ modeLine
1358
+ ],
1359
+ title,
1360
+ warningLines: plan.notes
1361
+ };
1023
1362
  }
1024
1363
 
1025
- // src/runtime-bridge-output.ts
1026
- function printCompletionPayload(payload, options = {}) {
1027
- const printLine = options.printLine ?? console.log;
1028
- const warnLine = options.warnLine ?? printLine;
1029
- for (const line of payload.preambleLines ?? []) {
1030
- printLine(line);
1031
- }
1032
- for (const warning of payload.warningLines ?? []) {
1033
- warnLine(formatOutputMarker("warning", warning, options.markerOptions));
1034
- }
1035
- const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
1036
- const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
1037
- printLine(hasLeadingContext && hasDetails ? `
1038
- ${payload.title}` : payload.title);
1039
- for (const line of payload.summaryLines ?? []) {
1040
- printLine(line);
1041
- }
1042
- if ((payload.nextSteps?.length ?? 0) > 0) {
1043
- printLine("Next steps:");
1044
- for (const step of payload.nextSteps ?? []) {
1045
- printLine(` ${step}`);
1046
- }
1047
- }
1048
- if ((payload.optionalLines?.length ?? 0) > 0) {
1049
- printLine(`
1050
- ${payload.optionalTitle ?? "Optional:"}`);
1051
- for (const step of payload.optionalLines ?? []) {
1052
- printLine(` ${step}`);
1053
- }
1054
- }
1055
- if (payload.optionalNote) {
1056
- printLine(`Note: ${payload.optionalNote}`);
1057
- }
1058
- }
1364
+ // src/runtime-output/structured.ts
1059
1365
  function toNonEmptyArray(values) {
1060
1366
  return values && values.length > 0 ? values : undefined;
1061
1367
  }
@@ -1064,13 +1370,6 @@ function extractPlannedFiles(payload) {
1064
1370
  return toNonEmptyArray(files);
1065
1371
  }
1066
1372
  var PROJECT_DIRECTORY_SUMMARY_PREFIX = "Project directory: ";
1067
- function resolveCreateCompletionPackageManager(packageManager) {
1068
- const parsedPackageManager = parsePackageManagerField(packageManager);
1069
- if (parsedPackageManager) {
1070
- return parsedPackageManager;
1071
- }
1072
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
1073
- }
1074
1373
  function extractCompletionProjectDir(completion) {
1075
1374
  const projectDir = completion?.summaryLines?.find((line) => line.startsWith(PROJECT_DIRECTORY_SUMMARY_PREFIX))?.slice(PROJECT_DIRECTORY_SUMMARY_PREFIX.length).trim();
1076
1375
  return projectDir && projectDir.length > 0 ? projectDir : undefined;
@@ -1123,6 +1422,25 @@ function buildStructuredInitSuccessPayload(plan) {
1123
1422
  }
1124
1423
  };
1125
1424
  }
1425
+ // src/runtime-output/create.ts
1426
+ var LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN = new RegExp(`^(?:corepack\\s+)?(${PACKAGE_MANAGER_IDS.map(escapeRegExp).join("|")})(?=$|[@:/+\\s])`, "iu");
1427
+ function parseCreateCompletionPackageManager(packageManager) {
1428
+ const normalizedPackageManager = packageManager.trim();
1429
+ const parsedPackageManager = parsePackageManagerField(normalizedPackageManager);
1430
+ if (parsedPackageManager) {
1431
+ return parsedPackageManager;
1432
+ }
1433
+ const looseMatch = LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN.exec(normalizedPackageManager);
1434
+ const loosePackageManager = looseMatch?.[1]?.toLowerCase();
1435
+ return PACKAGE_MANAGER_IDS.includes(loosePackageManager) ? loosePackageManager : null;
1436
+ }
1437
+ function resolveCreateCompletionPackageManager(packageManager) {
1438
+ const parsedPackageManager = parseCreateCompletionPackageManager(packageManager);
1439
+ if (parsedPackageManager) {
1440
+ return parsedPackageManager;
1441
+ }
1442
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
1443
+ }
1126
1444
  function formatCreateProgressLine(payload, markerOptions) {
1127
1445
  return formatOutputMarker("progress", `${payload.title}: ${payload.detail}`, markerOptions);
1128
1446
  }
@@ -1168,42 +1486,7 @@ function buildCreateDryRunPayload(flow, markerOptions) {
1168
1486
  warningLines: flow.result.warnings
1169
1487
  };
1170
1488
  }
1171
- function buildInitCompletionPayload(plan, markerOptions) {
1172
- const changeLines = [
1173
- ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
1174
- ...plan.packageChanges.packageManagerField ? [
1175
- `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
1176
- ] : [],
1177
- ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
1178
- ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
1179
- ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
1180
- ];
1181
- const modeLine = plan.commandMode === "apply" ? plan.status === "already-initialized" ? "Mode: apply requested; no files were written because the retrofit surface already existed." : "Mode: apply; package.json and retrofit helper files were written." : "Mode: preview only; no files were written.";
1182
- const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
1183
- const title = plan.status === "already-initialized" ? formatOutputMarker("success", `wp-typia init: ${plan.projectName} is already initialized`, markerOptions) : plan.commandMode === "apply" ? formatOutputMarker("success", `Applied retrofit init for ${plan.projectName}`, markerOptions) : formatOutputMarker("dryRun", `Retrofit init plan for ${plan.projectName}`, markerOptions);
1184
- return {
1185
- nextSteps: plan.nextSteps,
1186
- optionalLines: changeLines,
1187
- optionalNote: plan.summary,
1188
- optionalTitle,
1189
- summaryLines: [
1190
- `Project directory: ${plan.projectDir}`,
1191
- `Detected layout: ${plan.detectedLayout.description}`,
1192
- ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
1193
- `Package manager: ${plan.packageManager}`,
1194
- modeLine
1195
- ],
1196
- title,
1197
- warningLines: plan.notes
1198
- };
1199
- }
1200
- function buildMigrationCompletionPayload(options, markerOptions) {
1201
- const summaryLines = options.lines.filter((line) => line.trim().length > 0);
1202
- return {
1203
- summaryLines,
1204
- title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
1205
- };
1206
- }
1489
+ // src/runtime-output/add.ts
1207
1490
  function buildAddCompletionPayload(options, markerOptions) {
1208
1491
  const verificationLines = [
1209
1492
  formatPackageExecCommand(options.packageManager ?? inferPackageManagerId(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
@@ -1235,6 +1518,15 @@ function buildAddDryRunPayload(options, markerOptions) {
1235
1518
  warningLines: options.completion.warningLines
1236
1519
  };
1237
1520
  }
1521
+ // src/runtime-output/migrate.ts
1522
+ function buildMigrationCompletionPayload(options, markerOptions) {
1523
+ const summaryLines = options.lines.filter((line) => line.trim().length > 0);
1524
+ return {
1525
+ summaryLines,
1526
+ title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
1527
+ };
1528
+ }
1529
+ // src/runtime-output/sync.ts
1238
1530
  function buildSyncDryRunPayload(options, markerOptions) {
1239
1531
  const targetSuffix = options.target === "ai" ? " ai" : "";
1240
1532
  const targetSummary = options.target === "ai" ? "Sync target: AI artifacts only." : options.target === "default" ? "Sync target: generated project defaults." : undefined;
@@ -1251,227 +1543,62 @@ function buildSyncDryRunPayload(options, markerOptions) {
1251
1543
  title: formatOutputMarker("dryRun", `Dry run for wp-typia sync${targetSuffix}`, markerOptions)
1252
1544
  };
1253
1545
  }
1254
-
1255
- // src/runtime-capabilities.ts
1256
- function isInteractiveTerminal({
1257
- stdin = process.stdin,
1258
- stdout = process.stdout,
1259
- term = process.env.TERM
1260
- } = {}) {
1261
- return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
1262
- }
1263
- function supportsInteractiveTui(options = {}) {
1264
- const hasBunRuntime = options.hasBunRuntime ?? typeof Bun !== "undefined";
1265
- return hasBunRuntime && isInteractiveTerminal(options);
1266
- }
1267
- // src/runtime-bridge-sync.ts
1268
- import { spawnSync } from "child_process";
1269
- import fs3 from "fs";
1270
- import path2 from "path";
1271
- var SYNC_INSTALL_MARKERS = [
1272
- "node_modules",
1273
- ".pnp.cjs",
1274
- ".pnp.loader.mjs"
1275
- ];
1276
- var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
1277
- var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
1278
- function resolveSyncExecutionTarget(subcommand) {
1279
- if (!subcommand) {
1280
- return "default";
1281
- }
1282
- if (subcommand === "ai") {
1283
- return "ai";
1284
- }
1285
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
1286
- }
1287
- function getSyncRootError(cwd) {
1288
- return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.OUTSIDE_PROJECT_ROOT, `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.`);
1289
- }
1290
- function resolveSyncProjectContext(cwd) {
1291
- const packageJsonPath = path2.join(cwd, "package.json");
1292
- if (!fs3.existsSync(packageJsonPath)) {
1293
- throw getSyncRootError(cwd);
1294
- }
1295
- const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
1296
- const scripts = packageJson.scripts ?? {};
1297
- const syncScripts = {
1298
- sync: typeof scripts.sync === "string" ? {
1299
- command: scripts.sync,
1300
- scriptName: "sync"
1301
- } : undefined,
1302
- "sync-ai": typeof scripts["sync-ai"] === "string" ? {
1303
- command: scripts["sync-ai"],
1304
- scriptName: "sync-ai"
1305
- } : typeof scripts["sync-wordpress-ai"] === "string" ? {
1306
- command: scripts["sync-wordpress-ai"],
1307
- scriptName: "sync-wordpress-ai"
1308
- } : undefined,
1309
- "sync-rest": typeof scripts["sync-rest"] === "string" ? {
1310
- command: scripts["sync-rest"],
1311
- scriptName: "sync-rest"
1312
- } : undefined,
1313
- "sync-types": typeof scripts["sync-types"] === "string" ? {
1314
- command: scripts["sync-types"],
1315
- scriptName: "sync-types"
1316
- } : undefined
1317
- };
1318
- return {
1319
- cwd,
1320
- packageJsonPath,
1321
- packageManager: inferPackageManagerId(cwd, packageJson.packageManager),
1322
- scripts: syncScripts
1323
- };
1324
- }
1325
- function findInstalledDependencyMarkerDir(projectDir) {
1326
- let currentDir = path2.resolve(projectDir);
1327
- while (true) {
1328
- if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path2.join(currentDir, marker)))) {
1329
- return currentDir;
1330
- }
1331
- const parentDir = path2.dirname(currentDir);
1332
- if (parentDir === currentDir) {
1333
- return null;
1334
- }
1335
- currentDir = parentDir;
1546
+ // src/print-block.ts
1547
+ function printBlock(printLine, lines) {
1548
+ for (const line of lines) {
1549
+ printLine(line);
1336
1550
  }
1337
1551
  }
1338
- function scriptsLikelyNeedInstalledDependencies(project, target) {
1339
- const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
1340
- project.scripts["sync-types"],
1341
- project.scripts["sync-rest"],
1342
- project.scripts["sync-ai"]
1343
- ];
1344
- return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
1345
- }
1346
- function assertSyncDependenciesInstalled(project, target) {
1347
- if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
1348
- return;
1349
- }
1350
- const markerDir = findInstalledDependencyMarkerDir(project.cwd);
1351
- if (markerDir) {
1352
- return;
1552
+
1553
+ // src/runtime-output/print.ts
1554
+ function printCompletionPayload(payload, options = {}) {
1555
+ const printLine = options.printLine ?? console.log;
1556
+ const warnLine = options.warnLine ?? printLine;
1557
+ for (const line of payload.preambleLines ?? []) {
1558
+ printLine(line);
1353
1559
  }
1354
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.DEPENDENCIES_NOT_INSTALLED, `Project dependencies have not been installed yet. Run \`${formatInstallCommand(project.packageManager)}\` from the project root before \`wp-typia sync\`. The generated sync scripts rely on local tools such as \`tsx\`.`);
1355
- }
1356
- function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
1357
- switch (packageManager) {
1358
- case "bun":
1359
- return { args: ["run", scriptName, ...extraArgs], command: "bun" };
1360
- case "npm":
1361
- return {
1362
- args: [
1363
- "run",
1364
- scriptName,
1365
- ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
1366
- ],
1367
- command: "npm"
1368
- };
1369
- case "pnpm":
1370
- return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
1371
- case "yarn":
1372
- return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
1560
+ for (const warning of payload.warningLines ?? []) {
1561
+ warnLine(formatOutputMarker("warning", warning, options.markerOptions));
1373
1562
  }
1374
- }
1375
- function createSyncPlannedCommand(project, scriptName, extraArgs) {
1376
- const script = project.scripts[scriptName];
1377
- if (!script) {
1378
- return null;
1563
+ const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
1564
+ const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
1565
+ printLine(hasLeadingContext && hasDetails ? `
1566
+ ${payload.title}` : payload.title);
1567
+ for (const line of payload.summaryLines ?? []) {
1568
+ printLine(line);
1379
1569
  }
1380
- const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
1381
- return {
1382
- args: invocation.args,
1383
- command: invocation.command,
1384
- displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
1385
- scriptName: script.scriptName
1386
- };
1387
- }
1388
- function buildSyncPlannedCommands(project, extraArgs, target) {
1389
- if (target === "ai") {
1390
- const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
1391
- if (!syncAiCommand2) {
1392
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
1570
+ if ((payload.nextSteps?.length ?? 0) > 0) {
1571
+ printLine("Next steps:");
1572
+ for (const step of payload.nextSteps ?? []) {
1573
+ printLine(` ${step}`);
1393
1574
  }
1394
- return [syncAiCommand2];
1395
- }
1396
- if (project.scripts.sync) {
1397
- return [createSyncPlannedCommand(project, "sync", extraArgs)];
1398
1575
  }
1399
- const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
1400
- if (!syncTypesCommand) {
1401
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
1402
- }
1403
- const plannedCommands = [syncTypesCommand];
1404
- const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
1405
- if (syncRestCommand) {
1406
- plannedCommands.push(syncRestCommand);
1576
+ if ((payload.optionalLines?.length ?? 0) > 0) {
1577
+ printLine(`
1578
+ ${payload.optionalTitle ?? "Optional:"}`);
1579
+ for (const step of payload.optionalLines ?? []) {
1580
+ printLine(` ${step}`);
1581
+ }
1407
1582
  }
1408
- const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
1409
- if (syncAiCommand) {
1410
- plannedCommands.push(syncAiCommand);
1583
+ if (payload.optionalNote) {
1584
+ printLine(`Note: ${payload.optionalNote}`);
1411
1585
  }
1412
- return plannedCommands;
1413
1586
  }
1414
- function runProjectScript(project, plannedCommand, options) {
1415
- const result = spawnSync(plannedCommand.command, plannedCommand.args, {
1416
- cwd: project.cwd,
1417
- encoding: options.captureOutput ? "utf8" : undefined,
1418
- ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
1419
- shell: process.platform === "win32",
1420
- stdio: options.captureOutput ? "pipe" : "inherit"
1421
- });
1422
- const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
1423
- const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
1424
- if (result.error || result.status !== 0) {
1425
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
1426
- cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
1427
- });
1428
- }
1429
- return {
1430
- ...plannedCommand,
1431
- exitCode: result.status ?? 0,
1432
- ...stderr !== undefined ? { stderr } : {},
1433
- ...stdout !== undefined ? { stdout } : {}
1434
- };
1587
+ // src/runtime-capabilities.ts
1588
+ function isInteractiveTerminal({
1589
+ stdin = process.stdin,
1590
+ stdout = process.stdout,
1591
+ term = process.env.TERM
1592
+ } = {}) {
1593
+ return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
1435
1594
  }
1436
- async function executeSyncCommand({
1437
- captureOutput = false,
1438
- check = false,
1439
- cwd,
1440
- dryRun = false,
1441
- target = "default"
1442
- }) {
1443
- const project = resolveSyncProjectContext(cwd);
1444
- const extraArgs = check ? ["--check"] : [];
1445
- const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
1446
- const result = {
1447
- check,
1448
- dryRun,
1449
- packageJsonPath: project.packageJsonPath,
1450
- packageManager: project.packageManager,
1451
- plannedCommands,
1452
- projectDir: project.cwd,
1453
- target
1454
- };
1455
- if (dryRun) {
1456
- return result;
1457
- }
1458
- assertSyncDependenciesInstalled(project, target);
1459
- result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
1460
- captureOutput
1461
- }));
1462
- return result;
1595
+ function supportsInteractiveTui(options = {}) {
1596
+ const hasBunRuntime = options.hasBunRuntime ?? typeof Bun !== "undefined";
1597
+ return hasBunRuntime && isInteractiveTerminal(options);
1463
1598
  }
1464
1599
 
1465
- // src/runtime-bridge.ts
1466
- var loadCliAddRuntime = () => import("./cli-add-6dn9h94t.js");
1600
+ // src/runtime-bridge-shared.ts
1467
1601
  var loadCliDiagnosticsRuntime = () => import("./cli-diagnostics-5dvztm7q.js");
1468
- var loadCliDoctorRuntime = () => import("./cli-doctor-564c43ay.js");
1469
- var loadCliInitRuntime = () => import("./cli-init-znhqp8tr.js");
1470
- var loadCliPromptRuntime = () => import("./cli-prompt-614tq57c.js");
1471
- var loadCliScaffoldRuntime = () => import("./cli-scaffold-6trxyyk6.js");
1472
- var loadCliTemplatesRuntime = () => import("./cli-templates-hc71dfc2.js");
1473
- var loadCreateTemplateValidationRuntime = () => import("./create-template-validation-rtec5sng.js");
1474
- var loadMigrationsRuntime = () => import("./migrations-qc1r0yqe.js");
1475
1602
  async function wrapCliCommandError(command, error) {
1476
1603
  const { createCliCommandError } = await loadCliDiagnosticsRuntime();
1477
1604
  return createCliCommandError({ command, error });
@@ -1485,6 +1612,15 @@ function shouldWrapCliCommandError(options) {
1485
1612
  }
1486
1613
  return true;
1487
1614
  }
1615
+ function emitCompletion(payload, options) {
1616
+ if (options.emitOutput) {
1617
+ printCompletionPayload(payload, {
1618
+ printLine: options.printLine,
1619
+ warnLine: options.warnLine
1620
+ });
1621
+ }
1622
+ return payload;
1623
+ }
1488
1624
  function pushFlag(argv, name, value) {
1489
1625
  if (value === undefined || value === null || value === false) {
1490
1626
  return;
@@ -1495,6 +1631,10 @@ function pushFlag(argv, name, value) {
1495
1631
  }
1496
1632
  argv.push(`--${name}`, String(value));
1497
1633
  }
1634
+
1635
+ // src/runtime-bridge-add.ts
1636
+ var loadCliAddRuntime = () => import("./cli-add-21bvpfgw.js");
1637
+ var loadCliPromptRuntime = () => import("./cli-prompt-614tq57c.js");
1498
1638
  async function executeWorkspaceAddWithOptionalDryRun(options) {
1499
1639
  const simulated = options.dryRun ? await simulateWorkspaceAddDryRun({
1500
1640
  cwd: options.cwd,
@@ -1538,6 +1678,72 @@ async function executePlannedAddKind(kind, executionContext, context) {
1538
1678
  const plan = await getAddKindExecutionPlan(kind, executionContext);
1539
1679
  return executePreparedAddKind(kind, context, plan);
1540
1680
  }
1681
+ async function executeAddCommand({
1682
+ cwd,
1683
+ emitOutput = true,
1684
+ flags,
1685
+ interactive,
1686
+ kind,
1687
+ name,
1688
+ printLine = console.log,
1689
+ prompt,
1690
+ warnLine = console.warn
1691
+ }) {
1692
+ let activePrompt;
1693
+ const dryRun = Boolean(flags["dry-run"]);
1694
+ try {
1695
+ const addRuntime = await loadCliAddRuntime();
1696
+ const isInteractiveSession = interactive ?? isInteractiveTerminal();
1697
+ if (!kind) {
1698
+ if (shouldPrintMissingAddKindHelp({ emitOutput })) {
1699
+ printLine(addRuntime.formatAddHelpText());
1700
+ }
1701
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
1702
+ }
1703
+ if (!isAddKindId(kind)) {
1704
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
1705
+ }
1706
+ if (dryRun && !supportsAddKindDryRun(kind)) {
1707
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
1708
+ }
1709
+ const executionContext = {
1710
+ addRuntime,
1711
+ cwd,
1712
+ flags,
1713
+ getOrCreatePrompt: async () => {
1714
+ if (activePrompt) {
1715
+ return activePrompt;
1716
+ }
1717
+ const { createReadlinePrompt } = await loadCliPromptRuntime();
1718
+ activePrompt = prompt ?? createReadlinePrompt();
1719
+ return activePrompt;
1720
+ },
1721
+ isInteractiveSession,
1722
+ name,
1723
+ warnLine
1724
+ };
1725
+ return await executePlannedAddKind(kind, executionContext, {
1726
+ cwd,
1727
+ dryRun,
1728
+ emitOutput,
1729
+ printLine
1730
+ });
1731
+ } catch (error) {
1732
+ if (!shouldWrapCliCommandError({ emitOutput })) {
1733
+ throw error;
1734
+ }
1735
+ throw await wrapCliCommandError("add", error);
1736
+ } finally {
1737
+ if (activePrompt && activePrompt !== prompt) {
1738
+ activePrompt.close();
1739
+ }
1740
+ }
1741
+ }
1742
+ // src/runtime-bridge-create.ts
1743
+ var loadCliPromptRuntime2 = () => import("./cli-prompt-614tq57c.js");
1744
+ var loadCliScaffoldRuntime = () => import("./cli-scaffold-zhp2ym8z.js");
1745
+ var loadCliTemplatesRuntime = () => import("./cli-templates-hc71dfc2.js");
1746
+ var loadCreateTemplateValidationRuntime = () => import("./create-template-validation-rtec5sng.js");
1541
1747
  var PACKAGE_MANAGER_PROMPT_OPTIONS = [
1542
1748
  { label: "npm", value: "npm", hint: "Use npm" },
1543
1749
  { label: "pnpm", value: "pnpm", hint: "Use pnpm" },
@@ -1564,15 +1770,6 @@ var BOOLEAN_PROMPT_OPTIONS = [
1564
1770
  { label: "Yes", value: "yes", hint: "Enable this option" },
1565
1771
  { label: "No", value: "no", hint: "Keep the default disabled state" }
1566
1772
  ];
1567
- function emitCompletion(payload, options) {
1568
- if (options.emitOutput) {
1569
- printCompletionPayload(payload, {
1570
- printLine: options.printLine,
1571
- warnLine: options.warnLine
1572
- });
1573
- }
1574
- return payload;
1575
- }
1576
1773
  async function executeCreateCommand({
1577
1774
  projectDir,
1578
1775
  cwd,
@@ -1593,7 +1790,7 @@ async function executeCreateCommand({
1593
1790
  { runScaffoldFlow },
1594
1791
  { getTemplateSelectOptions }
1595
1792
  ] = await Promise.all([
1596
- loadCliPromptRuntime(),
1793
+ loadCliPromptRuntime2(),
1597
1794
  loadCliScaffoldRuntime(),
1598
1795
  loadCliTemplatesRuntime()
1599
1796
  ]);
@@ -1663,99 +1860,23 @@ async function executeCreateCommand({
1663
1860
  }
1664
1861
  }
1665
1862
  }
1666
- async function executeAddCommand({
1667
- cwd,
1668
- emitOutput = true,
1669
- flags,
1670
- interactive,
1671
- kind,
1672
- name,
1673
- printLine = console.log,
1674
- prompt,
1675
- warnLine = console.warn
1676
- }) {
1677
- let activePrompt;
1678
- const dryRun = Boolean(flags["dry-run"]);
1863
+ // src/runtime-bridge-doctor.ts
1864
+ var loadCliDoctorRuntime = () => import("./cli-doctor-wy2yjsge.js");
1865
+ async function executeDoctorCommand(cwd) {
1679
1866
  try {
1680
- const addRuntime = await loadCliAddRuntime();
1681
- const isInteractiveSession = interactive ?? isInteractiveTerminal();
1682
- if (!kind) {
1683
- if (shouldPrintMissingAddKindHelp({ emitOutput })) {
1684
- printLine(addRuntime.formatAddHelpText());
1685
- }
1686
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
1687
- }
1688
- if (!isAddKindId(kind)) {
1689
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
1690
- }
1691
- if (dryRun && !supportsAddKindDryRun(kind)) {
1692
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
1693
- }
1694
- const executionContext = {
1695
- addRuntime,
1696
- cwd,
1697
- flags,
1698
- getOrCreatePrompt: async () => {
1699
- if (activePrompt) {
1700
- return activePrompt;
1701
- }
1702
- const { createReadlinePrompt } = await loadCliPromptRuntime();
1703
- activePrompt = prompt ?? createReadlinePrompt();
1704
- return activePrompt;
1705
- },
1706
- isInteractiveSession,
1707
- name,
1708
- warnLine
1709
- };
1710
- return await executePlannedAddKind(kind, executionContext, {
1711
- cwd,
1712
- dryRun,
1713
- emitOutput,
1714
- printLine
1715
- });
1867
+ const { runDoctor } = await loadCliDoctorRuntime();
1868
+ await runDoctor(cwd);
1716
1869
  } catch (error) {
1717
- if (!shouldWrapCliCommandError({ emitOutput })) {
1718
- throw error;
1719
- }
1720
- throw await wrapCliCommandError("add", error);
1721
- } finally {
1722
- if (activePrompt && activePrompt !== prompt) {
1723
- activePrompt.close();
1724
- }
1725
- }
1726
- }
1727
- async function executeTemplatesCommand({ flags }, printLine = console.log) {
1728
- const {
1729
- formatTemplateDetails,
1730
- formatTemplateFeatures,
1731
- formatTemplateSummary,
1732
- getTemplateById,
1733
- listTemplates
1734
- } = await loadCliTemplatesRuntime();
1735
- const subcommand = flags.subcommand ?? "list";
1736
- if (subcommand === "list") {
1737
- for (const template of listTemplates()) {
1738
- printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
1739
- }
1740
- return;
1741
- }
1742
- if (subcommand === "inspect") {
1743
- if (!flags.id) {
1744
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
1745
- }
1746
- const template = getTemplateById(flags.id);
1747
- if (!template) {
1748
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
1749
- }
1750
- printBlock(printLine, [formatTemplateDetails(template)]);
1751
- return;
1870
+ throw await wrapCliCommandError("doctor", error);
1752
1871
  }
1753
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
1754
1872
  }
1873
+ // src/runtime-bridge-init.ts
1874
+ import path2 from "path";
1875
+ var loadCliInitRuntime = () => import("./cli-init-xnsbxncv.js");
1755
1876
  async function executeInitCommand({ apply, cwd, packageManager, projectDir }, options = {}) {
1756
1877
  try {
1757
1878
  const { runInitCommand } = await loadCliInitRuntime();
1758
- const resolvedProjectDir = projectDir ? (await import("path")).resolve(cwd, projectDir) : cwd;
1879
+ const resolvedProjectDir = projectDir ? path2.resolve(cwd, projectDir) : cwd;
1759
1880
  const plan = await runInitCommand({
1760
1881
  apply,
1761
1882
  packageManager,
@@ -1776,27 +1897,28 @@ async function executeInitCommand({ apply, cwd, packageManager, projectDir }, op
1776
1897
  throw await wrapCliCommandError("init", error);
1777
1898
  }
1778
1899
  }
1779
- async function executeDoctorCommand(cwd) {
1780
- try {
1781
- const { runDoctor } = await loadCliDoctorRuntime();
1782
- await runDoctor(cwd);
1783
- } catch (error) {
1784
- throw await wrapCliCommandError("doctor", error);
1785
- }
1786
- }
1900
+ // src/runtime-bridge-migrate.ts
1901
+ var loadMigrationsRuntime = () => import("./migrations-bx0yvc2v.js");
1902
+ var defaultPrintLine2 = (line) => {
1903
+ process.stdout.write(`${line}
1904
+ `);
1905
+ };
1787
1906
  async function executeMigrateCommand({
1788
1907
  command,
1789
1908
  cwd,
1790
1909
  flags,
1910
+ printLine = defaultPrintLine2,
1791
1911
  prompt,
1792
1912
  renderLine
1793
1913
  }) {
1794
- const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
1795
- if (!command) {
1796
- console.log(formatMigrationHelpText());
1797
- return;
1798
- }
1799
1914
  try {
1915
+ const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
1916
+ const outputLine = renderLine ?? printLine;
1917
+ if (!command) {
1918
+ const helpText = formatMigrationHelpText();
1919
+ outputLine(helpText);
1920
+ return;
1921
+ }
1800
1922
  const argv = [command];
1801
1923
  pushFlag(argv, "all", flags.all);
1802
1924
  pushFlag(argv, "force", flags.force);
@@ -1810,11 +1932,7 @@ async function executeMigrateCommand({
1810
1932
  const lines = renderLine ? [] : null;
1811
1933
  const captureLine = (line) => {
1812
1934
  lines?.push(line);
1813
- if (renderLine) {
1814
- renderLine(line);
1815
- return;
1816
- }
1817
- console.log(line);
1935
+ outputLine(line);
1818
1936
  };
1819
1937
  const result = await runMigrationCommand(parsed, cwd, {
1820
1938
  prompt,
@@ -1836,11 +1954,246 @@ async function executeMigrateCommand({
1836
1954
  throw await wrapCliCommandError("migrate", error);
1837
1955
  }
1838
1956
  }
1957
+ // src/runtime-bridge-templates.ts
1958
+ var loadCliTemplatesRuntime2 = () => import("./cli-templates-hc71dfc2.js");
1959
+ async function executeTemplatesCommand({ flags }, printLine = console.log) {
1960
+ const {
1961
+ formatTemplateDetails,
1962
+ formatTemplateFeatures,
1963
+ formatTemplateSummary,
1964
+ getTemplateById,
1965
+ listTemplates
1966
+ } = await loadCliTemplatesRuntime2();
1967
+ const subcommand = flags.subcommand ?? "list";
1968
+ if (subcommand === "list") {
1969
+ for (const template of listTemplates()) {
1970
+ printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
1971
+ }
1972
+ return;
1973
+ }
1974
+ if (subcommand === "inspect") {
1975
+ if (!flags.id) {
1976
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
1977
+ }
1978
+ const template = getTemplateById(flags.id);
1979
+ if (!template) {
1980
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
1981
+ }
1982
+ printBlock(printLine, [formatTemplateDetails(template)]);
1983
+ return;
1984
+ }
1985
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
1986
+ }
1839
1987
  async function listTemplatesForRuntime() {
1840
- const { listTemplates } = await loadCliTemplatesRuntime();
1988
+ const { listTemplates } = await loadCliTemplatesRuntime2();
1841
1989
  return listTemplates();
1842
1990
  }
1843
-
1991
+ // src/runtime-bridge-sync.ts
1992
+ import { spawnSync } from "child_process";
1993
+ import fs3 from "fs";
1994
+ import path3 from "path";
1995
+ var SYNC_INSTALL_MARKERS = [
1996
+ "node_modules",
1997
+ ".pnp.cjs",
1998
+ ".pnp.loader.mjs"
1999
+ ];
2000
+ var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
2001
+ var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
2002
+ function resolveSyncExecutionTarget(subcommand) {
2003
+ if (!subcommand) {
2004
+ return "default";
2005
+ }
2006
+ if (subcommand === "ai") {
2007
+ return "ai";
2008
+ }
2009
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
2010
+ }
2011
+ function getSyncRootError(cwd) {
2012
+ return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.OUTSIDE_PROJECT_ROOT, `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.`);
2013
+ }
2014
+ function readSyncPackageJson(packageJsonPath) {
2015
+ const source = fs3.readFileSync(packageJsonPath, "utf8");
2016
+ try {
2017
+ return JSON.parse(source);
2018
+ } catch (error) {
2019
+ const message = error instanceof Error ? error.message : String(error);
2020
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unable to parse ${packageJsonPath}: ${message}`, error instanceof Error ? { cause: error } : undefined);
2021
+ }
2022
+ }
2023
+ function resolveSyncProjectContext(cwd) {
2024
+ const packageJsonPath = path3.join(cwd, "package.json");
2025
+ if (!fs3.existsSync(packageJsonPath)) {
2026
+ throw getSyncRootError(cwd);
2027
+ }
2028
+ const packageJson = readSyncPackageJson(packageJsonPath);
2029
+ const scripts = packageJson.scripts ?? {};
2030
+ const syncScripts = {
2031
+ sync: typeof scripts.sync === "string" ? {
2032
+ command: scripts.sync,
2033
+ scriptName: "sync"
2034
+ } : undefined,
2035
+ "sync-ai": typeof scripts["sync-ai"] === "string" ? {
2036
+ command: scripts["sync-ai"],
2037
+ scriptName: "sync-ai"
2038
+ } : typeof scripts["sync-wordpress-ai"] === "string" ? {
2039
+ command: scripts["sync-wordpress-ai"],
2040
+ scriptName: "sync-wordpress-ai"
2041
+ } : undefined,
2042
+ "sync-rest": typeof scripts["sync-rest"] === "string" ? {
2043
+ command: scripts["sync-rest"],
2044
+ scriptName: "sync-rest"
2045
+ } : undefined,
2046
+ "sync-types": typeof scripts["sync-types"] === "string" ? {
2047
+ command: scripts["sync-types"],
2048
+ scriptName: "sync-types"
2049
+ } : undefined
2050
+ };
2051
+ return {
2052
+ cwd,
2053
+ packageJsonPath,
2054
+ packageManager: inferPackageManagerId(cwd, packageJson.packageManager),
2055
+ scripts: syncScripts
2056
+ };
2057
+ }
2058
+ function findInstalledDependencyMarkerDir(projectDir) {
2059
+ let currentDir = path3.resolve(projectDir);
2060
+ while (true) {
2061
+ if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path3.join(currentDir, marker)))) {
2062
+ return currentDir;
2063
+ }
2064
+ const parentDir = path3.dirname(currentDir);
2065
+ if (parentDir === currentDir) {
2066
+ return null;
2067
+ }
2068
+ currentDir = parentDir;
2069
+ }
2070
+ }
2071
+ function scriptsLikelyNeedInstalledDependencies(project, target) {
2072
+ const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
2073
+ project.scripts["sync-types"],
2074
+ project.scripts["sync-rest"],
2075
+ project.scripts["sync-ai"]
2076
+ ];
2077
+ return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
2078
+ }
2079
+ function assertSyncDependenciesInstalled(project, target) {
2080
+ if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
2081
+ return;
2082
+ }
2083
+ const markerDir = findInstalledDependencyMarkerDir(project.cwd);
2084
+ if (markerDir) {
2085
+ return;
2086
+ }
2087
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.DEPENDENCIES_NOT_INSTALLED, `Project dependencies have not been installed yet. Run \`${formatInstallCommand(project.packageManager)}\` from the project root before \`wp-typia sync\`. The generated sync scripts rely on local tools such as \`tsx\`.`);
2088
+ }
2089
+ function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
2090
+ switch (packageManager) {
2091
+ case "bun":
2092
+ return { args: ["run", scriptName, ...extraArgs], command: "bun" };
2093
+ case "npm":
2094
+ return {
2095
+ args: [
2096
+ "run",
2097
+ scriptName,
2098
+ ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
2099
+ ],
2100
+ command: "npm"
2101
+ };
2102
+ case "pnpm":
2103
+ return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
2104
+ case "yarn":
2105
+ return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
2106
+ }
2107
+ }
2108
+ function createSyncPlannedCommand(project, scriptName, extraArgs) {
2109
+ const script = project.scripts[scriptName];
2110
+ if (!script) {
2111
+ return null;
2112
+ }
2113
+ const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
2114
+ return {
2115
+ args: invocation.args,
2116
+ command: invocation.command,
2117
+ displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
2118
+ scriptName: script.scriptName
2119
+ };
2120
+ }
2121
+ function buildSyncPlannedCommands(project, extraArgs, target) {
2122
+ if (target === "ai") {
2123
+ const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2124
+ if (!syncAiCommand2) {
2125
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
2126
+ }
2127
+ return [syncAiCommand2];
2128
+ }
2129
+ if (project.scripts.sync) {
2130
+ return [createSyncPlannedCommand(project, "sync", extraArgs)];
2131
+ }
2132
+ const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
2133
+ if (!syncTypesCommand) {
2134
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
2135
+ }
2136
+ const plannedCommands = [syncTypesCommand];
2137
+ const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
2138
+ if (syncRestCommand) {
2139
+ plannedCommands.push(syncRestCommand);
2140
+ }
2141
+ const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2142
+ if (syncAiCommand) {
2143
+ plannedCommands.push(syncAiCommand);
2144
+ }
2145
+ return plannedCommands;
2146
+ }
2147
+ function runProjectScript(project, plannedCommand, options) {
2148
+ const result = spawnSync(plannedCommand.command, plannedCommand.args, {
2149
+ cwd: project.cwd,
2150
+ encoding: options.captureOutput ? "utf8" : undefined,
2151
+ ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
2152
+ shell: process.platform === "win32",
2153
+ stdio: options.captureOutput ? "pipe" : "inherit"
2154
+ });
2155
+ const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
2156
+ const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
2157
+ if (result.error || result.status !== 0) {
2158
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
2159
+ cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
2160
+ });
2161
+ }
2162
+ return {
2163
+ ...plannedCommand,
2164
+ exitCode: result.status ?? 0,
2165
+ ...stderr !== undefined ? { stderr } : {},
2166
+ ...stdout !== undefined ? { stdout } : {}
2167
+ };
2168
+ }
2169
+ async function executeSyncCommand({
2170
+ captureOutput = false,
2171
+ check = false,
2172
+ cwd,
2173
+ dryRun = false,
2174
+ target = "default"
2175
+ }) {
2176
+ const project = resolveSyncProjectContext(cwd);
2177
+ const extraArgs = check ? ["--check"] : [];
2178
+ const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
2179
+ const result = {
2180
+ check,
2181
+ dryRun,
2182
+ packageJsonPath: project.packageJsonPath,
2183
+ packageManager: project.packageManager,
2184
+ plannedCommands,
2185
+ projectDir: project.cwd,
2186
+ target
2187
+ };
2188
+ if (dryRun) {
2189
+ return result;
2190
+ }
2191
+ assertSyncDependenciesInstalled(project, target);
2192
+ result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
2193
+ captureOutput
2194
+ }));
2195
+ return result;
2196
+ }
1844
2197
  // src/ui/lazy-flow.tsx
1845
2198
  var import_react33 = __toESM(require_react(), 1);
1846
2199
 
@@ -2270,9 +2623,10 @@ function loadAddFlow() {
2270
2623
  var addOptions = buildCommandOptions(ADD_OPTION_METADATA);
2271
2624
  var addCommand = defineCommand({
2272
2625
  defaultFormat: "toon",
2273
- description: "Extend an official wp-typia workspace with blocks, variations, block styles, transforms, patterns, binding sources, plugin-level REST resources, workflow abilities, server-only AI features, editor plugins, or hooked blocks.",
2626
+ description: "Extend an official wp-typia workspace with blocks, integration envs, variations, block styles, transforms, patterns, binding sources, standalone contracts, plugin-level REST resources, post meta contracts, workflow abilities, server-only AI features, editor plugins, or hooked blocks.",
2274
2627
  handler: async (args) => {
2275
2628
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2629
+ const { printLine, warnLine } = resolveCommandOutputAdapters(args);
2276
2630
  try {
2277
2631
  if (prefersStructuredOutput) {
2278
2632
  const completion = await executeAddCommand({
@@ -2281,7 +2635,9 @@ var addCommand = defineCommand({
2281
2635
  flags: args.flags,
2282
2636
  interactive: false,
2283
2637
  kind: args.positional[0],
2284
- name: args.positional[1]
2638
+ name: args.positional[1],
2639
+ printLine,
2640
+ warnLine
2285
2641
  });
2286
2642
  args.output(buildStructuredCompletionSuccessPayload("add", completion, {
2287
2643
  dryRun: Boolean(args.flags["dry-run"]),
@@ -2295,7 +2651,9 @@ var addCommand = defineCommand({
2295
2651
  cwd: args.cwd,
2296
2652
  flags: args.flags,
2297
2653
  kind: args.positional[0],
2298
- name: args.positional[1]
2654
+ name: args.positional[1],
2655
+ printLine,
2656
+ warnLine
2299
2657
  });
2300
2658
  } catch (error) {
2301
2659
  emitCliDiagnosticFailure(args, {
@@ -2353,6 +2711,7 @@ var createCommand = defineCommand({
2353
2711
  description: "Scaffold a new wp-typia project.",
2354
2712
  handler: async (args) => {
2355
2713
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2714
+ const { printLine, warnLine } = resolveCommandOutputAdapters(args);
2356
2715
  const projectDir = args.positional[0];
2357
2716
  if (!projectDir) {
2358
2717
  emitCliDiagnosticFailure(args, {
@@ -2368,7 +2727,9 @@ var createCommand = defineCommand({
2368
2727
  emitOutput: !prefersStructuredOutput,
2369
2728
  flags: args.flags,
2370
2729
  interactive: prefersStructuredOutput ? false : undefined,
2371
- projectDir
2730
+ printLine,
2731
+ projectDir,
2732
+ warnLine
2372
2733
  });
2373
2734
  if (prefersStructuredOutput) {
2374
2735
  args.output(buildStructuredCompletionSuccessPayload("create", completion, {
@@ -2420,7 +2781,7 @@ var doctorCommand = defineCommand({
2420
2781
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2421
2782
  if (prefersStructuredOutput) {
2422
2783
  const [{ getDoctorChecks }, { getDoctorFailureDetailLines }] = await Promise.all([
2423
- import("./cli-doctor-564c43ay.js"),
2784
+ import("./cli-doctor-wy2yjsge.js"),
2424
2785
  import("./cli-diagnostics-5dvztm7q.js")
2425
2786
  ]);
2426
2787
  const checks = await getDoctorChecks(args.cwd);
@@ -2456,13 +2817,18 @@ var initCommand = defineCommand({
2456
2817
  description: "Preview or apply the minimum wp-typia retrofit plan for an existing project.",
2457
2818
  handler: async (args) => {
2458
2819
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2820
+ const { printLine, warnLine } = resolveCommandOutputAdapters(args);
2459
2821
  try {
2460
2822
  const plan = await executeInitCommand({
2461
2823
  apply: Boolean(args.flags.apply),
2462
2824
  cwd: args.cwd,
2463
2825
  packageManager: typeof args.flags["package-manager"] === "string" ? args.flags["package-manager"] : undefined,
2464
2826
  projectDir: args.positional[0]
2465
- }, { emitOutput: !prefersStructuredOutput });
2827
+ }, {
2828
+ emitOutput: !prefersStructuredOutput,
2829
+ printLine,
2830
+ warnLine
2831
+ });
2466
2832
  if (prefersStructuredOutput) {
2467
2833
  args.output(buildStructuredInitSuccessPayload(plan));
2468
2834
  }
@@ -2479,7 +2845,7 @@ var initCommand = defineCommand({
2479
2845
 
2480
2846
  // src/mcp.ts
2481
2847
  import fs4 from "fs/promises";
2482
- import path3 from "path";
2848
+ import path4 from "path";
2483
2849
 
2484
2850
  // ../../node_modules/.bun/@bunli+plugin-mcp@0.2.5+ef72ce197b058209/node_modules/@bunli/plugin-mcp/src/errors.ts
2485
2851
  class SchemaConversionError extends TaggedError("SchemaConversionError")() {
@@ -2498,7 +2864,7 @@ class McpToolsProviderError extends TaggedError("McpToolsProviderError")() {
2498
2864
  function jsonSchemaToZodSchema(schema, options = {}) {
2499
2865
  return convertSchema(schema, options, "$");
2500
2866
  }
2501
- function convertSchema(schema, options, path3) {
2867
+ function convertSchema(schema, options, path4) {
2502
2868
  const { coerce = true } = options;
2503
2869
  if (!schema || typeof schema !== "object") {
2504
2870
  return Result.ok(exports_external.unknown());
@@ -2513,49 +2879,49 @@ function convertSchema(schema, options, path3) {
2513
2879
  return Result.ok(exports_external.enum(enumValues));
2514
2880
  }
2515
2881
  const literals = enumValues.map((v) => exports_external.literal(v));
2516
- return unionFromSchemas(literals, path3);
2882
+ return unionFromSchemas(literals, path4);
2517
2883
  }
2518
2884
  }
2519
2885
  if (schema.anyOf && schema.anyOf.length > 0) {
2520
- const schemas = mapSchemas(schema.anyOf, options, `${path3}.anyOf`);
2886
+ const schemas = mapSchemas(schema.anyOf, options, `${path4}.anyOf`);
2521
2887
  if (Result.isError(schemas)) {
2522
2888
  return schemas;
2523
2889
  }
2524
- return unionFromSchemas(schemas.value, `${path3}.anyOf`);
2890
+ return unionFromSchemas(schemas.value, `${path4}.anyOf`);
2525
2891
  }
2526
2892
  if (schema.oneOf && schema.oneOf.length > 0) {
2527
- const schemas = mapSchemas(schema.oneOf, options, `${path3}.oneOf`);
2893
+ const schemas = mapSchemas(schema.oneOf, options, `${path4}.oneOf`);
2528
2894
  if (Result.isError(schemas)) {
2529
2895
  return schemas;
2530
2896
  }
2531
- return unionFromSchemas(schemas.value, `${path3}.oneOf`);
2897
+ return unionFromSchemas(schemas.value, `${path4}.oneOf`);
2532
2898
  }
2533
2899
  const schemaType = Array.isArray(schema.type) ? schema.type[0] : schema.type;
2534
2900
  switch (schemaType) {
2535
2901
  case "string":
2536
- return buildStringSchema(schema, path3);
2902
+ return buildStringSchema(schema, path4);
2537
2903
  case "number":
2538
2904
  case "integer":
2539
2905
  return Result.ok(buildNumberSchema(schema, coerce));
2540
2906
  case "boolean":
2541
2907
  return Result.ok(buildBooleanSchema());
2542
2908
  case "array":
2543
- return buildArraySchema(schema, options, path3);
2909
+ return buildArraySchema(schema, options, path4);
2544
2910
  case "object":
2545
- return buildObjectSchema(schema, options, path3);
2911
+ return buildObjectSchema(schema, options, path4);
2546
2912
  case "null":
2547
2913
  return Result.ok(exports_external.null());
2548
2914
  default:
2549
2915
  if (schema.properties) {
2550
- return buildObjectSchema(schema, options, path3);
2916
+ return buildObjectSchema(schema, options, path4);
2551
2917
  }
2552
2918
  if (schema.items) {
2553
- return buildArraySchema(schema, options, path3);
2919
+ return buildArraySchema(schema, options, path4);
2554
2920
  }
2555
2921
  return Result.ok(exports_external.unknown());
2556
2922
  }
2557
2923
  }
2558
- function buildStringSchema(schema, path3) {
2924
+ function buildStringSchema(schema, path4) {
2559
2925
  let zodSchema = exports_external.string();
2560
2926
  if (schema.minLength !== undefined) {
2561
2927
  zodSchema = zodSchema.min(schema.minLength);
@@ -2568,7 +2934,7 @@ function buildStringSchema(schema, path3) {
2568
2934
  const regexResult = Result.try({
2569
2935
  try: () => new RegExp(pattern),
2570
2936
  catch: (cause) => new SchemaConversionError({
2571
- path: path3,
2937
+ path: path4,
2572
2938
  message: `Invalid regex pattern "${pattern}"`,
2573
2939
  cause
2574
2940
  })
@@ -2625,19 +2991,19 @@ function buildNumberSchema(schema, coerce) {
2625
2991
  function buildBooleanSchema() {
2626
2992
  return exports_external.boolean();
2627
2993
  }
2628
- function buildArraySchema(schema, options, path3) {
2994
+ function buildArraySchema(schema, options, path4) {
2629
2995
  let itemSchema = exports_external.unknown();
2630
2996
  if (schema.items) {
2631
2997
  if (Array.isArray(schema.items)) {
2632
2998
  if (schema.items.length > 0) {
2633
- const itemResult = convertSchema(schema.items[0], options, `${path3}.items[0]`);
2999
+ const itemResult = convertSchema(schema.items[0], options, `${path4}.items[0]`);
2634
3000
  if (Result.isError(itemResult)) {
2635
3001
  return itemResult;
2636
3002
  }
2637
3003
  itemSchema = itemResult.value;
2638
3004
  }
2639
3005
  } else {
2640
- const itemResult = convertSchema(schema.items, options, `${path3}.items`);
3006
+ const itemResult = convertSchema(schema.items, options, `${path4}.items`);
2641
3007
  if (Result.isError(itemResult)) {
2642
3008
  return itemResult;
2643
3009
  }
@@ -2653,14 +3019,14 @@ function buildArraySchema(schema, options, path3) {
2653
3019
  }
2654
3020
  return Result.ok(zodSchema);
2655
3021
  }
2656
- function buildObjectSchema(schema, options, path3) {
3022
+ function buildObjectSchema(schema, options, path4) {
2657
3023
  if (!schema.properties) {
2658
3024
  return Result.ok(exports_external.record(exports_external.string(), exports_external.unknown()));
2659
3025
  }
2660
3026
  const shape = {};
2661
3027
  const requiredFields = new Set(schema.required || []);
2662
3028
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
2663
- const propResult = convertSchema(propSchema, options, `${path3}.properties.${propName}`);
3029
+ const propResult = convertSchema(propSchema, options, `${path4}.properties.${propName}`);
2664
3030
  if (Result.isError(propResult)) {
2665
3031
  return propResult;
2666
3032
  }
@@ -2675,10 +3041,10 @@ function buildObjectSchema(schema, options, path3) {
2675
3041
  }
2676
3042
  return Result.ok(exports_external.object(shape));
2677
3043
  }
2678
- function mapSchemas(schemas, options, path3) {
3044
+ function mapSchemas(schemas, options, path4) {
2679
3045
  const zodSchemas = [];
2680
3046
  for (let index = 0;index < schemas.length; index += 1) {
2681
- const converted = convertSchema(schemas[index], options, `${path3}[${index}]`);
3047
+ const converted = convertSchema(schemas[index], options, `${path4}[${index}]`);
2682
3048
  if (Result.isError(converted)) {
2683
3049
  return converted;
2684
3050
  }
@@ -2686,11 +3052,11 @@ function mapSchemas(schemas, options, path3) {
2686
3052
  }
2687
3053
  return Result.ok(zodSchemas);
2688
3054
  }
2689
- function unionFromSchemas(schemas, path3) {
3055
+ function unionFromSchemas(schemas, path4) {
2690
3056
  if (schemas.length === 0) {
2691
3057
  return Result.err(new SchemaConversionError({
2692
- path: path3,
2693
- message: `Cannot create union from an empty schema set at ${path3}`,
3058
+ path: path4,
3059
+ message: `Cannot create union from an empty schema set at ${path4}`,
2694
3060
  cause: new Error("Empty schema union")
2695
3061
  }));
2696
3062
  }
@@ -3013,7 +3379,7 @@ function getErrorCauseOptions(error) {
3013
3379
  return error instanceof Error ? { cause: error } : undefined;
3014
3380
  }
3015
3381
  async function readSchemaSource(cwd, source) {
3016
- const schemaPath = path3.resolve(cwd, source.path);
3382
+ const schemaPath = path4.resolve(cwd, source.path);
3017
3383
  const raw = await fs4.readFile(schemaPath, "utf8");
3018
3384
  let parsed;
3019
3385
  try {
@@ -3035,7 +3401,7 @@ async function readSchemaSource(cwd, source) {
3035
3401
  async function loadMcpToolGroups(cwd, schemaSources) {
3036
3402
  return Promise.all(schemaSources.map((source) => readSchemaSource(cwd, source)));
3037
3403
  }
3038
- async function syncMcpSchemas(cwd, schemaSources, outputDir = path3.join(cwd, ".bunli", "mcp")) {
3404
+ async function syncMcpSchemas(cwd, schemaSources, outputDir = path4.join(cwd, ".bunli", "mcp")) {
3039
3405
  const groups = await loadMcpToolGroups(cwd, schemaSources);
3040
3406
  const result = await generateMCPTypes({
3041
3407
  outputDir,
@@ -3058,7 +3424,7 @@ async function syncMcpSchemas(cwd, schemaSources, outputDir = path3.join(cwd, ".
3058
3424
  }
3059
3425
  }
3060
3426
  await fs4.mkdir(outputDir, { recursive: true });
3061
- await fs4.writeFile(path3.join(outputDir, "registry.json"), `${JSON.stringify(registry, null, 2)}
3427
+ await fs4.writeFile(path4.join(outputDir, "registry.json"), `${JSON.stringify(registry, null, 2)}
3062
3428
  `, "utf8");
3063
3429
  return {
3064
3430
  commandCount: registry.reduce((count, group) => count + group.tools.length, 0),
@@ -3068,12 +3434,24 @@ async function syncMcpSchemas(cwd, schemaSources, outputDir = path3.join(cwd, ".
3068
3434
  }
3069
3435
 
3070
3436
  // src/commands/mcp.ts
3437
+ function printMcpToolGroupSummary(summary, printLine) {
3438
+ for (const group of summary) {
3439
+ printLine(`${group.namespace} (${group.toolCount})`);
3440
+ for (const tool of group.tools) {
3441
+ printLine(` - ${tool}`);
3442
+ }
3443
+ }
3444
+ }
3445
+ function printMcpSyncSummary(result, printLine) {
3446
+ printLine(`Synced ${result.commandCount} MCP tools across ${result.groups.length} namespaces into ${result.outputDir}.`);
3447
+ }
3071
3448
  var mcpCommand = defineCommand({
3072
3449
  defaultFormat: "json",
3073
3450
  description: "Inspect or sync schema-driven MCP metadata for wp-typia.",
3074
3451
  handler: async (args) => {
3075
3452
  const subcommand = args.positional[0] ?? "list";
3076
3453
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
3454
+ const printLine = resolveCommandPrintLine(args);
3077
3455
  const userConfig = args.context?.store?.wpTypiaUserConfig && typeof args.context.store.wpTypiaUserConfig === "object" ? args.context.store.wpTypiaUserConfig : {};
3078
3456
  const schemaSources = getMcpSchemaSources(userConfig);
3079
3457
  if (schemaSources.length === 0) {
@@ -3098,12 +3476,7 @@ var mcpCommand = defineCommand({
3098
3476
  args.output({ groups: summary });
3099
3477
  return;
3100
3478
  }
3101
- for (const group of summary) {
3102
- console.log(`${group.namespace} (${group.toolCount})`);
3103
- for (const tool of group.tools) {
3104
- console.log(` - ${tool}`);
3105
- }
3106
- }
3479
+ printMcpToolGroupSummary(summary, printLine);
3107
3480
  return;
3108
3481
  }
3109
3482
  if (subcommand === "sync") {
@@ -3113,7 +3486,7 @@ var mcpCommand = defineCommand({
3113
3486
  args.output({ sync: result });
3114
3487
  return;
3115
3488
  }
3116
- console.log(`Synced ${result.commandCount} MCP tools across ${result.groups.length} namespaces into ${result.outputDir}.`);
3489
+ printMcpSyncSummary(result, printLine);
3117
3490
  return;
3118
3491
  }
3119
3492
  emitCliDiagnosticFailure(args, {
@@ -3150,11 +3523,13 @@ var migrateCommand = defineCommand({
3150
3523
  defaultFormat: "toon",
3151
3524
  description: "Run migration workflows for migration-capable wp-typia projects.",
3152
3525
  handler: async (args) => {
3526
+ const printLine = resolveCommandPrintLine(args);
3153
3527
  try {
3154
3528
  await executeMigrateCommand({
3155
3529
  command: args.positional[0],
3156
3530
  cwd: args.cwd,
3157
- flags: args.flags
3531
+ flags: args.flags,
3532
+ printLine
3158
3533
  });
3159
3534
  } catch (error) {
3160
3535
  emitCliDiagnosticFailure(args, {
@@ -3239,6 +3614,7 @@ var templatesCommand = defineCommand({
3239
3614
  const id = args.positional[1] ?? args.flags.id;
3240
3615
  const effectiveSubcommand = subcommand === "list" && typeof id === "string" && id.length > 0 ? "inspect" : subcommand;
3241
3616
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
3617
+ const printLine = resolveCommandPrintLine(args);
3242
3618
  try {
3243
3619
  if (prefersStructuredOutput) {
3244
3620
  const templates = await listTemplatesForRuntime();
@@ -3269,7 +3645,7 @@ var templatesCommand = defineCommand({
3269
3645
  }
3270
3646
  await executeTemplatesCommand({
3271
3647
  flags: { id, subcommand: effectiveSubcommand }
3272
- });
3648
+ }, printLine);
3273
3649
  } catch (error) {
3274
3650
  emitCliDiagnosticFailure(args, {
3275
3651
  command: "templates",
@@ -3297,4 +3673,4 @@ export {
3297
3673
  wpTypiaCommands
3298
3674
  };
3299
3675
 
3300
- //# debugId=1A737B9B812DF37F64756E2164756E21
3676
+ //# debugId=5AAD37B0D7C6B20F64756E2164756E21