wp-typia 0.22.9 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.9",
6
+ version: "0.23.0",
7
7
  description: "Canonical CLI package for wp-typia scaffolding and project workflows",
8
8
  packageManager: "bun@1.3.11",
9
9
  type: "module",
@@ -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.9",
76
+ "@wp-typia/project-tools": "0.23.0",
77
77
  "better-result": "^2.7.0",
78
78
  react: "^19.2.5",
79
79
  "react-dom": "^19.2.5",
@@ -97,9 +97,10 @@ var package_default = {
97
97
 
98
98
  // src/node-cli.ts
99
99
  import {
100
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES12,
100
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES13,
101
101
  createCliCommandError as createCliCommandError5,
102
102
  formatCliDiagnosticError,
103
+ isCliDiagnosticError,
103
104
  serializeCliDiagnosticError as serializeCliDiagnosticError2
104
105
  } from "@wp-typia/project-tools/cli-diagnostics";
105
106
 
@@ -109,6 +110,163 @@ import {
109
110
  CLI_DIAGNOSTIC_CODES,
110
111
  createCliDiagnosticCodeError
111
112
  } from "@wp-typia/project-tools/cli-diagnostics";
113
+
114
+ // src/command-options/add.ts
115
+ var ADD_OPTION_METADATA = {
116
+ "alternate-render-targets": {
117
+ description: "Comma-separated alternate render targets for dynamic block scaffolds (email,mjml,plain-text).",
118
+ type: "string"
119
+ },
120
+ anchor: {
121
+ description: "Anchor block name for hooked-block workflows.",
122
+ type: "string"
123
+ },
124
+ attribute: {
125
+ description: "Target block attribute for end-to-end binding-source workflows.",
126
+ type: "string"
127
+ },
128
+ auth: {
129
+ description: "Auth intent for manual REST contract workflows (public, authenticated, or public-write-protected).",
130
+ type: "string"
131
+ },
132
+ block: {
133
+ description: "Target block slug for variation, style, and end-to-end binding-source workflows.",
134
+ type: "string"
135
+ },
136
+ "controller-class": {
137
+ description: "Generated REST resource controller class used for route callbacks.",
138
+ type: "string"
139
+ },
140
+ "controller-extends": {
141
+ description: "Optional base class for generated REST resource controller wrappers.",
142
+ type: "string"
143
+ },
144
+ "data-storage": {
145
+ description: "Persistence storage mode for persistence-capable templates.",
146
+ type: "string"
147
+ },
148
+ "dry-run": {
149
+ argumentKind: "flag",
150
+ description: "Preview workspace file updates and completion guidance without writing them.",
151
+ type: "boolean"
152
+ },
153
+ "external-layer-id": {
154
+ description: "Explicit layer id when an external layer package exposes multiple selectable layers.",
155
+ type: "string"
156
+ },
157
+ "external-layer-source": {
158
+ description: "Local path, GitHub locator, or npm package that exposes wp-typia.layers.json for built-in block templates.",
159
+ type: "string"
160
+ },
161
+ from: {
162
+ description: "Source full block name (namespace/block) for transform workflows.",
163
+ type: "string"
164
+ },
165
+ "inner-blocks-preset": {
166
+ description: "Compound-only InnerBlocks preset (freeform, ordered, horizontal, locked-structure).",
167
+ type: "string"
168
+ },
169
+ manual: {
170
+ argumentKind: "flag",
171
+ description: "Create a type-only manual REST contract without PHP route/controller files.",
172
+ type: "boolean"
173
+ },
174
+ "hide-from-rest": {
175
+ argumentKind: "flag",
176
+ description: "Keep a generated post-meta contract out of WordPress REST/editor responses.",
177
+ type: "boolean"
178
+ },
179
+ "meta-key": {
180
+ description: "WordPress meta key for post-meta workflows; defaults to _<phpPrefix>_<name>.",
181
+ type: "string"
182
+ },
183
+ method: {
184
+ description: "HTTP method for manual REST contract workflows (GET, POST, PUT, PATCH, or DELETE).",
185
+ type: "string"
186
+ },
187
+ methods: {
188
+ description: "Comma-separated REST resource methods for rest-resource workflows.",
189
+ type: "string"
190
+ },
191
+ namespace: {
192
+ description: "REST namespace for rest-resource and ai-feature workflows.",
193
+ type: "string"
194
+ },
195
+ "permission-callback": {
196
+ description: "PHP permission callback for generated REST resource route registrations.",
197
+ type: "string"
198
+ },
199
+ "post-type": {
200
+ description: "WordPress post type key for post-meta workflows.",
201
+ type: "string"
202
+ },
203
+ "persistence-policy": {
204
+ description: "Persistence write policy for persistence-capable templates.",
205
+ type: "string"
206
+ },
207
+ path: {
208
+ description: "Route path pattern for manual REST contract workflows, relative to the REST namespace.",
209
+ type: "string"
210
+ },
211
+ position: {
212
+ description: "Hook position for hooked-block workflows.",
213
+ type: "string"
214
+ },
215
+ "query-type": {
216
+ description: "Exported TypeScript query type for manual REST contract workflows.",
217
+ type: "string"
218
+ },
219
+ "response-type": {
220
+ description: "Exported TypeScript response type for manual REST contract workflows.",
221
+ type: "string"
222
+ },
223
+ "route-pattern": {
224
+ description: "Generated REST resource item route pattern relative to the REST namespace.",
225
+ type: "string"
226
+ },
227
+ "secret-field": {
228
+ description: "Write-only request body field for manual settings REST contracts.",
229
+ type: "string"
230
+ },
231
+ "secret-state-field": {
232
+ description: "Masked response boolean field for --secret-field; defaults to has<SecretField>.",
233
+ type: "string"
234
+ },
235
+ service: {
236
+ description: "Optional local service starter for integration-env workflows (none or docker-compose).",
237
+ type: "string"
238
+ },
239
+ slot: {
240
+ description: "Document editor shell slot for editor-plugin workflows (sidebar or document-setting-panel).",
241
+ type: "string"
242
+ },
243
+ source: {
244
+ description: "Optional data source locator for admin-view workflows, such as rest-resource:products or core-data:postType/post.",
245
+ type: "string"
246
+ },
247
+ template: {
248
+ 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.",
249
+ type: "string"
250
+ },
251
+ type: {
252
+ description: "Exported TypeScript type or interface name for standalone contract workflows.",
253
+ type: "string"
254
+ },
255
+ "body-type": {
256
+ description: "Exported TypeScript body type for manual REST contract workflows.",
257
+ type: "string"
258
+ },
259
+ to: {
260
+ description: "Target workspace block slug or full block name for transform workflows.",
261
+ type: "string"
262
+ },
263
+ "wp-env": {
264
+ argumentKind: "flag",
265
+ description: "Add a local @wordpress/env preset for integration-env workflows.",
266
+ type: "boolean"
267
+ }
268
+ };
269
+ // src/command-options/create.ts
112
270
  var CREATE_OPTION_METADATA = {
113
271
  "alternate-render-targets": {
114
272
  description: "Comma-separated alternate render targets for dynamic block scaffolds (email,mjml,plain-text).",
@@ -196,81 +354,30 @@ var CREATE_OPTION_METADATA = {
196
354
  type: "boolean"
197
355
  }
198
356
  };
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).",
357
+ // src/command-options/doctor.ts
358
+ var DOCTOR_OPTION_METADATA = {
359
+ format: {
360
+ description: "Use `json` for machine-readable doctor check output or `text` for human-readable output.",
259
361
  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.",
362
+ }
363
+ };
364
+ // src/command-options/global.ts
365
+ var GLOBAL_OPTION_METADATA = {
366
+ config: {
367
+ description: "Config override file path.",
368
+ short: "c",
263
369
  type: "string"
264
370
  },
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.",
371
+ format: {
372
+ description: "Output format for supported commands (`json` or `text`).",
267
373
  type: "string"
268
374
  },
269
- to: {
270
- description: "Target workspace block slug or full block name for transform workflows.",
375
+ id: {
376
+ description: "Template id for top-level `templates inspect` convenience.",
271
377
  type: "string"
272
378
  }
273
379
  };
380
+ // src/command-options/init.ts
274
381
  var INIT_OPTION_METADATA = {
275
382
  apply: {
276
383
  argumentKind: "flag",
@@ -283,6 +390,14 @@ var INIT_OPTION_METADATA = {
283
390
  type: "string"
284
391
  }
285
392
  };
393
+ // src/command-options/mcp.ts
394
+ var MCP_OPTION_METADATA = {
395
+ "output-dir": {
396
+ description: "Output directory for generated MCP metadata.",
397
+ type: "string"
398
+ }
399
+ };
400
+ // src/command-options/migrate.ts
286
401
  var MIGRATE_OPTION_METADATA = {
287
402
  all: {
288
403
  argumentKind: "flag",
@@ -319,12 +434,7 @@ var MIGRATE_OPTION_METADATA = {
319
434
  type: "string"
320
435
  }
321
436
  };
322
- var MCP_OPTION_METADATA = {
323
- "output-dir": {
324
- description: "Output directory for generated MCP metadata.",
325
- type: "string"
326
- }
327
- };
437
+ // src/command-options/sync.ts
328
438
  var SYNC_OPTION_METADATA = {
329
439
  check: {
330
440
  argumentKind: "flag",
@@ -337,33 +447,14 @@ var SYNC_OPTION_METADATA = {
337
447
  type: "boolean"
338
448
  }
339
449
  };
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
- };
450
+ // src/command-options/templates.ts
346
451
  var TEMPLATES_OPTION_METADATA = {
347
452
  id: {
348
453
  description: "Template id for `templates inspect`.",
349
454
  type: "string"
350
455
  }
351
456
  };
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
- };
457
+ // src/command-option-metadata.ts
367
458
  var COMMAND_OPTION_METADATA_BY_GROUP = {
368
459
  add: ADD_OPTION_METADATA,
369
460
  create: CREATE_OPTION_METADATA,
@@ -927,14 +1018,21 @@ function extractWpTypiaConfigOverride(argv) {
927
1018
  };
928
1019
  }
929
1020
 
930
- // src/runtime-bridge.ts
1021
+ // src/runtime-bridge-add.ts
931
1022
  import {
932
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES8,
933
- createCliDiagnosticCodeError as createCliDiagnosticCodeError7
1023
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES7,
1024
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError6
934
1025
  } from "@wp-typia/project-tools/cli-diagnostics";
935
1026
 
936
1027
  // src/add-kind-ids.ts
937
1028
  import { ADD_KIND_IDS } from "@wp-typia/project-tools/cli-add-kind-ids";
1029
+ import { ADD_KIND_IDS as ADD_KIND_IDS2 } from "@wp-typia/project-tools/cli-add-kind-ids";
1030
+ function formatAddKindList() {
1031
+ return ADD_KIND_IDS.join(", ");
1032
+ }
1033
+ function formatAddKindUsagePlaceholder() {
1034
+ return `<${ADD_KIND_IDS.join("|")}>`;
1035
+ }
938
1036
 
939
1037
  // src/add-kind-registry-shared.ts
940
1038
  import {
@@ -959,6 +1057,11 @@ var NAME_SOURCE_VISIBLE_FIELDS = [
959
1057
  "name",
960
1058
  "source"
961
1059
  ];
1060
+ var NAME_TYPE_VISIBLE_FIELDS = [
1061
+ "kind",
1062
+ "name",
1063
+ "type"
1064
+ ];
962
1065
  var NAME_BLOCK_ATTRIBUTE_VISIBLE_FIELDS = [
963
1066
  "kind",
964
1067
  "name",
@@ -998,6 +1101,12 @@ var NAME_NAMESPACE_VISIBLE_FIELDS = [
998
1101
  "name",
999
1102
  "namespace"
1000
1103
  ];
1104
+ var NAME_POST_TYPE_TYPE_VISIBLE_FIELDS = [
1105
+ "kind",
1106
+ "name",
1107
+ "post-type",
1108
+ "type"
1109
+ ];
1001
1110
  function requireAddKindName(context, message) {
1002
1111
  if (!context.name) {
1003
1112
  throw createCliDiagnosticCodeError3(CLI_DIAGNOSTIC_CODES4.MISSING_ARGUMENT, message);
@@ -1044,6 +1153,7 @@ function assertAddBlockTemplateId(context, templateId) {
1044
1153
  }
1045
1154
 
1046
1155
  // src/add-kinds/ability.ts
1156
+ var ABILITY_MISSING_NAME_MESSAGE = "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.";
1047
1157
  var abilityAddKindEntry = defineAddKindRegistryEntry({
1048
1158
  completion: {
1049
1159
  nextSteps: (values) => [
@@ -1068,7 +1178,7 @@ var abilityAddKindEntry = defineAddKindRegistryEntry({
1068
1178
  abilitySlug: result.abilitySlug
1069
1179
  }),
1070
1180
  getWarnings: (result) => result.warnings,
1071
- missingNameMessage: "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.",
1181
+ missingNameMessage: ABILITY_MISSING_NAME_MESSAGE,
1072
1182
  warnLine: context.warnLine
1073
1183
  });
1074
1184
  },
@@ -1106,6 +1216,9 @@ function readOptionalLooseStringFlag(flags, name) {
1106
1216
  function readOptionalStrictStringFlag(flags, name) {
1107
1217
  return readOptionalCliStringFlagValue(flags, name, "strict");
1108
1218
  }
1219
+ function readOptionalDashedOrCamelStringFlag(flags, dashedName, camelName) {
1220
+ return readOptionalStrictStringFlag(flags, dashedName) ?? readOptionalStrictStringFlag(flags, camelName);
1221
+ }
1109
1222
  function requireStrictStringFlag(flags, name, message) {
1110
1223
  const value = readOptionalStrictStringFlag(flags, name);
1111
1224
  if (!value) {
@@ -1123,6 +1236,7 @@ function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message
1123
1236
  }
1124
1237
 
1125
1238
  // src/add-kinds/admin-view.ts
1239
+ 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>].";
1126
1240
  var adminViewAddKindEntry = defineAddKindRegistryEntry({
1127
1241
  completion: {
1128
1242
  nextSteps: (values) => [
@@ -1139,7 +1253,7 @@ var adminViewAddKindEntry = defineAddKindRegistryEntry({
1139
1253
  description: "Add an opt-in DataViews-powered admin screen",
1140
1254
  nameLabel: "Admin view name",
1141
1255
  async prepareExecution(context) {
1142
- 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>].");
1256
+ const name = requireAddKindName(context, ADMIN_VIEW_MISSING_NAME_MESSAGE);
1143
1257
  const source = readOptionalStrictStringFlag(context.flags, "source");
1144
1258
  return createNamedExecutionPlan(context, {
1145
1259
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
@@ -1151,8 +1265,9 @@ var adminViewAddKindEntry = defineAddKindRegistryEntry({
1151
1265
  adminViewSlug: result.adminViewSlug,
1152
1266
  ...result.source ? { source: result.source } : {}
1153
1267
  }),
1154
- missingNameMessage: "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].",
1155
- name
1268
+ missingNameMessage: ADMIN_VIEW_MISSING_NAME_MESSAGE,
1269
+ name,
1270
+ warnLine: context.warnLine
1156
1271
  });
1157
1272
  },
1158
1273
  sortOrder: 10,
@@ -1162,6 +1277,7 @@ var adminViewAddKindEntry = defineAddKindRegistryEntry({
1162
1277
  });
1163
1278
 
1164
1279
  // src/add-kinds/ai-feature.ts
1280
+ var AI_FEATURE_MISSING_NAME_MESSAGE = "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].";
1165
1281
  var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
1166
1282
  completion: {
1167
1283
  nextSteps: (values) => [
@@ -1178,7 +1294,7 @@ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
1178
1294
  description: "Add a server-owned WordPress AI feature endpoint",
1179
1295
  nameLabel: "AI feature name",
1180
1296
  async prepareExecution(context) {
1181
- const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
1297
+ const name = requireAddKindName(context, AI_FEATURE_MISSING_NAME_MESSAGE);
1182
1298
  const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1183
1299
  return createNamedExecutionPlan(context, {
1184
1300
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
@@ -1191,7 +1307,7 @@ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
1191
1307
  namespace: result.namespace
1192
1308
  }),
1193
1309
  getWarnings: (result) => result.warnings,
1194
- missingNameMessage: "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].",
1310
+ missingNameMessage: AI_FEATURE_MISSING_NAME_MESSAGE,
1195
1311
  name,
1196
1312
  warnLine: context.warnLine
1197
1313
  });
@@ -1203,6 +1319,7 @@ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
1203
1319
  });
1204
1320
 
1205
1321
  // src/add-kinds/binding-source.ts
1322
+ 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>].";
1206
1323
  var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
1207
1324
  completion: {
1208
1325
  nextSteps: (values) => [
@@ -1222,7 +1339,7 @@ var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
1222
1339
  description: "Add a shared block bindings source",
1223
1340
  nameLabel: "Binding source name",
1224
1341
  async prepareExecution(context) {
1225
- 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>].");
1342
+ const name = requireAddKindName(context, BINDING_SOURCE_MISSING_NAME_MESSAGE);
1226
1343
  const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
1227
1344
  return createNamedExecutionPlan(context, {
1228
1345
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
@@ -1236,8 +1353,9 @@ var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
1236
1353
  ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
1237
1354
  bindingSourceSlug: result.bindingSourceSlug
1238
1355
  }),
1239
- missingNameMessage: "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].",
1240
- name
1356
+ missingNameMessage: BINDING_SOURCE_MISSING_NAME_MESSAGE,
1357
+ name,
1358
+ warnLine: context.warnLine
1241
1359
  });
1242
1360
  },
1243
1361
  sortOrder: 70,
@@ -1263,6 +1381,7 @@ function toExternalLayerPromptOptions(options) {
1263
1381
  }
1264
1382
 
1265
1383
  // src/add-kinds/block.ts
1384
+ var BLOCK_MISSING_NAME_MESSAGE = "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]";
1266
1385
  var blockAddKindEntry = defineAddKindRegistryEntry({
1267
1386
  completion: {
1268
1387
  nextSteps: () => [
@@ -1280,7 +1399,7 @@ var blockAddKindEntry = defineAddKindRegistryEntry({
1280
1399
  hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
1281
1400
  nameLabel: "Block name",
1282
1401
  async prepareExecution(context) {
1283
- const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
1402
+ const name = requireAddKindName(context, BLOCK_MISSING_NAME_MESSAGE);
1284
1403
  const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
1285
1404
  const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
1286
1405
  const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
@@ -1318,7 +1437,7 @@ var blockAddKindEntry = defineAddKindRegistryEntry({
1318
1437
  templateId: result.templateId
1319
1438
  }),
1320
1439
  getWarnings: (result) => result.warnings,
1321
- missingNameMessage: "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]",
1440
+ missingNameMessage: BLOCK_MISSING_NAME_MESSAGE,
1322
1441
  name,
1323
1442
  warnLine: context.warnLine
1324
1443
  });
@@ -1340,11 +1459,56 @@ var blockAddKindEntry = defineAddKindRegistryEntry({
1340
1459
  })
1341
1460
  });
1342
1461
 
1343
- // src/add-kinds/editor-plugin.ts
1344
- var editorPluginAddKindEntry = defineAddKindRegistryEntry({
1462
+ // src/add-kinds/contract.ts
1463
+ var CONTRACT_MISSING_NAME_MESSAGE = "`wp-typia add contract` requires <name>. Usage: wp-typia add contract <name> [--type <ExportedTypeName>].";
1464
+ var contractAddKindEntry = defineAddKindRegistryEntry({
1345
1465
  completion: {
1346
1466
  nextSteps: (values) => [
1347
- `Review src/editor-plugins/${values.editorPluginSlug}/.`,
1467
+ `Edit ${values.typesFile} when the standalone wire shape changes.`,
1468
+ "Run `wp-typia sync-rest` or `wp-typia sync` to refresh the generated schema artifact."
1469
+ ],
1470
+ summaryLines: (values, projectDir) => [
1471
+ `Contract: ${values.contractSlug}`,
1472
+ `Source type: ${values.sourceTypeName}`,
1473
+ `Schema: ${values.schemaFile}`,
1474
+ `Project directory: ${projectDir}`
1475
+ ],
1476
+ title: "Added standalone contract"
1477
+ },
1478
+ description: "Add a standalone TypeScript schema contract",
1479
+ nameLabel: "Contract name",
1480
+ async prepareExecution(context) {
1481
+ const name = requireAddKindName(context, CONTRACT_MISSING_NAME_MESSAGE);
1482
+ const typeName = readOptionalStrictStringFlag(context.flags, "type");
1483
+ return createNamedExecutionPlan(context, {
1484
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddContractCommand({
1485
+ contractName: name2,
1486
+ cwd,
1487
+ typeName
1488
+ }),
1489
+ getValues: (result) => ({
1490
+ contractSlug: result.contractSlug,
1491
+ schemaFile: result.schemaFile,
1492
+ sourceTypeName: result.sourceTypeName,
1493
+ typesFile: result.typesFile
1494
+ }),
1495
+ missingNameMessage: CONTRACT_MISSING_NAME_MESSAGE,
1496
+ name,
1497
+ warnLine: context.warnLine
1498
+ });
1499
+ },
1500
+ sortOrder: 75,
1501
+ supportsDryRun: true,
1502
+ usage: "wp-typia add contract <name> [--type <ExportedTypeName>] [--dry-run]",
1503
+ visibleFieldNames: () => NAME_TYPE_VISIBLE_FIELDS
1504
+ });
1505
+
1506
+ // src/add-kinds/editor-plugin.ts
1507
+ 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>].";
1508
+ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
1509
+ completion: {
1510
+ nextSteps: (values) => [
1511
+ `Review src/editor-plugins/${values.editorPluginSlug}/.`,
1348
1512
  "Run your workspace build or dev command to verify the new editor plugin registration."
1349
1513
  ],
1350
1514
  summaryLines: (values, projectDir) => [
@@ -1357,7 +1521,7 @@ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
1357
1521
  description: "Add a slot-aware document editor extension shell",
1358
1522
  nameLabel: "Editor plugin name",
1359
1523
  async prepareExecution(context) {
1360
- const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].");
1524
+ const name = requireAddKindName(context, EDITOR_PLUGIN_MISSING_NAME_MESSAGE);
1361
1525
  const slot = readOptionalStrictStringFlag(context.flags, "slot");
1362
1526
  return createNamedExecutionPlan(context, {
1363
1527
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
@@ -1369,8 +1533,9 @@ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
1369
1533
  editorPluginSlug: result.editorPluginSlug,
1370
1534
  slot: result.slot
1371
1535
  }),
1372
- missingNameMessage: "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].",
1373
- name
1536
+ missingNameMessage: EDITOR_PLUGIN_MISSING_NAME_MESSAGE,
1537
+ name,
1538
+ warnLine: context.warnLine
1374
1539
  });
1375
1540
  },
1376
1541
  sortOrder: 120,
@@ -1380,6 +1545,7 @@ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
1380
1545
  });
1381
1546
 
1382
1547
  // src/add-kinds/hooked-block.ts
1548
+ 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>.";
1383
1549
  var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
1384
1550
  completion: {
1385
1551
  nextSteps: (values) => [
@@ -1397,7 +1563,7 @@ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
1397
1563
  description: "Add block.json hook metadata to an existing block",
1398
1564
  nameLabel: "Target block",
1399
1565
  async prepareExecution(context) {
1400
- 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>.");
1566
+ const name = requireAddKindName(context, HOOKED_BLOCK_MISSING_NAME_MESSAGE);
1401
1567
  const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
1402
1568
  const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
1403
1569
  return createNamedExecutionPlan(context, {
@@ -1412,8 +1578,9 @@ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
1412
1578
  blockSlug: result.blockSlug,
1413
1579
  position: result.position
1414
1580
  }),
1415
- 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>.",
1416
- name
1581
+ missingNameMessage: HOOKED_BLOCK_MISSING_NAME_MESSAGE,
1582
+ name,
1583
+ warnLine: context.warnLine
1417
1584
  });
1418
1585
  },
1419
1586
  sortOrder: 110,
@@ -1422,7 +1589,53 @@ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
1422
1589
  visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
1423
1590
  });
1424
1591
 
1592
+ // src/add-kinds/integration-env.ts
1593
+ var INTEGRATION_ENV_MISSING_NAME_MESSAGE = "`wp-typia add integration-env` requires <name>. Usage: wp-typia add integration-env <name> [--wp-env] [--service <none|docker-compose>].";
1594
+ var integrationEnvAddKindEntry = defineAddKindRegistryEntry({
1595
+ completion: {
1596
+ nextSteps: (values) => [
1597
+ `Review scripts/integration-smoke/${values.integrationEnvSlug}.mjs and docs/integration-env/${values.integrationEnvSlug}.md.`,
1598
+ "Copy `.env.example` to `.env`, adjust local URLs or credentials, then run the generated smoke script.",
1599
+ ...values.withWpEnv === "true" ? ["Run `npm run wp-env:start` before the smoke check when using the generated wp-env preset."] : []
1600
+ ],
1601
+ summaryLines: (values, projectDir) => [
1602
+ `Integration env: ${values.integrationEnvSlug}`,
1603
+ `wp-env preset: ${values.withWpEnv}`,
1604
+ `Service starter: ${values.service}`,
1605
+ `Project directory: ${projectDir}`
1606
+ ],
1607
+ title: "Added integration environment starter"
1608
+ },
1609
+ description: "Add an opt-in local WordPress integration smoke environment starter",
1610
+ nameLabel: "Integration env name",
1611
+ async prepareExecution(context) {
1612
+ const service = readOptionalStrictStringFlag(context.flags, "service");
1613
+ const withWpEnv = Boolean(context.flags["wp-env"]);
1614
+ return createNamedExecutionPlan(context, {
1615
+ execute: ({ cwd, name }) => context.addRuntime.runAddIntegrationEnvCommand({
1616
+ cwd,
1617
+ integrationEnvName: name,
1618
+ service,
1619
+ withWpEnv
1620
+ }),
1621
+ getValues: (result) => ({
1622
+ integrationEnvSlug: result.integrationEnvSlug,
1623
+ service: result.service,
1624
+ withWpEnv: String(result.withWpEnv)
1625
+ }),
1626
+ getWarnings: (result) => result.warnings,
1627
+ missingNameMessage: INTEGRATION_ENV_MISSING_NAME_MESSAGE,
1628
+ warnLine: context.warnLine
1629
+ });
1630
+ },
1631
+ sortOrder: 25,
1632
+ supportsDryRun: true,
1633
+ usage: "wp-typia add integration-env <name> [--wp-env] [--service <none|docker-compose>] [--dry-run]",
1634
+ visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
1635
+ });
1636
+
1425
1637
  // src/add-kinds/pattern.ts
1638
+ var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.";
1426
1639
  var patternAddKindEntry = defineAddKindRegistryEntry({
1427
1640
  completion: {
1428
1641
  nextSteps: (values) => [
@@ -1446,7 +1659,8 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
1446
1659
  getValues: (result) => ({
1447
1660
  patternSlug: result.patternSlug
1448
1661
  }),
1449
- missingNameMessage: "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>."
1662
+ missingNameMessage: PATTERN_MISSING_NAME_MESSAGE,
1663
+ warnLine: context.warnLine
1450
1664
  });
1451
1665
  },
1452
1666
  sortOrder: 60,
@@ -1455,50 +1669,182 @@ var patternAddKindEntry = defineAddKindRegistryEntry({
1455
1669
  visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
1456
1670
  });
1457
1671
 
1672
+ // src/add-kinds/post-meta.ts
1673
+ var POST_META_MISSING_NAME_MESSAGE = "`wp-typia add post-meta` requires <name>. Usage: wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>].";
1674
+ var POST_META_MISSING_POST_TYPE_MESSAGE = "`wp-typia add post-meta` requires --post-type <post-type>. Usage: wp-typia add post-meta <name> --post-type <post-type>.";
1675
+ var postMetaAddKindEntry = defineAddKindRegistryEntry({
1676
+ completion: {
1677
+ nextSteps: (values) => [
1678
+ `Edit ${values.typesFile} when the post meta shape changes.`,
1679
+ "Run `wp-typia sync-rest --check` to verify the generated meta schema is current.",
1680
+ `Smoke test ${values.metaKey} on the ${values.postType} post type in WordPress.`
1681
+ ],
1682
+ summaryLines: (values, projectDir) => [
1683
+ `Post meta contract: ${values.postMetaSlug}`,
1684
+ `Post type: ${values.postType}`,
1685
+ `Meta key: ${values.metaKey}`,
1686
+ `REST/editor exposure: ${values.showInRest}`,
1687
+ `Schema: ${values.schemaFile}`,
1688
+ `PHP: ${values.phpFile}`,
1689
+ `Project directory: ${projectDir}`
1690
+ ],
1691
+ title: "Added post meta contract"
1692
+ },
1693
+ description: "Add a typed WordPress post meta contract",
1694
+ hiddenBooleanSubmitFields: ["hide-from-rest"],
1695
+ hiddenStringSubmitFields: ["meta-key"],
1696
+ nameLabel: "Post meta name",
1697
+ async prepareExecution(context) {
1698
+ const name = requireAddKindName(context, POST_META_MISSING_NAME_MESSAGE);
1699
+ const hideFromRest = Boolean(context.flags["hide-from-rest"] ?? context.flags.hideFromRest);
1700
+ const metaKey = readOptionalDashedOrCamelStringFlag(context.flags, "meta-key", "metaKey");
1701
+ const postType = readOptionalDashedOrCamelStringFlag(context.flags, "post-type", "postType") ?? requireStrictStringFlag(context.flags, "post-type", POST_META_MISSING_POST_TYPE_MESSAGE);
1702
+ const typeName = readOptionalStrictStringFlag(context.flags, "type");
1703
+ return createNamedExecutionPlan(context, {
1704
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddPostMetaCommand({
1705
+ cwd,
1706
+ hideFromRest,
1707
+ metaKey,
1708
+ postMetaName: name2,
1709
+ postType,
1710
+ typeName
1711
+ }),
1712
+ getValues: (result) => ({
1713
+ metaKey: result.metaKey,
1714
+ phpFile: result.phpFile,
1715
+ postMetaSlug: result.postMetaSlug,
1716
+ postType: result.postType,
1717
+ schemaFile: result.schemaFile,
1718
+ showInRest: result.showInRest ? "enabled" : "disabled",
1719
+ sourceTypeName: result.sourceTypeName,
1720
+ typesFile: result.typesFile
1721
+ }),
1722
+ missingNameMessage: POST_META_MISSING_NAME_MESSAGE,
1723
+ name,
1724
+ warnLine: context.warnLine
1725
+ });
1726
+ },
1727
+ sortOrder: 85,
1728
+ supportsDryRun: true,
1729
+ usage: "wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>] [--hide-from-rest] [--dry-run]",
1730
+ visibleFieldNames: () => NAME_POST_TYPE_TYPE_VISIBLE_FIELDS
1731
+ });
1732
+
1458
1733
  // src/add-kinds/rest-resource.ts
1734
+ var REST_RESOURCE_MISSING_NAME_MESSAGE = "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] or wp-typia add rest-resource <name> --manual [--method GET] [--path /external].";
1735
+ function readOptionalDashedOrCamelStringFlag2(flags, dashedName, camelName) {
1736
+ return readOptionalStrictStringFlag(flags, dashedName) ?? readOptionalStrictStringFlag(flags, camelName);
1737
+ }
1459
1738
  var restResourceAddKindEntry = defineAddKindRegistryEntry({
1460
1739
  completion: {
1461
- nextSteps: (values) => [
1740
+ nextSteps: (values) => values.mode === "manual" ? [
1741
+ `Review src/rest/${values.restResourceSlug}/ and edit the manual contract types to match the external route owner.`,
1742
+ "Run sync-rest --check after changing the contract types to verify schemas, OpenAPI, and client artifacts."
1743
+ ] : [
1462
1744
  `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
1463
1745
  "Run your workspace build or dev command to verify the generated REST resource contract."
1464
1746
  ],
1465
1747
  summaryLines: (values, projectDir) => [
1466
1748
  `REST resource: ${values.restResourceSlug}`,
1749
+ `Mode: ${values.mode}`,
1467
1750
  `Namespace: ${values.namespace}`,
1468
- `Methods: ${values.methods}`,
1751
+ ...values.mode === "manual" ? [
1752
+ `Route: ${values.method} /${values.namespace}${values.pathPattern}`,
1753
+ `Auth: ${values.auth}`,
1754
+ ...values.secretFieldName ? [
1755
+ `Secret field: ${values.secretFieldName} -> ${values.secretStateFieldName}`
1756
+ ] : []
1757
+ ] : [
1758
+ `Methods: ${values.methods}`,
1759
+ ...values.routePattern ? [`Item route: /${values.namespace}${values.routePattern}`] : [],
1760
+ ...values.permissionCallback ? [`Permission callback: ${values.permissionCallback}`] : [],
1761
+ ...values.controllerClass ? [`Controller class: ${values.controllerClass}`] : []
1762
+ ],
1469
1763
  `Project directory: ${projectDir}`
1470
1764
  ],
1471
- title: "Added plugin-level REST resource"
1472
- },
1473
- description: "Add a plugin-level typed REST resource",
1765
+ title: "Added REST resource contract"
1766
+ },
1767
+ description: "Add a generated or type-only REST resource contract",
1768
+ hiddenBooleanSubmitFields: ["manual"],
1769
+ hiddenStringSubmitFields: [
1770
+ "auth",
1771
+ "body-type",
1772
+ "controller-class",
1773
+ "controller-extends",
1774
+ "method",
1775
+ "path",
1776
+ "permission-callback",
1777
+ "query-type",
1778
+ "response-type",
1779
+ "route-pattern",
1780
+ "secret-field",
1781
+ "secret-state-field"
1782
+ ],
1474
1783
  nameLabel: "REST resource name",
1475
1784
  async prepareExecution(context) {
1476
- const name = requireAddKindName(context, "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>].");
1785
+ const name = requireAddKindName(context, REST_RESOURCE_MISSING_NAME_MESSAGE);
1786
+ const auth = readOptionalStrictStringFlag(context.flags, "auth");
1787
+ const bodyTypeName = readOptionalStrictStringFlag(context.flags, "body-type");
1788
+ const controllerClass = readOptionalDashedOrCamelStringFlag2(context.flags, "controller-class", "controllerClass");
1789
+ const controllerExtends = readOptionalDashedOrCamelStringFlag2(context.flags, "controller-extends", "controllerExtends");
1790
+ const manual = Boolean(context.flags.manual);
1791
+ const method = readOptionalStrictStringFlag(context.flags, "method");
1477
1792
  const methods = readOptionalStrictStringFlag(context.flags, "methods");
1478
1793
  const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1794
+ const permissionCallback = readOptionalDashedOrCamelStringFlag2(context.flags, "permission-callback", "permissionCallback");
1795
+ const pathPattern = readOptionalStrictStringFlag(context.flags, "path");
1796
+ const queryTypeName = readOptionalStrictStringFlag(context.flags, "query-type");
1797
+ const responseTypeName = readOptionalStrictStringFlag(context.flags, "response-type");
1798
+ const routePattern = readOptionalDashedOrCamelStringFlag2(context.flags, "route-pattern", "routePattern");
1799
+ const secretFieldName = readOptionalDashedOrCamelStringFlag2(context.flags, "secret-field", "secretField");
1800
+ const secretStateFieldName = readOptionalDashedOrCamelStringFlag2(context.flags, "secret-state-field", "secretStateField");
1479
1801
  return createNamedExecutionPlan(context, {
1480
1802
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
1803
+ auth,
1804
+ bodyTypeName,
1805
+ controllerClass,
1806
+ controllerExtends,
1481
1807
  cwd,
1808
+ manual,
1809
+ method,
1482
1810
  methods,
1483
1811
  namespace,
1484
- restResourceName: name2
1812
+ permissionCallback,
1813
+ pathPattern,
1814
+ queryTypeName,
1815
+ restResourceName: name2,
1816
+ responseTypeName,
1817
+ routePattern,
1818
+ secretFieldName,
1819
+ secretStateFieldName
1485
1820
  }),
1486
1821
  getValues: (result) => ({
1822
+ auth: result.auth ?? "",
1823
+ controllerClass: result.controllerClass ?? "",
1824
+ method: result.method ?? "",
1487
1825
  methods: result.methods.join(", "),
1826
+ mode: result.mode,
1488
1827
  namespace: result.namespace,
1489
- restResourceSlug: result.restResourceSlug
1828
+ pathPattern: result.pathPattern ?? "",
1829
+ permissionCallback: result.permissionCallback ?? "",
1830
+ restResourceSlug: result.restResourceSlug,
1831
+ routePattern: result.routePattern ?? "",
1832
+ secretFieldName: result.secretFieldName ?? "",
1833
+ secretStateFieldName: result.secretStateFieldName ?? ""
1490
1834
  }),
1491
- missingNameMessage: "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>].",
1492
- name
1835
+ missingNameMessage: REST_RESOURCE_MISSING_NAME_MESSAGE,
1836
+ name,
1837
+ warnLine: context.warnLine
1493
1838
  });
1494
1839
  },
1495
1840
  sortOrder: 80,
1496
1841
  supportsDryRun: true,
1497
- usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
1842
+ usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--manual --method <GET|POST|PUT|PATCH|DELETE> --auth <public|authenticated|public-write-protected> --path <route-pattern> --query-type <Type> --body-type <Type> --response-type <Type> --secret-field <field> --secret-state-field <field>] [--dry-run]",
1498
1843
  visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
1499
1844
  });
1500
1845
 
1501
1846
  // src/add-kinds/style.ts
1847
+ var STYLE_MISSING_NAME_MESSAGE = "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.";
1502
1848
  var styleAddKindEntry = defineAddKindRegistryEntry({
1503
1849
  completion: {
1504
1850
  nextSteps: (values) => [
@@ -1515,7 +1861,7 @@ var styleAddKindEntry = defineAddKindRegistryEntry({
1515
1861
  description: "Add a Block Styles registration to an existing block",
1516
1862
  nameLabel: "Style name",
1517
1863
  async prepareExecution(context) {
1518
- const name = requireAddKindName(context, "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.");
1864
+ const name = requireAddKindName(context, STYLE_MISSING_NAME_MESSAGE);
1519
1865
  const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
1520
1866
  return createNamedExecutionPlan(context, {
1521
1867
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
@@ -1527,8 +1873,9 @@ var styleAddKindEntry = defineAddKindRegistryEntry({
1527
1873
  blockSlug: result.blockSlug,
1528
1874
  styleSlug: result.styleSlug
1529
1875
  }),
1530
- missingNameMessage: "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.",
1531
- name
1876
+ missingNameMessage: STYLE_MISSING_NAME_MESSAGE,
1877
+ name,
1878
+ warnLine: context.warnLine
1532
1879
  });
1533
1880
  },
1534
1881
  sortOrder: 40,
@@ -1538,6 +1885,7 @@ var styleAddKindEntry = defineAddKindRegistryEntry({
1538
1885
  });
1539
1886
 
1540
1887
  // src/add-kinds/transform.ts
1888
+ 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>.";
1541
1889
  var transformAddKindEntry = defineAddKindRegistryEntry({
1542
1890
  completion: {
1543
1891
  nextSteps: (values) => [
@@ -1555,7 +1903,7 @@ var transformAddKindEntry = defineAddKindRegistryEntry({
1555
1903
  description: "Add a block-to-block transform into a workspace block",
1556
1904
  nameLabel: "Transform name",
1557
1905
  async prepareExecution(context) {
1558
- 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>.");
1906
+ const name = requireAddKindName(context, TRANSFORM_MISSING_NAME_MESSAGE);
1559
1907
  const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
1560
1908
  const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
1561
1909
  return createNamedExecutionPlan(context, {
@@ -1571,8 +1919,9 @@ var transformAddKindEntry = defineAddKindRegistryEntry({
1571
1919
  toBlockName: result.toBlockName,
1572
1920
  transformSlug: result.transformSlug
1573
1921
  }),
1574
- missingNameMessage: "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.",
1575
- name
1922
+ missingNameMessage: TRANSFORM_MISSING_NAME_MESSAGE,
1923
+ name,
1924
+ warnLine: context.warnLine
1576
1925
  });
1577
1926
  },
1578
1927
  sortOrder: 50,
@@ -1582,6 +1931,7 @@ var transformAddKindEntry = defineAddKindRegistryEntry({
1582
1931
  });
1583
1932
 
1584
1933
  // src/add-kinds/variation.ts
1934
+ var VARIATION_MISSING_NAME_MESSAGE = "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>";
1585
1935
  var variationAddKindEntry = defineAddKindRegistryEntry({
1586
1936
  completion: {
1587
1937
  nextSteps: (values) => [
@@ -1598,7 +1948,7 @@ var variationAddKindEntry = defineAddKindRegistryEntry({
1598
1948
  description: "Add a variation to an existing block",
1599
1949
  nameLabel: "Variation name",
1600
1950
  async prepareExecution(context) {
1601
- const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
1951
+ const name = requireAddKindName(context, VARIATION_MISSING_NAME_MESSAGE);
1602
1952
  const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
1603
1953
  return createNamedExecutionPlan(context, {
1604
1954
  execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
@@ -1610,8 +1960,9 @@ var variationAddKindEntry = defineAddKindRegistryEntry({
1610
1960
  blockSlug: result.blockSlug,
1611
1961
  variationSlug: result.variationSlug
1612
1962
  }),
1613
- missingNameMessage: "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>",
1614
- name
1963
+ missingNameMessage: VARIATION_MISSING_NAME_MESSAGE,
1964
+ name,
1965
+ warnLine: context.warnLine
1615
1966
  });
1616
1967
  },
1617
1968
  sortOrder: 30,
@@ -1624,19 +1975,22 @@ var variationAddKindEntry = defineAddKindRegistryEntry({
1624
1975
  var ADD_KIND_REGISTRY = {
1625
1976
  "admin-view": adminViewAddKindEntry,
1626
1977
  block: blockAddKindEntry,
1978
+ "integration-env": integrationEnvAddKindEntry,
1627
1979
  variation: variationAddKindEntry,
1628
1980
  style: styleAddKindEntry,
1629
1981
  transform: transformAddKindEntry,
1630
1982
  pattern: patternAddKindEntry,
1631
1983
  "binding-source": bindingSourceAddKindEntry,
1984
+ contract: contractAddKindEntry,
1632
1985
  "rest-resource": restResourceAddKindEntry,
1986
+ "post-meta": postMetaAddKindEntry,
1633
1987
  ability: abilityAddKindEntry,
1634
1988
  "ai-feature": aiFeatureAddKindEntry,
1635
1989
  "hooked-block": hookedBlockAddKindEntry,
1636
1990
  "editor-plugin": editorPluginAddKindEntry
1637
1991
  };
1638
1992
  function isAddKindId(value) {
1639
- return typeof value === "string" && ADD_KIND_IDS.includes(value);
1993
+ return typeof value === "string" && ADD_KIND_IDS2.includes(value);
1640
1994
  }
1641
1995
  async function getAddKindExecutionPlan(kind, context) {
1642
1996
  return ADD_KIND_REGISTRY[kind].prepareExecution(context);
@@ -1649,12 +2003,6 @@ function buildAddKindCompletionDetails(kind, options) {
1649
2003
  title: descriptor.title
1650
2004
  };
1651
2005
  }
1652
- function formatAddKindList() {
1653
- return ADD_KIND_IDS.join(", ");
1654
- }
1655
- function formatAddKindUsagePlaceholder() {
1656
- return `<${ADD_KIND_IDS.join("|")}>`;
1657
- }
1658
2006
  function supportsAddKindDryRun(kind) {
1659
2007
  return ADD_KIND_REGISTRY[kind].supportsDryRun;
1660
2008
  }
@@ -1705,6 +2053,55 @@ async function copyWorkspaceProject(sourceDir, targetDir) {
1705
2053
  recursive: true
1706
2054
  });
1707
2055
  }
2056
+ function formatInstallMarkerError(error) {
2057
+ if (error instanceof Error) {
2058
+ return error.message;
2059
+ }
2060
+ return String(error);
2061
+ }
2062
+ function formatInstallMarkerFailures(failures) {
2063
+ return failures.map((failure) => `${failure.operation}: ${failure.reason}`).join("; ");
2064
+ }
2065
+ function ensureWorkspaceInstallMarker({
2066
+ fsAdapter = fs2,
2067
+ sourceMarker,
2068
+ targetMarker
2069
+ }) {
2070
+ const failures = [];
2071
+ try {
2072
+ fsAdapter.symlinkSync(sourceMarker, targetMarker);
2073
+ return;
2074
+ } catch (error) {
2075
+ failures.push({
2076
+ operation: "symlink",
2077
+ reason: formatInstallMarkerError(error)
2078
+ });
2079
+ }
2080
+ try {
2081
+ fsAdapter.linkSync(sourceMarker, targetMarker);
2082
+ return;
2083
+ } catch (error) {
2084
+ failures.push({
2085
+ operation: "hard link",
2086
+ reason: formatInstallMarkerError(error)
2087
+ });
2088
+ }
2089
+ try {
2090
+ fsAdapter.copyFileSync(sourceMarker, targetMarker);
2091
+ return;
2092
+ } catch (error) {
2093
+ failures.push({
2094
+ operation: "copy",
2095
+ reason: formatInstallMarkerError(error)
2096
+ });
2097
+ }
2098
+ throw new Error([
2099
+ "Failed to prepare dry-run install marker.",
2100
+ `Source: ${sourceMarker}`,
2101
+ `Target: ${targetMarker}`,
2102
+ `Fallback failures: ${formatInstallMarkerFailures(failures)}`
2103
+ ].join(" "));
2104
+ }
1708
2105
  function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
1709
2106
  const sourceNodeModules = path2.join(sourceDir, "node_modules");
1710
2107
  if (fs2.existsSync(sourceNodeModules)) {
@@ -1716,15 +2113,7 @@ function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
1716
2113
  continue;
1717
2114
  }
1718
2115
  const targetMarker = path2.join(targetDir, marker);
1719
- try {
1720
- fs2.symlinkSync(sourceMarker, targetMarker);
1721
- } catch {
1722
- try {
1723
- fs2.linkSync(sourceMarker, targetMarker);
1724
- } catch {
1725
- fs2.copyFileSync(sourceMarker, targetMarker);
1726
- }
1727
- }
2116
+ ensureWorkspaceInstallMarker({ sourceMarker, targetMarker });
1728
2117
  }
1729
2118
  }
1730
2119
  async function listWorkspaceFiles(rootDir) {
@@ -1807,17 +2196,10 @@ async function simulateWorkspaceAddDryRun({
1807
2196
  }
1808
2197
  }
1809
2198
 
1810
- // src/runtime-bridge-output.ts
1811
- import {
1812
- PACKAGE_MANAGER_IDS,
1813
- formatPackageExecCommand,
1814
- inferPackageManagerId,
1815
- parsePackageManagerField
1816
- } from "@wp-typia/project-tools/package-managers";
1817
- import {
1818
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES6,
1819
- createCliDiagnosticCodeError as createCliDiagnosticCodeError5
1820
- } from "@wp-typia/project-tools/cli-diagnostics";
2199
+ // src/string-utils.ts
2200
+ function escapeRegExp(source) {
2201
+ return source.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
2202
+ }
1821
2203
 
1822
2204
  // src/output-markers.ts
1823
2205
  var UNICODE_OUTPUT_MARKERS = {
@@ -1834,9 +2216,6 @@ var ASCII_OUTPUT_MARKERS = {
1834
2216
  };
1835
2217
  var ASCII_ENV_TRUTHY_VALUES = new Set(["1", "on", "true", "yes"]);
1836
2218
  var ASCII_ENV_FALSY_VALUES = new Set(["0", "off", "false", "no"]);
1837
- function escapeRegExp(source) {
1838
- return source.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1839
- }
1840
2219
  function readAsciiPreferenceFromEnv(env) {
1841
2220
  const rawValue = env.WP_TYPIA_ASCII;
1842
2221
  if (typeof rawValue !== "string") {
@@ -1897,47 +2276,38 @@ function stripLeadingOutputMarker(text, kind) {
1897
2276
  return text.replace(new RegExp(`^(?:${markerPattern})\\s*`, "u"), "");
1898
2277
  }
1899
2278
 
1900
- // src/print-block.ts
1901
- function printBlock(printLine, lines) {
1902
- for (const line of lines) {
1903
- printLine(line);
1904
- }
2279
+ // src/runtime-output/init.ts
2280
+ function buildInitCompletionPayload(plan, markerOptions) {
2281
+ const changeLines = [
2282
+ ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
2283
+ ...plan.packageChanges.packageManagerField ? [
2284
+ `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
2285
+ ] : [],
2286
+ ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
2287
+ ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
2288
+ ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
2289
+ ];
2290
+ 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.";
2291
+ const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
2292
+ 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);
2293
+ return {
2294
+ nextSteps: plan.nextSteps,
2295
+ optionalLines: changeLines,
2296
+ optionalNote: plan.summary,
2297
+ optionalTitle,
2298
+ summaryLines: [
2299
+ `Project directory: ${plan.projectDir}`,
2300
+ `Detected layout: ${plan.detectedLayout.description}`,
2301
+ ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
2302
+ `Package manager: ${plan.packageManager}`,
2303
+ modeLine
2304
+ ],
2305
+ title,
2306
+ warningLines: plan.notes
2307
+ };
1905
2308
  }
1906
2309
 
1907
- // src/runtime-bridge-output.ts
1908
- function printCompletionPayload(payload, options = {}) {
1909
- const printLine = options.printLine ?? console.log;
1910
- const warnLine = options.warnLine ?? printLine;
1911
- for (const line of payload.preambleLines ?? []) {
1912
- printLine(line);
1913
- }
1914
- for (const warning of payload.warningLines ?? []) {
1915
- warnLine(formatOutputMarker("warning", warning, options.markerOptions));
1916
- }
1917
- const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
1918
- const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
1919
- printLine(hasLeadingContext && hasDetails ? `
1920
- ${payload.title}` : payload.title);
1921
- for (const line of payload.summaryLines ?? []) {
1922
- printLine(line);
1923
- }
1924
- if ((payload.nextSteps?.length ?? 0) > 0) {
1925
- printLine("Next steps:");
1926
- for (const step of payload.nextSteps ?? []) {
1927
- printLine(` ${step}`);
1928
- }
1929
- }
1930
- if ((payload.optionalLines?.length ?? 0) > 0) {
1931
- printLine(`
1932
- ${payload.optionalTitle ?? "Optional:"}`);
1933
- for (const step of payload.optionalLines ?? []) {
1934
- printLine(` ${step}`);
1935
- }
1936
- }
1937
- if (payload.optionalNote) {
1938
- printLine(`Note: ${payload.optionalNote}`);
1939
- }
1940
- }
2310
+ // src/runtime-output/structured.ts
1941
2311
  function toNonEmptyArray(values) {
1942
2312
  return values && values.length > 0 ? values : undefined;
1943
2313
  }
@@ -1946,13 +2316,6 @@ function extractPlannedFiles(payload) {
1946
2316
  return toNonEmptyArray(files);
1947
2317
  }
1948
2318
  var PROJECT_DIRECTORY_SUMMARY_PREFIX = "Project directory: ";
1949
- function resolveCreateCompletionPackageManager(packageManager) {
1950
- const parsedPackageManager = parsePackageManagerField(packageManager);
1951
- if (parsedPackageManager) {
1952
- return parsedPackageManager;
1953
- }
1954
- throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
1955
- }
1956
2319
  function extractCompletionProjectDir(completion) {
1957
2320
  const projectDir = completion?.summaryLines?.find((line) => line.startsWith(PROJECT_DIRECTORY_SUMMARY_PREFIX))?.slice(PROJECT_DIRECTORY_SUMMARY_PREFIX.length).trim();
1958
2321
  return projectDir && projectDir.length > 0 ? projectDir : undefined;
@@ -2005,6 +2368,34 @@ function buildStructuredInitSuccessPayload(plan) {
2005
2368
  }
2006
2369
  };
2007
2370
  }
2371
+ // src/runtime-output/create.ts
2372
+ import {
2373
+ PACKAGE_MANAGER_IDS,
2374
+ formatPackageExecCommand,
2375
+ parsePackageManagerField
2376
+ } from "@wp-typia/project-tools/package-managers";
2377
+ import {
2378
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES6,
2379
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError5
2380
+ } from "@wp-typia/project-tools/cli-diagnostics";
2381
+ var LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN = new RegExp(`^(?:corepack\\s+)?(${PACKAGE_MANAGER_IDS.map(escapeRegExp).join("|")})(?=$|[@:/+\\s])`, "iu");
2382
+ function parseCreateCompletionPackageManager(packageManager) {
2383
+ const normalizedPackageManager = packageManager.trim();
2384
+ const parsedPackageManager = parsePackageManagerField(normalizedPackageManager);
2385
+ if (parsedPackageManager) {
2386
+ return parsedPackageManager;
2387
+ }
2388
+ const looseMatch = LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN.exec(normalizedPackageManager);
2389
+ const loosePackageManager = looseMatch?.[1]?.toLowerCase();
2390
+ return PACKAGE_MANAGER_IDS.includes(loosePackageManager) ? loosePackageManager : null;
2391
+ }
2392
+ function resolveCreateCompletionPackageManager(packageManager) {
2393
+ const parsedPackageManager = parseCreateCompletionPackageManager(packageManager);
2394
+ if (parsedPackageManager) {
2395
+ return parsedPackageManager;
2396
+ }
2397
+ throw createCliDiagnosticCodeError5(CLI_DIAGNOSTIC_CODES6.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
2398
+ }
2008
2399
  function formatCreateProgressLine(payload, markerOptions) {
2009
2400
  return formatOutputMarker("progress", `${payload.title}: ${payload.detail}`, markerOptions);
2010
2401
  }
@@ -2050,45 +2441,14 @@ function buildCreateDryRunPayload(flow, markerOptions) {
2050
2441
  warningLines: flow.result.warnings
2051
2442
  };
2052
2443
  }
2053
- function buildInitCompletionPayload(plan, markerOptions) {
2054
- const changeLines = [
2055
- ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
2056
- ...plan.packageChanges.packageManagerField ? [
2057
- `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
2058
- ] : [],
2059
- ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
2060
- ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
2061
- ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
2062
- ];
2063
- 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.";
2064
- const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
2065
- 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);
2066
- return {
2067
- nextSteps: plan.nextSteps,
2068
- optionalLines: changeLines,
2069
- optionalNote: plan.summary,
2070
- optionalTitle,
2071
- summaryLines: [
2072
- `Project directory: ${plan.projectDir}`,
2073
- `Detected layout: ${plan.detectedLayout.description}`,
2074
- ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
2075
- `Package manager: ${plan.packageManager}`,
2076
- modeLine
2077
- ],
2078
- title,
2079
- warningLines: plan.notes
2080
- };
2081
- }
2082
- function buildMigrationCompletionPayload(options, markerOptions) {
2083
- const summaryLines = options.lines.filter((line) => line.trim().length > 0);
2084
- return {
2085
- summaryLines,
2086
- title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
2087
- };
2088
- }
2444
+ // src/runtime-output/add.ts
2445
+ import {
2446
+ formatPackageExecCommand as formatPackageExecCommand2,
2447
+ inferPackageManagerId
2448
+ } from "@wp-typia/project-tools/package-managers";
2089
2449
  function buildAddCompletionPayload(options, markerOptions) {
2090
2450
  const verificationLines = [
2091
- formatPackageExecCommand(options.packageManager ?? inferPackageManagerId(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
2451
+ formatPackageExecCommand2(options.packageManager ?? inferPackageManagerId(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
2092
2452
  ];
2093
2453
  const verificationNote = "Run doctor via your package manager for a quick inventory and generated-artifact check after the add workflow.";
2094
2454
  const completion = buildAddKindCompletionDetails(options.kind, {
@@ -2117,10 +2477,19 @@ function buildAddDryRunPayload(options, markerOptions) {
2117
2477
  warningLines: options.completion.warningLines
2118
2478
  };
2119
2479
  }
2120
- function buildSyncDryRunPayload(options, markerOptions) {
2121
- const targetSuffix = options.target === "ai" ? " ai" : "";
2122
- const targetSummary = options.target === "ai" ? "Sync target: AI artifacts only." : options.target === "default" ? "Sync target: generated project defaults." : undefined;
2123
- return {
2480
+ // src/runtime-output/migrate.ts
2481
+ function buildMigrationCompletionPayload(options, markerOptions) {
2482
+ const summaryLines = options.lines.filter((line) => line.trim().length > 0);
2483
+ return {
2484
+ summaryLines,
2485
+ title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
2486
+ };
2487
+ }
2488
+ // src/runtime-output/sync.ts
2489
+ function buildSyncDryRunPayload(options, markerOptions) {
2490
+ const targetSuffix = options.target === "ai" ? " ai" : "";
2491
+ const targetSummary = options.target === "ai" ? "Sync target: AI artifacts only." : options.target === "default" ? "Sync target: generated project defaults." : undefined;
2492
+ return {
2124
2493
  optionalLines: options.plannedCommands.map((command) => command.displayCommand),
2125
2494
  optionalNote: options.check ? `No sync scripts were executed because --dry-run was enabled. Re-run \`wp-typia sync${targetSuffix} --check\` to verify generated artifacts without rewriting them.` : `No sync scripts were executed because --dry-run was enabled. Re-run \`wp-typia sync${targetSuffix}\` without --dry-run to apply generated-file updates, or add --check to verify without rewriting.`,
2126
2495
  optionalTitle: `Planned sync commands (${options.plannedCommands.length}):`,
@@ -2133,232 +2502,58 @@ function buildSyncDryRunPayload(options, markerOptions) {
2133
2502
  title: formatOutputMarker("dryRun", `Dry run for wp-typia sync${targetSuffix}`, markerOptions)
2134
2503
  };
2135
2504
  }
2136
-
2137
- // src/runtime-capabilities.ts
2138
- function isInteractiveTerminal({
2139
- stdin = process.stdin,
2140
- stdout = process.stdout,
2141
- term = process.env.TERM
2142
- } = {}) {
2143
- return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
2144
- }
2145
- // src/runtime-bridge-sync.ts
2146
- import { spawnSync } from "node:child_process";
2147
- import fs3 from "node:fs";
2148
- import path3 from "node:path";
2149
- import {
2150
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES7,
2151
- createCliDiagnosticCodeError as createCliDiagnosticCodeError6
2152
- } from "@wp-typia/project-tools/cli-diagnostics";
2153
- import {
2154
- formatInstallCommand,
2155
- formatRunScript,
2156
- inferPackageManagerId as inferPackageManagerId2
2157
- } from "@wp-typia/project-tools/package-managers";
2158
- var SYNC_INSTALL_MARKERS = [
2159
- "node_modules",
2160
- ".pnp.cjs",
2161
- ".pnp.loader.mjs"
2162
- ];
2163
- var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
2164
- var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
2165
- function resolveSyncExecutionTarget(subcommand) {
2166
- if (!subcommand) {
2167
- return "default";
2168
- }
2169
- if (subcommand === "ai") {
2170
- return "ai";
2171
- }
2172
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
2173
- }
2174
- function getSyncRootError(cwd) {
2175
- return createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.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.`);
2176
- }
2177
- function resolveSyncProjectContext(cwd) {
2178
- const packageJsonPath = path3.join(cwd, "package.json");
2179
- if (!fs3.existsSync(packageJsonPath)) {
2180
- throw getSyncRootError(cwd);
2181
- }
2182
- const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
2183
- const scripts = packageJson.scripts ?? {};
2184
- const syncScripts = {
2185
- sync: typeof scripts.sync === "string" ? {
2186
- command: scripts.sync,
2187
- scriptName: "sync"
2188
- } : undefined,
2189
- "sync-ai": typeof scripts["sync-ai"] === "string" ? {
2190
- command: scripts["sync-ai"],
2191
- scriptName: "sync-ai"
2192
- } : typeof scripts["sync-wordpress-ai"] === "string" ? {
2193
- command: scripts["sync-wordpress-ai"],
2194
- scriptName: "sync-wordpress-ai"
2195
- } : undefined,
2196
- "sync-rest": typeof scripts["sync-rest"] === "string" ? {
2197
- command: scripts["sync-rest"],
2198
- scriptName: "sync-rest"
2199
- } : undefined,
2200
- "sync-types": typeof scripts["sync-types"] === "string" ? {
2201
- command: scripts["sync-types"],
2202
- scriptName: "sync-types"
2203
- } : undefined
2204
- };
2205
- return {
2206
- cwd,
2207
- packageJsonPath,
2208
- packageManager: inferPackageManagerId2(cwd, packageJson.packageManager),
2209
- scripts: syncScripts
2210
- };
2211
- }
2212
- function findInstalledDependencyMarkerDir(projectDir) {
2213
- let currentDir = path3.resolve(projectDir);
2214
- while (true) {
2215
- if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path3.join(currentDir, marker)))) {
2216
- return currentDir;
2217
- }
2218
- const parentDir = path3.dirname(currentDir);
2219
- if (parentDir === currentDir) {
2220
- return null;
2221
- }
2222
- currentDir = parentDir;
2505
+ // src/print-block.ts
2506
+ function printBlock(printLine, lines) {
2507
+ for (const line of lines) {
2508
+ printLine(line);
2223
2509
  }
2224
2510
  }
2225
- function scriptsLikelyNeedInstalledDependencies(project, target) {
2226
- const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
2227
- project.scripts["sync-types"],
2228
- project.scripts["sync-rest"],
2229
- project.scripts["sync-ai"]
2230
- ];
2231
- return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
2232
- }
2233
- function assertSyncDependenciesInstalled(project, target) {
2234
- if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
2235
- return;
2236
- }
2237
- const markerDir = findInstalledDependencyMarkerDir(project.cwd);
2238
- if (markerDir) {
2239
- return;
2511
+
2512
+ // src/runtime-output/print.ts
2513
+ function printCompletionPayload(payload, options = {}) {
2514
+ const printLine = options.printLine ?? console.log;
2515
+ const warnLine = options.warnLine ?? printLine;
2516
+ for (const line of payload.preambleLines ?? []) {
2517
+ printLine(line);
2240
2518
  }
2241
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.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\`.`);
2242
- }
2243
- function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
2244
- switch (packageManager) {
2245
- case "bun":
2246
- return { args: ["run", scriptName, ...extraArgs], command: "bun" };
2247
- case "npm":
2248
- return {
2249
- args: [
2250
- "run",
2251
- scriptName,
2252
- ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
2253
- ],
2254
- command: "npm"
2255
- };
2256
- case "pnpm":
2257
- return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
2258
- case "yarn":
2259
- return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
2519
+ for (const warning of payload.warningLines ?? []) {
2520
+ warnLine(formatOutputMarker("warning", warning, options.markerOptions));
2260
2521
  }
2261
- }
2262
- function createSyncPlannedCommand(project, scriptName, extraArgs) {
2263
- const script = project.scripts[scriptName];
2264
- if (!script) {
2265
- return null;
2522
+ const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
2523
+ const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
2524
+ printLine(hasLeadingContext && hasDetails ? `
2525
+ ${payload.title}` : payload.title);
2526
+ for (const line of payload.summaryLines ?? []) {
2527
+ printLine(line);
2266
2528
  }
2267
- const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
2268
- return {
2269
- args: invocation.args,
2270
- command: invocation.command,
2271
- displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
2272
- scriptName: script.scriptName
2273
- };
2274
- }
2275
- function buildSyncPlannedCommands(project, extraArgs, target) {
2276
- if (target === "ai") {
2277
- const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2278
- if (!syncAiCommand2) {
2279
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
2529
+ if ((payload.nextSteps?.length ?? 0) > 0) {
2530
+ printLine("Next steps:");
2531
+ for (const step of payload.nextSteps ?? []) {
2532
+ printLine(` ${step}`);
2280
2533
  }
2281
- return [syncAiCommand2];
2282
2534
  }
2283
- if (project.scripts.sync) {
2284
- return [createSyncPlannedCommand(project, "sync", extraArgs)];
2285
- }
2286
- const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
2287
- if (!syncTypesCommand) {
2288
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
2289
- }
2290
- const plannedCommands = [syncTypesCommand];
2291
- const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
2292
- if (syncRestCommand) {
2293
- plannedCommands.push(syncRestCommand);
2294
- }
2295
- const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2296
- if (syncAiCommand) {
2297
- plannedCommands.push(syncAiCommand);
2535
+ if ((payload.optionalLines?.length ?? 0) > 0) {
2536
+ printLine(`
2537
+ ${payload.optionalTitle ?? "Optional:"}`);
2538
+ for (const step of payload.optionalLines ?? []) {
2539
+ printLine(` ${step}`);
2540
+ }
2298
2541
  }
2299
- return plannedCommands;
2300
- }
2301
- function runProjectScript(project, plannedCommand, options) {
2302
- const result = spawnSync(plannedCommand.command, plannedCommand.args, {
2303
- cwd: project.cwd,
2304
- encoding: options.captureOutput ? "utf8" : undefined,
2305
- ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
2306
- shell: process.platform === "win32",
2307
- stdio: options.captureOutput ? "pipe" : "inherit"
2308
- });
2309
- const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
2310
- const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
2311
- if (result.error || result.status !== 0) {
2312
- throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
2313
- cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
2314
- });
2542
+ if (payload.optionalNote) {
2543
+ printLine(`Note: ${payload.optionalNote}`);
2315
2544
  }
2316
- return {
2317
- ...plannedCommand,
2318
- exitCode: result.status ?? 0,
2319
- ...stderr !== undefined ? { stderr } : {},
2320
- ...stdout !== undefined ? { stdout } : {}
2321
- };
2322
2545
  }
2323
- async function executeSyncCommand({
2324
- captureOutput = false,
2325
- check = false,
2326
- cwd,
2327
- dryRun = false,
2328
- target = "default"
2329
- }) {
2330
- const project = resolveSyncProjectContext(cwd);
2331
- const extraArgs = check ? ["--check"] : [];
2332
- const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
2333
- const result = {
2334
- check,
2335
- dryRun,
2336
- packageJsonPath: project.packageJsonPath,
2337
- packageManager: project.packageManager,
2338
- plannedCommands,
2339
- projectDir: project.cwd,
2340
- target
2341
- };
2342
- if (dryRun) {
2343
- return result;
2344
- }
2345
- assertSyncDependenciesInstalled(project, target);
2346
- result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
2347
- captureOutput
2348
- }));
2349
- return result;
2546
+ // src/runtime-capabilities.ts
2547
+ function isInteractiveTerminal({
2548
+ stdin = process.stdin,
2549
+ stdout = process.stdout,
2550
+ term = process.env.TERM
2551
+ } = {}) {
2552
+ return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
2350
2553
  }
2351
2554
 
2352
- // src/runtime-bridge.ts
2353
- var loadCliAddRuntime = () => import("@wp-typia/project-tools/cli-add");
2555
+ // src/runtime-bridge-shared.ts
2354
2556
  var loadCliDiagnosticsRuntime = () => import("@wp-typia/project-tools/cli-diagnostics");
2355
- var loadCliDoctorRuntime = () => import("@wp-typia/project-tools/cli-doctor");
2356
- var loadCliInitRuntime = () => import("@wp-typia/project-tools/cli-init");
2357
- var loadCliPromptRuntime = () => import("@wp-typia/project-tools/cli-prompt");
2358
- var loadCliScaffoldRuntime = () => import("@wp-typia/project-tools/cli-scaffold");
2359
- var loadCliTemplatesRuntime = () => import("@wp-typia/project-tools/cli-templates");
2360
- var loadCreateTemplateValidationRuntime = () => import("@wp-typia/project-tools/create-template-validation");
2361
- var loadMigrationsRuntime = () => import("@wp-typia/project-tools/migrations");
2362
2557
  async function wrapCliCommandError(command, error) {
2363
2558
  const { createCliCommandError: createCliCommandError3 } = await loadCliDiagnosticsRuntime();
2364
2559
  return createCliCommandError3({ command, error });
@@ -2372,6 +2567,15 @@ function shouldWrapCliCommandError(options) {
2372
2567
  }
2373
2568
  return true;
2374
2569
  }
2570
+ function emitCompletion(payload, options) {
2571
+ if (options.emitOutput) {
2572
+ printCompletionPayload(payload, {
2573
+ printLine: options.printLine,
2574
+ warnLine: options.warnLine
2575
+ });
2576
+ }
2577
+ return payload;
2578
+ }
2375
2579
  function pushFlag(argv, name, value) {
2376
2580
  if (value === undefined || value === null || value === false) {
2377
2581
  return;
@@ -2382,6 +2586,10 @@ function pushFlag(argv, name, value) {
2382
2586
  }
2383
2587
  argv.push(`--${name}`, String(value));
2384
2588
  }
2589
+
2590
+ // src/runtime-bridge-add.ts
2591
+ var loadCliAddRuntime = () => import("@wp-typia/project-tools/cli-add");
2592
+ var loadCliPromptRuntime = () => import("@wp-typia/project-tools/cli-prompt");
2385
2593
  async function executeWorkspaceAddWithOptionalDryRun(options) {
2386
2594
  const simulated = options.dryRun ? await simulateWorkspaceAddDryRun({
2387
2595
  cwd: options.cwd,
@@ -2396,35 +2604,101 @@ async function executeWorkspaceAddWithOptionalDryRun(options) {
2396
2604
  warnLine: options.warnLine
2397
2605
  });
2398
2606
  }
2399
- return emitCompletion(buildAddDryRunPayload({
2400
- completion,
2401
- fileOperations: simulated.fileOperations
2402
- }), {
2403
- emitOutput: options.emitOutput ?? true,
2404
- printLine: options.printLine,
2405
- warnLine: options.warnLine
2406
- });
2407
- }
2408
- function executePreparedAddKind(kind, context, plan) {
2409
- return executeWorkspaceAddWithOptionalDryRun({
2410
- buildCompletion: (result) => buildAddCompletionPayload({
2411
- kind,
2412
- projectDir: result.projectDir,
2413
- values: plan.getValues(result),
2414
- warnings: plan.getWarnings?.(result)
2415
- }),
2416
- cwd: context.cwd,
2417
- dryRun: context.dryRun,
2418
- emitOutput: context.emitOutput,
2419
- execute: plan.execute,
2420
- printLine: context.printLine,
2421
- warnLine: plan.warnLine
2422
- });
2423
- }
2424
- async function executePlannedAddKind(kind, executionContext, context) {
2425
- const plan = await getAddKindExecutionPlan(kind, executionContext);
2426
- return executePreparedAddKind(kind, context, plan);
2607
+ return emitCompletion(buildAddDryRunPayload({
2608
+ completion,
2609
+ fileOperations: simulated.fileOperations
2610
+ }), {
2611
+ emitOutput: options.emitOutput ?? true,
2612
+ printLine: options.printLine,
2613
+ warnLine: options.warnLine
2614
+ });
2615
+ }
2616
+ function executePreparedAddKind(kind, context, plan) {
2617
+ return executeWorkspaceAddWithOptionalDryRun({
2618
+ buildCompletion: (result) => buildAddCompletionPayload({
2619
+ kind,
2620
+ projectDir: result.projectDir,
2621
+ values: plan.getValues(result),
2622
+ warnings: plan.getWarnings?.(result)
2623
+ }),
2624
+ cwd: context.cwd,
2625
+ dryRun: context.dryRun,
2626
+ emitOutput: context.emitOutput,
2627
+ execute: plan.execute,
2628
+ printLine: context.printLine,
2629
+ warnLine: plan.warnLine
2630
+ });
2631
+ }
2632
+ async function executePlannedAddKind(kind, executionContext, context) {
2633
+ const plan = await getAddKindExecutionPlan(kind, executionContext);
2634
+ return executePreparedAddKind(kind, context, plan);
2635
+ }
2636
+ async function executeAddCommand({
2637
+ cwd,
2638
+ emitOutput = true,
2639
+ flags,
2640
+ interactive,
2641
+ kind,
2642
+ name,
2643
+ printLine = console.log,
2644
+ prompt,
2645
+ warnLine = console.warn
2646
+ }) {
2647
+ let activePrompt;
2648
+ const dryRun = Boolean(flags["dry-run"]);
2649
+ try {
2650
+ const addRuntime = await loadCliAddRuntime();
2651
+ const isInteractiveSession = interactive ?? isInteractiveTerminal();
2652
+ if (!kind) {
2653
+ if (shouldPrintMissingAddKindHelp({ emitOutput })) {
2654
+ printLine(addRuntime.formatAddHelpText());
2655
+ }
2656
+ throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
2657
+ }
2658
+ if (!isAddKindId(kind)) {
2659
+ throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
2660
+ }
2661
+ if (dryRun && !supportsAddKindDryRun(kind)) {
2662
+ throw createCliDiagnosticCodeError6(CLI_DIAGNOSTIC_CODES7.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
2663
+ }
2664
+ const executionContext = {
2665
+ addRuntime,
2666
+ cwd,
2667
+ flags,
2668
+ getOrCreatePrompt: async () => {
2669
+ if (activePrompt) {
2670
+ return activePrompt;
2671
+ }
2672
+ const { createReadlinePrompt } = await loadCliPromptRuntime();
2673
+ activePrompt = prompt ?? createReadlinePrompt();
2674
+ return activePrompt;
2675
+ },
2676
+ isInteractiveSession,
2677
+ name,
2678
+ warnLine
2679
+ };
2680
+ return await executePlannedAddKind(kind, executionContext, {
2681
+ cwd,
2682
+ dryRun,
2683
+ emitOutput,
2684
+ printLine
2685
+ });
2686
+ } catch (error) {
2687
+ if (!shouldWrapCliCommandError({ emitOutput })) {
2688
+ throw error;
2689
+ }
2690
+ throw await wrapCliCommandError("add", error);
2691
+ } finally {
2692
+ if (activePrompt && activePrompt !== prompt) {
2693
+ activePrompt.close();
2694
+ }
2695
+ }
2427
2696
  }
2697
+ // src/runtime-bridge-create.ts
2698
+ var loadCliPromptRuntime2 = () => import("@wp-typia/project-tools/cli-prompt");
2699
+ var loadCliScaffoldRuntime = () => import("@wp-typia/project-tools/cli-scaffold");
2700
+ var loadCliTemplatesRuntime = () => import("@wp-typia/project-tools/cli-templates");
2701
+ var loadCreateTemplateValidationRuntime = () => import("@wp-typia/project-tools/create-template-validation");
2428
2702
  var PACKAGE_MANAGER_PROMPT_OPTIONS = [
2429
2703
  { label: "npm", value: "npm", hint: "Use npm" },
2430
2704
  { label: "pnpm", value: "pnpm", hint: "Use pnpm" },
@@ -2451,15 +2725,6 @@ var BOOLEAN_PROMPT_OPTIONS = [
2451
2725
  { label: "Yes", value: "yes", hint: "Enable this option" },
2452
2726
  { label: "No", value: "no", hint: "Keep the default disabled state" }
2453
2727
  ];
2454
- function emitCompletion(payload, options) {
2455
- if (options.emitOutput) {
2456
- printCompletionPayload(payload, {
2457
- printLine: options.printLine,
2458
- warnLine: options.warnLine
2459
- });
2460
- }
2461
- return payload;
2462
- }
2463
2728
  async function executeCreateCommand({
2464
2729
  projectDir,
2465
2730
  cwd,
@@ -2480,7 +2745,7 @@ async function executeCreateCommand({
2480
2745
  { runScaffoldFlow },
2481
2746
  { getTemplateSelectOptions }
2482
2747
  ] = await Promise.all([
2483
- loadCliPromptRuntime(),
2748
+ loadCliPromptRuntime2(),
2484
2749
  loadCliScaffoldRuntime(),
2485
2750
  loadCliTemplatesRuntime()
2486
2751
  ]);
@@ -2550,185 +2815,354 @@ async function executeCreateCommand({
2550
2815
  }
2551
2816
  }
2552
2817
  }
2553
- async function executeAddCommand({
2818
+ // src/runtime-bridge-doctor.ts
2819
+ var loadCliDoctorRuntime = () => import("@wp-typia/project-tools/cli-doctor");
2820
+ async function executeDoctorCommand(cwd) {
2821
+ try {
2822
+ const { runDoctor } = await loadCliDoctorRuntime();
2823
+ await runDoctor(cwd);
2824
+ } catch (error) {
2825
+ throw await wrapCliCommandError("doctor", error);
2826
+ }
2827
+ }
2828
+ // src/runtime-bridge-init.ts
2829
+ import path3 from "node:path";
2830
+ var loadCliInitRuntime = () => import("@wp-typia/project-tools/cli-init");
2831
+ async function executeInitCommand({ apply, cwd, packageManager, projectDir }, options = {}) {
2832
+ try {
2833
+ const { runInitCommand } = await loadCliInitRuntime();
2834
+ const resolvedProjectDir = projectDir ? path3.resolve(cwd, projectDir) : cwd;
2835
+ const plan = await runInitCommand({
2836
+ apply,
2837
+ packageManager,
2838
+ projectDir: resolvedProjectDir
2839
+ });
2840
+ const completion = buildInitCompletionPayload(plan);
2841
+ if (options.emitOutput ?? true) {
2842
+ printCompletionPayload(completion, {
2843
+ printLine: options.printLine,
2844
+ warnLine: options.warnLine
2845
+ });
2846
+ }
2847
+ return plan;
2848
+ } catch (error) {
2849
+ if (!shouldWrapCliCommandError({ emitOutput: options.emitOutput })) {
2850
+ throw error;
2851
+ }
2852
+ throw await wrapCliCommandError("init", error);
2853
+ }
2854
+ }
2855
+ // src/runtime-bridge-migrate.ts
2856
+ var loadMigrationsRuntime = () => import("@wp-typia/project-tools/migrations");
2857
+ var defaultPrintLine = (line) => {
2858
+ process.stdout.write(`${line}
2859
+ `);
2860
+ };
2861
+ async function executeMigrateCommand({
2862
+ command,
2554
2863
  cwd,
2555
- emitOutput = true,
2556
2864
  flags,
2557
- interactive,
2558
- kind,
2559
- name,
2560
- printLine = console.log,
2865
+ printLine = defaultPrintLine,
2561
2866
  prompt,
2562
- warnLine = console.warn
2867
+ renderLine
2563
2868
  }) {
2564
- let activePrompt;
2565
- const dryRun = Boolean(flags["dry-run"]);
2566
2869
  try {
2567
- const addRuntime = await loadCliAddRuntime();
2568
- const isInteractiveSession = interactive ?? isInteractiveTerminal();
2569
- if (!kind) {
2570
- if (shouldPrintMissingAddKindHelp({ emitOutput })) {
2571
- printLine(addRuntime.formatAddHelpText());
2572
- }
2573
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
2574
- }
2575
- if (!isAddKindId(kind)) {
2576
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
2577
- }
2578
- if (dryRun && !supportsAddKindDryRun(kind)) {
2579
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
2870
+ const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
2871
+ const outputLine = renderLine ?? printLine;
2872
+ if (!command) {
2873
+ const helpText = formatMigrationHelpText();
2874
+ outputLine(helpText);
2875
+ return;
2580
2876
  }
2581
- const executionContext = {
2582
- addRuntime,
2583
- cwd,
2584
- flags,
2585
- getOrCreatePrompt: async () => {
2586
- if (activePrompt) {
2587
- return activePrompt;
2588
- }
2589
- const { createReadlinePrompt } = await loadCliPromptRuntime();
2590
- activePrompt = prompt ?? createReadlinePrompt();
2591
- return activePrompt;
2592
- },
2593
- isInteractiveSession,
2594
- name,
2595
- warnLine
2877
+ const argv = [command];
2878
+ pushFlag(argv, "all", flags.all);
2879
+ pushFlag(argv, "force", flags.force);
2880
+ pushFlag(argv, "current-migration-version", readOptionalLooseStringFlag(flags, "current-migration-version"));
2881
+ pushFlag(argv, "migration-version", readOptionalLooseStringFlag(flags, "migration-version"));
2882
+ pushFlag(argv, "from-migration-version", readOptionalLooseStringFlag(flags, "from-migration-version"));
2883
+ pushFlag(argv, "to-migration-version", readOptionalLooseStringFlag(flags, "to-migration-version"));
2884
+ pushFlag(argv, "iterations", readOptionalLooseStringFlag(flags, "iterations"));
2885
+ pushFlag(argv, "seed", readOptionalLooseStringFlag(flags, "seed"));
2886
+ const parsed = parseMigrationArgs(argv);
2887
+ const lines = renderLine ? [] : null;
2888
+ const captureLine = (line) => {
2889
+ lines?.push(line);
2890
+ outputLine(line);
2596
2891
  };
2597
- return await executePlannedAddKind(kind, executionContext, {
2598
- cwd,
2599
- dryRun,
2600
- emitOutput,
2601
- printLine
2892
+ const result = await runMigrationCommand(parsed, cwd, {
2893
+ prompt,
2894
+ renderLine: captureLine
2602
2895
  });
2896
+ if (renderLine) {
2897
+ return result && typeof result === "object" && "cancelled" in result && result.cancelled === true ? undefined : buildMigrationCompletionPayload({
2898
+ command: parsed.command ?? "plan",
2899
+ lines: lines ?? []
2900
+ });
2901
+ }
2902
+ if (result && typeof result === "object" && "cancelled" in result && result.cancelled === true) {
2903
+ return;
2904
+ }
2603
2905
  } catch (error) {
2604
- if (!shouldWrapCliCommandError({ emitOutput })) {
2906
+ if (!shouldWrapCliCommandError({ renderLine })) {
2605
2907
  throw error;
2606
2908
  }
2607
- throw await wrapCliCommandError("add", error);
2608
- } finally {
2609
- if (activePrompt && activePrompt !== prompt) {
2610
- activePrompt.close();
2909
+ throw await wrapCliCommandError("migrate", error);
2910
+ }
2911
+ }
2912
+ // src/runtime-bridge-templates.ts
2913
+ import {
2914
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES8,
2915
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError7
2916
+ } from "@wp-typia/project-tools/cli-diagnostics";
2917
+ var loadCliTemplatesRuntime2 = () => import("@wp-typia/project-tools/cli-templates");
2918
+ async function executeTemplatesCommand({ flags }, printLine = console.log) {
2919
+ const {
2920
+ formatTemplateDetails,
2921
+ formatTemplateFeatures,
2922
+ formatTemplateSummary,
2923
+ getTemplateById,
2924
+ listTemplates
2925
+ } = await loadCliTemplatesRuntime2();
2926
+ const subcommand = flags.subcommand ?? "list";
2927
+ if (subcommand === "list") {
2928
+ for (const template of listTemplates()) {
2929
+ printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
2930
+ }
2931
+ return;
2932
+ }
2933
+ if (subcommand === "inspect") {
2934
+ if (!flags.id) {
2935
+ throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
2936
+ }
2937
+ const template = getTemplateById(flags.id);
2938
+ if (!template) {
2939
+ throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
2940
+ }
2941
+ printBlock(printLine, [formatTemplateDetails(template)]);
2942
+ return;
2943
+ }
2944
+ throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
2945
+ }
2946
+ // src/runtime-bridge-sync.ts
2947
+ import { spawnSync } from "node:child_process";
2948
+ import fs3 from "node:fs";
2949
+ import path4 from "node:path";
2950
+ import {
2951
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES9,
2952
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError8
2953
+ } from "@wp-typia/project-tools/cli-diagnostics";
2954
+ import {
2955
+ formatInstallCommand,
2956
+ formatRunScript,
2957
+ inferPackageManagerId as inferPackageManagerId2
2958
+ } from "@wp-typia/project-tools/package-managers";
2959
+ var SYNC_INSTALL_MARKERS = [
2960
+ "node_modules",
2961
+ ".pnp.cjs",
2962
+ ".pnp.loader.mjs"
2963
+ ];
2964
+ var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
2965
+ var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
2966
+ function resolveSyncExecutionTarget(subcommand) {
2967
+ if (!subcommand) {
2968
+ return "default";
2969
+ }
2970
+ if (subcommand === "ai") {
2971
+ return "ai";
2972
+ }
2973
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
2974
+ }
2975
+ function getSyncRootError(cwd) {
2976
+ 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.`);
2977
+ }
2978
+ function readSyncPackageJson(packageJsonPath) {
2979
+ const source = fs3.readFileSync(packageJsonPath, "utf8");
2980
+ try {
2981
+ return JSON.parse(source);
2982
+ } catch (error) {
2983
+ const message = error instanceof Error ? error.message : String(error);
2984
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_ARGUMENT, `Unable to parse ${packageJsonPath}: ${message}`, error instanceof Error ? { cause: error } : undefined);
2985
+ }
2986
+ }
2987
+ function resolveSyncProjectContext(cwd) {
2988
+ const packageJsonPath = path4.join(cwd, "package.json");
2989
+ if (!fs3.existsSync(packageJsonPath)) {
2990
+ throw getSyncRootError(cwd);
2991
+ }
2992
+ const packageJson = readSyncPackageJson(packageJsonPath);
2993
+ const scripts = packageJson.scripts ?? {};
2994
+ const syncScripts = {
2995
+ sync: typeof scripts.sync === "string" ? {
2996
+ command: scripts.sync,
2997
+ scriptName: "sync"
2998
+ } : undefined,
2999
+ "sync-ai": typeof scripts["sync-ai"] === "string" ? {
3000
+ command: scripts["sync-ai"],
3001
+ scriptName: "sync-ai"
3002
+ } : typeof scripts["sync-wordpress-ai"] === "string" ? {
3003
+ command: scripts["sync-wordpress-ai"],
3004
+ scriptName: "sync-wordpress-ai"
3005
+ } : undefined,
3006
+ "sync-rest": typeof scripts["sync-rest"] === "string" ? {
3007
+ command: scripts["sync-rest"],
3008
+ scriptName: "sync-rest"
3009
+ } : undefined,
3010
+ "sync-types": typeof scripts["sync-types"] === "string" ? {
3011
+ command: scripts["sync-types"],
3012
+ scriptName: "sync-types"
3013
+ } : undefined
3014
+ };
3015
+ return {
3016
+ cwd,
3017
+ packageJsonPath,
3018
+ packageManager: inferPackageManagerId2(cwd, packageJson.packageManager),
3019
+ scripts: syncScripts
3020
+ };
3021
+ }
3022
+ function findInstalledDependencyMarkerDir(projectDir) {
3023
+ let currentDir = path4.resolve(projectDir);
3024
+ while (true) {
3025
+ if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path4.join(currentDir, marker)))) {
3026
+ return currentDir;
3027
+ }
3028
+ const parentDir = path4.dirname(currentDir);
3029
+ if (parentDir === currentDir) {
3030
+ return null;
2611
3031
  }
3032
+ currentDir = parentDir;
2612
3033
  }
2613
3034
  }
2614
- async function executeTemplatesCommand({ flags }, printLine = console.log) {
2615
- const {
2616
- formatTemplateDetails,
2617
- formatTemplateFeatures,
2618
- formatTemplateSummary,
2619
- getTemplateById,
2620
- listTemplates
2621
- } = await loadCliTemplatesRuntime();
2622
- const subcommand = flags.subcommand ?? "list";
2623
- if (subcommand === "list") {
2624
- for (const template of listTemplates()) {
2625
- printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
2626
- }
3035
+ function scriptsLikelyNeedInstalledDependencies(project, target) {
3036
+ const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
3037
+ project.scripts["sync-types"],
3038
+ project.scripts["sync-rest"],
3039
+ project.scripts["sync-ai"]
3040
+ ];
3041
+ return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
3042
+ }
3043
+ function assertSyncDependenciesInstalled(project, target) {
3044
+ if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
2627
3045
  return;
2628
3046
  }
2629
- if (subcommand === "inspect") {
2630
- if (!flags.id) {
2631
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
2632
- }
2633
- const template = getTemplateById(flags.id);
2634
- if (!template) {
2635
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
2636
- }
2637
- printBlock(printLine, [formatTemplateDetails(template)]);
3047
+ const markerDir = findInstalledDependencyMarkerDir(project.cwd);
3048
+ if (markerDir) {
2638
3049
  return;
2639
3050
  }
2640
- throw createCliDiagnosticCodeError7(CLI_DIAGNOSTIC_CODES8.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
3051
+ 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\`.`);
2641
3052
  }
2642
- async function executeInitCommand({ apply, cwd, packageManager, projectDir }, options = {}) {
2643
- try {
2644
- const { runInitCommand } = await loadCliInitRuntime();
2645
- const resolvedProjectDir = projectDir ? (await import("node:path")).resolve(cwd, projectDir) : cwd;
2646
- const plan = await runInitCommand({
2647
- apply,
2648
- packageManager,
2649
- projectDir: resolvedProjectDir
2650
- });
2651
- const completion = buildInitCompletionPayload(plan);
2652
- if (options.emitOutput ?? true) {
2653
- printCompletionPayload(completion, {
2654
- printLine: options.printLine,
2655
- warnLine: options.warnLine
2656
- });
2657
- }
2658
- return plan;
2659
- } catch (error) {
2660
- if (!shouldWrapCliCommandError({ emitOutput: options.emitOutput })) {
2661
- throw error;
3053
+ function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
3054
+ switch (packageManager) {
3055
+ case "bun":
3056
+ return { args: ["run", scriptName, ...extraArgs], command: "bun" };
3057
+ case "npm":
3058
+ return {
3059
+ args: [
3060
+ "run",
3061
+ scriptName,
3062
+ ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
3063
+ ],
3064
+ command: "npm"
3065
+ };
3066
+ case "pnpm":
3067
+ return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
3068
+ case "yarn":
3069
+ return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
3070
+ }
3071
+ }
3072
+ function createSyncPlannedCommand(project, scriptName, extraArgs) {
3073
+ const script = project.scripts[scriptName];
3074
+ if (!script) {
3075
+ return null;
3076
+ }
3077
+ const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
3078
+ return {
3079
+ args: invocation.args,
3080
+ command: invocation.command,
3081
+ displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
3082
+ scriptName: script.scriptName
3083
+ };
3084
+ }
3085
+ function buildSyncPlannedCommands(project, extraArgs, target) {
3086
+ if (target === "ai") {
3087
+ const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
3088
+ if (!syncAiCommand2) {
3089
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
2662
3090
  }
2663
- throw await wrapCliCommandError("init", error);
3091
+ return [syncAiCommand2];
3092
+ }
3093
+ if (project.scripts.sync) {
3094
+ return [createSyncPlannedCommand(project, "sync", extraArgs)];
3095
+ }
3096
+ const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
3097
+ if (!syncTypesCommand) {
3098
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
3099
+ }
3100
+ const plannedCommands = [syncTypesCommand];
3101
+ const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
3102
+ if (syncRestCommand) {
3103
+ plannedCommands.push(syncRestCommand);
3104
+ }
3105
+ const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
3106
+ if (syncAiCommand) {
3107
+ plannedCommands.push(syncAiCommand);
2664
3108
  }
3109
+ return plannedCommands;
2665
3110
  }
2666
- async function executeDoctorCommand(cwd) {
2667
- try {
2668
- const { runDoctor } = await loadCliDoctorRuntime();
2669
- await runDoctor(cwd);
2670
- } catch (error) {
2671
- throw await wrapCliCommandError("doctor", error);
3111
+ function runProjectScript(project, plannedCommand, options) {
3112
+ const result = spawnSync(plannedCommand.command, plannedCommand.args, {
3113
+ cwd: project.cwd,
3114
+ encoding: options.captureOutput ? "utf8" : undefined,
3115
+ ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
3116
+ shell: process.platform === "win32",
3117
+ stdio: options.captureOutput ? "pipe" : "inherit"
3118
+ });
3119
+ const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
3120
+ const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
3121
+ if (result.error || result.status !== 0) {
3122
+ throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
3123
+ cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
3124
+ });
2672
3125
  }
3126
+ return {
3127
+ ...plannedCommand,
3128
+ exitCode: result.status ?? 0,
3129
+ ...stderr !== undefined ? { stderr } : {},
3130
+ ...stdout !== undefined ? { stdout } : {}
3131
+ };
2673
3132
  }
2674
- async function executeMigrateCommand({
2675
- command,
3133
+ async function executeSyncCommand({
3134
+ captureOutput = false,
3135
+ check = false,
2676
3136
  cwd,
2677
- flags,
2678
- prompt,
2679
- renderLine
3137
+ dryRun = false,
3138
+ target = "default"
2680
3139
  }) {
2681
- const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
2682
- if (!command) {
2683
- console.log(formatMigrationHelpText());
2684
- return;
2685
- }
2686
- try {
2687
- const argv = [command];
2688
- pushFlag(argv, "all", flags.all);
2689
- pushFlag(argv, "force", flags.force);
2690
- pushFlag(argv, "current-migration-version", readOptionalLooseStringFlag(flags, "current-migration-version"));
2691
- pushFlag(argv, "migration-version", readOptionalLooseStringFlag(flags, "migration-version"));
2692
- pushFlag(argv, "from-migration-version", readOptionalLooseStringFlag(flags, "from-migration-version"));
2693
- pushFlag(argv, "to-migration-version", readOptionalLooseStringFlag(flags, "to-migration-version"));
2694
- pushFlag(argv, "iterations", readOptionalLooseStringFlag(flags, "iterations"));
2695
- pushFlag(argv, "seed", readOptionalLooseStringFlag(flags, "seed"));
2696
- const parsed = parseMigrationArgs(argv);
2697
- const lines = renderLine ? [] : null;
2698
- const captureLine = (line) => {
2699
- lines?.push(line);
2700
- if (renderLine) {
2701
- renderLine(line);
2702
- return;
2703
- }
2704
- console.log(line);
2705
- };
2706
- const result = await runMigrationCommand(parsed, cwd, {
2707
- prompt,
2708
- renderLine: captureLine
2709
- });
2710
- if (renderLine) {
2711
- return result && typeof result === "object" && "cancelled" in result && result.cancelled === true ? undefined : buildMigrationCompletionPayload({
2712
- command: parsed.command ?? "plan",
2713
- lines: lines ?? []
2714
- });
2715
- }
2716
- if (result && typeof result === "object" && "cancelled" in result && result.cancelled === true) {
2717
- return;
2718
- }
2719
- } catch (error) {
2720
- if (!shouldWrapCliCommandError({ renderLine })) {
2721
- throw error;
2722
- }
2723
- throw await wrapCliCommandError("migrate", error);
3140
+ const project = resolveSyncProjectContext(cwd);
3141
+ const extraArgs = check ? ["--check"] : [];
3142
+ const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
3143
+ const result = {
3144
+ check,
3145
+ dryRun,
3146
+ packageJsonPath: project.packageJsonPath,
3147
+ packageManager: project.packageManager,
3148
+ plannedCommands,
3149
+ projectDir: project.cwd,
3150
+ target
3151
+ };
3152
+ if (dryRun) {
3153
+ return result;
2724
3154
  }
3155
+ assertSyncDependenciesInstalled(project, target);
3156
+ result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
3157
+ captureOutput
3158
+ }));
3159
+ return result;
2725
3160
  }
2726
-
2727
3161
  // src/command-contract.ts
2728
- import path4 from "node:path";
3162
+ import path5 from "node:path";
2729
3163
  import {
2730
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES9,
2731
- createCliDiagnosticCodeError as createCliDiagnosticCodeError8
3164
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES10,
3165
+ createCliDiagnosticCodeError as createCliDiagnosticCodeError9
2732
3166
  } from "@wp-typia/project-tools/cli-diagnostics";
2733
3167
 
2734
3168
  // src/command-registry.ts
@@ -2770,7 +3204,7 @@ var WP_TYPIA_COMMAND_REGISTRY = [
2770
3204
  nodeFallback: true,
2771
3205
  optionGroups: ["add"],
2772
3206
  requiresBunRuntime: false,
2773
- subcommands: ADD_KIND_IDS
3207
+ subcommands: ADD_KIND_IDS2
2774
3208
  },
2775
3209
  {
2776
3210
  commandTree: true,
@@ -2997,12 +3431,12 @@ function looksLikeStructuredProjectInput(value) {
2997
3431
  return value.startsWith("@") && value.includes("/");
2998
3432
  }
2999
3433
  function assertPositionalAliasProjectDir(projectDir) {
3000
- const normalizedProjectDir = path4.normalize(projectDir).replace(/[\\/]+$/u, "") || path4.normalize(projectDir);
3434
+ const normalizedProjectDir = path5.normalize(projectDir).replace(/[\\/]+$/u, "") || path5.normalize(projectDir);
3001
3435
  if (normalizedProjectDir === "." || normalizedProjectDir === "..") {
3002
- throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_ARGUMENT, `The positional alias does not scaffold into \`${projectDir}\`. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` with an explicit child directory instead.`);
3436
+ 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.`);
3003
3437
  }
3004
3438
  if (looksLikeStructuredProjectInput(projectDir)) {
3005
- throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_ARGUMENT, `The positional alias only accepts unambiguous local project directories. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for \`${projectDir}\`.`);
3439
+ throw createCliDiagnosticCodeError9(CLI_DIAGNOSTIC_CODES10.INVALID_ARGUMENT, `The positional alias only accepts unambiguous local project directories. Use \`${WP_TYPIA_CANONICAL_CREATE_USAGE}\` for \`${projectDir}\`.`);
3006
3440
  }
3007
3441
  }
3008
3442
  function normalizeWpTypiaArgv(argv) {
@@ -3016,7 +3450,7 @@ function normalizeWpTypiaArgv(argv) {
3016
3450
  return argv;
3017
3451
  }
3018
3452
  if (firstPositional === "migrations") {
3019
- throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.INVALID_ARGUMENT, "`wp-typia migrations` was removed in favor of `wp-typia migrate`. Use `wp-typia migrate <subcommand>` instead.");
3453
+ throw createCliDiagnosticCodeError9(CLI_DIAGNOSTIC_CODES10.INVALID_ARGUMENT, "`wp-typia migrations` was removed in favor of `wp-typia migrate`. Use `wp-typia migrate <subcommand>` instead.");
3020
3454
  }
3021
3455
  if (isReservedTopLevelCommandName(firstPositional)) {
3022
3456
  assertStringOptionValues(argv);
@@ -3024,7 +3458,7 @@ function normalizeWpTypiaArgv(argv) {
3024
3458
  }
3025
3459
  if (positionalIndexes.length > 1) {
3026
3460
  const extraPositionals = positionalIndexes.slice(1).map((index) => argv[index]).filter((value) => typeof value === "string" && value.length > 0);
3027
- throw createCliDiagnosticCodeError8(CLI_DIAGNOSTIC_CODES9.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(", ")}.`);
3461
+ 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(", ")}.`);
3028
3462
  }
3029
3463
  assertPositionalAliasProjectDir(firstPositional);
3030
3464
  const normalizedArgv = [
@@ -3038,14 +3472,15 @@ function normalizeWpTypiaArgv(argv) {
3038
3472
 
3039
3473
  // src/node-fallback/dispatchers/add.ts
3040
3474
  import {
3041
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES10,
3475
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES11,
3042
3476
  createCliCommandError as createCliCommandError3
3043
3477
  } from "@wp-typia/project-tools/cli-diagnostics";
3044
3478
  async function dispatchNodeFallbackAdd({
3045
3479
  cwd,
3046
3480
  mergedFlags,
3047
3481
  positionals,
3048
- printLine
3482
+ printLine,
3483
+ warnLine
3049
3484
  }) {
3050
3485
  if (!positionals[1]) {
3051
3486
  if (shouldPrintMissingAddKindHelp({ format: mergedFlags.format })) {
@@ -3053,7 +3488,7 @@ async function dispatchNodeFallbackAdd({
3053
3488
  printLine(formatAddHelpText());
3054
3489
  }
3055
3490
  throw createCliCommandError3({
3056
- code: CLI_DIAGNOSTIC_CODES10.MISSING_ARGUMENT,
3491
+ code: CLI_DIAGNOSTIC_CODES11.MISSING_ARGUMENT,
3057
3492
  command: "add",
3058
3493
  detailLines: buildMissingAddKindDetailLines()
3059
3494
  });
@@ -3067,7 +3502,9 @@ async function dispatchNodeFallbackAdd({
3067
3502
  flags: mergedFlags,
3068
3503
  interactive: false,
3069
3504
  kind: positionals[1],
3070
- name: positionals[2]
3505
+ name: positionals[2],
3506
+ printLine,
3507
+ warnLine
3071
3508
  });
3072
3509
  } catch (error) {
3073
3510
  throw createCliCommandError3({
@@ -3088,25 +3525,28 @@ async function dispatchNodeFallbackAdd({
3088
3525
  flags: mergedFlags,
3089
3526
  interactive: undefined,
3090
3527
  kind: positionals[1],
3091
- name: positionals[2]
3528
+ name: positionals[2],
3529
+ printLine,
3530
+ warnLine
3092
3531
  });
3093
3532
  }
3094
3533
 
3095
3534
  // src/node-fallback/dispatchers/create.ts
3096
3535
  import {
3097
- CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES11,
3536
+ CLI_DIAGNOSTIC_CODES as CLI_DIAGNOSTIC_CODES12,
3098
3537
  createCliCommandError as createCliCommandError4
3099
3538
  } from "@wp-typia/project-tools/cli-diagnostics";
3100
3539
  async function dispatchNodeFallbackCreate({
3101
3540
  cwd,
3102
3541
  mergedFlags,
3103
3542
  positionals,
3104
- printLine
3543
+ printLine,
3544
+ warnLine
3105
3545
  }) {
3106
3546
  const projectDir = positionals[1];
3107
3547
  if (!projectDir) {
3108
3548
  throw createCliCommandError4({
3109
- code: CLI_DIAGNOSTIC_CODES11.MISSING_ARGUMENT,
3549
+ code: CLI_DIAGNOSTIC_CODES12.MISSING_ARGUMENT,
3110
3550
  command: "create",
3111
3551
  detailLines: buildMissingCreateProjectDirDetailLines()
3112
3552
  });
@@ -3118,7 +3558,9 @@ async function dispatchNodeFallbackCreate({
3118
3558
  emitOutput: mergedFlags.format !== "json",
3119
3559
  flags: mergedFlags,
3120
3560
  interactive: mergedFlags.format === "json" ? false : undefined,
3121
- projectDir
3561
+ printLine,
3562
+ projectDir,
3563
+ warnLine
3122
3564
  });
3123
3565
  } catch (error) {
3124
3566
  throw createCliCommandError4({
@@ -3143,6 +3585,7 @@ var NODE_FALLBACK_RUNTIME_SUMMARY_LINES = [
3143
3585
  `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}`,
3144
3586
  "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."
3145
3587
  ];
3588
+ var NODE_FALLBACK_NO_COMMAND_REASON_LINE = "No command provided. Run wp-typia --help for usage information.";
3146
3589
  function renderGeneralHelp(printLine) {
3147
3590
  printBlock(printLine, [
3148
3591
  `wp-typia ${package_default.version}`,
@@ -3161,6 +3604,10 @@ function renderGeneralHelp(printLine) {
3161
3604
  `- ${WP_TYPIA_POSITIONAL_ALIAS_USAGE}`
3162
3605
  ]);
3163
3606
  }
3607
+ function renderNoCommandHelp(printLine) {
3608
+ printBlock(printLine, [NODE_FALLBACK_NO_COMMAND_REASON_LINE, ""]);
3609
+ renderGeneralHelp(printLine);
3610
+ }
3164
3611
  function renderNodeFallbackCommandHelp(printLine, config) {
3165
3612
  printBlock(printLine, [
3166
3613
  config.heading,
@@ -3220,6 +3667,20 @@ var NODE_FALLBACK_BOOLEAN_OPTION_NAMES = ["help", "version"];
3220
3667
  var printLine = (line) => {
3221
3668
  console.log(line);
3222
3669
  };
3670
+ var warnLine = (line) => {
3671
+ console.warn(line);
3672
+ };
3673
+ function createNoCommandCliError() {
3674
+ return createCliCommandError5({
3675
+ code: CLI_DIAGNOSTIC_CODES13.INVALID_COMMAND,
3676
+ command: "wp-typia",
3677
+ detailLines: [NODE_FALLBACK_NO_COMMAND_REASON_LINE],
3678
+ summary: "No command was provided."
3679
+ });
3680
+ }
3681
+ function isNoCommandCliDiagnostic(error) {
3682
+ return isCliDiagnosticError(error) && error.code === CLI_DIAGNOSTIC_CODES13.INVALID_COMMAND && error.command === "wp-typia" && error.detailLines.includes(NODE_FALLBACK_NO_COMMAND_REASON_LINE);
3683
+ }
3223
3684
  function hasFlagBeforeTerminator(argv, flag) {
3224
3685
  for (const arg of argv) {
3225
3686
  if (arg === "--") {
@@ -3300,7 +3761,7 @@ function renderTemplatesJson(flags, subcommand) {
3300
3761
  const templateId = flags.id;
3301
3762
  if (!templateId) {
3302
3763
  throw createCliCommandError5({
3303
- code: CLI_DIAGNOSTIC_CODES12.MISSING_ARGUMENT,
3764
+ code: CLI_DIAGNOSTIC_CODES13.MISSING_ARGUMENT,
3304
3765
  command: "templates",
3305
3766
  detailLines: ["`wp-typia templates inspect` requires <template-id>."]
3306
3767
  });
@@ -3308,7 +3769,7 @@ function renderTemplatesJson(flags, subcommand) {
3308
3769
  const template = getTemplateById(templateId);
3309
3770
  if (!template) {
3310
3771
  throw createCliCommandError5({
3311
- code: CLI_DIAGNOSTIC_CODES12.INVALID_ARGUMENT,
3772
+ code: CLI_DIAGNOSTIC_CODES13.INVALID_ARGUMENT,
3312
3773
  command: "templates",
3313
3774
  detailLines: [`Unknown template "${templateId}".`]
3314
3775
  });
@@ -3319,7 +3780,7 @@ function renderTemplatesJson(flags, subcommand) {
3319
3780
  }
3320
3781
  function renderUnsupportedCommand(command) {
3321
3782
  throw createCliCommandError5({
3322
- code: CLI_DIAGNOSTIC_CODES12.UNSUPPORTED_COMMAND,
3783
+ code: CLI_DIAGNOSTIC_CODES13.UNSUPPORTED_COMMAND,
3323
3784
  command,
3324
3785
  detailLines: [
3325
3786
  [
@@ -3345,7 +3806,7 @@ async function renderDoctorJson() {
3345
3806
  }, null, 2));
3346
3807
  if (checks.some((check) => check.status === "fail")) {
3347
3808
  throw createCliCommandError6({
3348
- code: CLI_DIAGNOSTIC_CODES12.DOCTOR_CHECK_FAILED,
3809
+ code: CLI_DIAGNOSTIC_CODES13.DOCTOR_CHECK_FAILED,
3349
3810
  command: "doctor",
3350
3811
  detailLines: getDoctorFailureDetailLines(checks),
3351
3812
  summary: "One or more doctor checks failed."
@@ -3365,7 +3826,9 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3365
3826
  init: async ({
3366
3827
  cwd,
3367
3828
  mergedFlags,
3368
- positionals
3829
+ positionals,
3830
+ printLine: printLine2,
3831
+ warnLine: warnLine2
3369
3832
  }) => {
3370
3833
  const plan = await executeInitCommand({
3371
3834
  apply: Boolean(mergedFlags.apply),
@@ -3373,27 +3836,33 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3373
3836
  packageManager: typeof mergedFlags["package-manager"] === "string" ? mergedFlags["package-manager"] : undefined,
3374
3837
  projectDir: positionals[1]
3375
3838
  }, {
3376
- emitOutput: mergedFlags.format !== "json"
3839
+ emitOutput: mergedFlags.format !== "json",
3840
+ printLine: printLine2,
3841
+ warnLine: warnLine2
3377
3842
  });
3378
3843
  if (mergedFlags.format === "json") {
3379
- printLine(JSON.stringify(buildStructuredInitSuccessPayload(plan), null, 2));
3844
+ printLine2(JSON.stringify(buildStructuredInitSuccessPayload(plan), null, 2));
3380
3845
  }
3381
3846
  },
3382
3847
  migrate: async ({
3383
3848
  cwd,
3384
3849
  mergedFlags,
3385
- positionals
3850
+ positionals,
3851
+ printLine: printLine2
3386
3852
  }) => {
3387
3853
  await executeMigrateCommand({
3388
3854
  command: positionals[1],
3389
3855
  cwd,
3390
- flags: mergedFlags
3856
+ flags: mergedFlags,
3857
+ printLine: printLine2
3391
3858
  });
3392
3859
  },
3393
3860
  sync: async ({
3394
3861
  cwd,
3395
3862
  mergedFlags,
3396
- positionals
3863
+ positionals,
3864
+ printLine: printLine2,
3865
+ warnLine: warnLine2
3397
3866
  }) => {
3398
3867
  try {
3399
3868
  const syncTarget = resolveSyncExecutionTarget(positionals[1]);
@@ -3405,7 +3874,7 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3405
3874
  target: syncTarget
3406
3875
  });
3407
3876
  if (mergedFlags.format === "json") {
3408
- printLine(JSON.stringify({
3877
+ printLine2(JSON.stringify({
3409
3878
  sync
3410
3879
  }, null, 2));
3411
3880
  return;
@@ -3417,7 +3886,10 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3417
3886
  plannedCommands: sync.plannedCommands,
3418
3887
  projectDir: sync.projectDir,
3419
3888
  target: sync.target
3420
- }));
3889
+ }), {
3890
+ printLine: printLine2,
3891
+ warnLine: warnLine2
3892
+ });
3421
3893
  }
3422
3894
  } catch (error) {
3423
3895
  throw createCliCommandError5({
@@ -3428,14 +3900,15 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3428
3900
  },
3429
3901
  templates: async ({
3430
3902
  mergedFlags,
3431
- positionals
3903
+ positionals,
3904
+ printLine: printLine2
3432
3905
  }) => {
3433
3906
  const subcommand = positionals[1];
3434
3907
  const templateId = typeof mergedFlags.id === "string" ? mergedFlags.id : positionals[2];
3435
3908
  const resolvedSubcommand = templateId ? "inspect" : subcommand ?? "list";
3436
3909
  if (resolvedSubcommand !== "list" && resolvedSubcommand !== "inspect") {
3437
3910
  throw createCliCommandError5({
3438
- code: CLI_DIAGNOSTIC_CODES12.INVALID_COMMAND,
3911
+ code: CLI_DIAGNOSTIC_CODES13.INVALID_COMMAND,
3439
3912
  command: "templates",
3440
3913
  detailLines: [
3441
3914
  `Unknown templates subcommand "${resolvedSubcommand}". Expected list or inspect.`
@@ -3454,7 +3927,7 @@ var NODE_FALLBACK_COMMAND_DISPATCHERS = {
3454
3927
  id: templateId,
3455
3928
  subcommand: resolvedSubcommand
3456
3929
  }
3457
- });
3930
+ }, printLine2);
3458
3931
  }
3459
3932
  };
3460
3933
  async function runNodeCli(argv = process.argv.slice(2)) {
@@ -3473,9 +3946,11 @@ async function runNodeCli(argv = process.argv.slice(2)) {
3473
3946
  const helpTarget = command === "help" ? subcommand : command;
3474
3947
  const versionRequested = hasFlagBeforeTerminator(cliArgv, "--version") || command === "version";
3475
3948
  if (cliArgv.length === 0) {
3476
- renderGeneralHelp(printLine);
3477
- process.exitCode = 1;
3478
- return;
3949
+ const noCommandError = createNoCommandCliError();
3950
+ if (rawMergedFlags.format !== "json") {
3951
+ renderNoCommandHelp(printLine);
3952
+ }
3953
+ throw noCommandError;
3479
3954
  }
3480
3955
  if (helpRequested) {
3481
3956
  if (helpTarget) {
@@ -3508,7 +3983,8 @@ async function runNodeCli(argv = process.argv.slice(2)) {
3508
3983
  cwd: process.cwd(),
3509
3984
  mergedFlags,
3510
3985
  positionals,
3511
- printLine
3986
+ printLine,
3987
+ warnLine
3512
3988
  });
3513
3989
  return;
3514
3990
  }
@@ -3532,6 +4008,10 @@ async function runNodeCliEntrypoint(argv = process.argv.slice(2)) {
3532
4008
  process.exitCode = 1;
3533
4009
  return;
3534
4010
  }
4011
+ if (isNoCommandCliDiagnostic(error)) {
4012
+ process.exitCode = 1;
4013
+ return;
4014
+ }
3535
4015
  console.error(`Error: ${await formatCliDiagnosticError(error)}`);
3536
4016
  process.exitCode = 1;
3537
4017
  }
@@ -3543,4 +4023,4 @@ export {
3543
4023
  hasFlagBeforeTerminator
3544
4024
  };
3545
4025
 
3546
- //# debugId=B5CA87A93189F22464756E2164756E21
4026
+ //# debugId=CA11CB4ECD0D26E464756E2164756E21