wp-typia 0.22.8 → 0.22.10

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.
@@ -3,7 +3,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "wp-typia",
6
- version: "0.22.8",
6
+ version: "0.22.10",
7
7
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
8
8
  packageManager: "bun@1.3.11",
9
9
  type: "module",
@@ -73,7 +73,7 @@ var package_default = {
73
73
  "@bunli/tui": "0.6.0",
74
74
  "@bunli/utils": "0.6.0",
75
75
  "@wp-typia/api-client": "^0.4.5",
76
- "@wp-typia/project-tools": "0.22.8",
76
+ "@wp-typia/project-tools": "0.22.10",
77
77
  "better-result": "^2.7.0",
78
78
  react: "^19.2.5",
79
79
  "react-dom": "^19.2.5",
@@ -97,7 +97,7 @@ var package_default = {
97
97
 
98
98
  // src/node-cli.ts
99
99
  import {
100
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES11,
100
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES13,
101
101
  createCliCommandError as createCliCommandError5,
102
102
  formatCliDiagnosticError,
103
103
  serializeCliDiagnosticError as serializeCliDiagnosticError2
@@ -109,6 +109,84 @@ import {
109
109
  CLI_DIAGNOSTIC_CODES,
110
110
  createCliDiagnosticCodeError
111
111
  } from "@wp-typia/project-tools/cli-diagnostics";
112
+
113
+ // src/command-options/add.ts
114
+ var ADD_OPTION_METADATA = {
115
+ "alternate-render-targets": {
116
+ description: "Comma-separated alternate render targets for dynamic block scaffolds (email,mjml,plain-text).",
117
+ type: "string"
118
+ },
119
+ anchor: {
120
+ description: "Anchor block name for hooked-block workflows.",
121
+ type: "string"
122
+ },
123
+ attribute: {
124
+ description: "Target block attribute for end-to-end binding-source workflows.",
125
+ type: "string"
126
+ },
127
+ block: {
128
+ description: "Target block slug for variation, style, and end-to-end binding-source workflows.",
129
+ type: "string"
130
+ },
131
+ "data-storage": {
132
+ description: "Persistence storage mode for persistence-capable templates.",
133
+ type: "string"
134
+ },
135
+ "dry-run": {
136
+ argumentKind: "flag",
137
+ description: "Preview workspace file updates and completion guidance without writing them.",
138
+ type: "boolean"
139
+ },
140
+ "external-layer-id": {
141
+ description: "Explicit layer id when an external layer package exposes multiple selectable layers.",
142
+ type: "string"
143
+ },
144
+ "external-layer-source": {
145
+ description: "Local path, GitHub locator, or npm package that exposes wp-typia.layers.json for built-in block templates.",
146
+ type: "string"
147
+ },
148
+ from: {
149
+ description: "Source full block name (namespace/block) for transform workflows.",
150
+ type: "string"
151
+ },
152
+ "inner-blocks-preset": {
153
+ description: "Compound-only InnerBlocks preset (freeform, ordered, horizontal, locked-structure).",
154
+ type: "string"
155
+ },
156
+ methods: {
157
+ description: "Comma-separated REST resource methods for rest-resource workflows.",
158
+ type: "string"
159
+ },
160
+ namespace: {
161
+ description: "REST namespace for rest-resource and ai-feature workflows.",
162
+ type: "string"
163
+ },
164
+ "persistence-policy": {
165
+ description: "Persistence write policy for persistence-capable templates.",
166
+ type: "string"
167
+ },
168
+ position: {
169
+ description: "Hook position for hooked-block workflows.",
170
+ type: "string"
171
+ },
172
+ slot: {
173
+ description: "Document editor shell slot for editor-plugin workflows (sidebar or document-setting-panel).",
174
+ type: "string"
175
+ },
176
+ source: {
177
+ description: "Optional data source locator for admin-view workflows, such as rest-resource:products or core-data:postType/post.",
178
+ type: "string"
179
+ },
180
+ template: {
181
+ description: "Optional built-in block family for the new block; interactive flows let you choose it when omitted and non-interactive runs default to basic.",
182
+ type: "string"
183
+ },
184
+ to: {
185
+ description: "Target workspace block slug or full block name for transform workflows.",
186
+ type: "string"
187
+ }
188
+ };
189
+ // src/command-options/create.ts
112
190
  var CREATE_OPTION_METADATA = {
113
191
  "alternate-render-targets": {
114
192
  description: "Comma-separated alternate render targets for dynamic block scaffolds (email,mjml,plain-text).",
@@ -196,81 +274,30 @@ var CREATE_OPTION_METADATA = {
196
274
  type: "boolean"
197
275
  }
198
276
  };
199
- var ADD_OPTION_METADATA = {
200
- "alternate-render-targets": {
201
- description: "Comma-separated alternate render targets for dynamic block scaffolds (email,mjml,plain-text).",
202
- type: "string"
203
- },
204
- anchor: {
205
- description: "Anchor block name for hooked-block workflows.",
206
- type: "string"
207
- },
208
- attribute: {
209
- description: "Target block attribute for end-to-end binding-source workflows.",
210
- type: "string"
211
- },
212
- block: {
213
- description: "Target block slug for variation, style, and end-to-end binding-source workflows.",
214
- type: "string"
215
- },
216
- "data-storage": {
217
- description: "Persistence storage mode for persistence-capable templates.",
218
- type: "string"
219
- },
220
- "dry-run": {
221
- argumentKind: "flag",
222
- description: "Preview workspace file updates and completion guidance without writing them.",
223
- type: "boolean"
224
- },
225
- "external-layer-id": {
226
- description: "Explicit layer id when an external layer package exposes multiple selectable layers.",
227
- type: "string"
228
- },
229
- "external-layer-source": {
230
- description: "Local path, GitHub locator, or npm package that exposes wp-typia.layers.json for built-in block templates.",
231
- type: "string"
232
- },
233
- from: {
234
- description: "Source full block name (namespace/block) for transform workflows.",
235
- type: "string"
236
- },
237
- "inner-blocks-preset": {
238
- description: "Compound-only InnerBlocks preset (freeform, ordered, horizontal, locked-structure).",
239
- type: "string"
240
- },
241
- methods: {
242
- description: "Comma-separated REST resource methods for rest-resource workflows.",
243
- type: "string"
244
- },
245
- namespace: {
246
- description: "REST namespace for rest-resource and ai-feature workflows.",
247
- type: "string"
248
- },
249
- "persistence-policy": {
250
- description: "Persistence write policy for persistence-capable templates.",
251
- type: "string"
252
- },
253
- position: {
254
- description: "Hook position for hooked-block workflows.",
255
- type: "string"
256
- },
257
- slot: {
258
- description: "Document editor shell slot for editor-plugin workflows (sidebar or document-setting-panel).",
277
+ // src/command-options/doctor.ts
278
+ var DOCTOR_OPTION_METADATA = {
279
+ format: {
280
+ description: "Use `json` for machine-readable doctor check output or `text` for human-readable output.",
259
281
  type: "string"
260
- },
261
- source: {
262
- description: "Optional data source locator for admin-view workflows, such as rest-resource:products or core-data:postType/post.",
282
+ }
283
+ };
284
+ // src/command-options/global.ts
285
+ var GLOBAL_OPTION_METADATA = {
286
+ config: {
287
+ description: "Config override file path.",
288
+ short: "c",
263
289
  type: "string"
264
290
  },
265
- template: {
266
- description: "Optional built-in block family for the new block; interactive flows let you choose it when omitted and non-interactive runs default to basic.",
291
+ format: {
292
+ description: "Output format for supported commands (`json` or `text`).",
267
293
  type: "string"
268
294
  },
269
- to: {
270
- description: "Target workspace block slug or full block name for transform workflows.",
295
+ id: {
296
+ description: "Template id for top-level `templates inspect` convenience.",
271
297
  type: "string"
272
298
  }
273
299
  };
300
+ // src/command-options/init.ts
274
301
  var INIT_OPTION_METADATA = {
275
302
  apply: {
276
303
  argumentKind: "flag",
@@ -283,6 +310,14 @@ var INIT_OPTION_METADATA = {
283
310
  type: "string"
284
311
  }
285
312
  };
313
+ // src/command-options/mcp.ts
314
+ var MCP_OPTION_METADATA = {
315
+ "output-dir": {
316
+ description: "Output directory for generated MCP metadata.",
317
+ type: "string"
318
+ }
319
+ };
320
+ // src/command-options/migrate.ts
286
321
  var MIGRATE_OPTION_METADATA = {
287
322
  all: {
288
323
  argumentKind: "flag",
@@ -319,12 +354,7 @@ var MIGRATE_OPTION_METADATA = {
319
354
  type: "string"
320
355
  }
321
356
  };
322
- var MCP_OPTION_METADATA = {
323
- "output-dir": {
324
- description: "Output directory for generated MCP metadata.",
325
- type: "string"
326
- }
327
- };
357
+ // src/command-options/sync.ts
328
358
  var SYNC_OPTION_METADATA = {
329
359
  check: {
330
360
  argumentKind: "flag",
@@ -337,33 +367,14 @@ var SYNC_OPTION_METADATA = {
337
367
  type: "boolean"
338
368
  }
339
369
  };
340
- var DOCTOR_OPTION_METADATA = {
341
- format: {
342
- description: "Use `json` for machine-readable doctor check output or `text` for human-readable output.",
343
- type: "string"
344
- }
345
- };
370
+ // src/command-options/templates.ts
346
371
  var TEMPLATES_OPTION_METADATA = {
347
372
  id: {
348
373
  description: "Template id for `templates inspect`.",
349
374
  type: "string"
350
375
  }
351
376
  };
352
- var GLOBAL_OPTION_METADATA = {
353
- config: {
354
- description: "Config override file path.",
355
- short: "c",
356
- type: "string"
357
- },
358
- format: {
359
- description: "Output format for supported commands (`json` or `text`).",
360
- type: "string"
361
- },
362
- id: {
363
- description: "Template id for top-level `templates inspect` convenience.",
364
- type: "string"
365
- }
366
- };
377
+ // src/command-option-metadata.ts
367
378
  var COMMAND_OPTION_METADATA_BY_GROUP = {
368
379
  add: ADD_OPTION_METADATA,
369
380
  create: CREATE_OPTION_METADATA,
@@ -927,82 +938,27 @@ function extractWpTypiaConfigOverride(argv) {
927
938
  };
928
939
  }
929
940
 
930
- // src/runtime-bridge.ts
941
+ // src/runtime-bridge-add.ts
931
942
  import {
932
943
  CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES7,
933
944
  createCliDiagnosticCodeError as createCliDiagnosticCodeError6
934
945
  } from "@wp-typia/project-tools/cli-diagnostics";
935
946
 
936
- // src/add-kind-registry.ts
937
- import {
938
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES5,
939
- createCliDiagnosticCodeError as createCliDiagnosticCodeError4
940
- } from "@wp-typia/project-tools/cli-diagnostics";
941
-
942
947
  // src/add-kind-ids.ts
943
948
  import { ADD_KIND_IDS } from "@wp-typia/project-tools/cli-add-kind-ids";
949
+ import { ADD_KIND_IDS as ADD_KIND_IDS2 } from "@wp-typia/project-tools/cli-add-kind-ids";
950
+ function formatAddKindList() {
951
+ return ADD_KIND_IDS.join(", ");
952
+ }
953
+ function formatAddKindUsagePlaceholder() {
954
+ return `<${ADD_KIND_IDS.join("|")}>`;
955
+ }
944
956
 
945
- // src/cli-string-flags.ts
957
+ // src/add-kind-registry-shared.ts
946
958
  import {
947
959
  CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES4,
948
960
  createCliDiagnosticCodeError as createCliDiagnosticCodeError3
949
961
  } from "@wp-typia/project-tools/cli-diagnostics";
950
- function readOptionalCliStringFlagValue(flags, name, mode) {
951
- const value = flags[name];
952
- if (value === undefined || value === null) {
953
- return;
954
- }
955
- if (typeof value !== "string") {
956
- throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
957
- }
958
- const trimmed = value.trim();
959
- if (trimmed.length === 0) {
960
- if (mode === "strict") {
961
- throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
962
- }
963
- return;
964
- }
965
- return mode === "strict" ? value : trimmed;
966
- }
967
- function readOptionalLooseStringFlag(flags, name) {
968
- return readOptionalCliStringFlagValue(flags, name, "loose");
969
- }
970
- function readOptionalStrictStringFlag(flags, name) {
971
- return readOptionalCliStringFlagValue(flags, name, "strict");
972
- }
973
- function requireStrictStringFlag(flags, name, message) {
974
- const value = readOptionalStrictStringFlag(flags, name);
975
- if (!value) {
976
- throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.MISSING_ARGUMENT, message);
977
- }
978
- return value;
979
- }
980
- function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message) {
981
- const leftValue = readOptionalStrictStringFlag(flags, leftName);
982
- const rightValue = readOptionalStrictStringFlag(flags, rightName);
983
- if (Boolean(leftValue) !== Boolean(rightValue)) {
984
- throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.MISSING_ARGUMENT, message);
985
- }
986
- return [leftValue, rightValue];
987
- }
988
-
989
- // src/external-layer-prompt-options.ts
990
- function formatExternalLayerSelectHint(option) {
991
- const details = [
992
- option.description,
993
- option.extends.length > 0 ? `extends ${option.extends.join(", ")}` : undefined
994
- ].filter((value) => typeof value === "string" && value.length > 0);
995
- return details.length > 0 ? details.join(" · ") : undefined;
996
- }
997
- function toExternalLayerPromptOptions(options) {
998
- return options.map((option) => ({
999
- hint: formatExternalLayerSelectHint(option),
1000
- label: option.id,
1001
- value: option.id
1002
- }));
1003
- }
1004
-
1005
- // src/add-kind-registry.ts
1006
962
  var BLOCK_VISIBLE_FIELD_ORDER = [
1007
963
  "kind",
1008
964
  "name",
@@ -1062,7 +1018,7 @@ var NAME_NAMESPACE_VISIBLE_FIELDS = [
1062
1018
  ];
1063
1019
  function requireAddKindName(context, message) {
1064
1020
  if (!context.name) {
1065
- throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.MISSING_ARGUMENT, message);
1021
+ throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.MISSING_ARGUMENT, message);
1066
1022
  }
1067
1023
  return context.name;
1068
1024
  }
@@ -1084,512 +1040,634 @@ function isAddPersistenceTemplate(template) {
1084
1040
  function formatAddBlockTemplateIds(addRuntime) {
1085
1041
  return addRuntime.ADD_BLOCK_TEMPLATE_IDS.join(", ");
1086
1042
  }
1043
+ function getMistypedAddBlockTemplateMessage(addRuntime, templateId) {
1044
+ const suggestion = addRuntime.suggestAddBlockTemplateId(templateId);
1045
+ if (!suggestion) {
1046
+ return null;
1047
+ }
1048
+ return `Unknown add-block template "${templateId}". Did you mean "${suggestion}"? Use \`--template ${suggestion}\`, or run \`wp-typia templates list\` to inspect available templates.`;
1049
+ }
1087
1050
  function assertAddBlockTemplateId(context, templateId) {
1051
+ if (templateId === "query-loop") {
1052
+ throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.INVALID_ARGUMENT, "`wp-typia add block --template query-loop` is not supported. Query Loop is a create-time `core/query` variation scaffold, so use `wp-typia create <project-dir> --template query-loop` instead.");
1053
+ }
1088
1054
  if (context.addRuntime.isAddBlockTemplateId(templateId)) {
1089
1055
  return templateId;
1090
1056
  }
1091
- if (templateId === "query-loop") {
1092
- throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.INVALID_ARGUMENT, "`wp-typia add block --template query-loop` is not supported. Query Loop is a create-time `core/query` variation scaffold, so use `wp-typia create <project-dir> --template query-loop` instead.");
1057
+ const mistypedAddBlockTemplateMessage = getMistypedAddBlockTemplateMessage(context.addRuntime, templateId);
1058
+ if (mistypedAddBlockTemplateMessage) {
1059
+ throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.UNKNOWN_TEMPLATE, mistypedAddBlockTemplateMessage);
1093
1060
  }
1094
- throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.UNKNOWN_TEMPLATE, `Unknown add-block template "${templateId}". Expected one of: ${formatAddBlockTemplateIds(context.addRuntime)}. Run \`wp-typia templates list\` to inspect available templates.`);
1061
+ throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.UNKNOWN_TEMPLATE, `Unknown add-block template "${templateId}". Expected one of: ${formatAddBlockTemplateIds(context.addRuntime)}. Run \`wp-typia templates list\` to inspect available templates.`);
1095
1062
  }
1096
- var ADD_KIND_REGISTRY = {
1097
- "admin-view": defineAddKindRegistryEntry({
1098
- completion: {
1099
- nextSteps: (values) => [
1100
- `Review src/admin-views/${values.adminViewSlug}/ and inc/admin-views/${values.adminViewSlug}.php.`,
1101
- "Run your workspace build or dev command to verify the generated DataViews admin screen."
1102
- ],
1103
- summaryLines: (values, projectDir) => [
1104
- `Admin view: ${values.adminViewSlug}`,
1105
- ...values.source ? [`Source: ${values.source}`] : [],
1106
- `Project directory: ${projectDir}`
1107
- ],
1108
- title: "Added DataViews admin screen"
1109
- },
1110
- description: "Add an opt-in DataViews-powered admin screen",
1111
- nameLabel: "Admin view name",
1112
- async prepareExecution(context) {
1113
- 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>].");
1114
- const source = readOptionalStrictStringFlag(context.flags, "source");
1115
- return createNamedExecutionPlan(context, {
1116
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
1117
- adminViewName: name2,
1118
- cwd,
1119
- source
1120
- }),
1121
- getValues: (result) => ({
1122
- adminViewSlug: result.adminViewSlug,
1123
- ...result.source ? { source: result.source } : {}
1124
- }),
1125
- missingNameMessage: "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].",
1126
- name
1127
- });
1128
- },
1129
- sortOrder: 10,
1130
- supportsDryRun: true,
1131
- usage: "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]",
1132
- visibleFieldNames: () => NAME_SOURCE_VISIBLE_FIELDS
1133
- }),
1134
- "binding-source": defineAddKindRegistryEntry({
1135
- completion: {
1136
- nextSteps: (values) => [
1137
- `Review src/bindings/${values.bindingSourceSlug}/server.php and src/bindings/${values.bindingSourceSlug}/editor.ts.`,
1138
- ...values.blockSlug && values.attributeName ? [
1139
- `Review src/blocks/${values.blockSlug}/block.json for the ${values.attributeName} bindable attribute.`
1140
- ] : [],
1141
- "Run your workspace build or dev command to verify the binding source hooks and editor registration."
1142
- ],
1143
- summaryLines: (values, projectDir) => [
1144
- `Binding source: ${values.bindingSourceSlug}`,
1145
- ...values.blockSlug && values.attributeName ? [`Target: ${values.blockSlug}.${values.attributeName}`] : [],
1146
- `Project directory: ${projectDir}`
1147
- ],
1148
- title: "Added binding source"
1149
- },
1150
- description: "Add a shared block bindings source",
1151
- nameLabel: "Binding source name",
1152
- async prepareExecution(context) {
1153
- 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>].");
1154
- const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
1155
- return createNamedExecutionPlan(context, {
1156
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
1157
- attributeName,
1158
- bindingSourceName: name2,
1159
- blockName,
1160
- cwd
1161
- }),
1162
- getValues: (result) => ({
1163
- ...result.attributeName ? { attributeName: result.attributeName } : {},
1164
- ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
1165
- bindingSourceSlug: result.bindingSourceSlug
1166
- }),
1167
- missingNameMessage: "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].",
1168
- name
1169
- });
1170
- },
1171
- sortOrder: 70,
1172
- supportsDryRun: true,
1173
- usage: "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--dry-run]",
1174
- visibleFieldNames: () => NAME_BLOCK_ATTRIBUTE_VISIBLE_FIELDS
1175
- }),
1176
- block: defineAddKindRegistryEntry({
1177
- completion: {
1178
- nextSteps: () => [
1179
- "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
1180
- "Run your workspace build or dev command to verify the new scaffolded block family."
1181
- ],
1182
- summaryLines: (values, projectDir) => [
1183
- `Blocks: ${values.blockSlugs}`,
1184
- `Template family: ${values.templateId}`,
1185
- `Project directory: ${projectDir}`
1186
- ],
1187
- title: "Added workspace block"
1188
- },
1189
- description: "Add a real block slice",
1190
- hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
1191
- nameLabel: "Block name",
1192
- async prepareExecution(context) {
1193
- const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
1194
- const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
1195
- const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
1196
- const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
1197
- const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
1198
- const alternateRenderTargets = readOptionalStrictStringFlag(context.flags, "alternate-render-targets");
1199
- const dataStorageMode = readOptionalStrictStringFlag(context.flags, "data-storage");
1200
- const innerBlocksPreset = readOptionalStrictStringFlag(context.flags, "inner-blocks-preset");
1201
- const persistencePolicy = readOptionalStrictStringFlag(context.flags, "persistence-policy");
1202
- const requestedTemplateId = readOptionalStrictStringFlag(context.flags, "template");
1203
- let resolvedTemplateId = requestedTemplateId ? assertAddBlockTemplateId(context, requestedTemplateId) : undefined;
1204
- if (!resolvedTemplateId && context.isInteractiveSession) {
1205
- const templatePrompt = await context.getOrCreatePrompt();
1206
- resolvedTemplateId = await templatePrompt.select("Select a block template", context.addRuntime.ADD_BLOCK_TEMPLATE_IDS.map((templateId) => ({
1207
- hint: `Scaffold the ${templateId} block family`,
1208
- label: templateId,
1209
- value: templateId
1210
- })), 1);
1211
- }
1212
- resolvedTemplateId ??= "basic";
1213
- return createNamedExecutionPlan(context, {
1214
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockCommand({
1215
- alternateRenderTargets,
1216
- blockName: name2,
1217
- cwd,
1218
- dataStorageMode,
1219
- externalLayerId,
1220
- externalLayerSource,
1221
- innerBlocksPreset,
1222
- persistencePolicy,
1223
- selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
1224
- templateId: resolvedTemplateId
1225
- }),
1226
- getValues: (result) => ({
1227
- blockSlugs: result.blockSlugs.join(", "),
1228
- templateId: result.templateId
1229
- }),
1230
- getWarnings: (result) => result.warnings,
1231
- missingNameMessage: "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]",
1232
- name,
1233
- warnLine: context.warnLine
1234
- });
1235
- },
1236
- sortOrder: 20,
1237
- supportsDryRun: true,
1238
- usage: "wp-typia add block <name> [--template <basic|interactivity|persistence|compound>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--inner-blocks-preset <freeform|ordered|horizontal|locked-structure>] [--alternate-render-targets <email,mjml,plain-text>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--dry-run]",
1239
- visibleFieldNames: ({ template }) => BLOCK_VISIBLE_FIELD_ORDER.filter((fieldName) => {
1240
- if (fieldName === "alternate-render-targets") {
1241
- return isAddPersistenceTemplate(template);
1242
- }
1243
- if (fieldName === "inner-blocks-preset") {
1244
- return template === "compound";
1245
- }
1246
- if (fieldName === "data-storage" || fieldName === "persistence-policy") {
1247
- return isAddPersistenceTemplate(template);
1248
- }
1249
- return true;
1250
- })
1251
- }),
1252
- ability: defineAddKindRegistryEntry({
1253
- completion: {
1254
- nextSteps: (values) => [
1255
- `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
1256
- "Run `wp-typia sync` or `npm run sync-abilities -- --check` and then your workspace build/dev command to verify the generated workflow ability."
1257
- ],
1258
- summaryLines: (values, projectDir) => [
1259
- `Ability: ${values.abilitySlug}`,
1260
- `Project directory: ${projectDir}`
1261
- ],
1262
- title: "Added workflow ability"
1263
- },
1264
- description: "Add a typed server/client workflow ability scaffold",
1265
- nameLabel: "Ability name",
1266
- async prepareExecution(context) {
1267
- return createNamedExecutionPlan(context, {
1268
- execute: ({ cwd, name }) => context.addRuntime.runAddAbilityCommand({
1269
- abilityName: name,
1270
- cwd
1271
- }),
1272
- getValues: (result) => ({
1273
- abilitySlug: result.abilitySlug
1274
- }),
1275
- getWarnings: (result) => result.warnings,
1276
- missingNameMessage: "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.",
1277
- warnLine: context.warnLine
1278
- });
1279
- },
1280
- sortOrder: 90,
1281
- supportsDryRun: true,
1282
- usage: "wp-typia add ability <name> [--dry-run]",
1283
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
1284
- }),
1285
- "editor-plugin": defineAddKindRegistryEntry({
1286
- completion: {
1287
- nextSteps: (values) => [
1288
- `Review src/editor-plugins/${values.editorPluginSlug}/.`,
1289
- "Run your workspace build or dev command to verify the new editor plugin registration."
1290
- ],
1291
- summaryLines: (values, projectDir) => [
1292
- `Editor plugin: ${values.editorPluginSlug}`,
1293
- `Slot: ${values.slot}`,
1294
- `Project directory: ${projectDir}`
1295
- ],
1296
- title: "Added editor plugin"
1297
- },
1298
- description: "Add a slot-aware document editor extension shell",
1299
- nameLabel: "Editor plugin name",
1300
- async prepareExecution(context) {
1301
- const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].");
1302
- const slot = readOptionalStrictStringFlag(context.flags, "slot");
1303
- return createNamedExecutionPlan(context, {
1304
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
1305
- cwd,
1306
- editorPluginName: name2,
1307
- slot
1308
- }),
1309
- getValues: (result) => ({
1310
- editorPluginSlug: result.editorPluginSlug,
1311
- slot: result.slot
1312
- }),
1313
- missingNameMessage: "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].",
1314
- name
1315
- });
1316
- },
1317
- sortOrder: 120,
1318
- supportsDryRun: true,
1319
- usage: "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>] [--dry-run]",
1320
- visibleFieldNames: () => NAME_SLOT_VISIBLE_FIELDS
1321
- }),
1322
- "hooked-block": defineAddKindRegistryEntry({
1323
- completion: {
1324
- nextSteps: (values) => [
1325
- `Review src/blocks/${values.blockSlug}/block.json for the new blockHooks entry.`,
1326
- "Run your workspace build or dev command to verify the updated hooked-block metadata."
1327
- ],
1328
- summaryLines: (values, projectDir) => [
1329
- `Block: ${values.blockSlug}`,
1330
- `Anchor: ${values.anchorBlockName}`,
1331
- `Position: ${values.position}`,
1332
- `Project directory: ${projectDir}`
1333
- ],
1334
- title: "Added blockHooks metadata"
1335
- },
1336
- description: "Add block.json hook metadata to an existing block",
1337
- nameLabel: "Target block",
1338
- async prepareExecution(context) {
1339
- 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>.");
1340
- const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
1341
- const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
1342
- return createNamedExecutionPlan(context, {
1343
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddHookedBlockCommand({
1344
- anchorBlockName,
1345
- blockName: name2,
1346
- cwd,
1347
- position
1348
- }),
1349
- getValues: (result) => ({
1350
- anchorBlockName: result.anchorBlockName,
1351
- blockSlug: result.blockSlug,
1352
- position: result.position
1353
- }),
1354
- 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>.",
1355
- name
1356
- });
1357
- },
1358
- sortOrder: 110,
1359
- supportsDryRun: true,
1360
- usage: "wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild> [--dry-run]",
1361
- visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
1362
- }),
1363
- pattern: defineAddKindRegistryEntry({
1364
- completion: {
1365
- nextSteps: (values) => [
1366
- `Review src/patterns/${values.patternSlug}.php.`,
1367
- "Run your workspace build or dev command to verify the new pattern registration."
1368
- ],
1369
- summaryLines: (values, projectDir) => [
1370
- `Pattern: ${values.patternSlug}`,
1371
- `Project directory: ${projectDir}`
1372
- ],
1373
- title: "Added workspace pattern"
1374
- },
1375
- description: "Add a PHP block pattern shell",
1376
- nameLabel: "Pattern name",
1377
- async prepareExecution(context) {
1378
- return createNamedExecutionPlan(context, {
1379
- execute: ({ cwd, name }) => context.addRuntime.runAddPatternCommand({
1380
- cwd,
1381
- patternName: name
1382
- }),
1383
- getValues: (result) => ({
1384
- patternSlug: result.patternSlug
1385
- }),
1386
- missingNameMessage: "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>."
1387
- });
1388
- },
1389
- sortOrder: 60,
1390
- supportsDryRun: true,
1391
- usage: "wp-typia add pattern <name> [--dry-run]",
1392
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
1393
- }),
1394
- style: defineAddKindRegistryEntry({
1395
- completion: {
1396
- nextSteps: (values) => [
1397
- `Review src/blocks/${values.blockSlug}/styles/${values.styleSlug}.ts.`,
1398
- "Run your workspace build or dev command to verify the new block style registration."
1399
- ],
1400
- summaryLines: (values, projectDir) => [
1401
- `Block style: ${values.styleSlug}`,
1402
- `Target block: ${values.blockSlug}`,
1403
- `Project directory: ${projectDir}`
1404
- ],
1405
- title: "Added block style"
1406
- },
1407
- description: "Add a Block Styles registration to an existing block",
1408
- nameLabel: "Style name",
1409
- async prepareExecution(context) {
1410
- const name = requireAddKindName(context, "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.");
1411
- const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
1412
- return createNamedExecutionPlan(context, {
1413
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
1414
- blockName: blockSlug,
1415
- cwd,
1416
- styleName: name2
1417
- }),
1418
- getValues: (result) => ({
1419
- blockSlug: result.blockSlug,
1420
- styleSlug: result.styleSlug
1421
- }),
1422
- missingNameMessage: "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.",
1423
- name
1424
- });
1425
- },
1426
- sortOrder: 40,
1427
- supportsDryRun: true,
1428
- usage: "wp-typia add style <name> --block <block-slug> [--dry-run]",
1429
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
1430
- }),
1431
- transform: defineAddKindRegistryEntry({
1432
- completion: {
1433
- nextSteps: (values) => [
1434
- `Review src/blocks/${values.blockSlug}/transforms/${values.transformSlug}.ts.`,
1435
- "Run your workspace build or dev command to verify the new block transform registration."
1436
- ],
1437
- summaryLines: (values, projectDir) => [
1438
- `Block transform: ${values.transformSlug}`,
1439
- `From: ${values.fromBlockName}`,
1440
- `To: ${values.toBlockName}`,
1441
- `Project directory: ${projectDir}`
1442
- ],
1443
- title: "Added block transform"
1444
- },
1445
- description: "Add a block-to-block transform into a workspace block",
1446
- nameLabel: "Transform name",
1447
- async prepareExecution(context) {
1448
- 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>.");
1449
- const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
1450
- const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
1451
- return createNamedExecutionPlan(context, {
1452
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockTransformCommand({
1453
- cwd,
1454
- fromBlockName,
1455
- toBlockName,
1456
- transformName: name2
1457
- }),
1458
- getValues: (result) => ({
1459
- blockSlug: result.blockSlug,
1460
- fromBlockName: result.fromBlockName,
1461
- toBlockName: result.toBlockName,
1462
- transformSlug: result.transformSlug
1463
- }),
1464
- missingNameMessage: "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.",
1465
- name
1466
- });
1467
- },
1468
- sortOrder: 50,
1469
- supportsDryRun: true,
1470
- usage: "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]",
1471
- visibleFieldNames: () => NAME_FROM_TO_VISIBLE_FIELDS
1472
- }),
1473
- "rest-resource": defineAddKindRegistryEntry({
1474
- completion: {
1475
- nextSteps: (values) => [
1476
- `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
1477
- "Run your workspace build or dev command to verify the generated REST resource contract."
1478
- ],
1479
- summaryLines: (values, projectDir) => [
1480
- `REST resource: ${values.restResourceSlug}`,
1481
- `Namespace: ${values.namespace}`,
1482
- `Methods: ${values.methods}`,
1483
- `Project directory: ${projectDir}`
1484
- ],
1485
- title: "Added plugin-level REST resource"
1486
- },
1487
- description: "Add a plugin-level typed REST resource",
1488
- nameLabel: "REST resource name",
1489
- async prepareExecution(context) {
1490
- 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>].");
1491
- const methods = readOptionalStrictStringFlag(context.flags, "methods");
1492
- const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1493
- return createNamedExecutionPlan(context, {
1494
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
1495
- cwd,
1496
- methods,
1497
- namespace,
1498
- restResourceName: name2
1499
- }),
1500
- getValues: (result) => ({
1501
- methods: result.methods.join(", "),
1502
- namespace: result.namespace,
1503
- restResourceSlug: result.restResourceSlug
1504
- }),
1505
- missingNameMessage: "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create>].",
1506
- name
1507
- });
1508
- },
1509
- sortOrder: 80,
1510
- supportsDryRun: true,
1511
- usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
1512
- visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
1513
- }),
1514
- "ai-feature": defineAddKindRegistryEntry({
1515
- completion: {
1516
- nextSteps: (values) => [
1517
- `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
1518
- "Run `wp-typia sync-rest` and `wp-typia sync ai` or your workspace build/dev command to verify the generated REST artifacts and AI schema."
1519
- ],
1520
- summaryLines: (values, projectDir) => [
1521
- `AI feature: ${values.aiFeatureSlug}`,
1522
- `Namespace: ${values.namespace}`,
1523
- `Project directory: ${projectDir}`
1524
- ],
1525
- title: "Added server-only AI feature"
1526
- },
1527
- description: "Add a server-owned WordPress AI feature endpoint",
1528
- nameLabel: "AI feature name",
1529
- async prepareExecution(context) {
1530
- const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
1531
- const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1532
- return createNamedExecutionPlan(context, {
1533
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
1534
- aiFeatureName: name2,
1535
- cwd,
1536
- namespace
1537
- }),
1538
- getValues: (result) => ({
1539
- aiFeatureSlug: result.aiFeatureSlug,
1540
- namespace: result.namespace
1541
- }),
1542
- getWarnings: (result) => result.warnings,
1543
- missingNameMessage: "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].",
1544
- name,
1545
- warnLine: context.warnLine
1546
- });
1547
- },
1548
- sortOrder: 100,
1549
- supportsDryRun: true,
1550
- usage: "wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]",
1551
- visibleFieldNames: () => NAME_NAMESPACE_VISIBLE_FIELDS
1552
- }),
1553
- variation: defineAddKindRegistryEntry({
1554
- completion: {
1555
- nextSteps: (values) => [
1556
- `Review src/blocks/${values.blockSlug}/variations/${values.variationSlug}.ts.`,
1557
- "Run your workspace build or dev command to pick up the new variation."
1558
- ],
1559
- summaryLines: (values, projectDir) => [
1560
- `Variation: ${values.variationSlug}`,
1561
- `Target block: ${values.blockSlug}`,
1562
- `Project directory: ${projectDir}`
1563
- ],
1564
- title: "Added workspace variation"
1565
- },
1566
- description: "Add a variation to an existing block",
1567
- nameLabel: "Variation name",
1568
- async prepareExecution(context) {
1569
- const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
1570
- const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
1571
- return createNamedExecutionPlan(context, {
1572
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
1573
- blockName: blockSlug,
1574
- cwd,
1575
- variationName: name2
1576
- }),
1577
- getValues: (result) => ({
1578
- blockSlug: result.blockSlug,
1579
- variationSlug: result.variationSlug
1580
- }),
1581
- missingNameMessage: "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>",
1582
- name
1583
- });
1584
- },
1585
- sortOrder: 30,
1586
- supportsDryRun: true,
1587
- usage: "wp-typia add variation <name> --block <block-slug> [--dry-run]",
1588
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
1063
+
1064
+ // src/add-kinds/ability.ts
1065
+ var ABILITY_MISSING_NAME_MESSAGE = "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.";
1066
+ var abilityAddKindEntry = defineAddKindRegistryEntry({
1067
+ completion: {
1068
+ nextSteps: (values) => [
1069
+ `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
1070
+ "Run `wp-typia sync` or `npm run sync-abilities -- --check` and then your workspace build/dev command to verify the generated workflow ability."
1071
+ ],
1072
+ summaryLines: (values, projectDir) => [
1073
+ `Ability: ${values.abilitySlug}`,
1074
+ `Project directory: ${projectDir}`
1075
+ ],
1076
+ title: "Added workflow ability"
1077
+ },
1078
+ description: "Add a typed server/client workflow ability scaffold",
1079
+ nameLabel: "Ability name",
1080
+ async prepareExecution(context) {
1081
+ return createNamedExecutionPlan(context, {
1082
+ execute: ({ cwd, name }) => context.addRuntime.runAddAbilityCommand({
1083
+ abilityName: name,
1084
+ cwd
1085
+ }),
1086
+ getValues: (result) => ({
1087
+ abilitySlug: result.abilitySlug
1088
+ }),
1089
+ getWarnings: (result) => result.warnings,
1090
+ missingNameMessage: ABILITY_MISSING_NAME_MESSAGE,
1091
+ warnLine: context.warnLine
1092
+ });
1093
+ },
1094
+ sortOrder: 90,
1095
+ supportsDryRun: true,
1096
+ usage: "wp-typia add ability <name> [--dry-run]",
1097
+ visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
1098
+ });
1099
+
1100
+ // src/cli-string-flags.ts
1101
+ import {
1102
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES5,
1103
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError4
1104
+ } from "@wp-typia/project-tools/cli-diagnostics";
1105
+ function readOptionalCliStringFlagValue(flags, name, mode) {
1106
+ const value = flags[name];
1107
+ if (value === undefined || value === null) {
1108
+ return;
1109
+ }
1110
+ if (typeof value !== "string") {
1111
+ throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
1112
+ }
1113
+ const trimmed = value.trim();
1114
+ if (trimmed.length === 0) {
1115
+ if (mode === "strict") {
1116
+ throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
1117
+ }
1118
+ return;
1119
+ }
1120
+ return mode === "strict" ? value : trimmed;
1121
+ }
1122
+ function readOptionalLooseStringFlag(flags, name) {
1123
+ return readOptionalCliStringFlagValue(flags, name, "loose");
1124
+ }
1125
+ function readOptionalStrictStringFlag(flags, name) {
1126
+ return readOptionalCliStringFlagValue(flags, name, "strict");
1127
+ }
1128
+ function requireStrictStringFlag(flags, name, message) {
1129
+ const value = readOptionalStrictStringFlag(flags, name);
1130
+ if (!value) {
1131
+ throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.MISSING_ARGUMENT, message);
1132
+ }
1133
+ return value;
1134
+ }
1135
+ function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message) {
1136
+ const leftValue = readOptionalStrictStringFlag(flags, leftName);
1137
+ const rightValue = readOptionalStrictStringFlag(flags, rightName);
1138
+ if (Boolean(leftValue) !== Boolean(rightValue)) {
1139
+ throw createCliDiagnosticCodeError4(CLI_DIAGNOSTIC_CODES5.MISSING_ARGUMENT, message);
1140
+ }
1141
+ return [leftValue, rightValue];
1142
+ }
1143
+
1144
+ // src/add-kinds/admin-view.ts
1145
+ 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>].";
1146
+ var adminViewAddKindEntry = defineAddKindRegistryEntry({
1147
+ completion: {
1148
+ nextSteps: (values) => [
1149
+ `Review src/admin-views/${values.adminViewSlug}/ and inc/admin-views/${values.adminViewSlug}.php.`,
1150
+ "Run your workspace build or dev command to verify the generated DataViews admin screen."
1151
+ ],
1152
+ summaryLines: (values, projectDir) => [
1153
+ `Admin view: ${values.adminViewSlug}`,
1154
+ ...values.source ? [`Source: ${values.source}`] : [],
1155
+ `Project directory: ${projectDir}`
1156
+ ],
1157
+ title: "Added DataViews admin screen"
1158
+ },
1159
+ description: "Add an opt-in DataViews-powered admin screen",
1160
+ nameLabel: "Admin view name",
1161
+ async prepareExecution(context) {
1162
+ const name = requireAddKindName(context, ADMIN_VIEW_MISSING_NAME_MESSAGE);
1163
+ const source = readOptionalStrictStringFlag(context.flags, "source");
1164
+ return createNamedExecutionPlan(context, {
1165
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
1166
+ adminViewName: name2,
1167
+ cwd,
1168
+ source
1169
+ }),
1170
+ getValues: (result) => ({
1171
+ adminViewSlug: result.adminViewSlug,
1172
+ ...result.source ? { source: result.source } : {}
1173
+ }),
1174
+ missingNameMessage: ADMIN_VIEW_MISSING_NAME_MESSAGE,
1175
+ name
1176
+ });
1177
+ },
1178
+ sortOrder: 10,
1179
+ supportsDryRun: true,
1180
+ usage: "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]",
1181
+ visibleFieldNames: () => NAME_SOURCE_VISIBLE_FIELDS
1182
+ });
1183
+
1184
+ // src/add-kinds/ai-feature.ts
1185
+ var AI_FEATURE_MISSING_NAME_MESSAGE = "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].";
1186
+ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
1187
+ completion: {
1188
+ nextSteps: (values) => [
1189
+ `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
1190
+ "Run `wp-typia sync-rest` and `wp-typia sync ai` or your workspace build/dev command to verify the generated REST artifacts and AI schema."
1191
+ ],
1192
+ summaryLines: (values, projectDir) => [
1193
+ `AI feature: ${values.aiFeatureSlug}`,
1194
+ `Namespace: ${values.namespace}`,
1195
+ `Project directory: ${projectDir}`
1196
+ ],
1197
+ title: "Added server-only AI feature"
1198
+ },
1199
+ description: "Add a server-owned WordPress AI feature endpoint",
1200
+ nameLabel: "AI feature name",
1201
+ async prepareExecution(context) {
1202
+ const name = requireAddKindName(context, AI_FEATURE_MISSING_NAME_MESSAGE);
1203
+ const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1204
+ return createNamedExecutionPlan(context, {
1205
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
1206
+ aiFeatureName: name2,
1207
+ cwd,
1208
+ namespace
1209
+ }),
1210
+ getValues: (result) => ({
1211
+ aiFeatureSlug: result.aiFeatureSlug,
1212
+ namespace: result.namespace
1213
+ }),
1214
+ getWarnings: (result) => result.warnings,
1215
+ missingNameMessage: AI_FEATURE_MISSING_NAME_MESSAGE,
1216
+ name,
1217
+ warnLine: context.warnLine
1218
+ });
1219
+ },
1220
+ sortOrder: 100,
1221
+ supportsDryRun: true,
1222
+ usage: "wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]",
1223
+ visibleFieldNames: () => NAME_NAMESPACE_VISIBLE_FIELDS
1224
+ });
1225
+
1226
+ // src/add-kinds/binding-source.ts
1227
+ 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>].";
1228
+ var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
1229
+ completion: {
1230
+ nextSteps: (values) => [
1231
+ `Review src/bindings/${values.bindingSourceSlug}/server.php and src/bindings/${values.bindingSourceSlug}/editor.ts.`,
1232
+ ...values.blockSlug && values.attributeName ? [
1233
+ `Review src/blocks/${values.blockSlug}/block.json for the ${values.attributeName} bindable attribute.`
1234
+ ] : [],
1235
+ "Run your workspace build or dev command to verify the binding source hooks and editor registration."
1236
+ ],
1237
+ summaryLines: (values, projectDir) => [
1238
+ `Binding source: ${values.bindingSourceSlug}`,
1239
+ ...values.blockSlug && values.attributeName ? [`Target: ${values.blockSlug}.${values.attributeName}`] : [],
1240
+ `Project directory: ${projectDir}`
1241
+ ],
1242
+ title: "Added binding source"
1243
+ },
1244
+ description: "Add a shared block bindings source",
1245
+ nameLabel: "Binding source name",
1246
+ async prepareExecution(context) {
1247
+ const name = requireAddKindName(context, BINDING_SOURCE_MISSING_NAME_MESSAGE);
1248
+ const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
1249
+ return createNamedExecutionPlan(context, {
1250
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
1251
+ attributeName,
1252
+ bindingSourceName: name2,
1253
+ blockName,
1254
+ cwd
1255
+ }),
1256
+ getValues: (result) => ({
1257
+ ...result.attributeName ? { attributeName: result.attributeName } : {},
1258
+ ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
1259
+ bindingSourceSlug: result.bindingSourceSlug
1260
+ }),
1261
+ missingNameMessage: BINDING_SOURCE_MISSING_NAME_MESSAGE,
1262
+ name
1263
+ });
1264
+ },
1265
+ sortOrder: 70,
1266
+ supportsDryRun: true,
1267
+ usage: "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--dry-run]",
1268
+ visibleFieldNames: () => NAME_BLOCK_ATTRIBUTE_VISIBLE_FIELDS
1269
+ });
1270
+
1271
+ // src/external-layer-prompt-options.ts
1272
+ function formatExternalLayerSelectHint(option) {
1273
+ const details = [
1274
+ option.description,
1275
+ option.extends.length > 0 ? `extends ${option.extends.join(", ")}` : undefined
1276
+ ].filter((value) => typeof value === "string" && value.length > 0);
1277
+ return details.length > 0 ? details.join(" · ") : undefined;
1278
+ }
1279
+ function toExternalLayerPromptOptions(options) {
1280
+ return options.map((option) => ({
1281
+ hint: formatExternalLayerSelectHint(option),
1282
+ label: option.id,
1283
+ value: option.id
1284
+ }));
1285
+ }
1286
+
1287
+ // src/add-kinds/block.ts
1288
+ var BLOCK_MISSING_NAME_MESSAGE = "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]";
1289
+ var blockAddKindEntry = defineAddKindRegistryEntry({
1290
+ completion: {
1291
+ nextSteps: () => [
1292
+ "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
1293
+ "Run your workspace build or dev command to verify the new scaffolded block family."
1294
+ ],
1295
+ summaryLines: (values, projectDir) => [
1296
+ `Blocks: ${values.blockSlugs}`,
1297
+ `Template family: ${values.templateId}`,
1298
+ `Project directory: ${projectDir}`
1299
+ ],
1300
+ title: "Added workspace block"
1301
+ },
1302
+ description: "Add a real block slice",
1303
+ hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
1304
+ nameLabel: "Block name",
1305
+ async prepareExecution(context) {
1306
+ const name = requireAddKindName(context, BLOCK_MISSING_NAME_MESSAGE);
1307
+ const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
1308
+ const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
1309
+ const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
1310
+ const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
1311
+ const alternateRenderTargets = readOptionalStrictStringFlag(context.flags, "alternate-render-targets");
1312
+ const dataStorageMode = readOptionalStrictStringFlag(context.flags, "data-storage");
1313
+ const innerBlocksPreset = readOptionalStrictStringFlag(context.flags, "inner-blocks-preset");
1314
+ const persistencePolicy = readOptionalStrictStringFlag(context.flags, "persistence-policy");
1315
+ const requestedTemplateId = readOptionalStrictStringFlag(context.flags, "template");
1316
+ let resolvedTemplateId = requestedTemplateId ? assertAddBlockTemplateId(context, requestedTemplateId) : undefined;
1317
+ if (!resolvedTemplateId && context.isInteractiveSession) {
1318
+ const templatePrompt = await context.getOrCreatePrompt();
1319
+ resolvedTemplateId = await templatePrompt.select("Select a block template", context.addRuntime.ADD_BLOCK_TEMPLATE_IDS.map((templateId) => ({
1320
+ hint: `Scaffold the ${templateId} block family`,
1321
+ label: templateId,
1322
+ value: templateId
1323
+ })), 1);
1324
+ }
1325
+ resolvedTemplateId ??= "basic";
1326
+ return createNamedExecutionPlan(context, {
1327
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockCommand({
1328
+ alternateRenderTargets,
1329
+ blockName: name2,
1330
+ cwd,
1331
+ dataStorageMode,
1332
+ externalLayerId,
1333
+ externalLayerSource,
1334
+ innerBlocksPreset,
1335
+ persistencePolicy,
1336
+ selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
1337
+ templateId: resolvedTemplateId
1338
+ }),
1339
+ getValues: (result) => ({
1340
+ blockSlugs: result.blockSlugs.join(", "),
1341
+ templateId: result.templateId
1342
+ }),
1343
+ getWarnings: (result) => result.warnings,
1344
+ missingNameMessage: BLOCK_MISSING_NAME_MESSAGE,
1345
+ name,
1346
+ warnLine: context.warnLine
1347
+ });
1348
+ },
1349
+ sortOrder: 20,
1350
+ supportsDryRun: true,
1351
+ usage: "wp-typia add block <name> [--template <basic|interactivity|persistence|compound>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--inner-blocks-preset <freeform|ordered|horizontal|locked-structure>] [--alternate-render-targets <email,mjml,plain-text>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--dry-run]",
1352
+ visibleFieldNames: ({ template }) => BLOCK_VISIBLE_FIELD_ORDER.filter((fieldName) => {
1353
+ if (fieldName === "alternate-render-targets") {
1354
+ return isAddPersistenceTemplate(template);
1355
+ }
1356
+ if (fieldName === "inner-blocks-preset") {
1357
+ return template === "compound";
1358
+ }
1359
+ if (fieldName === "data-storage" || fieldName === "persistence-policy") {
1360
+ return isAddPersistenceTemplate(template);
1361
+ }
1362
+ return true;
1589
1363
  })
1364
+ });
1365
+
1366
+ // src/add-kinds/editor-plugin.ts
1367
+ 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>].";
1368
+ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
1369
+ completion: {
1370
+ nextSteps: (values) => [
1371
+ `Review src/editor-plugins/${values.editorPluginSlug}/.`,
1372
+ "Run your workspace build or dev command to verify the new editor plugin registration."
1373
+ ],
1374
+ summaryLines: (values, projectDir) => [
1375
+ `Editor plugin: ${values.editorPluginSlug}`,
1376
+ `Slot: ${values.slot}`,
1377
+ `Project directory: ${projectDir}`
1378
+ ],
1379
+ title: "Added editor plugin"
1380
+ },
1381
+ description: "Add a slot-aware document editor extension shell",
1382
+ nameLabel: "Editor plugin name",
1383
+ async prepareExecution(context) {
1384
+ const name = requireAddKindName(context, EDITOR_PLUGIN_MISSING_NAME_MESSAGE);
1385
+ const slot = readOptionalStrictStringFlag(context.flags, "slot");
1386
+ return createNamedExecutionPlan(context, {
1387
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
1388
+ cwd,
1389
+ editorPluginName: name2,
1390
+ slot
1391
+ }),
1392
+ getValues: (result) => ({
1393
+ editorPluginSlug: result.editorPluginSlug,
1394
+ slot: result.slot
1395
+ }),
1396
+ missingNameMessage: EDITOR_PLUGIN_MISSING_NAME_MESSAGE,
1397
+ name
1398
+ });
1399
+ },
1400
+ sortOrder: 120,
1401
+ supportsDryRun: true,
1402
+ usage: "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>] [--dry-run]",
1403
+ visibleFieldNames: () => NAME_SLOT_VISIBLE_FIELDS
1404
+ });
1405
+
1406
+ // src/add-kinds/hooked-block.ts
1407
+ 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>.";
1408
+ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
1409
+ completion: {
1410
+ nextSteps: (values) => [
1411
+ `Review src/blocks/${values.blockSlug}/block.json for the new blockHooks entry.`,
1412
+ "Run your workspace build or dev command to verify the updated hooked-block metadata."
1413
+ ],
1414
+ summaryLines: (values, projectDir) => [
1415
+ `Block: ${values.blockSlug}`,
1416
+ `Anchor: ${values.anchorBlockName}`,
1417
+ `Position: ${values.position}`,
1418
+ `Project directory: ${projectDir}`
1419
+ ],
1420
+ title: "Added blockHooks metadata"
1421
+ },
1422
+ description: "Add block.json hook metadata to an existing block",
1423
+ nameLabel: "Target block",
1424
+ async prepareExecution(context) {
1425
+ const name = requireAddKindName(context, HOOKED_BLOCK_MISSING_NAME_MESSAGE);
1426
+ const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
1427
+ const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
1428
+ return createNamedExecutionPlan(context, {
1429
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddHookedBlockCommand({
1430
+ anchorBlockName,
1431
+ blockName: name2,
1432
+ cwd,
1433
+ position
1434
+ }),
1435
+ getValues: (result) => ({
1436
+ anchorBlockName: result.anchorBlockName,
1437
+ blockSlug: result.blockSlug,
1438
+ position: result.position
1439
+ }),
1440
+ missingNameMessage: HOOKED_BLOCK_MISSING_NAME_MESSAGE,
1441
+ name
1442
+ });
1443
+ },
1444
+ sortOrder: 110,
1445
+ supportsDryRun: true,
1446
+ usage: "wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild> [--dry-run]",
1447
+ visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
1448
+ });
1449
+
1450
+ // src/add-kinds/pattern.ts
1451
+ var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.";
1452
+ var patternAddKindEntry = defineAddKindRegistryEntry({
1453
+ completion: {
1454
+ nextSteps: (values) => [
1455
+ `Review src/patterns/${values.patternSlug}.php.`,
1456
+ "Run your workspace build or dev command to verify the new pattern registration."
1457
+ ],
1458
+ summaryLines: (values, projectDir) => [
1459
+ `Pattern: ${values.patternSlug}`,
1460
+ `Project directory: ${projectDir}`
1461
+ ],
1462
+ title: "Added workspace pattern"
1463
+ },
1464
+ description: "Add a PHP block pattern shell",
1465
+ nameLabel: "Pattern name",
1466
+ async prepareExecution(context) {
1467
+ return createNamedExecutionPlan(context, {
1468
+ execute: ({ cwd, name }) => context.addRuntime.runAddPatternCommand({
1469
+ cwd,
1470
+ patternName: name
1471
+ }),
1472
+ getValues: (result) => ({
1473
+ patternSlug: result.patternSlug
1474
+ }),
1475
+ missingNameMessage: PATTERN_MISSING_NAME_MESSAGE,
1476
+ warnLine: context.warnLine
1477
+ });
1478
+ },
1479
+ sortOrder: 60,
1480
+ supportsDryRun: true,
1481
+ usage: "wp-typia add pattern <name> [--dry-run]",
1482
+ visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
1483
+ });
1484
+
1485
+ // src/add-kinds/rest-resource.ts
1486
+ 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>].";
1487
+ var restResourceAddKindEntry = defineAddKindRegistryEntry({
1488
+ completion: {
1489
+ nextSteps: (values) => [
1490
+ `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
1491
+ "Run your workspace build or dev command to verify the generated REST resource contract."
1492
+ ],
1493
+ summaryLines: (values, projectDir) => [
1494
+ `REST resource: ${values.restResourceSlug}`,
1495
+ `Namespace: ${values.namespace}`,
1496
+ `Methods: ${values.methods}`,
1497
+ `Project directory: ${projectDir}`
1498
+ ],
1499
+ title: "Added plugin-level REST resource"
1500
+ },
1501
+ description: "Add a plugin-level typed REST resource",
1502
+ nameLabel: "REST resource name",
1503
+ async prepareExecution(context) {
1504
+ const name = requireAddKindName(context, REST_RESOURCE_MISSING_NAME_MESSAGE);
1505
+ const methods = readOptionalStrictStringFlag(context.flags, "methods");
1506
+ const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1507
+ return createNamedExecutionPlan(context, {
1508
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
1509
+ cwd,
1510
+ methods,
1511
+ namespace,
1512
+ restResourceName: name2
1513
+ }),
1514
+ getValues: (result) => ({
1515
+ methods: result.methods.join(", "),
1516
+ namespace: result.namespace,
1517
+ restResourceSlug: result.restResourceSlug
1518
+ }),
1519
+ missingNameMessage: REST_RESOURCE_MISSING_NAME_MESSAGE,
1520
+ name
1521
+ });
1522
+ },
1523
+ sortOrder: 80,
1524
+ supportsDryRun: true,
1525
+ usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
1526
+ visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
1527
+ });
1528
+
1529
+ // src/add-kinds/style.ts
1530
+ var STYLE_MISSING_NAME_MESSAGE = "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.";
1531
+ var styleAddKindEntry = defineAddKindRegistryEntry({
1532
+ completion: {
1533
+ nextSteps: (values) => [
1534
+ `Review src/blocks/${values.blockSlug}/styles/${values.styleSlug}.ts.`,
1535
+ "Run your workspace build or dev command to verify the new block style registration."
1536
+ ],
1537
+ summaryLines: (values, projectDir) => [
1538
+ `Block style: ${values.styleSlug}`,
1539
+ `Target block: ${values.blockSlug}`,
1540
+ `Project directory: ${projectDir}`
1541
+ ],
1542
+ title: "Added block style"
1543
+ },
1544
+ description: "Add a Block Styles registration to an existing block",
1545
+ nameLabel: "Style name",
1546
+ async prepareExecution(context) {
1547
+ const name = requireAddKindName(context, STYLE_MISSING_NAME_MESSAGE);
1548
+ const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
1549
+ return createNamedExecutionPlan(context, {
1550
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
1551
+ blockName: blockSlug,
1552
+ cwd,
1553
+ styleName: name2
1554
+ }),
1555
+ getValues: (result) => ({
1556
+ blockSlug: result.blockSlug,
1557
+ styleSlug: result.styleSlug
1558
+ }),
1559
+ missingNameMessage: STYLE_MISSING_NAME_MESSAGE,
1560
+ name
1561
+ });
1562
+ },
1563
+ sortOrder: 40,
1564
+ supportsDryRun: true,
1565
+ usage: "wp-typia add style <name> --block <block-slug> [--dry-run]",
1566
+ visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
1567
+ });
1568
+
1569
+ // src/add-kinds/transform.ts
1570
+ 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>.";
1571
+ var transformAddKindEntry = defineAddKindRegistryEntry({
1572
+ completion: {
1573
+ nextSteps: (values) => [
1574
+ `Review src/blocks/${values.blockSlug}/transforms/${values.transformSlug}.ts.`,
1575
+ "Run your workspace build or dev command to verify the new block transform registration."
1576
+ ],
1577
+ summaryLines: (values, projectDir) => [
1578
+ `Block transform: ${values.transformSlug}`,
1579
+ `From: ${values.fromBlockName}`,
1580
+ `To: ${values.toBlockName}`,
1581
+ `Project directory: ${projectDir}`
1582
+ ],
1583
+ title: "Added block transform"
1584
+ },
1585
+ description: "Add a block-to-block transform into a workspace block",
1586
+ nameLabel: "Transform name",
1587
+ async prepareExecution(context) {
1588
+ const name = requireAddKindName(context, TRANSFORM_MISSING_NAME_MESSAGE);
1589
+ const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
1590
+ const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
1591
+ return createNamedExecutionPlan(context, {
1592
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockTransformCommand({
1593
+ cwd,
1594
+ fromBlockName,
1595
+ toBlockName,
1596
+ transformName: name2
1597
+ }),
1598
+ getValues: (result) => ({
1599
+ blockSlug: result.blockSlug,
1600
+ fromBlockName: result.fromBlockName,
1601
+ toBlockName: result.toBlockName,
1602
+ transformSlug: result.transformSlug
1603
+ }),
1604
+ missingNameMessage: TRANSFORM_MISSING_NAME_MESSAGE,
1605
+ name
1606
+ });
1607
+ },
1608
+ sortOrder: 50,
1609
+ supportsDryRun: true,
1610
+ usage: "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]",
1611
+ visibleFieldNames: () => NAME_FROM_TO_VISIBLE_FIELDS
1612
+ });
1613
+
1614
+ // src/add-kinds/variation.ts
1615
+ var VARIATION_MISSING_NAME_MESSAGE = "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>";
1616
+ var variationAddKindEntry = defineAddKindRegistryEntry({
1617
+ completion: {
1618
+ nextSteps: (values) => [
1619
+ `Review src/blocks/${values.blockSlug}/variations/${values.variationSlug}.ts.`,
1620
+ "Run your workspace build or dev command to pick up the new variation."
1621
+ ],
1622
+ summaryLines: (values, projectDir) => [
1623
+ `Variation: ${values.variationSlug}`,
1624
+ `Target block: ${values.blockSlug}`,
1625
+ `Project directory: ${projectDir}`
1626
+ ],
1627
+ title: "Added workspace variation"
1628
+ },
1629
+ description: "Add a variation to an existing block",
1630
+ nameLabel: "Variation name",
1631
+ async prepareExecution(context) {
1632
+ const name = requireAddKindName(context, VARIATION_MISSING_NAME_MESSAGE);
1633
+ const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
1634
+ return createNamedExecutionPlan(context, {
1635
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
1636
+ blockName: blockSlug,
1637
+ cwd,
1638
+ variationName: name2
1639
+ }),
1640
+ getValues: (result) => ({
1641
+ blockSlug: result.blockSlug,
1642
+ variationSlug: result.variationSlug
1643
+ }),
1644
+ missingNameMessage: VARIATION_MISSING_NAME_MESSAGE,
1645
+ name
1646
+ });
1647
+ },
1648
+ sortOrder: 30,
1649
+ supportsDryRun: true,
1650
+ usage: "wp-typia add variation <name> --block <block-slug> [--dry-run]",
1651
+ visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
1652
+ });
1653
+
1654
+ // src/add-kind-registry.ts
1655
+ var ADD_KIND_REGISTRY = {
1656
+ "admin-view": adminViewAddKindEntry,
1657
+ block: blockAddKindEntry,
1658
+ variation: variationAddKindEntry,
1659
+ style: styleAddKindEntry,
1660
+ transform: transformAddKindEntry,
1661
+ pattern: patternAddKindEntry,
1662
+ "binding-source": bindingSourceAddKindEntry,
1663
+ "rest-resource": restResourceAddKindEntry,
1664
+ ability: abilityAddKindEntry,
1665
+ "ai-feature": aiFeatureAddKindEntry,
1666
+ "hooked-block": hookedBlockAddKindEntry,
1667
+ "editor-plugin": editorPluginAddKindEntry
1590
1668
  };
1591
1669
  function isAddKindId(value) {
1592
- return typeof value === "string" && ADD_KIND_IDS.includes(value);
1670
+ return typeof value === "string" && ADD_KIND_IDS2.includes(value);
1593
1671
  }
1594
1672
  async function getAddKindExecutionPlan(kind, context) {
1595
1673
  return ADD_KIND_REGISTRY[kind].prepareExecution(context);
@@ -1602,16 +1680,31 @@ function buildAddKindCompletionDetails(kind, options) {
1602
1680
  title: descriptor.title
1603
1681
  };
1604
1682
  }
1605
- function formatAddKindList() {
1606
- return ADD_KIND_IDS.join(", ");
1607
- }
1608
- function formatAddKindUsagePlaceholder() {
1609
- return `<${ADD_KIND_IDS.join("|")}>`;
1610
- }
1611
1683
  function supportsAddKindDryRun(kind) {
1612
1684
  return ADD_KIND_REGISTRY[kind].supportsDryRun;
1613
1685
  }
1614
1686
 
1687
+ // src/cli-error-messages.ts
1688
+ var MISSING_CREATE_PROJECT_DIR_DETAIL_LINES = [
1689
+ "`wp-typia create` requires <project-dir>.",
1690
+ "`--dry-run` still needs a logical project directory name because wp-typia derives slugs, package names, and planned file paths from it."
1691
+ ];
1692
+ function formatMissingAddKindDetailLine() {
1693
+ return `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`;
1694
+ }
1695
+ function buildMissingAddKindDetailLines() {
1696
+ return [formatMissingAddKindDetailLine()];
1697
+ }
1698
+ function shouldPrintMissingAddKindHelp(options) {
1699
+ if (typeof options.emitOutput === "boolean") {
1700
+ return options.emitOutput;
1701
+ }
1702
+ return options.format !== "json";
1703
+ }
1704
+ function buildMissingCreateProjectDirDetailLines() {
1705
+ return [...MISSING_CREATE_PROJECT_DIR_DETAIL_LINES];
1706
+ }
1707
+
1615
1708
  // src/runtime-bridge-add-dry-run.ts
1616
1709
  import fs2 from "node:fs";
1617
1710
  import { promises as fsp } from "node:fs";
@@ -1637,6 +1730,55 @@ async function copyWorkspaceProject(sourceDir, targetDir) {
1637
1730
  recursive: true
1638
1731
  });
1639
1732
  }
1733
+ function formatInstallMarkerError(error) {
1734
+ if (error instanceof Error) {
1735
+ return error.message;
1736
+ }
1737
+ return String(error);
1738
+ }
1739
+ function formatInstallMarkerFailures(failures) {
1740
+ return failures.map((failure) => `${failure.operation}: ${failure.reason}`).join("; ");
1741
+ }
1742
+ function ensureWorkspaceInstallMarker({
1743
+ fsAdapter = fs2,
1744
+ sourceMarker,
1745
+ targetMarker
1746
+ }) {
1747
+ const failures = [];
1748
+ try {
1749
+ fsAdapter.symlinkSync(sourceMarker, targetMarker);
1750
+ return;
1751
+ } catch (error) {
1752
+ failures.push({
1753
+ operation: "symlink",
1754
+ reason: formatInstallMarkerError(error)
1755
+ });
1756
+ }
1757
+ try {
1758
+ fsAdapter.linkSync(sourceMarker, targetMarker);
1759
+ return;
1760
+ } catch (error) {
1761
+ failures.push({
1762
+ operation: "hard link",
1763
+ reason: formatInstallMarkerError(error)
1764
+ });
1765
+ }
1766
+ try {
1767
+ fsAdapter.copyFileSync(sourceMarker, targetMarker);
1768
+ return;
1769
+ } catch (error) {
1770
+ failures.push({
1771
+ operation: "copy",
1772
+ reason: formatInstallMarkerError(error)
1773
+ });
1774
+ }
1775
+ throw new Error([
1776
+ "Failed to prepare dry-run install marker.",
1777
+ `Source: ${sourceMarker}`,
1778
+ `Target: ${targetMarker}`,
1779
+ `Fallback failures: ${formatInstallMarkerFailures(failures)}`
1780
+ ].join(" "));
1781
+ }
1640
1782
  function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
1641
1783
  const sourceNodeModules = path2.join(sourceDir, "node_modules");
1642
1784
  if (fs2.existsSync(sourceNodeModules)) {
@@ -1648,15 +1790,7 @@ function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
1648
1790
  continue;
1649
1791
  }
1650
1792
  const targetMarker = path2.join(targetDir, marker);
1651
- try {
1652
- fs2.symlinkSync(sourceMarker, targetMarker);
1653
- } catch {
1654
- try {
1655
- fs2.linkSync(sourceMarker, targetMarker);
1656
- } catch {
1657
- fs2.copyFileSync(sourceMarker, targetMarker);
1658
- }
1659
- }
1793
+ ensureWorkspaceInstallMarker({ sourceMarker, targetMarker });
1660
1794
  }
1661
1795
  }
1662
1796
  async function listWorkspaceFiles(rootDir) {
@@ -1739,12 +1873,6 @@ async function simulateWorkspaceAddDryRun({
1739
1873
  }
1740
1874
  }
1741
1875
 
1742
- // src/runtime-bridge-output.ts
1743
- import {
1744
- formatPackageExecCommand,
1745
- inferPackageManagerId
1746
- } from "@wp-typia/project-tools/package-managers";
1747
-
1748
1876
  // src/output-markers.ts
1749
1877
  var UNICODE_OUTPUT_MARKERS = {
1750
1878
  dryRun: "\uD83E\uDDEA",
@@ -1823,40 +1951,38 @@ function stripLeadingOutputMarker(text, kind) {
1823
1951
  return text.replace(new RegExp(`^(?:${markerPattern})\\s*`, "u"), "");
1824
1952
  }
1825
1953
 
1826
- // src/runtime-bridge-output.ts
1827
- function printCompletionPayload(payload, options = {}) {
1828
- const printLine = options.printLine ?? console.log;
1829
- const warnLine = options.warnLine ?? printLine;
1830
- for (const line of payload.preambleLines ?? []) {
1831
- printLine(line);
1832
- }
1833
- for (const warning of payload.warningLines ?? []) {
1834
- warnLine(formatOutputMarker("warning", warning, options.markerOptions));
1835
- }
1836
- const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
1837
- const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
1838
- printLine(hasLeadingContext && hasDetails ? `
1839
- ${payload.title}` : payload.title);
1840
- for (const line of payload.summaryLines ?? []) {
1841
- printLine(line);
1842
- }
1843
- if ((payload.nextSteps?.length ?? 0) > 0) {
1844
- printLine("Next steps:");
1845
- for (const step of payload.nextSteps ?? []) {
1846
- printLine(` ${step}`);
1847
- }
1848
- }
1849
- if ((payload.optionalLines?.length ?? 0) > 0) {
1850
- printLine(`
1851
- ${payload.optionalTitle ?? "Optional:"}`);
1852
- for (const step of payload.optionalLines ?? []) {
1853
- printLine(` ${step}`);
1854
- }
1855
- }
1856
- if (payload.optionalNote) {
1857
- printLine(`Note: ${payload.optionalNote}`);
1858
- }
1954
+ // src/runtime-output/init.ts
1955
+ function buildInitCompletionPayload(plan, markerOptions) {
1956
+ const changeLines = [
1957
+ ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
1958
+ ...plan.packageChanges.packageManagerField ? [
1959
+ `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
1960
+ ] : [],
1961
+ ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
1962
+ ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
1963
+ ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
1964
+ ];
1965
+ 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.";
1966
+ const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
1967
+ 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);
1968
+ return {
1969
+ nextSteps: plan.nextSteps,
1970
+ optionalLines: changeLines,
1971
+ optionalNote: plan.summary,
1972
+ optionalTitle,
1973
+ summaryLines: [
1974
+ `Project directory: ${plan.projectDir}`,
1975
+ `Detected layout: ${plan.detectedLayout.description}`,
1976
+ ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
1977
+ `Package manager: ${plan.packageManager}`,
1978
+ modeLine
1979
+ ],
1980
+ title,
1981
+ warningLines: plan.notes
1982
+ };
1859
1983
  }
1984
+
1985
+ // src/runtime-output/structured.ts
1860
1986
  function toNonEmptyArray(values) {
1861
1987
  return values && values.length > 0 ? values : undefined;
1862
1988
  }
@@ -1917,12 +2043,44 @@ function buildStructuredInitSuccessPayload(plan) {
1917
2043
  }
1918
2044
  };
1919
2045
  }
2046
+ // src/runtime-output/create.ts
2047
+ import {
2048
+ PACKAGE_MANAGER_IDS,
2049
+ formatPackageExecCommand,
2050
+ parsePackageManagerField
2051
+ } from "@wp-typia/project-tools/package-managers";
2052
+ import {
2053
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES6,
2054
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError5
2055
+ } from "@wp-typia/project-tools/cli-diagnostics";
2056
+ function escapeRegExp2(source) {
2057
+ return source.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
2058
+ }
2059
+ var LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN = new RegExp(`^(?:corepack\\s+)?(${PACKAGE_MANAGER_IDS.map(escapeRegExp2).join("|")})(?=$|[@:/+\\s])`, "iu");
2060
+ function parseCreateCompletionPackageManager(packageManager) {
2061
+ const normalizedPackageManager = packageManager.trim();
2062
+ const parsedPackageManager = parsePackageManagerField(normalizedPackageManager);
2063
+ if (parsedPackageManager) {
2064
+ return parsedPackageManager;
2065
+ }
2066
+ const looseMatch = LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN.exec(normalizedPackageManager);
2067
+ const loosePackageManager = looseMatch?.[1]?.toLowerCase();
2068
+ return PACKAGE_MANAGER_IDS.includes(loosePackageManager) ? loosePackageManager : null;
2069
+ }
2070
+ function resolveCreateCompletionPackageManager(packageManager) {
2071
+ const parsedPackageManager = parseCreateCompletionPackageManager(packageManager);
2072
+ if (parsedPackageManager) {
2073
+ return parsedPackageManager;
2074
+ }
2075
+ throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
2076
+ }
1920
2077
  function formatCreateProgressLine(payload, markerOptions) {
1921
2078
  return formatOutputMarker("progress", `${payload.title}: ${payload.detail}`, markerOptions);
1922
2079
  }
1923
2080
  function buildCreateCompletionPayload(flow, markerOptions) {
2081
+ const packageManager = resolveCreateCompletionPackageManager(flow.packageManager);
1924
2082
  const verificationSteps = [
1925
- formatPackageExecCommand(flow.packageManager, `wp-typia@${package_default.version}`, "doctor"),
2083
+ formatPackageExecCommand(packageManager, `wp-typia@${package_default.version}`, "doctor"),
1926
2084
  ...flow.optionalOnboarding.steps
1927
2085
  ];
1928
2086
  return {
@@ -1961,45 +2119,14 @@ function buildCreateDryRunPayload(flow, markerOptions) {
1961
2119
  warningLines: flow.result.warnings
1962
2120
  };
1963
2121
  }
1964
- function buildInitCompletionPayload(plan, markerOptions) {
1965
- const changeLines = [
1966
- ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
1967
- ...plan.packageChanges.packageManagerField ? [
1968
- `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
1969
- ] : [],
1970
- ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
1971
- ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
1972
- ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
1973
- ];
1974
- 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.";
1975
- const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
1976
- 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);
1977
- return {
1978
- nextSteps: plan.nextSteps,
1979
- optionalLines: changeLines,
1980
- optionalNote: plan.summary,
1981
- optionalTitle,
1982
- summaryLines: [
1983
- `Project directory: ${plan.projectDir}`,
1984
- `Detected layout: ${plan.detectedLayout.description}`,
1985
- ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
1986
- `Package manager: ${plan.packageManager}`,
1987
- modeLine
1988
- ],
1989
- title,
1990
- warningLines: plan.notes
1991
- };
1992
- }
1993
- function buildMigrationCompletionPayload(options, markerOptions) {
1994
- const summaryLines = options.lines.filter((line) => line.trim().length > 0);
1995
- return {
1996
- summaryLines,
1997
- title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
1998
- };
1999
- }
2122
+ // src/runtime-output/add.ts
2123
+ import {
2124
+ formatPackageExecCommand as formatPackageExecCommand2,
2125
+ inferPackageManagerId
2126
+ } from "@wp-typia/project-tools/package-managers";
2000
2127
  function buildAddCompletionPayload(options, markerOptions) {
2001
2128
  const verificationLines = [
2002
- formatPackageExecCommand(options.packageManager ?? inferPackageManagerId(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
2129
+ formatPackageExecCommand2(options.packageManager ?? inferPackageManagerId(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
2003
2130
  ];
2004
2131
  const verificationNote = "Run doctor via your package manager for a quick inventory and generated-artifact check after the add workflow.";
2005
2132
  const completion = buildAddKindCompletionDetails(options.kind, {
@@ -2028,6 +2155,15 @@ function buildAddDryRunPayload(options, markerOptions) {
2028
2155
  warningLines: options.completion.warningLines
2029
2156
  };
2030
2157
  }
2158
+ // src/runtime-output/migrate.ts
2159
+ function buildMigrationCompletionPayload(options, markerOptions) {
2160
+ const summaryLines = options.lines.filter((line) => line.trim().length > 0);
2161
+ return {
2162
+ summaryLines,
2163
+ title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
2164
+ };
2165
+ }
2166
+ // src/runtime-output/sync.ts
2031
2167
  function buildSyncDryRunPayload(options, markerOptions) {
2032
2168
  const targetSuffix = options.target === "ai" ? " ai" : "";
2033
2169
  const targetSummary = options.target === "ai" ? "Sync target: AI artifacts only." : options.target === "default" ? "Sync target: generated project defaults." : undefined;
@@ -2044,237 +2180,58 @@ function buildSyncDryRunPayload(options, markerOptions) {
2044
2180
  title: formatOutputMarker("dryRun", `Dry run for wp-typia sync${targetSuffix}`, markerOptions)
2045
2181
  };
2046
2182
  }
2047
- function printBlock(lines, printLine) {
2183
+ // src/print-block.ts
2184
+ function printBlock(printLine, lines) {
2048
2185
  for (const line of lines) {
2049
2186
  printLine(line);
2050
2187
  }
2051
2188
  }
2052
2189
 
2053
- // src/runtime-capabilities.ts
2054
- function isInteractiveTerminal({
2055
- stdin = process.stdin,
2056
- stdout = process.stdout,
2057
- term = process.env.TERM
2058
- } = {}) {
2059
- return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
2060
- }
2061
- // src/runtime-bridge-sync.ts
2062
- import { spawnSync } from "node:child_process";
2063
- import fs3 from "node:fs";
2064
- import path3 from "node:path";
2065
- import {
2066
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES6,
2067
- createCliDiagnosticCodeError as createCliDiagnosticCodeError5
2068
- } from "@wp-typia/project-tools/cli-diagnostics";
2069
- import {
2070
- formatInstallCommand,
2071
- formatRunScript,
2072
- inferPackageManagerId as inferPackageManagerId2
2073
- } from "@wp-typia/project-tools/package-managers";
2074
- var SYNC_INSTALL_MARKERS = [
2075
- "node_modules",
2076
- ".pnp.cjs",
2077
- ".pnp.loader.mjs"
2078
- ];
2079
- var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
2080
- var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
2081
- function resolveSyncExecutionTarget(subcommand) {
2082
- if (!subcommand) {
2083
- return "default";
2190
+ // src/runtime-output/print.ts
2191
+ function printCompletionPayload(payload, options = {}) {
2192
+ const printLine = options.printLine ?? console.log;
2193
+ const warnLine = options.warnLine ?? printLine;
2194
+ for (const line of payload.preambleLines ?? []) {
2195
+ printLine(line);
2084
2196
  }
2085
- if (subcommand === "ai") {
2086
- return "ai";
2197
+ for (const warning of payload.warningLines ?? []) {
2198
+ warnLine(formatOutputMarker("warning", warning, options.markerOptions));
2087
2199
  }
2088
- throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
2089
- }
2090
- function getSyncRootError(cwd) {
2091
- return createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.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.`);
2092
- }
2093
- function resolveSyncProjectContext(cwd) {
2094
- const packageJsonPath = path3.join(cwd, "package.json");
2095
- if (!fs3.existsSync(packageJsonPath)) {
2096
- throw getSyncRootError(cwd);
2200
+ const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
2201
+ const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
2202
+ printLine(hasLeadingContext && hasDetails ? `
2203
+ ${payload.title}` : payload.title);
2204
+ for (const line of payload.summaryLines ?? []) {
2205
+ printLine(line);
2097
2206
  }
2098
- const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
2099
- const scripts = packageJson.scripts ?? {};
2100
- const syncScripts = {
2101
- sync: typeof scripts.sync === "string" ? {
2102
- command: scripts.sync,
2103
- scriptName: "sync"
2104
- } : undefined,
2105
- "sync-ai": typeof scripts["sync-ai"] === "string" ? {
2106
- command: scripts["sync-ai"],
2107
- scriptName: "sync-ai"
2108
- } : typeof scripts["sync-wordpress-ai"] === "string" ? {
2109
- command: scripts["sync-wordpress-ai"],
2110
- scriptName: "sync-wordpress-ai"
2111
- } : undefined,
2112
- "sync-rest": typeof scripts["sync-rest"] === "string" ? {
2113
- command: scripts["sync-rest"],
2114
- scriptName: "sync-rest"
2115
- } : undefined,
2116
- "sync-types": typeof scripts["sync-types"] === "string" ? {
2117
- command: scripts["sync-types"],
2118
- scriptName: "sync-types"
2119
- } : undefined
2120
- };
2121
- return {
2122
- cwd,
2123
- packageJsonPath,
2124
- packageManager: inferPackageManagerId2(cwd, packageJson.packageManager),
2125
- scripts: syncScripts
2126
- };
2127
- }
2128
- function findInstalledDependencyMarkerDir(projectDir) {
2129
- let currentDir = path3.resolve(projectDir);
2130
- while (true) {
2131
- if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path3.join(currentDir, marker)))) {
2132
- return currentDir;
2133
- }
2134
- const parentDir = path3.dirname(currentDir);
2135
- if (parentDir === currentDir) {
2136
- return null;
2207
+ if ((payload.nextSteps?.length ?? 0) > 0) {
2208
+ printLine("Next steps:");
2209
+ for (const step of payload.nextSteps ?? []) {
2210
+ printLine(` ${step}`);
2137
2211
  }
2138
- currentDir = parentDir;
2139
- }
2140
- }
2141
- function scriptsLikelyNeedInstalledDependencies(project, target) {
2142
- const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
2143
- project.scripts["sync-types"],
2144
- project.scripts["sync-rest"],
2145
- project.scripts["sync-ai"]
2146
- ];
2147
- return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
2148
- }
2149
- function assertSyncDependenciesInstalled(project, target) {
2150
- if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
2151
- return;
2152
- }
2153
- const markerDir = findInstalledDependencyMarkerDir(project.cwd);
2154
- if (markerDir) {
2155
- return;
2156
2212
  }
2157
- throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.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\`.`);
2158
- }
2159
- function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
2160
- switch (packageManager) {
2161
- case "bun":
2162
- return { args: ["run", scriptName, ...extraArgs], command: "bun" };
2163
- case "npm":
2164
- return {
2165
- args: [
2166
- "run",
2167
- scriptName,
2168
- ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
2169
- ],
2170
- command: "npm"
2171
- };
2172
- case "pnpm":
2173
- return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
2174
- case "yarn":
2175
- return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
2176
- }
2177
- }
2178
- function createSyncPlannedCommand(project, scriptName, extraArgs) {
2179
- const script = project.scripts[scriptName];
2180
- if (!script) {
2181
- return null;
2182
- }
2183
- const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
2184
- return {
2185
- args: invocation.args,
2186
- command: invocation.command,
2187
- displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
2188
- scriptName: script.scriptName
2189
- };
2190
- }
2191
- function buildSyncPlannedCommands(project, extraArgs, target) {
2192
- if (target === "ai") {
2193
- const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2194
- if (!syncAiCommand2) {
2195
- throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
2213
+ if ((payload.optionalLines?.length ?? 0) > 0) {
2214
+ printLine(`
2215
+ ${payload.optionalTitle ?? "Optional:"}`);
2216
+ for (const step of payload.optionalLines ?? []) {
2217
+ printLine(` ${step}`);
2196
2218
  }
2197
- return [syncAiCommand2];
2198
- }
2199
- if (project.scripts.sync) {
2200
- return [createSyncPlannedCommand(project, "sync", extraArgs)];
2201
- }
2202
- const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
2203
- if (!syncTypesCommand) {
2204
- throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
2205
2219
  }
2206
- const plannedCommands = [syncTypesCommand];
2207
- const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
2208
- if (syncRestCommand) {
2209
- plannedCommands.push(syncRestCommand);
2210
- }
2211
- const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2212
- if (syncAiCommand) {
2213
- plannedCommands.push(syncAiCommand);
2214
- }
2215
- return plannedCommands;
2216
- }
2217
- function runProjectScript(project, plannedCommand, options) {
2218
- const result = spawnSync(plannedCommand.command, plannedCommand.args, {
2219
- cwd: project.cwd,
2220
- encoding: options.captureOutput ? "utf8" : undefined,
2221
- ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
2222
- shell: process.platform === "win32",
2223
- stdio: options.captureOutput ? "pipe" : "inherit"
2224
- });
2225
- const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
2226
- const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
2227
- if (result.error || result.status !== 0) {
2228
- throw new Error(`\`${plannedCommand.displayCommand}\` failed.`, {
2229
- cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
2230
- });
2220
+ if (payload.optionalNote) {
2221
+ printLine(`Note: ${payload.optionalNote}`);
2231
2222
  }
2232
- return {
2233
- ...plannedCommand,
2234
- exitCode: result.status ?? 0,
2235
- ...stderr !== undefined ? { stderr } : {},
2236
- ...stdout !== undefined ? { stdout } : {}
2237
- };
2238
2223
  }
2239
- async function executeSyncCommand({
2240
- captureOutput = false,
2241
- check = false,
2242
- cwd,
2243
- dryRun = false,
2244
- target = "default"
2245
- }) {
2246
- const project = resolveSyncProjectContext(cwd);
2247
- const extraArgs = check ? ["--check"] : [];
2248
- const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
2249
- const result = {
2250
- check,
2251
- dryRun,
2252
- packageJsonPath: project.packageJsonPath,
2253
- packageManager: project.packageManager,
2254
- plannedCommands,
2255
- projectDir: project.cwd,
2256
- target
2257
- };
2258
- if (dryRun) {
2259
- return result;
2260
- }
2261
- assertSyncDependenciesInstalled(project, target);
2262
- result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
2263
- captureOutput
2264
- }));
2265
- return result;
2224
+ // src/runtime-capabilities.ts
2225
+ function isInteractiveTerminal({
2226
+ stdin = process.stdin,
2227
+ stdout = process.stdout,
2228
+ term = process.env.TERM
2229
+ } = {}) {
2230
+ return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
2266
2231
  }
2267
2232
 
2268
- // src/runtime-bridge.ts
2269
- var loadCliAddRuntime = () => import("@wp-typia/project-tools/cli-add");
2233
+ // src/runtime-bridge-shared.ts
2270
2234
  var loadCliDiagnosticsRuntime = () => import("@wp-typia/project-tools/cli-diagnostics");
2271
- var loadCliDoctorRuntime = () => import("@wp-typia/project-tools/cli-doctor");
2272
- var loadCliInitRuntime = () => import("@wp-typia/project-tools/cli-init");
2273
- var loadCliPromptRuntime = () => import("@wp-typia/project-tools/cli-prompt");
2274
- var loadCliScaffoldRuntime = () => import("@wp-typia/project-tools/cli-scaffold");
2275
- var loadCliTemplatesRuntime = () => import("@wp-typia/project-tools/cli-templates");
2276
- var loadCreateTemplateValidationRuntime = () => import("@wp-typia/project-tools/create-template-validation");
2277
- var loadMigrationsRuntime = () => import("@wp-typia/project-tools/migrations");
2278
2235
  async function wrapCliCommandError(command, error) {
2279
2236
  const { createCliCommandError: createCliCommandError3 } = await loadCliDiagnosticsRuntime();
2280
2237
  return createCliCommandError3({ command, error });
@@ -2288,6 +2245,15 @@ function shouldWrapCliCommandError(options) {
2288
2245
  }
2289
2246
  return true;
2290
2247
  }
2248
+ function emitCompletion(payload, options) {
2249
+ if (options.emitOutput) {
2250
+ printCompletionPayload(payload, {
2251
+ printLine: options.printLine,
2252
+ warnLine: options.warnLine
2253
+ });
2254
+ }
2255
+ return payload;
2256
+ }
2291
2257
  function pushFlag(argv, name, value) {
2292
2258
  if (value === undefined || value === null || value === false) {
2293
2259
  return;
@@ -2298,6 +2264,10 @@ function pushFlag(argv, name, value) {
2298
2264
  }
2299
2265
  argv.push(`--${name}`, String(value));
2300
2266
  }
2267
+
2268
+ // src/runtime-bridge-add.ts
2269
+ var loadCliAddRuntime = () => import("@wp-typia/project-tools/cli-add");
2270
+ var loadCliPromptRuntime = () => import("@wp-typia/project-tools/cli-prompt");
2301
2271
  async function executeWorkspaceAddWithOptionalDryRun(options) {
2302
2272
  const simulated = options.dryRun ? await simulateWorkspaceAddDryRun({
2303
2273
  cwd: options.cwd,
@@ -2341,6 +2311,72 @@ async function executePlannedAddKind(kind, executionContext, context) {
2341
2311
  const plan = await getAddKindExecutionPlan(kind, executionContext);
2342
2312
  return executePreparedAddKind(kind, context, plan);
2343
2313
  }
2314
+ async function executeAddCommand({
2315
+ cwd,
2316
+ emitOutput = true,
2317
+ flags,
2318
+ interactive,
2319
+ kind,
2320
+ name,
2321
+ printLine = console.log,
2322
+ prompt,
2323
+ warnLine = console.warn
2324
+ }) {
2325
+ let activePrompt;
2326
+ const dryRun = Boolean(flags["dry-run"]);
2327
+ try {
2328
+ const addRuntime = await loadCliAddRuntime();
2329
+ const isInteractiveSession = interactive ?? isInteractiveTerminal();
2330
+ if (!kind) {
2331
+ if (shouldPrintMissingAddKindHelp({ emitOutput })) {
2332
+ printLine(addRuntime.formatAddHelpText());
2333
+ }
2334
+ throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
2335
+ }
2336
+ if (!isAddKindId(kind)) {
2337
+ throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
2338
+ }
2339
+ if (dryRun && !supportsAddKindDryRun(kind)) {
2340
+ throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
2341
+ }
2342
+ const executionContext = {
2343
+ addRuntime,
2344
+ cwd,
2345
+ flags,
2346
+ getOrCreatePrompt: async () => {
2347
+ if (activePrompt) {
2348
+ return activePrompt;
2349
+ }
2350
+ const { createReadlinePrompt } = await loadCliPromptRuntime();
2351
+ activePrompt = prompt ?? createReadlinePrompt();
2352
+ return activePrompt;
2353
+ },
2354
+ isInteractiveSession,
2355
+ name,
2356
+ warnLine
2357
+ };
2358
+ return await executePlannedAddKind(kind, executionContext, {
2359
+ cwd,
2360
+ dryRun,
2361
+ emitOutput,
2362
+ printLine
2363
+ });
2364
+ } catch (error) {
2365
+ if (!shouldWrapCliCommandError({ emitOutput })) {
2366
+ throw error;
2367
+ }
2368
+ throw await wrapCliCommandError("add", error);
2369
+ } finally {
2370
+ if (activePrompt && activePrompt !== prompt) {
2371
+ activePrompt.close();
2372
+ }
2373
+ }
2374
+ }
2375
+ // src/runtime-bridge-create.ts
2376
+ var loadCliPromptRuntime2 = () => import("@wp-typia/project-tools/cli-prompt");
2377
+ var loadCliScaffoldRuntime = () => import("@wp-typia/project-tools/cli-scaffold");
2378
+ var loadCliTemplatesRuntime = () => import("@wp-typia/project-tools/cli-templates");
2379
+ var loadCreateTemplateValidationRuntime = () => import("@wp-typia/project-tools/create-template-validation");
2344
2380
  var PACKAGE_MANAGER_PROMPT_OPTIONS = [
2345
2381
  { label: "npm", value: "npm", hint: "Use npm" },
2346
2382
  { label: "pnpm", value: "pnpm", hint: "Use pnpm" },
@@ -2367,15 +2403,6 @@ var BOOLEAN_PROMPT_OPTIONS = [
2367
2403
  { label: "Yes", value: "yes", hint: "Enable this option" },
2368
2404
  { label: "No", value: "no", hint: "Keep the default disabled state" }
2369
2405
  ];
2370
- function emitCompletion(payload, options) {
2371
- if (options.emitOutput) {
2372
- printCompletionPayload(payload, {
2373
- printLine: options.printLine,
2374
- warnLine: options.warnLine
2375
- });
2376
- }
2377
- return payload;
2378
- }
2379
2406
  async function executeCreateCommand({
2380
2407
  projectDir,
2381
2408
  cwd,
@@ -2396,7 +2423,7 @@ async function executeCreateCommand({
2396
2423
  { runScaffoldFlow },
2397
2424
  { getTemplateSelectOptions }
2398
2425
  ] = await Promise.all([
2399
- loadCliPromptRuntime(),
2426
+ loadCliPromptRuntime2(),
2400
2427
  loadCliScaffoldRuntime(),
2401
2428
  loadCliTemplatesRuntime()
2402
2429
  ]);
@@ -2466,99 +2493,23 @@ async function executeCreateCommand({
2466
2493
  }
2467
2494
  }
2468
2495
  }
2469
- async function executeAddCommand({
2470
- cwd,
2471
- emitOutput = true,
2472
- flags,
2473
- interactive,
2474
- kind,
2475
- name,
2476
- printLine = console.log,
2477
- prompt,
2478
- warnLine = console.warn
2479
- }) {
2480
- let activePrompt;
2481
- const dryRun = Boolean(flags["dry-run"]);
2496
+ // src/runtime-bridge-doctor.ts
2497
+ var loadCliDoctorRuntime = () => import("@wp-typia/project-tools/cli-doctor");
2498
+ async function executeDoctorCommand(cwd) {
2482
2499
  try {
2483
- const addRuntime = await loadCliAddRuntime();
2484
- const isInteractiveSession = interactive ?? isInteractiveTerminal();
2485
- if (!kind) {
2486
- if (emitOutput) {
2487
- printLine(addRuntime.formatAddHelpText());
2488
- }
2489
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.MISSING_ARGUMENT, `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`);
2490
- }
2491
- if (!isAddKindId(kind)) {
2492
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
2493
- }
2494
- if (dryRun && !supportsAddKindDryRun(kind)) {
2495
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
2496
- }
2497
- const executionContext = {
2498
- addRuntime,
2499
- cwd,
2500
- flags,
2501
- getOrCreatePrompt: async () => {
2502
- if (activePrompt) {
2503
- return activePrompt;
2504
- }
2505
- const { createReadlinePrompt } = await loadCliPromptRuntime();
2506
- activePrompt = prompt ?? createReadlinePrompt();
2507
- return activePrompt;
2508
- },
2509
- isInteractiveSession,
2510
- name,
2511
- warnLine
2512
- };
2513
- return await executePlannedAddKind(kind, executionContext, {
2514
- cwd,
2515
- dryRun,
2516
- emitOutput,
2517
- printLine
2518
- });
2500
+ const { runDoctor } = await loadCliDoctorRuntime();
2501
+ await runDoctor(cwd);
2519
2502
  } catch (error) {
2520
- if (!shouldWrapCliCommandError({ emitOutput })) {
2521
- throw error;
2522
- }
2523
- throw await wrapCliCommandError("add", error);
2524
- } finally {
2525
- if (activePrompt && activePrompt !== prompt) {
2526
- activePrompt.close();
2527
- }
2528
- }
2529
- }
2530
- async function executeTemplatesCommand({ flags }, printLine = console.log) {
2531
- const {
2532
- formatTemplateDetails,
2533
- formatTemplateFeatures,
2534
- formatTemplateSummary,
2535
- getTemplateById,
2536
- listTemplates
2537
- } = await loadCliTemplatesRuntime();
2538
- const subcommand = flags.subcommand ?? "list";
2539
- if (subcommand === "list") {
2540
- for (const template of listTemplates()) {
2541
- printBlock([formatTemplateSummary(template), formatTemplateFeatures(template)], printLine);
2542
- }
2543
- return;
2544
- }
2545
- if (subcommand === "inspect") {
2546
- if (!flags.id) {
2547
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
2548
- }
2549
- const template = getTemplateById(flags.id);
2550
- if (!template) {
2551
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
2552
- }
2553
- printBlock([formatTemplateDetails(template)], printLine);
2554
- return;
2503
+ throw await wrapCliCommandError("doctor", error);
2555
2504
  }
2556
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
2557
2505
  }
2506
+ // src/runtime-bridge-init.ts
2507
+ import path3 from "node:path";
2508
+ var loadCliInitRuntime = () => import("@wp-typia/project-tools/cli-init");
2558
2509
  async function executeInitCommand({ apply, cwd, packageManager, projectDir }, options = {}) {
2559
2510
  try {
2560
2511
  const { runInitCommand } = await loadCliInitRuntime();
2561
- const resolvedProjectDir = projectDir ? (await import("node:path")).resolve(cwd, projectDir) : cwd;
2512
+ const resolvedProjectDir = projectDir ? path3.resolve(cwd, projectDir) : cwd;
2562
2513
  const plan = await runInitCommand({
2563
2514
  apply,
2564
2515
  packageManager,
@@ -2575,18 +2526,12 @@ async function executeInitCommand({ apply, cwd, packageManager, projectDir }, op
2575
2526
  } catch (error) {
2576
2527
  if (!shouldWrapCliCommandError({ emitOutput: options.emitOutput })) {
2577
2528
  throw error;
2578
- }
2579
- throw await wrapCliCommandError("init", error);
2580
- }
2581
- }
2582
- async function executeDoctorCommand(cwd) {
2583
- try {
2584
- const { runDoctor } = await loadCliDoctorRuntime();
2585
- await runDoctor(cwd);
2586
- } catch (error) {
2587
- throw await wrapCliCommandError("doctor", error);
2529
+ }
2530
+ throw await wrapCliCommandError("init", error);
2588
2531
  }
2589
2532
  }
2533
+ // src/runtime-bridge-migrate.ts
2534
+ var loadMigrationsRuntime = () => import("@wp-typia/project-tools/migrations");
2590
2535
  async function executeMigrateCommand({
2591
2536
  command,
2592
2537
  cwd,
@@ -2594,12 +2539,17 @@ async function executeMigrateCommand({
2594
2539
  prompt,
2595
2540
  renderLine
2596
2541
  }) {
2597
- const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
2598
- if (!command) {
2599
- console.log(formatMigrationHelpText());
2600
- return;
2601
- }
2602
2542
  try {
2543
+ const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
2544
+ if (!command) {
2545
+ const helpText = formatMigrationHelpText();
2546
+ if (renderLine) {
2547
+ renderLine(helpText);
2548
+ } else {
2549
+ console.log(helpText);
2550
+ }
2551
+ return;
2552
+ }
2603
2553
  const argv = [command];
2604
2554
  pushFlag(argv, "all", flags.all);
2605
2555
  pushFlag(argv, "force", flags.force);
@@ -2639,13 +2589,261 @@ async function executeMigrateCommand({
2639
2589
  throw await wrapCliCommandError("migrate", error);
2640
2590
  }
2641
2591
  }
2642
-
2643
- // src/command-contract.ts
2644
- import path4 from "node:path";
2592
+ // src/runtime-bridge-templates.ts
2645
2593
  import {
2646
2594
  CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES8,
2647
2595
  createCliDiagnosticCodeError as createCliDiagnosticCodeError7
2648
2596
  } from "@wp-typia/project-tools/cli-diagnostics";
2597
+ var loadCliTemplatesRuntime2 = () => import("@wp-typia/project-tools/cli-templates");
2598
+ async function executeTemplatesCommand({ flags }, printLine = console.log) {
2599
+ const {
2600
+ formatTemplateDetails,
2601
+ formatTemplateFeatures,
2602
+ formatTemplateSummary,
2603
+ getTemplateById,
2604
+ listTemplates
2605
+ } = await loadCliTemplatesRuntime2();
2606
+ const subcommand = flags.subcommand ?? "list";
2607
+ if (subcommand === "list") {
2608
+ for (const template of listTemplates()) {
2609
+ printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
2610
+ }
2611
+ return;
2612
+ }
2613
+ if (subcommand === "inspect") {
2614
+ if (!flags.id) {
2615
+ throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
2616
+ }
2617
+ const template = getTemplateById(flags.id);
2618
+ if (!template) {
2619
+ throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
2620
+ }
2621
+ printBlock(printLine, [formatTemplateDetails(template)]);
2622
+ return;
2623
+ }
2624
+ throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
2625
+ }
2626
+ // src/runtime-bridge-sync.ts
2627
+ import { spawnSync } from "node:child_process";
2628
+ import fs3 from "node:fs";
2629
+ import path4 from "node:path";
2630
+ import {
2631
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES9,
2632
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError8
2633
+ } from "@wp-typia/project-tools/cli-diagnostics";
2634
+ import {
2635
+ formatInstallCommand,
2636
+ formatRunScript,
2637
+ inferPackageManagerId as inferPackageManagerId2
2638
+ } from "@wp-typia/project-tools/package-managers";
2639
+ var SYNC_INSTALL_MARKERS = [
2640
+ "node_modules",
2641
+ ".pnp.cjs",
2642
+ ".pnp.loader.mjs"
2643
+ ];
2644
+ var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
2645
+ var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
2646
+ function resolveSyncExecutionTarget(subcommand) {
2647
+ if (!subcommand) {
2648
+ return "default";
2649
+ }
2650
+ if (subcommand === "ai") {
2651
+ return "ai";
2652
+ }
2653
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
2654
+ }
2655
+ function getSyncRootError(cwd) {
2656
+ return createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.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.`);
2657
+ }
2658
+ function readSyncPackageJson(packageJsonPath) {
2659
+ const source = fs3.readFileSync(packageJsonPath, "utf8");
2660
+ try {
2661
+ return JSON.parse(source);
2662
+ } catch (error) {
2663
+ const message = error instanceof Error ? error.message : String(error);
2664
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_ARGUMENT, `Unable to parse ${packageJsonPath}: ${message}`, error instanceof Error ? { cause: error } : undefined);
2665
+ }
2666
+ }
2667
+ function resolveSyncProjectContext(cwd) {
2668
+ const packageJsonPath = path4.join(cwd, "package.json");
2669
+ if (!fs3.existsSync(packageJsonPath)) {
2670
+ throw getSyncRootError(cwd);
2671
+ }
2672
+ const packageJson = readSyncPackageJson(packageJsonPath);
2673
+ const scripts = packageJson.scripts ?? {};
2674
+ const syncScripts = {
2675
+ sync: typeof scripts.sync === "string" ? {
2676
+ command: scripts.sync,
2677
+ scriptName: "sync"
2678
+ } : undefined,
2679
+ "sync-ai": typeof scripts["sync-ai"] === "string" ? {
2680
+ command: scripts["sync-ai"],
2681
+ scriptName: "sync-ai"
2682
+ } : typeof scripts["sync-wordpress-ai"] === "string" ? {
2683
+ command: scripts["sync-wordpress-ai"],
2684
+ scriptName: "sync-wordpress-ai"
2685
+ } : undefined,
2686
+ "sync-rest": typeof scripts["sync-rest"] === "string" ? {
2687
+ command: scripts["sync-rest"],
2688
+ scriptName: "sync-rest"
2689
+ } : undefined,
2690
+ "sync-types": typeof scripts["sync-types"] === "string" ? {
2691
+ command: scripts["sync-types"],
2692
+ scriptName: "sync-types"
2693
+ } : undefined
2694
+ };
2695
+ return {
2696
+ cwd,
2697
+ packageJsonPath,
2698
+ packageManager: inferPackageManagerId2(cwd, packageJson.packageManager),
2699
+ scripts: syncScripts
2700
+ };
2701
+ }
2702
+ function findInstalledDependencyMarkerDir(projectDir) {
2703
+ let currentDir = path4.resolve(projectDir);
2704
+ while (true) {
2705
+ if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path4.join(currentDir, marker)))) {
2706
+ return currentDir;
2707
+ }
2708
+ const parentDir = path4.dirname(currentDir);
2709
+ if (parentDir === currentDir) {
2710
+ return null;
2711
+ }
2712
+ currentDir = parentDir;
2713
+ }
2714
+ }
2715
+ function scriptsLikelyNeedInstalledDependencies(project, target) {
2716
+ const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
2717
+ project.scripts["sync-types"],
2718
+ project.scripts["sync-rest"],
2719
+ project.scripts["sync-ai"]
2720
+ ];
2721
+ return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
2722
+ }
2723
+ function assertSyncDependenciesInstalled(project, target) {
2724
+ if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
2725
+ return;
2726
+ }
2727
+ const markerDir = findInstalledDependencyMarkerDir(project.cwd);
2728
+ if (markerDir) {
2729
+ return;
2730
+ }
2731
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.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\`.`);
2732
+ }
2733
+ function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
2734
+ switch (packageManager) {
2735
+ case "bun":
2736
+ return { args: ["run", scriptName, ...extraArgs], command: "bun" };
2737
+ case "npm":
2738
+ return {
2739
+ args: [
2740
+ "run",
2741
+ scriptName,
2742
+ ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
2743
+ ],
2744
+ command: "npm"
2745
+ };
2746
+ case "pnpm":
2747
+ return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
2748
+ case "yarn":
2749
+ return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
2750
+ }
2751
+ }
2752
+ function createSyncPlannedCommand(project, scriptName, extraArgs) {
2753
+ const script = project.scripts[scriptName];
2754
+ if (!script) {
2755
+ return null;
2756
+ }
2757
+ const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
2758
+ return {
2759
+ args: invocation.args,
2760
+ command: invocation.command,
2761
+ displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
2762
+ scriptName: script.scriptName
2763
+ };
2764
+ }
2765
+ function buildSyncPlannedCommands(project, extraArgs, target) {
2766
+ if (target === "ai") {
2767
+ const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2768
+ if (!syncAiCommand2) {
2769
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
2770
+ }
2771
+ return [syncAiCommand2];
2772
+ }
2773
+ if (project.scripts.sync) {
2774
+ return [createSyncPlannedCommand(project, "sync", extraArgs)];
2775
+ }
2776
+ const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
2777
+ if (!syncTypesCommand) {
2778
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
2779
+ }
2780
+ const plannedCommands = [syncTypesCommand];
2781
+ const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
2782
+ if (syncRestCommand) {
2783
+ plannedCommands.push(syncRestCommand);
2784
+ }
2785
+ const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2786
+ if (syncAiCommand) {
2787
+ plannedCommands.push(syncAiCommand);
2788
+ }
2789
+ return plannedCommands;
2790
+ }
2791
+ function runProjectScript(project, plannedCommand, options) {
2792
+ const result = spawnSync(plannedCommand.command, plannedCommand.args, {
2793
+ cwd: project.cwd,
2794
+ encoding: options.captureOutput ? "utf8" : undefined,
2795
+ ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
2796
+ shell: process.platform === "win32",
2797
+ stdio: options.captureOutput ? "pipe" : "inherit"
2798
+ });
2799
+ const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
2800
+ const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
2801
+ if (result.error || result.status !== 0) {
2802
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
2803
+ cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
2804
+ });
2805
+ }
2806
+ return {
2807
+ ...plannedCommand,
2808
+ exitCode: result.status ?? 0,
2809
+ ...stderr !== undefined ? { stderr } : {},
2810
+ ...stdout !== undefined ? { stdout } : {}
2811
+ };
2812
+ }
2813
+ async function executeSyncCommand({
2814
+ captureOutput = false,
2815
+ check = false,
2816
+ cwd,
2817
+ dryRun = false,
2818
+ target = "default"
2819
+ }) {
2820
+ const project = resolveSyncProjectContext(cwd);
2821
+ const extraArgs = check ? ["--check"] : [];
2822
+ const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
2823
+ const result = {
2824
+ check,
2825
+ dryRun,
2826
+ packageJsonPath: project.packageJsonPath,
2827
+ packageManager: project.packageManager,
2828
+ plannedCommands,
2829
+ projectDir: project.cwd,
2830
+ target
2831
+ };
2832
+ if (dryRun) {
2833
+ return result;
2834
+ }
2835
+ assertSyncDependenciesInstalled(project, target);
2836
+ result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
2837
+ captureOutput
2838
+ }));
2839
+ return result;
2840
+ }
2841
+ // src/command-contract.ts
2842
+ import path5 from "node:path";
2843
+ import {
2844
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES10,
2845
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError9
2846
+ } from "@wp-typia/project-tools/cli-diagnostics";
2649
2847
 
2650
2848
  // src/command-registry.ts
2651
2849
  var WP_TYPIA_CANONICAL_CREATE_USAGE = "wp-typia create <project-dir>";
@@ -2686,7 +2884,7 @@ var WP_TYPIA_COMMAND_REGISTRY = [
2686
2884
  nodeFallback: true,
2687
2885
  optionGroups: ["add"],
2688
2886
  requiresBunRuntime: false,
2689
- subcommands: ADD_KIND_IDS
2887
+ subcommands: ADD_KIND_IDS2
2690
2888
  },
2691
2889
  {
2692
2890
  commandTree: true,
@@ -2913,12 +3111,12 @@ function looksLikeStructuredProjectInput(value) {
2913
3111
  return value.startsWith("@") && value.includes("/");
2914
3112
  }
2915
3113
  function assertPositionalAliasProjectDir(projectDir) {
2916
- const normalizedProjectDir = path4.normalize(projectDir).replace(/[\\/]+$/u, "") || path4.normalize(projectDir);
3114
+ const normalizedProjectDir = path5.normalize(projectDir).replace(/[\\/]+$/u, "") || path5.normalize(projectDir);
2917
3115
  if (normalizedProjectDir === "." || normalizedProjectDir === "..") {
2918
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `The positional alias does not scaffold into \`${projectDir}\`. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` with an explicit child directory instead.`);
3116
+ throw createCliDiagnosticCodeError9(CLI_DIAGNOSTIC_CODES10.INVALID_ARGUMENT, `The positional alias does not scaffold into \`${projectDir}\`. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` with an explicit child directory instead.`);
2919
3117
  }
2920
3118
  if (looksLikeStructuredProjectInput(projectDir)) {
2921
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `The positional alias only accepts unambiguous local project directories. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for \`${projectDir}\`.`);
3119
+ throw createCliDiagnosticCodeError9(CLI_DIAGNOSTIC_CODES10.INVALID_ARGUMENT, `The positional alias only accepts unambiguous local project directories. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for \`${projectDir}\`.`);
2922
3120
  }
2923
3121
  }
2924
3122
  function normalizeWpTypiaArgv(argv) {
@@ -2932,7 +3130,7 @@ function normalizeWpTypiaArgv(argv) {
2932
3130
  return argv;
2933
3131
  }
2934
3132
  if (firstPositional === "migrations") {
2935
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, "`wp-typia migrations` was removed in favor of `wp-typia migrate`. Use `wp-typia migrate <subcommand>` instead.");
3133
+ throw createCliDiagnosticCodeError9(CLI_DIAGNOSTIC_CODES10.INVALID_ARGUMENT, "`wp-typia migrations` was removed in favor of `wp-typia migrate`. Use `wp-typia migrate <subcommand>` instead.");
2936
3134
  }
2937
3135
  if (isReservedTopLevelCommandName(firstPositional)) {
2938
3136
  assertStringOptionValues(argv);
@@ -2940,7 +3138,7 @@ function normalizeWpTypiaArgv(argv) {
2940
3138
  }
2941
3139
  if (positionalIndexes.length > 1) {
2942
3140
  const extraPositionals = positionalIndexes.slice(1).map((index) => argv[index]).filter((value) => typeof value === "string" && value.length > 0);
2943
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `The positional alias only accepts a single project directory. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for scaffold invocations with additional positional arguments, or check the command spelling if you meant another top-level command. Extra positional arguments: ${extraPositionals.map((value) => `\`${value}\``).join(", ")}.`);
3141
+ throw createCliDiagnosticCodeError9(CLI_DIAGNOSTIC_CODES10.INVALID_ARGUMENT, `The positional alias only accepts a single project directory. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for scaffold invocations with additional positional arguments, or check the command spelling if you meant another top-level command. Extra positional arguments: ${extraPositionals.map((value) => `\`${value}\``).join(", ")}.`);
2944
3142
  }
2945
3143
  assertPositionalAliasProjectDir(firstPositional);
2946
3144
  const normalizedArgv = [
@@ -2954,26 +3152,25 @@ function normalizeWpTypiaArgv(argv) {
2954
3152
 
2955
3153
  // src/node-fallback/dispatchers/add.ts
2956
3154
  import {
2957
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES9,
3155
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES11,
2958
3156
  createCliCommandError as createCliCommandError3
2959
3157
  } from "@wp-typia/project-tools/cli-diagnostics";
2960
3158
  async function dispatchNodeFallbackAdd({
2961
3159
  cwd,
2962
3160
  mergedFlags,
2963
3161
  positionals,
2964
- printLine
3162
+ printLine,
3163
+ warnLine
2965
3164
  }) {
2966
3165
  if (!positionals[1]) {
2967
- if (mergedFlags.format !== "json") {
3166
+ if (shouldPrintMissingAddKindHelp({ format: mergedFlags.format })) {
2968
3167
  const { formatAddHelpText } = await import("@wp-typia/project-tools/cli-add");
2969
3168
  printLine(formatAddHelpText());
2970
3169
  }
2971
3170
  throw createCliCommandError3({
2972
- code: CLI_DIAGNOSTIC_CODES9.MISSING_ARGUMENT,
3171
+ code: CLI_DIAGNOSTIC_CODES11.MISSING_ARGUMENT,
2973
3172
  command: "add",
2974
- detailLines: [
2975
- `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`
2976
- ]
3173
+ detailLines: buildMissingAddKindDetailLines()
2977
3174
  });
2978
3175
  }
2979
3176
  if (mergedFlags.format === "json") {
@@ -2985,7 +3182,9 @@ async function dispatchNodeFallbackAdd({
2985
3182
  flags: mergedFlags,
2986
3183
  interactive: false,
2987
3184
  kind: positionals[1],
2988
- name: positionals[2]
3185
+ name: positionals[2],
3186
+ printLine,
3187
+ warnLine
2989
3188
  });
2990
3189
  } catch (error) {
2991
3190
  throw createCliCommandError3({
@@ -3006,30 +3205,30 @@ async function dispatchNodeFallbackAdd({
3006
3205
  flags: mergedFlags,
3007
3206
  interactive: undefined,
3008
3207
  kind: positionals[1],
3009
- name: positionals[2]
3208
+ name: positionals[2],
3209
+ printLine,
3210
+ warnLine
3010
3211
  });
3011
3212
  }
3012
3213
 
3013
3214
  // src/node-fallback/dispatchers/create.ts
3014
3215
  import {
3015
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES10,
3216
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES12,
3016
3217
  createCliCommandError as createCliCommandError4
3017
3218
  } from "@wp-typia/project-tools/cli-diagnostics";
3018
3219
  async function dispatchNodeFallbackCreate({
3019
3220
  cwd,
3020
3221
  mergedFlags,
3021
3222
  positionals,
3022
- printLine
3223
+ printLine,
3224
+ warnLine
3023
3225
  }) {
3024
3226
  const projectDir = positionals[1];
3025
3227
  if (!projectDir) {
3026
3228
  throw createCliCommandError4({
3027
- code: CLI_DIAGNOSTIC_CODES10.MISSING_ARGUMENT,
3229
+ code: CLI_DIAGNOSTIC_CODES12.MISSING_ARGUMENT,
3028
3230
  command: "create",
3029
- detailLines: [
3030
- "`wp-typia create` requires <project-dir>.",
3031
- "`--dry-run` still needs a logical project directory name because wp-typia derives slugs, package names, and planned file paths from it."
3032
- ]
3231
+ detailLines: buildMissingCreateProjectDirDetailLines()
3033
3232
  });
3034
3233
  }
3035
3234
  let completion;
@@ -3039,7 +3238,9 @@ async function dispatchNodeFallbackCreate({
3039
3238
  emitOutput: mergedFlags.format !== "json",
3040
3239
  flags: mergedFlags,
3041
3240
  interactive: mergedFlags.format === "json" ? false : undefined,
3042
- projectDir
3241
+ printLine,
3242
+ projectDir,
3243
+ warnLine
3043
3244
  });
3044
3245
  } catch (error) {
3045
3246
  throw createCliCommandError4({
@@ -3064,13 +3265,9 @@ var NODE_FALLBACK_RUNTIME_SUMMARY_LINES = [
3064
3265
  `Install Bun 1.3.11+ or use \`bunx wp-typia ...\` for the full Bunli/OpenTUI runtime and Bun-only command surfaces such as \`skills\`, \`completions\`, and \`mcp\`. ${STANDALONE_GUIDANCE_LINE}`,
3065
3266
  "Output markers: WP_TYPIA_ASCII=1 forces ASCII markers, WP_TYPIA_ASCII=0 opts back into Unicode markers, and non-empty NO_COLOR requests ASCII markers when WP_TYPIA_ASCII is unset."
3066
3267
  ];
3067
- function printBlock2(printLine, lines) {
3068
- for (const line of lines) {
3069
- printLine(line);
3070
- }
3071
- }
3268
+ var NODE_FALLBACK_NO_COMMAND_REASON_LINE = "No command provided. Run wp-typia --help for usage information.";
3072
3269
  function renderGeneralHelp(printLine) {
3073
- printBlock2(printLine, [
3270
+ printBlock(printLine, [
3074
3271
  `wp-typia ${package_default.version}`,
3075
3272
  "",
3076
3273
  "Canonical CLI package for wp-typia scaffolding and project workflows.",
@@ -3087,8 +3284,12 @@ function renderGeneralHelp(printLine) {
3087
3284
  `- ${WP_TYPIA_POSITIONAL_ALIAS_USAGE}`
3088
3285
  ]);
3089
3286
  }
3287
+ function renderNoCommandHelp(printLine) {
3288
+ printBlock(printLine, [NODE_FALLBACK_NO_COMMAND_REASON_LINE, ""]);
3289
+ renderGeneralHelp(printLine);
3290
+ }
3090
3291
  function renderNodeFallbackCommandHelp(printLine, config) {
3091
- printBlock2(printLine, [
3292
+ printBlock(printLine, [
3092
3293
  config.heading,
3093
3294
  "",
3094
3295
  ...NODE_FALLBACK_RUNTIME_SUMMARY_LINES,
@@ -3146,6 +3347,9 @@ var NODE_FALLBACK_BOOLEAN_OPTION_NAMES = ["help", "version"];
3146
3347
  var printLine = (line) => {
3147
3348
  console.log(line);
3148
3349
  };
3350
+ var warnLine = (line) => {
3351
+ console.warn(line);
3352
+ };
3149
3353
  function hasFlagBeforeTerminator(argv, flag) {
3150
3354
  for (const arg of argv) {
3151
3355
  if (arg === "--") {
@@ -3226,7 +3430,7 @@ function renderTemplatesJson(flags, subcommand) {
3226
3430
  const templateId = flags.id;
3227
3431
  if (!templateId) {
3228
3432
  throw createCliCommandError5({
3229
- code: CLI_DIAGNOSTIC_CODES11.MISSING_ARGUMENT,
3433
+ code: CLI_DIAGNOSTIC_CODES13.MISSING_ARGUMENT,
3230
3434
  command: "templates",
3231
3435
  detailLines: ["`wp-typia templates inspect` requires <template-id>."]
3232
3436
  });
@@ -3234,7 +3438,7 @@ function renderTemplatesJson(flags, subcommand) {
3234
3438
  const template = getTemplateById(templateId);
3235
3439
  if (!template) {
3236
3440
  throw createCliCommandError5({
3237
- code: CLI_DIAGNOSTIC_CODES11.INVALID_ARGUMENT,
3441
+ code: CLI_DIAGNOSTIC_CODES13.INVALID_ARGUMENT,
3238
3442
  command: "templates",
3239
3443
  detailLines: [`Unknown template "${templateId}".`]
3240
3444
  });
@@ -3245,7 +3449,7 @@ function renderTemplatesJson(flags, subcommand) {
3245
3449
  }
3246
3450
  function renderUnsupportedCommand(command) {
3247
3451
  throw createCliCommandError5({
3248
- code: CLI_DIAGNOSTIC_CODES11.UNSUPPORTED_COMMAND,
3452
+ code: CLI_DIAGNOSTIC_CODES13.UNSUPPORTED_COMMAND,
3249
3453
  command,
3250
3454
  detailLines: [
3251
3455
  [
@@ -3271,7 +3475,7 @@ async function renderDoctorJson() {
3271
3475
  }, null, 2));
3272
3476
  if (checks.some((check) => check.status === "fail")) {
3273
3477
  throw createCliCommandError6({
3274
- code: CLI_DIAGNOSTIC_CODES11.DOCTOR_CHECK_FAILED,
3478
+ code: CLI_DIAGNOSTIC_CODES13.DOCTOR_CHECK_FAILED,
3275
3479
  command: "doctor",
3276
3480
  detailLines: getDoctorFailureDetailLines(checks),
3277
3481
  summary: "One or more doctor checks failed."
@@ -3291,7 +3495,9 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3291
3495
  init: async ({
3292
3496
  cwd,
3293
3497
  mergedFlags,
3294
- positionals
3498
+ positionals,
3499
+ printLine: printLine2,
3500
+ warnLine: warnLine2
3295
3501
  }) => {
3296
3502
  const plan = await executeInitCommand({
3297
3503
  apply: Boolean(mergedFlags.apply),
@@ -3299,10 +3505,12 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3299
3505
  packageManager: typeof mergedFlags["package-manager"] === "string" ? mergedFlags["package-manager"] : undefined,
3300
3506
  projectDir: positionals[1]
3301
3507
  }, {
3302
- emitOutput: mergedFlags.format !== "json"
3508
+ emitOutput: mergedFlags.format !== "json",
3509
+ printLine: printLine2,
3510
+ warnLine: warnLine2
3303
3511
  });
3304
3512
  if (mergedFlags.format === "json") {
3305
- printLine(JSON.stringify(buildStructuredInitSuccessPayload(plan), null, 2));
3513
+ printLine2(JSON.stringify(buildStructuredInitSuccessPayload(plan), null, 2));
3306
3514
  }
3307
3515
  },
3308
3516
  migrate: async ({
@@ -3319,7 +3527,9 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3319
3527
  sync: async ({
3320
3528
  cwd,
3321
3529
  mergedFlags,
3322
- positionals
3530
+ positionals,
3531
+ printLine: printLine2,
3532
+ warnLine: warnLine2
3323
3533
  }) => {
3324
3534
  try {
3325
3535
  const syncTarget = resolveSyncExecutionTarget(positionals[1]);
@@ -3331,7 +3541,7 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3331
3541
  target: syncTarget
3332
3542
  });
3333
3543
  if (mergedFlags.format === "json") {
3334
- printLine(JSON.stringify({
3544
+ printLine2(JSON.stringify({
3335
3545
  sync
3336
3546
  }, null, 2));
3337
3547
  return;
@@ -3343,7 +3553,10 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3343
3553
  plannedCommands: sync.plannedCommands,
3344
3554
  projectDir: sync.projectDir,
3345
3555
  target: sync.target
3346
- }));
3556
+ }), {
3557
+ printLine: printLine2,
3558
+ warnLine: warnLine2
3559
+ });
3347
3560
  }
3348
3561
  } catch (error) {
3349
3562
  throw createCliCommandError5({
@@ -3361,7 +3574,7 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3361
3574
  const resolvedSubcommand = templateId ? "inspect" : subcommand ?? "list";
3362
3575
  if (resolvedSubcommand !== "list" && resolvedSubcommand !== "inspect") {
3363
3576
  throw createCliCommandError5({
3364
- code: CLI_DIAGNOSTIC_CODES11.INVALID_COMMAND,
3577
+ code: CLI_DIAGNOSTIC_CODES13.INVALID_COMMAND,
3365
3578
  command: "templates",
3366
3579
  detailLines: [
3367
3580
  `Unknown templates subcommand "${resolvedSubcommand}". Expected list or inspect.`
@@ -3399,7 +3612,7 @@ async function runNodeCli(argv = process.argv.slice(2)) {
3399
3612
  const helpTarget = command === "help" ? subcommand : command;
3400
3613
  const versionRequested = hasFlagBeforeTerminator(cliArgv, "--version") || command === "version";
3401
3614
  if (cliArgv.length === 0) {
3402
- renderGeneralHelp(printLine);
3615
+ renderNoCommandHelp(printLine);
3403
3616
  process.exitCode = 1;
3404
3617
  return;
3405
3618
  }
@@ -3434,7 +3647,8 @@ async function runNodeCli(argv = process.argv.slice(2)) {
3434
3647
  cwd: process.cwd(),
3435
3648
  mergedFlags,
3436
3649
  positionals,
3437
- printLine
3650
+ printLine,
3651
+ warnLine
3438
3652
  });
3439
3653
  return;
3440
3654
  }
@@ -3469,4 +3683,4 @@ export {
3469
3683
  hasFlagBeforeTerminator
3470
3684
  };
3471
3685
 
3472
- //# debugId=8C4AF690141E04CA64756E2164756E21
3686
+ //# debugId=7726AE527215959664756E2164756E21