wp-typia 0.20.5 → 0.22.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.
@@ -2,9 +2,12 @@
2
2
  import {
3
3
  ADD_OPTION_METADATA,
4
4
  CREATE_OPTION_METADATA,
5
+ DOCTOR_OPTION_METADATA,
6
+ INIT_OPTION_METADATA,
5
7
  MIGRATE_OPTION_METADATA,
6
8
  SYNC_OPTION_METADATA,
7
9
  TEMPLATES_OPTION_METADATA,
10
+ WP_TYPIA_TOP_LEVEL_COMMAND_NAMES,
8
11
  buildCommandOptions,
9
12
  emitCliDiagnosticFailure,
10
13
  getAddBlockDefaults,
@@ -13,7 +16,7 @@ import {
13
16
  package_default,
14
17
  prefersStructuredCliOutput,
15
18
  resolveCommandOptionValues
16
- } from "./cli-xnh2s5kz.js";
19
+ } from "./cli-ktp869eh.js";
17
20
  import {
18
21
  Result,
19
22
  TaggedError,
@@ -30,12 +33,13 @@ import"./cli-ac2ebaf8.js";
30
33
  import {
31
34
  formatPackageExecCommand
32
35
  } from "./cli-sj5mtyzj.js";
33
- import {
34
- CLI_DIAGNOSTIC_CODES
35
- } from "./cli-xxzpb58s.js";
36
36
  import {
37
37
  createManagedTempRoot
38
38
  } from "./cli-t73q5aqz.js";
39
+ import {
40
+ CLI_DIAGNOSTIC_CODES,
41
+ createCliDiagnosticCodeError
42
+ } from "./cli-p95wr1q8.js";
39
43
  import {
40
44
  __require,
41
45
  __toESM
@@ -66,17 +70,6 @@ function resolveBundledModuleHref(baseUrl, candidates, options = {}) {
66
70
  }
67
71
 
68
72
  // src/add-kind-registry.ts
69
- var ADD_KIND_IDS = [
70
- "block",
71
- "variation",
72
- "pattern",
73
- "binding-source",
74
- "rest-resource",
75
- "ability",
76
- "ai-feature",
77
- "editor-plugin",
78
- "hooked-block"
79
- ];
80
73
  var BLOCK_VISIBLE_FIELD_ORDER = [
81
74
  "kind",
82
75
  "name",
@@ -86,30 +79,123 @@ var BLOCK_VISIBLE_FIELD_ORDER = [
86
79
  "data-storage",
87
80
  "persistence-policy"
88
81
  ];
89
- function isAddKindId(value) {
90
- return typeof value === "string" && ADD_KIND_IDS.includes(value);
82
+ function readOptionalStringFlag(flags, name) {
83
+ const value = flags[name];
84
+ if (value === undefined || value === null) {
85
+ return;
86
+ }
87
+ if (typeof value !== "string" || value.trim().length === 0) {
88
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
89
+ }
90
+ return value;
91
+ }
92
+ function requireAddKindName(context, message) {
93
+ if (!context.name) {
94
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
95
+ }
96
+ return context.name;
97
+ }
98
+ function formatExternalLayerSelectHint(option2) {
99
+ const details = [
100
+ option2.description,
101
+ option2.extends.length > 0 ? `extends ${option2.extends.join(", ")}` : undefined
102
+ ].filter((value) => typeof value === "string" && value.length > 0);
103
+ return details.length > 0 ? details.join(" \xB7 ") : undefined;
104
+ }
105
+ function toExternalLayerPromptOptions(options) {
106
+ return options.map((option2) => ({
107
+ hint: formatExternalLayerSelectHint(option2),
108
+ label: option2.id,
109
+ value: option2.id
110
+ }));
111
+ }
112
+ function defineAddKindRegistryEntry(entry) {
113
+ return entry;
91
114
  }
92
115
  function isAddPersistenceTemplate(template) {
93
116
  return template === "persistence" || template === "compound";
94
117
  }
95
118
  var ADD_KIND_REGISTRY = {
96
- "binding-source": {
119
+ "admin-view": defineAddKindRegistryEntry({
120
+ completion: {
121
+ nextSteps: (values) => [
122
+ `Review src/admin-views/${values.adminViewSlug}/ and inc/admin-views/${values.adminViewSlug}.php.`,
123
+ "Run your workspace build or dev command to verify the generated DataViews admin screen."
124
+ ],
125
+ summaryLines: (values, projectDir) => [
126
+ `Admin view: ${values.adminViewSlug}`,
127
+ ...values.source ? [`Source: ${values.source}`] : [],
128
+ `Project directory: ${projectDir}`
129
+ ],
130
+ title: "Added DataViews admin screen"
131
+ },
132
+ description: "Add an opt-in DataViews-powered admin screen",
133
+ nameLabel: "Admin view name",
134
+ async prepareExecution(context) {
135
+ 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>].");
136
+ const source = readOptionalStringFlag(context.flags, "source");
137
+ return {
138
+ execute: (cwd) => context.addRuntime.runAddAdminViewCommand({
139
+ adminViewName: name,
140
+ cwd,
141
+ source
142
+ }),
143
+ getValues: (result) => ({
144
+ adminViewSlug: result.adminViewSlug,
145
+ ...result.source ? { source: result.source } : {}
146
+ })
147
+ };
148
+ },
149
+ sortOrder: 10,
150
+ supportsDryRun: true,
151
+ usage: "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]",
152
+ visibleFieldNames: () => ["kind", "name", "source"]
153
+ }),
154
+ "binding-source": defineAddKindRegistryEntry({
97
155
  completion: {
98
156
  nextSteps: (values) => [
99
157
  `Review src/bindings/${values.bindingSourceSlug}/server.php and src/bindings/${values.bindingSourceSlug}/editor.ts.`,
158
+ ...values.blockSlug && values.attributeName ? [
159
+ `Review src/blocks/${values.blockSlug}/block.json for the ${values.attributeName} bindable attribute.`
160
+ ] : [],
100
161
  "Run your workspace build or dev command to verify the binding source hooks and editor registration."
101
162
  ],
102
163
  summaryLines: (values, projectDir) => [
103
164
  `Binding source: ${values.bindingSourceSlug}`,
165
+ ...values.blockSlug && values.attributeName ? [`Target: ${values.blockSlug}.${values.attributeName}`] : [],
104
166
  `Project directory: ${projectDir}`
105
167
  ],
106
168
  title: "Added binding source"
107
169
  },
108
170
  description: "Add a shared block bindings source",
109
171
  nameLabel: "Binding source name",
110
- visibleFieldNames: () => ["kind", "name"]
111
- },
112
- block: {
172
+ async prepareExecution(context) {
173
+ 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>].");
174
+ const blockName = readOptionalStringFlag(context.flags, "block");
175
+ const attributeName = readOptionalStringFlag(context.flags, "attribute");
176
+ if (Boolean(blockName) !== Boolean(attributeName)) {
177
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
178
+ }
179
+ return {
180
+ execute: (cwd) => context.addRuntime.runAddBindingSourceCommand({
181
+ attributeName,
182
+ bindingSourceName: name,
183
+ blockName,
184
+ cwd
185
+ }),
186
+ getValues: (result) => ({
187
+ ...result.attributeName ? { attributeName: result.attributeName } : {},
188
+ ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
189
+ bindingSourceSlug: result.bindingSourceSlug
190
+ })
191
+ };
192
+ },
193
+ sortOrder: 70,
194
+ supportsDryRun: true,
195
+ usage: "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--dry-run]",
196
+ visibleFieldNames: () => ["kind", "name", "block", "attribute"]
197
+ }),
198
+ block: defineAddKindRegistryEntry({
113
199
  completion: {
114
200
  nextSteps: () => [
115
201
  "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
@@ -125,6 +211,50 @@ var ADD_KIND_REGISTRY = {
125
211
  description: "Add a real block slice",
126
212
  hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
127
213
  nameLabel: "Block name",
214
+ async prepareExecution(context) {
215
+ const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
216
+ const externalLayerId = readOptionalStringFlag(context.flags, "external-layer-id");
217
+ const externalLayerSource = readOptionalStringFlag(context.flags, "external-layer-source");
218
+ const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
219
+ const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
220
+ const alternateRenderTargets = readOptionalStringFlag(context.flags, "alternate-render-targets");
221
+ const dataStorageMode = readOptionalStringFlag(context.flags, "data-storage");
222
+ const innerBlocksPreset = readOptionalStringFlag(context.flags, "inner-blocks-preset");
223
+ const persistencePolicy = readOptionalStringFlag(context.flags, "persistence-policy");
224
+ let resolvedTemplateId = readOptionalStringFlag(context.flags, "template");
225
+ if (!resolvedTemplateId && context.isInteractiveSession) {
226
+ const templatePrompt = await context.getOrCreatePrompt();
227
+ resolvedTemplateId = await templatePrompt.select("Select a block template", context.addRuntime.ADD_BLOCK_TEMPLATE_IDS.map((templateId) => ({
228
+ hint: `Scaffold the ${templateId} block family`,
229
+ label: templateId,
230
+ value: templateId
231
+ })), 1);
232
+ }
233
+ resolvedTemplateId ??= "basic";
234
+ return {
235
+ execute: (cwd) => context.addRuntime.runAddBlockCommand({
236
+ alternateRenderTargets,
237
+ blockName: name,
238
+ cwd,
239
+ dataStorageMode,
240
+ externalLayerId,
241
+ externalLayerSource,
242
+ innerBlocksPreset,
243
+ persistencePolicy,
244
+ selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
245
+ templateId: resolvedTemplateId
246
+ }),
247
+ getValues: (result) => ({
248
+ blockSlugs: result.blockSlugs.join(", "),
249
+ templateId: result.templateId
250
+ }),
251
+ getWarnings: (result) => result.warnings,
252
+ warnLine: context.warnLine
253
+ };
254
+ },
255
+ sortOrder: 20,
256
+ supportsDryRun: true,
257
+ usage: "wp-typia add block <name> [--template <basic|interactivity|persistence|compound>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--inner-blocks-preset <freeform|ordered|horizontal|locked-structure>] [--alternate-render-targets <email,mjml,plain-text>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--dry-run]",
128
258
  visibleFieldNames: ({ template }) => BLOCK_VISIBLE_FIELD_ORDER.filter((fieldName) => {
129
259
  if (fieldName === "alternate-render-targets") {
130
260
  return isAddPersistenceTemplate(template);
@@ -137,8 +267,8 @@ var ADD_KIND_REGISTRY = {
137
267
  }
138
268
  return true;
139
269
  })
140
- },
141
- ability: {
270
+ }),
271
+ ability: defineAddKindRegistryEntry({
142
272
  completion: {
143
273
  nextSteps: (values) => [
144
274
  `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
@@ -152,9 +282,24 @@ var ADD_KIND_REGISTRY = {
152
282
  },
153
283
  description: "Add a typed server/client workflow ability scaffold",
154
284
  nameLabel: "Ability name",
285
+ async prepareExecution(context) {
286
+ const name = requireAddKindName(context, "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.");
287
+ return {
288
+ execute: (cwd) => context.addRuntime.runAddAbilityCommand({
289
+ abilityName: name,
290
+ cwd
291
+ }),
292
+ getValues: (result) => ({
293
+ abilitySlug: result.abilitySlug
294
+ })
295
+ };
296
+ },
297
+ sortOrder: 90,
298
+ supportsDryRun: true,
299
+ usage: "wp-typia add ability <name> [--dry-run]",
155
300
  visibleFieldNames: () => ["kind", "name"]
156
- },
157
- "editor-plugin": {
301
+ }),
302
+ "editor-plugin": defineAddKindRegistryEntry({
158
303
  completion: {
159
304
  nextSteps: (values) => [
160
305
  `Review src/editor-plugins/${values.editorPluginSlug}/.`,
@@ -167,11 +312,29 @@ var ADD_KIND_REGISTRY = {
167
312
  ],
168
313
  title: "Added editor plugin"
169
314
  },
170
- description: "Add a document-level editor extension shell",
315
+ description: "Add a slot-aware document editor extension shell",
171
316
  nameLabel: "Editor plugin name",
317
+ async prepareExecution(context) {
318
+ const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].");
319
+ const slot = readOptionalStringFlag(context.flags, "slot");
320
+ return {
321
+ execute: (cwd) => context.addRuntime.runAddEditorPluginCommand({
322
+ cwd,
323
+ editorPluginName: name,
324
+ slot
325
+ }),
326
+ getValues: (result) => ({
327
+ editorPluginSlug: result.editorPluginSlug,
328
+ slot: result.slot
329
+ })
330
+ };
331
+ },
332
+ sortOrder: 120,
333
+ supportsDryRun: true,
334
+ usage: "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>] [--dry-run]",
172
335
  visibleFieldNames: () => ["kind", "name", "slot"]
173
- },
174
- "hooked-block": {
336
+ }),
337
+ "hooked-block": defineAddKindRegistryEntry({
175
338
  completion: {
176
339
  nextSteps: (values) => [
177
340
  `Review src/blocks/${values.blockSlug}/block.json for the new blockHooks entry.`,
@@ -187,9 +350,36 @@ var ADD_KIND_REGISTRY = {
187
350
  },
188
351
  description: "Add block.json hook metadata to an existing block",
189
352
  nameLabel: "Target block",
353
+ async prepareExecution(context) {
354
+ 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>.");
355
+ const anchorBlockName = readOptionalStringFlag(context.flags, "anchor");
356
+ if (!anchorBlockName) {
357
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
358
+ }
359
+ const position = readOptionalStringFlag(context.flags, "position");
360
+ if (!position) {
361
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
362
+ }
363
+ return {
364
+ execute: (cwd) => context.addRuntime.runAddHookedBlockCommand({
365
+ anchorBlockName,
366
+ blockName: name,
367
+ cwd,
368
+ position
369
+ }),
370
+ getValues: (result) => ({
371
+ anchorBlockName: result.anchorBlockName,
372
+ blockSlug: result.blockSlug,
373
+ position: result.position
374
+ })
375
+ };
376
+ },
377
+ sortOrder: 110,
378
+ supportsDryRun: true,
379
+ usage: "wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild> [--dry-run]",
190
380
  visibleFieldNames: () => ["kind", "name", "anchor", "position"]
191
- },
192
- pattern: {
381
+ }),
382
+ pattern: defineAddKindRegistryEntry({
193
383
  completion: {
194
384
  nextSteps: (values) => [
195
385
  `Review src/patterns/${values.patternSlug}.php.`,
@@ -203,9 +393,108 @@ var ADD_KIND_REGISTRY = {
203
393
  },
204
394
  description: "Add a PHP block pattern shell",
205
395
  nameLabel: "Pattern name",
396
+ async prepareExecution(context) {
397
+ const name = requireAddKindName(context, "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.");
398
+ return {
399
+ execute: (cwd) => context.addRuntime.runAddPatternCommand({
400
+ cwd,
401
+ patternName: name
402
+ }),
403
+ getValues: (result) => ({
404
+ patternSlug: result.patternSlug
405
+ })
406
+ };
407
+ },
408
+ sortOrder: 60,
409
+ supportsDryRun: true,
410
+ usage: "wp-typia add pattern <name> [--dry-run]",
206
411
  visibleFieldNames: () => ["kind", "name"]
207
- },
208
- "rest-resource": {
412
+ }),
413
+ style: defineAddKindRegistryEntry({
414
+ completion: {
415
+ nextSteps: (values) => [
416
+ `Review src/blocks/${values.blockSlug}/styles/${values.styleSlug}.ts.`,
417
+ "Run your workspace build or dev command to verify the new block style registration."
418
+ ],
419
+ summaryLines: (values, projectDir) => [
420
+ `Block style: ${values.styleSlug}`,
421
+ `Target block: ${values.blockSlug}`,
422
+ `Project directory: ${projectDir}`
423
+ ],
424
+ title: "Added block style"
425
+ },
426
+ description: "Add a Block Styles registration to an existing block",
427
+ nameLabel: "Style name",
428
+ async prepareExecution(context) {
429
+ const name = requireAddKindName(context, "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.");
430
+ const blockSlug = readOptionalStringFlag(context.flags, "block");
431
+ if (!blockSlug) {
432
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add style` requires --block <block-slug>.");
433
+ }
434
+ return {
435
+ execute: (cwd) => context.addRuntime.runAddBlockStyleCommand({
436
+ blockName: blockSlug,
437
+ cwd,
438
+ styleName: name
439
+ }),
440
+ getValues: (result) => ({
441
+ blockSlug: result.blockSlug,
442
+ styleSlug: result.styleSlug
443
+ })
444
+ };
445
+ },
446
+ sortOrder: 40,
447
+ supportsDryRun: true,
448
+ usage: "wp-typia add style <name> --block <block-slug> [--dry-run]",
449
+ visibleFieldNames: () => ["kind", "name", "block"]
450
+ }),
451
+ transform: defineAddKindRegistryEntry({
452
+ completion: {
453
+ nextSteps: (values) => [
454
+ `Review src/blocks/${values.blockSlug}/transforms/${values.transformSlug}.ts.`,
455
+ "Run your workspace build or dev command to verify the new block transform registration."
456
+ ],
457
+ summaryLines: (values, projectDir) => [
458
+ `Block transform: ${values.transformSlug}`,
459
+ `From: ${values.fromBlockName}`,
460
+ `To: ${values.toBlockName}`,
461
+ `Project directory: ${projectDir}`
462
+ ],
463
+ title: "Added block transform"
464
+ },
465
+ description: "Add a block-to-block transform into a workspace block",
466
+ nameLabel: "Transform name",
467
+ async prepareExecution(context) {
468
+ 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>.");
469
+ const fromBlockName = readOptionalStringFlag(context.flags, "from");
470
+ if (!fromBlockName) {
471
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add transform` requires --from <namespace/block>.");
472
+ }
473
+ const toBlockName = readOptionalStringFlag(context.flags, "to");
474
+ if (!toBlockName) {
475
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
476
+ }
477
+ return {
478
+ execute: (cwd) => context.addRuntime.runAddBlockTransformCommand({
479
+ cwd,
480
+ fromBlockName,
481
+ toBlockName,
482
+ transformName: name
483
+ }),
484
+ getValues: (result) => ({
485
+ blockSlug: result.blockSlug,
486
+ fromBlockName: result.fromBlockName,
487
+ toBlockName: result.toBlockName,
488
+ transformSlug: result.transformSlug
489
+ })
490
+ };
491
+ },
492
+ sortOrder: 50,
493
+ supportsDryRun: true,
494
+ usage: "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]",
495
+ visibleFieldNames: () => ["kind", "name", "from", "to"]
496
+ }),
497
+ "rest-resource": defineAddKindRegistryEntry({
209
498
  completion: {
210
499
  nextSteps: (values) => [
211
500
  `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
@@ -221,9 +510,30 @@ var ADD_KIND_REGISTRY = {
221
510
  },
222
511
  description: "Add a plugin-level typed REST resource",
223
512
  nameLabel: "REST resource name",
513
+ async prepareExecution(context) {
514
+ 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>].");
515
+ const methods = readOptionalStringFlag(context.flags, "methods");
516
+ const namespace = readOptionalStringFlag(context.flags, "namespace");
517
+ return {
518
+ execute: (cwd) => context.addRuntime.runAddRestResourceCommand({
519
+ cwd,
520
+ methods,
521
+ namespace,
522
+ restResourceName: name
523
+ }),
524
+ getValues: (result) => ({
525
+ methods: result.methods.join(", "),
526
+ namespace: result.namespace,
527
+ restResourceSlug: result.restResourceSlug
528
+ })
529
+ };
530
+ },
531
+ sortOrder: 80,
532
+ supportsDryRun: true,
533
+ usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
224
534
  visibleFieldNames: () => ["kind", "name", "namespace", "methods"]
225
- },
226
- "ai-feature": {
535
+ }),
536
+ "ai-feature": defineAddKindRegistryEntry({
227
537
  completion: {
228
538
  nextSteps: (values) => [
229
539
  `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
@@ -238,9 +548,29 @@ var ADD_KIND_REGISTRY = {
238
548
  },
239
549
  description: "Add a server-owned WordPress AI feature endpoint",
240
550
  nameLabel: "AI feature name",
551
+ async prepareExecution(context) {
552
+ const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
553
+ const namespace = readOptionalStringFlag(context.flags, "namespace");
554
+ return {
555
+ execute: (cwd) => context.addRuntime.runAddAiFeatureCommand({
556
+ aiFeatureName: name,
557
+ cwd,
558
+ namespace
559
+ }),
560
+ getValues: (result) => ({
561
+ aiFeatureSlug: result.aiFeatureSlug,
562
+ namespace: result.namespace
563
+ }),
564
+ getWarnings: (result) => result.warnings,
565
+ warnLine: context.warnLine
566
+ };
567
+ },
568
+ sortOrder: 100,
569
+ supportsDryRun: true,
570
+ usage: "wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]",
241
571
  visibleFieldNames: () => ["kind", "name", "namespace"]
242
- },
243
- variation: {
572
+ }),
573
+ variation: defineAddKindRegistryEntry({
244
574
  completion: {
245
575
  nextSteps: (values) => [
246
576
  `Review src/blocks/${values.blockSlug}/variations/${values.variationSlug}.ts.`,
@@ -255,9 +585,37 @@ var ADD_KIND_REGISTRY = {
255
585
  },
256
586
  description: "Add a variation to an existing block",
257
587
  nameLabel: "Variation name",
588
+ async prepareExecution(context) {
589
+ const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
590
+ const blockSlug = readOptionalStringFlag(context.flags, "block");
591
+ if (!blockSlug) {
592
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia add variation` requires --block <block-slug>.");
593
+ }
594
+ return {
595
+ execute: (cwd) => context.addRuntime.runAddVariationCommand({
596
+ blockName: blockSlug,
597
+ cwd,
598
+ variationName: name
599
+ }),
600
+ getValues: (result) => ({
601
+ blockSlug: result.blockSlug,
602
+ variationSlug: result.variationSlug
603
+ })
604
+ };
605
+ },
606
+ sortOrder: 30,
607
+ supportsDryRun: true,
608
+ usage: "wp-typia add variation <name> --block <block-slug> [--dry-run]",
258
609
  visibleFieldNames: () => ["kind", "name", "block"]
259
- }
610
+ })
260
611
  };
612
+ var ADD_KIND_IDS = Object.keys(ADD_KIND_REGISTRY).sort((left, right) => ADD_KIND_REGISTRY[left].sortOrder - ADD_KIND_REGISTRY[right].sortOrder);
613
+ function isAddKindId(value) {
614
+ return typeof value === "string" && ADD_KIND_IDS.includes(value);
615
+ }
616
+ async function getAddKindExecutionPlan(kind, context) {
617
+ return ADD_KIND_REGISTRY[kind].prepareExecution(context);
618
+ }
261
619
  function buildAddKindCompletionDetails(kind, options) {
262
620
  const descriptor = ADD_KIND_REGISTRY[kind].completion;
263
621
  return {
@@ -272,6 +630,9 @@ function formatAddKindList() {
272
630
  function formatAddKindUsagePlaceholder() {
273
631
  return `<${ADD_KIND_IDS.join("|")}>`;
274
632
  }
633
+ function supportsAddKindDryRun(kind) {
634
+ return ADD_KIND_REGISTRY[kind].supportsDryRun;
635
+ }
275
636
 
276
637
  // src/runtime-bridge-add-dry-run.ts
277
638
  import fs2 from "fs";
@@ -435,6 +796,9 @@ function readAsciiPreferenceFromEnv(env) {
435
796
  }
436
797
  return;
437
798
  }
799
+ function hasNoColorPreference(env) {
800
+ return typeof env.NO_COLOR === "string" && env.NO_COLOR.length > 0;
801
+ }
438
802
  function prefersAsciiOutput(options = {}) {
439
803
  if (options.forceAscii) {
440
804
  return true;
@@ -444,6 +808,9 @@ function prefersAsciiOutput(options = {}) {
444
808
  if (envPreference !== undefined) {
445
809
  return envPreference;
446
810
  }
811
+ if (hasNoColorPreference(env)) {
812
+ return true;
813
+ }
447
814
  const term = options.term ?? env.TERM;
448
815
  if (term === "dumb") {
449
816
  return true;
@@ -509,6 +876,77 @@ ${payload.optionalTitle ?? "Optional:"}`);
509
876
  printLine(`Note: ${payload.optionalNote}`);
510
877
  }
511
878
  }
879
+ function toNonEmptyArray(values) {
880
+ return values && values.length > 0 ? values : undefined;
881
+ }
882
+ function extractPlannedFiles(payload) {
883
+ const files = payload.optionalLines?.map((line) => line.match(/^(?:delete|update|write)\s+(.+)$/u)?.[1]).filter((value) => typeof value === "string" && value.length > 0);
884
+ return toNonEmptyArray(files);
885
+ }
886
+ var PROJECT_DIRECTORY_SUMMARY_PREFIX = "Project directory: ";
887
+ function extractCompletionProjectDir(completion) {
888
+ const projectDir = completion?.summaryLines?.find((line) => line.startsWith(PROJECT_DIRECTORY_SUMMARY_PREFIX))?.slice(PROJECT_DIRECTORY_SUMMARY_PREFIX.length).trim();
889
+ return projectDir && projectDir.length > 0 ? projectDir : undefined;
890
+ }
891
+ function serializeCompletionPayload(payload) {
892
+ return {
893
+ nextSteps: toNonEmptyArray(payload.nextSteps),
894
+ optionalLines: toNonEmptyArray(payload.optionalLines),
895
+ optionalNote: payload.optionalNote,
896
+ optionalTitle: payload.optionalTitle,
897
+ preambleLines: toNonEmptyArray(payload.preambleLines),
898
+ summaryLines: toNonEmptyArray(payload.summaryLines),
899
+ title: stripLeadingOutputMarker(payload.title),
900
+ warningLines: toNonEmptyArray(payload.warningLines)
901
+ };
902
+ }
903
+ function buildStructuredCompletionSuccessPayload(command, completion, metadata = {}) {
904
+ const serializedCompletion = completion ? serializeCompletionPayload(completion) : undefined;
905
+ return {
906
+ ok: true,
907
+ data: {
908
+ ...metadata,
909
+ command,
910
+ ...serializedCompletion ? {
911
+ completion: serializedCompletion,
912
+ files: extractPlannedFiles(serializedCompletion),
913
+ nextSteps: serializedCompletion.nextSteps,
914
+ optionalLines: serializedCompletion.optionalLines,
915
+ optionalNote: serializedCompletion.optionalNote,
916
+ optionalTitle: serializedCompletion.optionalTitle,
917
+ preambleLines: serializedCompletion.preambleLines,
918
+ summaryLines: serializedCompletion.summaryLines,
919
+ title: serializedCompletion.title,
920
+ warnings: serializedCompletion.warningLines
921
+ } : {}
922
+ }
923
+ };
924
+ }
925
+ function buildStructuredInitSuccessPayload(plan) {
926
+ const completion = serializeCompletionPayload(buildInitCompletionPayload(plan));
927
+ const files = Array.from(new Set([
928
+ ...plan.plannedFiles.map((filePlan) => filePlan.path),
929
+ ...plan.commandMode === "preview-only" ? plan.generatedArtifacts : []
930
+ ]));
931
+ return {
932
+ ok: true,
933
+ data: {
934
+ command: "init",
935
+ completion,
936
+ detectedLayout: plan.detectedLayout,
937
+ files: toNonEmptyArray(files),
938
+ mode: plan.commandMode === "apply" ? "apply" : "preview",
939
+ nextSteps: toNonEmptyArray(plan.nextSteps),
940
+ packageManager: plan.packageManager,
941
+ plan,
942
+ projectDir: plan.projectDir,
943
+ status: plan.status,
944
+ summary: plan.summary,
945
+ title: completion.title,
946
+ warnings: toNonEmptyArray(plan.notes)
947
+ }
948
+ };
949
+ }
512
950
  function formatCreateProgressLine(payload, markerOptions) {
513
951
  return formatOutputMarker("progress", `${payload.title}: ${payload.detail}`, markerOptions);
514
952
  }
@@ -554,28 +992,31 @@ function buildCreateDryRunPayload(flow, markerOptions) {
554
992
  };
555
993
  }
556
994
  function buildInitCompletionPayload(plan, markerOptions) {
557
- const plannedChanges = [
995
+ const changeLines = [
558
996
  ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
559
997
  ...plan.packageChanges.packageManagerField ? [
560
998
  `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
561
999
  ] : [],
562
1000
  ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
563
- ...plan.plannedFiles.map((filePlan) => `file add ${filePlan.path} (${filePlan.purpose})`),
564
- ...plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`)
1001
+ ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
1002
+ ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
565
1003
  ];
1004
+ 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.";
1005
+ const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
1006
+ 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);
566
1007
  return {
567
1008
  nextSteps: plan.nextSteps,
568
- optionalLines: plannedChanges,
1009
+ optionalLines: changeLines,
569
1010
  optionalNote: plan.summary,
570
- optionalTitle: `Planned adoption changes (${plannedChanges.length}):`,
1011
+ optionalTitle,
571
1012
  summaryLines: [
572
1013
  `Project directory: ${plan.projectDir}`,
573
1014
  `Detected layout: ${plan.detectedLayout.description}`,
574
1015
  ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
575
1016
  `Package manager: ${plan.packageManager}`,
576
- "Mode: preview only; no files were written."
1017
+ modeLine
577
1018
  ],
578
- title: plan.status === "already-initialized" ? formatOutputMarker("success", `wp-typia init: ${plan.projectName} is already initialized`, markerOptions) : formatOutputMarker("dryRun", `Retrofit init plan for ${plan.projectName}`, markerOptions),
1019
+ title,
579
1020
  warningLines: plan.notes
580
1021
  };
581
1022
  }
@@ -664,16 +1105,16 @@ function printBlock(lines, printLine) {
664
1105
  printLine(line);
665
1106
  }
666
1107
  }
667
- function formatExternalLayerSelectHint(option2) {
1108
+ function formatExternalLayerSelectHint2(option2) {
668
1109
  const details = [
669
1110
  option2.description,
670
1111
  option2.extends.length > 0 ? `extends ${option2.extends.join(", ")}` : undefined
671
1112
  ].filter((value) => typeof value === "string" && value.length > 0);
672
1113
  return details.length > 0 ? details.join(" \xB7 ") : undefined;
673
1114
  }
674
- function toExternalLayerPromptOptions(options) {
1115
+ function toExternalLayerPromptOptions2(options) {
675
1116
  return options.map((option2) => ({
676
- hint: formatExternalLayerSelectHint(option2),
1117
+ hint: formatExternalLayerSelectHint2(option2),
677
1118
  label: option2.id,
678
1119
  value: option2.id
679
1120
  }));
@@ -709,7 +1150,7 @@ function resolveSyncExecutionTarget(subcommand) {
709
1150
  if (subcommand === "ai") {
710
1151
  return "ai";
711
1152
  }
712
- throw new Error(`Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
1153
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
713
1154
  }
714
1155
  function formatRunScript(packageManagerId, scriptName, extraArgs = "") {
715
1156
  const args = extraArgs.trim();
@@ -737,7 +1178,7 @@ function formatInstallCommand(packageManagerId) {
737
1178
  }
738
1179
  }
739
1180
  function getSyncRootError(cwd) {
740
- return new Error(`No generated wp-typia project root was found at ${cwd}. Run \`wp-typia sync\` from a scaffolded project or official workspace root that already contains generated sync scripts. If you expected this directory to work, cd into the scaffold root first or rerun the scaffold before syncing.`);
1181
+ return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.OUTSIDE_PROJECT_ROOT, `No generated wp-typia project root was found at ${cwd}. Run \`wp-typia sync\` from a scaffolded project or official workspace root that already contains generated sync scripts. If you expected this directory to work, cd into the scaffold root first or rerun the scaffold before syncing.`);
741
1182
  }
742
1183
  function inferSyncPackageManager(cwd, packageManagerField) {
743
1184
  const field = String(packageManagerField ?? "");
@@ -827,7 +1268,7 @@ function assertSyncDependenciesInstalled(project, target) {
827
1268
  if (markerDir) {
828
1269
  return;
829
1270
  }
830
- throw new Error(`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\`.`);
1271
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.DEPENDENCIES_NOT_INSTALLED, `Project dependencies have not been installed yet. Run \`${formatInstallCommand(project.packageManager)}\` from the project root before \`wp-typia sync\`. The generated sync scripts rely on local tools such as \`tsx\`.`);
831
1272
  }
832
1273
  function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
833
1274
  switch (packageManager) {
@@ -865,7 +1306,7 @@ function buildSyncPlannedCommands(project, extraArgs, target) {
865
1306
  if (target === "ai") {
866
1307
  const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
867
1308
  if (!syncAiCommand2) {
868
- throw new Error(`Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
1309
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
869
1310
  }
870
1311
  return [syncAiCommand2];
871
1312
  }
@@ -874,7 +1315,7 @@ function buildSyncPlannedCommands(project, extraArgs, target) {
874
1315
  }
875
1316
  const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
876
1317
  if (!syncTypesCommand) {
877
- throw new Error(`Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
1318
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
878
1319
  }
879
1320
  const plannedCommands = [syncTypesCommand];
880
1321
  const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
@@ -939,14 +1380,14 @@ async function executeSyncCommand({
939
1380
  }
940
1381
 
941
1382
  // src/runtime-bridge.ts
942
- var loadCliAddRuntime = () => import("./cli-add-6byyahb8.js");
943
- var loadCliDiagnosticsRuntime = () => import("./cli-diagnostics-zecc6w1f.js");
944
- var loadCliDoctorRuntime = () => import("./cli-doctor-2bc4sq7v.js");
945
- var loadCliInitRuntime = () => import("./cli-init-gdyp9enw.js");
1383
+ var loadCliAddRuntime = () => import("./cli-add-kjhghdqq.js");
1384
+ var loadCliDiagnosticsRuntime = () => import("./cli-diagnostics-5dvztm7q.js");
1385
+ var loadCliDoctorRuntime = () => import("./cli-doctor-p3jxvn0k.js");
1386
+ var loadCliInitRuntime = () => import("./cli-init-djhwr245.js");
946
1387
  var loadCliPromptRuntime = () => import("./cli-prompt-614tq57c.js");
947
- var loadCliScaffoldRuntime = () => import("./cli-scaffold-19gyvxxt.js");
1388
+ var loadCliScaffoldRuntime = () => import("./cli-scaffold-376yw891.js");
948
1389
  var loadCliTemplatesRuntime = () => import("./cli-templates-9t2a7zqd.js");
949
- var loadMigrationsRuntime = () => import("./migrations-1p6mbkyw.js");
1390
+ var loadMigrationsRuntime = () => import("./migrations-nwas5bwt.js");
950
1391
  async function wrapCliCommandError(command, error) {
951
1392
  const { createCliCommandError } = await loadCliDiagnosticsRuntime();
952
1393
  return createCliCommandError({ command, error });
@@ -960,23 +1401,13 @@ function shouldWrapCliCommandError(options) {
960
1401
  }
961
1402
  return true;
962
1403
  }
963
- function readOptionalStringFlag(flags, name) {
964
- const value = flags[name];
965
- if (value === undefined || value === null) {
966
- return;
967
- }
968
- if (typeof value !== "string" || value.trim().length === 0) {
969
- throw new Error(`\`--${name}\` requires a value.`);
970
- }
971
- return value;
972
- }
973
1404
  function readOptionalLooseStringFlag(flags, name) {
974
1405
  const value = flags[name];
975
1406
  if (value === undefined || value === null) {
976
1407
  return;
977
1408
  }
978
1409
  if (typeof value !== "string") {
979
- throw new Error(`\`--${name}\` requires a value.`);
1410
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
980
1411
  }
981
1412
  const trimmed = value.trim();
982
1413
  return trimmed.length > 0 ? trimmed : undefined;
@@ -991,223 +1422,6 @@ function pushFlag(argv, name, value) {
991
1422
  }
992
1423
  argv.push(`--${name}`, String(value));
993
1424
  }
994
- function requireAddKindName(context, message) {
995
- if (!context.name) {
996
- throw new Error(message);
997
- }
998
- return context.name;
999
- }
1000
- function runRegisteredAddKind(context, plan) {
1001
- return executeWorkspaceAddWithOptionalDryRun({
1002
- buildCompletion: plan.buildCompletion,
1003
- cwd: context.cwd,
1004
- dryRun: context.dryRun,
1005
- emitOutput: context.emitOutput,
1006
- execute: plan.execute,
1007
- printLine: context.printLine,
1008
- warnLine: plan.warnLine
1009
- });
1010
- }
1011
- var ADD_KIND_EXECUTION_REGISTRY = {
1012
- ability: async (context) => {
1013
- const name = requireAddKindName(context, "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.");
1014
- return runRegisteredAddKind(context, {
1015
- buildCompletion: (result) => buildAddCompletionPayload({
1016
- kind: "ability",
1017
- projectDir: result.projectDir,
1018
- values: {
1019
- abilitySlug: result.abilitySlug
1020
- }
1021
- }),
1022
- execute: (targetCwd) => context.addRuntime.runAddAbilityCommand({
1023
- abilityName: name,
1024
- cwd: targetCwd
1025
- })
1026
- });
1027
- },
1028
- "binding-source": async (context) => {
1029
- const name = requireAddKindName(context, "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name>.");
1030
- return runRegisteredAddKind(context, {
1031
- buildCompletion: (result) => buildAddCompletionPayload({
1032
- kind: "binding-source",
1033
- projectDir: result.projectDir,
1034
- values: {
1035
- bindingSourceSlug: result.bindingSourceSlug
1036
- }
1037
- }),
1038
- execute: (targetCwd) => context.addRuntime.runAddBindingSourceCommand({
1039
- bindingSourceName: name,
1040
- cwd: targetCwd
1041
- })
1042
- });
1043
- },
1044
- block: async (context) => {
1045
- const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
1046
- if (!context.flags.template && context.isInteractiveSession) {
1047
- throw new Error("`wp-typia add block` requires --template <basic|interactivity|persistence|compound> in interactive terminals. Non-interactive runs default to --template basic.");
1048
- }
1049
- const externalLayerId = readOptionalStringFlag(context.flags, "external-layer-id");
1050
- const externalLayerSource = readOptionalStringFlag(context.flags, "external-layer-source");
1051
- const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
1052
- const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
1053
- const alternateRenderTargets = readOptionalStringFlag(context.flags, "alternate-render-targets");
1054
- const dataStorageMode = readOptionalStringFlag(context.flags, "data-storage");
1055
- const innerBlocksPreset = readOptionalStringFlag(context.flags, "inner-blocks-preset");
1056
- const persistencePolicy = readOptionalStringFlag(context.flags, "persistence-policy");
1057
- const resolvedTemplateId = readOptionalStringFlag(context.flags, "template") ?? "basic";
1058
- return runRegisteredAddKind(context, {
1059
- buildCompletion: (result) => buildAddCompletionPayload({
1060
- kind: "block",
1061
- projectDir: result.projectDir,
1062
- values: {
1063
- blockSlugs: result.blockSlugs.join(", "),
1064
- templateId: result.templateId
1065
- },
1066
- warnings: result.warnings
1067
- }),
1068
- execute: (targetCwd) => context.addRuntime.runAddBlockCommand({
1069
- alternateRenderTargets,
1070
- blockName: name,
1071
- cwd: targetCwd,
1072
- dataStorageMode,
1073
- externalLayerId,
1074
- externalLayerSource,
1075
- innerBlocksPreset,
1076
- persistencePolicy,
1077
- selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
1078
- templateId: resolvedTemplateId
1079
- }),
1080
- warnLine: context.warnLine
1081
- });
1082
- },
1083
- "editor-plugin": async (context) => {
1084
- const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <PluginSidebar>].");
1085
- const slot = readOptionalStringFlag(context.flags, "slot");
1086
- return runRegisteredAddKind(context, {
1087
- buildCompletion: (result) => buildAddCompletionPayload({
1088
- kind: "editor-plugin",
1089
- projectDir: result.projectDir,
1090
- values: {
1091
- editorPluginSlug: result.editorPluginSlug,
1092
- slot: result.slot
1093
- }
1094
- }),
1095
- execute: (targetCwd) => context.addRuntime.runAddEditorPluginCommand({
1096
- cwd: targetCwd,
1097
- editorPluginName: name,
1098
- slot
1099
- })
1100
- });
1101
- },
1102
- "ai-feature": async (context) => {
1103
- const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
1104
- const namespace = readOptionalStringFlag(context.flags, "namespace");
1105
- return runRegisteredAddKind(context, {
1106
- buildCompletion: (result) => buildAddCompletionPayload({
1107
- kind: "ai-feature",
1108
- projectDir: result.projectDir,
1109
- values: {
1110
- aiFeatureSlug: result.aiFeatureSlug,
1111
- namespace: result.namespace
1112
- },
1113
- warnings: result.warnings
1114
- }),
1115
- execute: (targetCwd) => context.addRuntime.runAddAiFeatureCommand({
1116
- aiFeatureName: name,
1117
- cwd: targetCwd,
1118
- namespace
1119
- })
1120
- });
1121
- },
1122
- "hooked-block": async (context) => {
1123
- 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>.");
1124
- const anchorBlockName = readOptionalStringFlag(context.flags, "anchor");
1125
- if (!anchorBlockName) {
1126
- throw new Error("`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
1127
- }
1128
- const position = readOptionalStringFlag(context.flags, "position");
1129
- if (!position) {
1130
- throw new Error("`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
1131
- }
1132
- return runRegisteredAddKind(context, {
1133
- buildCompletion: (result) => buildAddCompletionPayload({
1134
- kind: "hooked-block",
1135
- projectDir: result.projectDir,
1136
- values: {
1137
- anchorBlockName: result.anchorBlockName,
1138
- blockSlug: result.blockSlug,
1139
- position: result.position
1140
- }
1141
- }),
1142
- execute: (targetCwd) => context.addRuntime.runAddHookedBlockCommand({
1143
- anchorBlockName,
1144
- blockName: name,
1145
- cwd: targetCwd,
1146
- position
1147
- })
1148
- });
1149
- },
1150
- pattern: async (context) => {
1151
- const name = requireAddKindName(context, "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.");
1152
- return runRegisteredAddKind(context, {
1153
- buildCompletion: (result) => buildAddCompletionPayload({
1154
- kind: "pattern",
1155
- projectDir: result.projectDir,
1156
- values: {
1157
- patternSlug: result.patternSlug
1158
- }
1159
- }),
1160
- execute: (targetCwd) => context.addRuntime.runAddPatternCommand({
1161
- cwd: targetCwd,
1162
- patternName: name
1163
- })
1164
- });
1165
- },
1166
- "rest-resource": async (context) => {
1167
- 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>].");
1168
- const methods = readOptionalStringFlag(context.flags, "methods");
1169
- const namespace = readOptionalStringFlag(context.flags, "namespace");
1170
- return runRegisteredAddKind(context, {
1171
- buildCompletion: (result) => buildAddCompletionPayload({
1172
- kind: "rest-resource",
1173
- projectDir: result.projectDir,
1174
- values: {
1175
- methods: result.methods.join(", "),
1176
- namespace: result.namespace,
1177
- restResourceSlug: result.restResourceSlug
1178
- }
1179
- }),
1180
- execute: (targetCwd) => context.addRuntime.runAddRestResourceCommand({
1181
- cwd: targetCwd,
1182
- methods,
1183
- namespace,
1184
- restResourceName: name
1185
- })
1186
- });
1187
- },
1188
- variation: async (context) => {
1189
- const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
1190
- const blockSlug = readOptionalStringFlag(context.flags, "block");
1191
- if (!blockSlug) {
1192
- throw new Error("`wp-typia add variation` requires --block <block-slug>.");
1193
- }
1194
- return runRegisteredAddKind(context, {
1195
- buildCompletion: (result) => buildAddCompletionPayload({
1196
- kind: "variation",
1197
- projectDir: result.projectDir,
1198
- values: {
1199
- blockSlug: result.blockSlug,
1200
- variationSlug: result.variationSlug
1201
- }
1202
- }),
1203
- execute: (targetCwd) => context.addRuntime.runAddVariationCommand({
1204
- blockName: blockSlug,
1205
- cwd: targetCwd,
1206
- variationName: name
1207
- })
1208
- });
1209
- }
1210
- };
1211
1425
  async function executeWorkspaceAddWithOptionalDryRun(options) {
1212
1426
  const simulated = options.dryRun ? await simulateWorkspaceAddDryRun({
1213
1427
  cwd: options.cwd,
@@ -1231,6 +1445,26 @@ async function executeWorkspaceAddWithOptionalDryRun(options) {
1231
1445
  warnLine: options.warnLine
1232
1446
  });
1233
1447
  }
1448
+ function executePreparedAddKind(kind, context, plan) {
1449
+ return executeWorkspaceAddWithOptionalDryRun({
1450
+ buildCompletion: (result) => buildAddCompletionPayload({
1451
+ kind,
1452
+ projectDir: result.projectDir,
1453
+ values: plan.getValues(result),
1454
+ warnings: plan.getWarnings?.(result)
1455
+ }),
1456
+ cwd: context.cwd,
1457
+ dryRun: context.dryRun,
1458
+ emitOutput: context.emitOutput,
1459
+ execute: plan.execute,
1460
+ printLine: context.printLine,
1461
+ warnLine: plan.warnLine
1462
+ });
1463
+ }
1464
+ async function executePlannedAddKind(kind, executionContext, context) {
1465
+ const plan = await getAddKindExecutionPlan(kind, executionContext);
1466
+ return executePreparedAddKind(kind, context, plan);
1467
+ }
1234
1468
  var PACKAGE_MANAGER_PROMPT_OPTIONS = [
1235
1469
  { label: "npm", value: "npm", hint: "Use npm" },
1236
1470
  { label: "pnpm", value: "pnpm", hint: "Use pnpm" },
@@ -1319,7 +1553,7 @@ async function executeCreateCommand({
1319
1553
  promptText: activePrompt ? (message, defaultValue, validate) => activePrompt.text(message, defaultValue, validate) : undefined,
1320
1554
  queryPostType: readOptionalLooseStringFlag(flags, "query-post-type"),
1321
1555
  selectDataStorage: activePrompt ? () => activePrompt.select("Select a data storage mode", [...DATA_STORAGE_PROMPT_OPTIONS], 1) : undefined,
1322
- selectExternalLayerId: shouldPromptForExternalLayerSelection && activePrompt ? (options) => activePrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
1556
+ selectExternalLayerId: shouldPromptForExternalLayerSelection && activePrompt ? (options) => activePrompt.select("Select an external layer", toExternalLayerPromptOptions2(options), 1) : undefined,
1323
1557
  selectPackageManager: activePrompt ? () => activePrompt.select("Select a package manager", [...PACKAGE_MANAGER_PROMPT_OPTIONS], 1) : undefined,
1324
1558
  selectPersistencePolicy: activePrompt ? () => activePrompt.select("Select a persistence policy", [...PERSISTENCE_POLICY_PROMPT_OPTIONS], 1) : undefined,
1325
1559
  selectTemplate: activePrompt ? () => activePrompt.select("Select a template", getTemplateSelectOptions(), 1) : undefined,
@@ -1372,16 +1606,17 @@ async function executeAddCommand({
1372
1606
  if (emitOutput) {
1373
1607
  printLine(addRuntime.formatAddHelpText());
1374
1608
  }
1375
- throw new Error(`\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`);
1609
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`);
1376
1610
  }
1377
1611
  if (!isAddKindId(kind)) {
1378
- throw new Error(`Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
1612
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
1379
1613
  }
1380
- return await ADD_KIND_EXECUTION_REGISTRY[kind]({
1614
+ if (dryRun && !supportsAddKindDryRun(kind)) {
1615
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
1616
+ }
1617
+ const executionContext = {
1381
1618
  addRuntime,
1382
1619
  cwd,
1383
- dryRun,
1384
- emitOutput,
1385
1620
  flags,
1386
1621
  getOrCreatePrompt: async () => {
1387
1622
  if (activePrompt) {
@@ -1393,8 +1628,13 @@ async function executeAddCommand({
1393
1628
  },
1394
1629
  isInteractiveSession,
1395
1630
  name,
1396
- printLine,
1397
1631
  warnLine
1632
+ };
1633
+ return await executePlannedAddKind(kind, executionContext, {
1634
+ cwd,
1635
+ dryRun,
1636
+ emitOutput,
1637
+ printLine
1398
1638
  });
1399
1639
  } catch (error) {
1400
1640
  if (!shouldWrapCliCommandError({ emitOutput })) {
@@ -1424,22 +1664,26 @@ async function executeTemplatesCommand({ flags }, printLine = console.log) {
1424
1664
  }
1425
1665
  if (subcommand === "inspect") {
1426
1666
  if (!flags.id) {
1427
- throw new Error("`wp-typia templates inspect` requires <template-id>.");
1667
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
1428
1668
  }
1429
1669
  const template = getTemplateById(flags.id);
1430
1670
  if (!template) {
1431
- throw new Error(`Unknown template "${flags.id}".`);
1671
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
1432
1672
  }
1433
1673
  printBlock([formatTemplateDetails(template)], printLine);
1434
1674
  return;
1435
1675
  }
1436
- throw new Error(`Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
1676
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
1437
1677
  }
1438
- async function executeInitCommand({ cwd, projectDir }, options = {}) {
1678
+ async function executeInitCommand({ apply, cwd, packageManager, projectDir }, options = {}) {
1439
1679
  try {
1440
- const { getInitPlan } = await loadCliInitRuntime();
1680
+ const { runInitCommand } = await loadCliInitRuntime();
1441
1681
  const resolvedProjectDir = projectDir ? (await import("path")).resolve(cwd, projectDir) : cwd;
1442
- const plan = getInitPlan(resolvedProjectDir);
1682
+ const plan = await runInitCommand({
1683
+ apply,
1684
+ packageManager,
1685
+ projectDir: resolvedProjectDir
1686
+ });
1443
1687
  const completion = buildInitCompletionPayload(plan);
1444
1688
  if (options.emitOutput ?? true) {
1445
1689
  printCompletionPayload(completion, {
@@ -1449,6 +1693,9 @@ async function executeInitCommand({ cwd, projectDir }, options = {}) {
1449
1693
  }
1450
1694
  return plan;
1451
1695
  } catch (error) {
1696
+ if (!shouldWrapCliCommandError({ emitOutput: options.emitOutput })) {
1697
+ throw error;
1698
+ }
1452
1699
  throw await wrapCliCommandError("init", error);
1453
1700
  }
1454
1701
  }
@@ -1946,7 +2193,7 @@ function loadAddFlow() {
1946
2193
  var addOptions = buildCommandOptions(ADD_OPTION_METADATA);
1947
2194
  var addCommand = defineCommand({
1948
2195
  defaultFormat: "toon",
1949
- description: "Extend an official wp-typia workspace with blocks, variations, patterns, binding sources, plugin-level REST resources, workflow abilities, server-only AI features, editor plugins, or hooked blocks.",
2196
+ description: "Extend an official wp-typia workspace with blocks, variations, block styles, transforms, patterns, binding sources, plugin-level REST resources, workflow abilities, server-only AI features, editor plugins, or hooked blocks.",
1950
2197
  handler: async (args) => {
1951
2198
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
1952
2199
  try {
@@ -1959,7 +2206,12 @@ var addCommand = defineCommand({
1959
2206
  kind: args.positional[0],
1960
2207
  name: args.positional[1]
1961
2208
  });
1962
- args.output({ completion });
2209
+ args.output(buildStructuredCompletionSuccessPayload("add", completion, {
2210
+ dryRun: Boolean(args.flags["dry-run"]),
2211
+ kind: args.positional[0],
2212
+ name: args.positional[1],
2213
+ projectDir: extractCompletionProjectDir(completion) ?? args.cwd
2214
+ }));
1963
2215
  return;
1964
2216
  }
1965
2217
  await executeAddCommand({
@@ -1994,7 +2246,7 @@ var addCommand = defineCommand({
1994
2246
  kind: args.positional[0] ?? "block",
1995
2247
  name: args.positional[1] ?? "",
1996
2248
  position: initialValues.position ?? "after",
1997
- slot: initialValues.slot ?? "PluginSidebar"
2249
+ slot: initialValues.slot ?? "sidebar"
1998
2250
  }
1999
2251
  }
2000
2252
  });
@@ -2023,9 +2275,11 @@ var createCommand = defineCommand({
2023
2275
  defaultFormat: "toon",
2024
2276
  description: "Scaffold a new wp-typia project.",
2025
2277
  handler: async (args) => {
2278
+ const prefersStructuredOutput = prefersStructuredCliOutput(args);
2026
2279
  const projectDir = args.positional[0];
2027
2280
  if (!projectDir) {
2028
2281
  emitCliDiagnosticFailure(args, {
2282
+ code: CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT,
2029
2283
  command: "create",
2030
2284
  detailLines: [
2031
2285
  "`wp-typia create` requires <project-dir>.",
@@ -2035,11 +2289,20 @@ var createCommand = defineCommand({
2035
2289
  return;
2036
2290
  }
2037
2291
  try {
2038
- await executeCreateCommand({
2292
+ const completion = await executeCreateCommand({
2039
2293
  cwd: args.cwd,
2294
+ emitOutput: !prefersStructuredOutput,
2040
2295
  flags: args.flags,
2296
+ interactive: prefersStructuredOutput ? false : undefined,
2041
2297
  projectDir
2042
2298
  });
2299
+ if (prefersStructuredOutput) {
2300
+ args.output(buildStructuredCompletionSuccessPayload("create", completion, {
2301
+ dryRun: Boolean(args.flags["dry-run"]),
2302
+ projectDir: extractCompletionProjectDir(completion) ?? projectDir,
2303
+ template: typeof args.flags.template === "string" ? args.flags.template : undefined
2304
+ }));
2305
+ }
2043
2306
  } catch (error) {
2044
2307
  emitCliDiagnosticFailure(args, {
2045
2308
  command: "create",
@@ -2083,8 +2346,8 @@ var doctorCommand = defineCommand({
2083
2346
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2084
2347
  if (prefersStructuredOutput) {
2085
2348
  const [{ getDoctorChecks }, { getDoctorFailureDetailLines }] = await Promise.all([
2086
- import("./cli-doctor-2bc4sq7v.js"),
2087
- import("./cli-diagnostics-zecc6w1f.js")
2349
+ import("./cli-doctor-p3jxvn0k.js"),
2350
+ import("./cli-diagnostics-5dvztm7q.js")
2088
2351
  ]);
2089
2352
  const checks = await getDoctorChecks(args.cwd);
2090
2353
  if (checks.some((check) => check.status === "fail")) {
@@ -2109,22 +2372,25 @@ var doctorCommand = defineCommand({
2109
2372
  });
2110
2373
  }
2111
2374
  },
2112
- name: "doctor"
2375
+ name: "doctor",
2376
+ options: buildCommandOptions(DOCTOR_OPTION_METADATA)
2113
2377
  });
2114
2378
 
2115
2379
  // src/commands/init.ts
2116
2380
  var initCommand = defineCommand({
2117
2381
  defaultFormat: "toon",
2118
- description: "Preview the minimum wp-typia retrofit plan for an existing project.",
2382
+ description: "Preview or apply the minimum wp-typia retrofit plan for an existing project.",
2119
2383
  handler: async (args) => {
2120
2384
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2121
2385
  try {
2122
2386
  const plan = await executeInitCommand({
2387
+ apply: Boolean(args.flags.apply),
2123
2388
  cwd: args.cwd,
2389
+ packageManager: typeof args.flags["package-manager"] === "string" ? args.flags["package-manager"] : undefined,
2124
2390
  projectDir: args.positional[0]
2125
2391
  }, { emitOutput: !prefersStructuredOutput });
2126
2392
  if (prefersStructuredOutput) {
2127
- args.output({ init: plan });
2393
+ args.output(buildStructuredInitSuccessPayload(plan));
2128
2394
  }
2129
2395
  } catch (error) {
2130
2396
  emitCliDiagnosticFailure(args, {
@@ -2134,7 +2400,7 @@ var initCommand = defineCommand({
2134
2400
  }
2135
2401
  },
2136
2402
  name: "init",
2137
- options: {}
2403
+ options: buildCommandOptions(INIT_OPTION_METADATA)
2138
2404
  });
2139
2405
 
2140
2406
  // src/mcp.ts
@@ -2934,18 +3200,19 @@ var templatesCommand = defineCommand({
2934
3200
  });
2935
3201
 
2936
3202
  // src/command-list.ts
2937
- var wpTypiaCommands = [
2938
- createCommand,
2939
- initCommand,
2940
- syncCommand,
2941
- addCommand,
2942
- migrateCommand,
2943
- templatesCommand,
2944
- doctorCommand,
2945
- mcpCommand
2946
- ];
3203
+ var WP_TYPIA_COMMANDS_BY_NAME = {
3204
+ add: addCommand,
3205
+ create: createCommand,
3206
+ doctor: doctorCommand,
3207
+ init: initCommand,
3208
+ mcp: mcpCommand,
3209
+ migrate: migrateCommand,
3210
+ sync: syncCommand,
3211
+ templates: templatesCommand
3212
+ };
3213
+ var wpTypiaCommands = WP_TYPIA_TOP_LEVEL_COMMAND_NAMES.map((commandName) => WP_TYPIA_COMMANDS_BY_NAME[commandName]);
2947
3214
  export {
2948
3215
  wpTypiaCommands
2949
3216
  };
2950
3217
 
2951
- //# debugId=F507311661D3283E64756E2164756E21
3218
+ //# debugId=45C7A2D5B9B34F8064756E2164756E21