wp-typia 0.22.8 → 0.22.9

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.
@@ -17,7 +17,7 @@ import {
17
17
  package_default,
18
18
  prefersStructuredCliOutput,
19
19
  resolveCommandOptionValues
20
- } from "./cli-e7n7hbvr.js";
20
+ } from "./cli-y934dq2k.js";
21
21
  import {
22
22
  Result,
23
23
  TaggedError,
@@ -42,10 +42,12 @@ import {
42
42
  createCliDiagnosticCodeError
43
43
  } from "./cli-p95wr1q8.js";
44
44
  import {
45
+ PACKAGE_MANAGER_IDS,
45
46
  formatInstallCommand,
46
47
  formatPackageExecCommand,
47
48
  formatRunScript,
48
- inferPackageManagerId
49
+ inferPackageManagerId,
50
+ parsePackageManagerField
49
51
  } from "./cli-52ke0ptp.js";
50
52
  import {
51
53
  __require,
@@ -67,7 +69,7 @@ function resolveBundledModuleHref(baseUrl, candidates, options = {}) {
67
69
  }
68
70
  const missingCandidates = candidates.map((candidate) => fileURLToPath(new URL(candidate, baseUrl)));
69
71
  const label = options.moduleLabel ?? "bundled wp-typia runtime module";
70
- throw new Error([
72
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_BUILD_ARTIFACT, [
71
73
  `Missing bundled build artifacts for ${label}.`,
72
74
  "None of the expected files were found:",
73
75
  ...missingCandidates.map((candidatePath) => `- ${candidatePath}`),
@@ -76,63 +78,7 @@ function resolveBundledModuleHref(baseUrl, candidates, options = {}) {
76
78
  `));
77
79
  }
78
80
 
79
- // src/cli-string-flags.ts
80
- function readOptionalCliStringFlagValue(flags, name, mode) {
81
- const value = flags[name];
82
- if (value === undefined || value === null) {
83
- return;
84
- }
85
- if (typeof value !== "string") {
86
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
87
- }
88
- const trimmed = value.trim();
89
- if (trimmed.length === 0) {
90
- if (mode === "strict") {
91
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
92
- }
93
- return;
94
- }
95
- return mode === "strict" ? value : trimmed;
96
- }
97
- function readOptionalLooseStringFlag(flags, name) {
98
- return readOptionalCliStringFlagValue(flags, name, "loose");
99
- }
100
- function readOptionalStrictStringFlag(flags, name) {
101
- return readOptionalCliStringFlagValue(flags, name, "strict");
102
- }
103
- function requireStrictStringFlag(flags, name, message) {
104
- const value = readOptionalStrictStringFlag(flags, name);
105
- if (!value) {
106
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
107
- }
108
- return value;
109
- }
110
- function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message) {
111
- const leftValue = readOptionalStrictStringFlag(flags, leftName);
112
- const rightValue = readOptionalStrictStringFlag(flags, rightName);
113
- if (Boolean(leftValue) !== Boolean(rightValue)) {
114
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
115
- }
116
- return [leftValue, rightValue];
117
- }
118
-
119
- // src/external-layer-prompt-options.ts
120
- function formatExternalLayerSelectHint(option2) {
121
- const details = [
122
- option2.description,
123
- option2.extends.length > 0 ? `extends ${option2.extends.join(", ")}` : undefined
124
- ].filter((value) => typeof value === "string" && value.length > 0);
125
- return details.length > 0 ? details.join(" \xB7 ") : undefined;
126
- }
127
- function toExternalLayerPromptOptions(options) {
128
- return options.map((option2) => ({
129
- hint: formatExternalLayerSelectHint(option2),
130
- label: option2.id,
131
- value: option2.id
132
- }));
133
- }
134
-
135
- // src/add-kind-registry.ts
81
+ // src/add-kind-registry-shared.ts
136
82
  var BLOCK_VISIBLE_FIELD_ORDER = [
137
83
  "kind",
138
84
  "name",
@@ -214,509 +160,614 @@ function isAddPersistenceTemplate(template) {
214
160
  function formatAddBlockTemplateIds(addRuntime) {
215
161
  return addRuntime.ADD_BLOCK_TEMPLATE_IDS.join(", ");
216
162
  }
163
+ function getMistypedAddBlockTemplateMessage(addRuntime, templateId) {
164
+ const suggestion = addRuntime.suggestAddBlockTemplateId(templateId);
165
+ if (!suggestion) {
166
+ return null;
167
+ }
168
+ return `Unknown add-block template "${templateId}". Did you mean "${suggestion}"? Use \`--template ${suggestion}\`, or run \`wp-typia templates list\` to inspect available templates.`;
169
+ }
217
170
  function assertAddBlockTemplateId(context, templateId) {
171
+ if (templateId === "query-loop") {
172
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "`wp-typia add block --template query-loop` is not supported. Query Loop is a create-time `core/query` variation scaffold, so use `wp-typia create <project-dir> --template query-loop` instead.");
173
+ }
218
174
  if (context.addRuntime.isAddBlockTemplateId(templateId)) {
219
175
  return templateId;
220
176
  }
221
- if (templateId === "query-loop") {
222
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "`wp-typia add block --template query-loop` is not supported. Query Loop is a create-time `core/query` variation scaffold, so use `wp-typia create <project-dir> --template query-loop` instead.");
177
+ const mistypedAddBlockTemplateMessage = getMistypedAddBlockTemplateMessage(context.addRuntime, templateId);
178
+ if (mistypedAddBlockTemplateMessage) {
179
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, mistypedAddBlockTemplateMessage);
223
180
  }
224
181
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, `Unknown add-block template "${templateId}". Expected one of: ${formatAddBlockTemplateIds(context.addRuntime)}. Run \`wp-typia templates list\` to inspect available templates.`);
225
182
  }
226
- var ADD_KIND_REGISTRY = {
227
- "admin-view": defineAddKindRegistryEntry({
228
- completion: {
229
- nextSteps: (values) => [
230
- `Review src/admin-views/${values.adminViewSlug}/ and inc/admin-views/${values.adminViewSlug}.php.`,
231
- "Run your workspace build or dev command to verify the generated DataViews admin screen."
232
- ],
233
- summaryLines: (values, projectDir) => [
234
- `Admin view: ${values.adminViewSlug}`,
235
- ...values.source ? [`Source: ${values.source}`] : [],
236
- `Project directory: ${projectDir}`
237
- ],
238
- title: "Added DataViews admin screen"
239
- },
240
- description: "Add an opt-in DataViews-powered admin screen",
241
- nameLabel: "Admin view name",
242
- async prepareExecution(context) {
243
- 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>].");
244
- const source = readOptionalStrictStringFlag(context.flags, "source");
245
- return createNamedExecutionPlan(context, {
246
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
247
- adminViewName: name2,
248
- cwd,
249
- source
250
- }),
251
- getValues: (result) => ({
252
- adminViewSlug: result.adminViewSlug,
253
- ...result.source ? { source: result.source } : {}
254
- }),
255
- missingNameMessage: "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].",
256
- name
257
- });
258
- },
259
- sortOrder: 10,
260
- supportsDryRun: true,
261
- usage: "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]",
262
- visibleFieldNames: () => NAME_SOURCE_VISIBLE_FIELDS
263
- }),
264
- "binding-source": defineAddKindRegistryEntry({
265
- completion: {
266
- nextSteps: (values) => [
267
- `Review src/bindings/${values.bindingSourceSlug}/server.php and src/bindings/${values.bindingSourceSlug}/editor.ts.`,
268
- ...values.blockSlug && values.attributeName ? [
269
- `Review src/blocks/${values.blockSlug}/block.json for the ${values.attributeName} bindable attribute.`
270
- ] : [],
271
- "Run your workspace build or dev command to verify the binding source hooks and editor registration."
272
- ],
273
- summaryLines: (values, projectDir) => [
274
- `Binding source: ${values.bindingSourceSlug}`,
275
- ...values.blockSlug && values.attributeName ? [`Target: ${values.blockSlug}.${values.attributeName}`] : [],
276
- `Project directory: ${projectDir}`
277
- ],
278
- title: "Added binding source"
279
- },
280
- description: "Add a shared block bindings source",
281
- nameLabel: "Binding source name",
282
- async prepareExecution(context) {
283
- 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>].");
284
- const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
285
- return createNamedExecutionPlan(context, {
286
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
287
- attributeName,
288
- bindingSourceName: name2,
289
- blockName,
290
- cwd
291
- }),
292
- getValues: (result) => ({
293
- ...result.attributeName ? { attributeName: result.attributeName } : {},
294
- ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
295
- bindingSourceSlug: result.bindingSourceSlug
296
- }),
297
- missingNameMessage: "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].",
298
- name
299
- });
300
- },
301
- sortOrder: 70,
302
- supportsDryRun: true,
303
- usage: "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--dry-run]",
304
- visibleFieldNames: () => NAME_BLOCK_ATTRIBUTE_VISIBLE_FIELDS
305
- }),
306
- block: defineAddKindRegistryEntry({
307
- completion: {
308
- nextSteps: () => [
309
- "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
310
- "Run your workspace build or dev command to verify the new scaffolded block family."
311
- ],
312
- summaryLines: (values, projectDir) => [
313
- `Blocks: ${values.blockSlugs}`,
314
- `Template family: ${values.templateId}`,
315
- `Project directory: ${projectDir}`
316
- ],
317
- title: "Added workspace block"
318
- },
319
- description: "Add a real block slice",
320
- hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
321
- nameLabel: "Block name",
322
- async prepareExecution(context) {
323
- const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
324
- const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
325
- const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
326
- const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
327
- const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
328
- const alternateRenderTargets = readOptionalStrictStringFlag(context.flags, "alternate-render-targets");
329
- const dataStorageMode = readOptionalStrictStringFlag(context.flags, "data-storage");
330
- const innerBlocksPreset = readOptionalStrictStringFlag(context.flags, "inner-blocks-preset");
331
- const persistencePolicy = readOptionalStrictStringFlag(context.flags, "persistence-policy");
332
- const requestedTemplateId = readOptionalStrictStringFlag(context.flags, "template");
333
- let resolvedTemplateId = requestedTemplateId ? assertAddBlockTemplateId(context, requestedTemplateId) : undefined;
334
- if (!resolvedTemplateId && context.isInteractiveSession) {
335
- const templatePrompt = await context.getOrCreatePrompt();
336
- resolvedTemplateId = await templatePrompt.select("Select a block template", context.addRuntime.ADD_BLOCK_TEMPLATE_IDS.map((templateId) => ({
337
- hint: `Scaffold the ${templateId} block family`,
338
- label: templateId,
339
- value: templateId
340
- })), 1);
341
- }
342
- resolvedTemplateId ??= "basic";
343
- return createNamedExecutionPlan(context, {
344
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockCommand({
345
- alternateRenderTargets,
346
- blockName: name2,
347
- cwd,
348
- dataStorageMode,
349
- externalLayerId,
350
- externalLayerSource,
351
- innerBlocksPreset,
352
- persistencePolicy,
353
- selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
354
- templateId: resolvedTemplateId
355
- }),
356
- getValues: (result) => ({
357
- blockSlugs: result.blockSlugs.join(", "),
358
- templateId: result.templateId
359
- }),
360
- getWarnings: (result) => result.warnings,
361
- missingNameMessage: "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]",
362
- name,
363
- warnLine: context.warnLine
364
- });
365
- },
366
- sortOrder: 20,
367
- supportsDryRun: true,
368
- 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]",
369
- visibleFieldNames: ({ template }) => BLOCK_VISIBLE_FIELD_ORDER.filter((fieldName) => {
370
- if (fieldName === "alternate-render-targets") {
371
- return isAddPersistenceTemplate(template);
372
- }
373
- if (fieldName === "inner-blocks-preset") {
374
- return template === "compound";
375
- }
376
- if (fieldName === "data-storage" || fieldName === "persistence-policy") {
377
- return isAddPersistenceTemplate(template);
378
- }
379
- return true;
380
- })
381
- }),
382
- ability: defineAddKindRegistryEntry({
383
- completion: {
384
- nextSteps: (values) => [
385
- `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
386
- "Run `wp-typia sync` or `npm run sync-abilities -- --check` and then your workspace build/dev command to verify the generated workflow ability."
387
- ],
388
- summaryLines: (values, projectDir) => [
389
- `Ability: ${values.abilitySlug}`,
390
- `Project directory: ${projectDir}`
391
- ],
392
- title: "Added workflow ability"
393
- },
394
- description: "Add a typed server/client workflow ability scaffold",
395
- nameLabel: "Ability name",
396
- async prepareExecution(context) {
397
- return createNamedExecutionPlan(context, {
398
- execute: ({ cwd, name }) => context.addRuntime.runAddAbilityCommand({
399
- abilityName: name,
400
- cwd
401
- }),
402
- getValues: (result) => ({
403
- abilitySlug: result.abilitySlug
404
- }),
405
- getWarnings: (result) => result.warnings,
406
- missingNameMessage: "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.",
407
- warnLine: context.warnLine
408
- });
409
- },
410
- sortOrder: 90,
411
- supportsDryRun: true,
412
- usage: "wp-typia add ability <name> [--dry-run]",
413
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
414
- }),
415
- "editor-plugin": defineAddKindRegistryEntry({
416
- completion: {
417
- nextSteps: (values) => [
418
- `Review src/editor-plugins/${values.editorPluginSlug}/.`,
419
- "Run your workspace build or dev command to verify the new editor plugin registration."
420
- ],
421
- summaryLines: (values, projectDir) => [
422
- `Editor plugin: ${values.editorPluginSlug}`,
423
- `Slot: ${values.slot}`,
424
- `Project directory: ${projectDir}`
425
- ],
426
- title: "Added editor plugin"
427
- },
428
- description: "Add a slot-aware document editor extension shell",
429
- nameLabel: "Editor plugin name",
430
- async prepareExecution(context) {
431
- const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].");
432
- const slot = readOptionalStrictStringFlag(context.flags, "slot");
433
- return createNamedExecutionPlan(context, {
434
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
435
- cwd,
436
- editorPluginName: name2,
437
- slot
438
- }),
439
- getValues: (result) => ({
440
- editorPluginSlug: result.editorPluginSlug,
441
- slot: result.slot
442
- }),
443
- missingNameMessage: "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].",
444
- name
445
- });
446
- },
447
- sortOrder: 120,
448
- supportsDryRun: true,
449
- usage: "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>] [--dry-run]",
450
- visibleFieldNames: () => NAME_SLOT_VISIBLE_FIELDS
451
- }),
452
- "hooked-block": defineAddKindRegistryEntry({
453
- completion: {
454
- nextSteps: (values) => [
455
- `Review src/blocks/${values.blockSlug}/block.json for the new blockHooks entry.`,
456
- "Run your workspace build or dev command to verify the updated hooked-block metadata."
457
- ],
458
- summaryLines: (values, projectDir) => [
459
- `Block: ${values.blockSlug}`,
460
- `Anchor: ${values.anchorBlockName}`,
461
- `Position: ${values.position}`,
462
- `Project directory: ${projectDir}`
463
- ],
464
- title: "Added blockHooks metadata"
465
- },
466
- description: "Add block.json hook metadata to an existing block",
467
- nameLabel: "Target block",
468
- async prepareExecution(context) {
469
- 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>.");
470
- const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
471
- const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
472
- return createNamedExecutionPlan(context, {
473
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddHookedBlockCommand({
474
- anchorBlockName,
475
- blockName: name2,
476
- cwd,
477
- position
478
- }),
479
- getValues: (result) => ({
480
- anchorBlockName: result.anchorBlockName,
481
- blockSlug: result.blockSlug,
482
- position: result.position
483
- }),
484
- 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>.",
485
- name
486
- });
487
- },
488
- sortOrder: 110,
489
- supportsDryRun: true,
490
- usage: "wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild> [--dry-run]",
491
- visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
492
- }),
493
- pattern: defineAddKindRegistryEntry({
494
- completion: {
495
- nextSteps: (values) => [
496
- `Review src/patterns/${values.patternSlug}.php.`,
497
- "Run your workspace build or dev command to verify the new pattern registration."
498
- ],
499
- summaryLines: (values, projectDir) => [
500
- `Pattern: ${values.patternSlug}`,
501
- `Project directory: ${projectDir}`
502
- ],
503
- title: "Added workspace pattern"
504
- },
505
- description: "Add a PHP block pattern shell",
506
- nameLabel: "Pattern name",
507
- async prepareExecution(context) {
508
- return createNamedExecutionPlan(context, {
509
- execute: ({ cwd, name }) => context.addRuntime.runAddPatternCommand({
510
- cwd,
511
- patternName: name
512
- }),
513
- getValues: (result) => ({
514
- patternSlug: result.patternSlug
515
- }),
516
- missingNameMessage: "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>."
517
- });
518
- },
519
- sortOrder: 60,
520
- supportsDryRun: true,
521
- usage: "wp-typia add pattern <name> [--dry-run]",
522
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
523
- }),
524
- style: defineAddKindRegistryEntry({
525
- completion: {
526
- nextSteps: (values) => [
527
- `Review src/blocks/${values.blockSlug}/styles/${values.styleSlug}.ts.`,
528
- "Run your workspace build or dev command to verify the new block style registration."
529
- ],
530
- summaryLines: (values, projectDir) => [
531
- `Block style: ${values.styleSlug}`,
532
- `Target block: ${values.blockSlug}`,
533
- `Project directory: ${projectDir}`
534
- ],
535
- title: "Added block style"
536
- },
537
- description: "Add a Block Styles registration to an existing block",
538
- nameLabel: "Style name",
539
- async prepareExecution(context) {
540
- const name = requireAddKindName(context, "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.");
541
- const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
542
- return createNamedExecutionPlan(context, {
543
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
544
- blockName: blockSlug,
545
- cwd,
546
- styleName: name2
547
- }),
548
- getValues: (result) => ({
549
- blockSlug: result.blockSlug,
550
- styleSlug: result.styleSlug
551
- }),
552
- missingNameMessage: "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.",
553
- name
554
- });
555
- },
556
- sortOrder: 40,
557
- supportsDryRun: true,
558
- usage: "wp-typia add style <name> --block <block-slug> [--dry-run]",
559
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
560
- }),
561
- transform: defineAddKindRegistryEntry({
562
- completion: {
563
- nextSteps: (values) => [
564
- `Review src/blocks/${values.blockSlug}/transforms/${values.transformSlug}.ts.`,
565
- "Run your workspace build or dev command to verify the new block transform registration."
566
- ],
567
- summaryLines: (values, projectDir) => [
568
- `Block transform: ${values.transformSlug}`,
569
- `From: ${values.fromBlockName}`,
570
- `To: ${values.toBlockName}`,
571
- `Project directory: ${projectDir}`
572
- ],
573
- title: "Added block transform"
574
- },
575
- description: "Add a block-to-block transform into a workspace block",
576
- nameLabel: "Transform name",
577
- async prepareExecution(context) {
578
- 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>.");
579
- const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
580
- const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
581
- return createNamedExecutionPlan(context, {
582
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockTransformCommand({
583
- cwd,
584
- fromBlockName,
585
- toBlockName,
586
- transformName: name2
587
- }),
588
- getValues: (result) => ({
589
- blockSlug: result.blockSlug,
590
- fromBlockName: result.fromBlockName,
591
- toBlockName: result.toBlockName,
592
- transformSlug: result.transformSlug
593
- }),
594
- missingNameMessage: "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.",
595
- name
596
- });
597
- },
598
- sortOrder: 50,
599
- supportsDryRun: true,
600
- usage: "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]",
601
- visibleFieldNames: () => NAME_FROM_TO_VISIBLE_FIELDS
602
- }),
603
- "rest-resource": defineAddKindRegistryEntry({
604
- completion: {
605
- nextSteps: (values) => [
606
- `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
607
- "Run your workspace build or dev command to verify the generated REST resource contract."
608
- ],
609
- summaryLines: (values, projectDir) => [
610
- `REST resource: ${values.restResourceSlug}`,
611
- `Namespace: ${values.namespace}`,
612
- `Methods: ${values.methods}`,
613
- `Project directory: ${projectDir}`
614
- ],
615
- title: "Added plugin-level REST resource"
616
- },
617
- description: "Add a plugin-level typed REST resource",
618
- nameLabel: "REST resource name",
619
- async prepareExecution(context) {
620
- 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>].");
621
- const methods = readOptionalStrictStringFlag(context.flags, "methods");
622
- const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
623
- return createNamedExecutionPlan(context, {
624
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
625
- cwd,
626
- methods,
627
- namespace,
628
- restResourceName: name2
629
- }),
630
- getValues: (result) => ({
631
- methods: result.methods.join(", "),
632
- namespace: result.namespace,
633
- restResourceSlug: result.restResourceSlug
634
- }),
635
- missingNameMessage: "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create>].",
636
- name
637
- });
638
- },
639
- sortOrder: 80,
640
- supportsDryRun: true,
641
- usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
642
- visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
643
- }),
644
- "ai-feature": defineAddKindRegistryEntry({
645
- completion: {
646
- nextSteps: (values) => [
647
- `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
648
- "Run `wp-typia sync-rest` and `wp-typia sync ai` or your workspace build/dev command to verify the generated REST artifacts and AI schema."
649
- ],
650
- summaryLines: (values, projectDir) => [
651
- `AI feature: ${values.aiFeatureSlug}`,
652
- `Namespace: ${values.namespace}`,
653
- `Project directory: ${projectDir}`
654
- ],
655
- title: "Added server-only AI feature"
656
- },
657
- description: "Add a server-owned WordPress AI feature endpoint",
658
- nameLabel: "AI feature name",
659
- async prepareExecution(context) {
660
- const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
661
- const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
662
- return createNamedExecutionPlan(context, {
663
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
664
- aiFeatureName: name2,
665
- cwd,
666
- namespace
667
- }),
668
- getValues: (result) => ({
669
- aiFeatureSlug: result.aiFeatureSlug,
670
- namespace: result.namespace
671
- }),
672
- getWarnings: (result) => result.warnings,
673
- missingNameMessage: "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].",
674
- name,
675
- warnLine: context.warnLine
676
- });
677
- },
678
- sortOrder: 100,
679
- supportsDryRun: true,
680
- usage: "wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]",
681
- visibleFieldNames: () => NAME_NAMESPACE_VISIBLE_FIELDS
682
- }),
683
- variation: defineAddKindRegistryEntry({
684
- completion: {
685
- nextSteps: (values) => [
686
- `Review src/blocks/${values.blockSlug}/variations/${values.variationSlug}.ts.`,
687
- "Run your workspace build or dev command to pick up the new variation."
688
- ],
689
- summaryLines: (values, projectDir) => [
690
- `Variation: ${values.variationSlug}`,
691
- `Target block: ${values.blockSlug}`,
692
- `Project directory: ${projectDir}`
693
- ],
694
- title: "Added workspace variation"
695
- },
696
- description: "Add a variation to an existing block",
697
- nameLabel: "Variation name",
698
- async prepareExecution(context) {
699
- const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
700
- const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
701
- return createNamedExecutionPlan(context, {
702
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
703
- blockName: blockSlug,
704
- cwd,
705
- variationName: name2
706
- }),
707
- getValues: (result) => ({
708
- blockSlug: result.blockSlug,
709
- variationSlug: result.variationSlug
710
- }),
711
- missingNameMessage: "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>",
712
- name
713
- });
714
- },
715
- sortOrder: 30,
716
- supportsDryRun: true,
717
- usage: "wp-typia add variation <name> --block <block-slug> [--dry-run]",
718
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
183
+
184
+ // src/add-kinds/ability.ts
185
+ var abilityAddKindEntry = defineAddKindRegistryEntry({
186
+ completion: {
187
+ nextSteps: (values) => [
188
+ `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
189
+ "Run `wp-typia sync` or `npm run sync-abilities -- --check` and then your workspace build/dev command to verify the generated workflow ability."
190
+ ],
191
+ summaryLines: (values, projectDir) => [
192
+ `Ability: ${values.abilitySlug}`,
193
+ `Project directory: ${projectDir}`
194
+ ],
195
+ title: "Added workflow ability"
196
+ },
197
+ description: "Add a typed server/client workflow ability scaffold",
198
+ nameLabel: "Ability name",
199
+ async prepareExecution(context) {
200
+ return createNamedExecutionPlan(context, {
201
+ execute: ({ cwd, name }) => context.addRuntime.runAddAbilityCommand({
202
+ abilityName: name,
203
+ cwd
204
+ }),
205
+ getValues: (result) => ({
206
+ abilitySlug: result.abilitySlug
207
+ }),
208
+ getWarnings: (result) => result.warnings,
209
+ missingNameMessage: "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.",
210
+ warnLine: context.warnLine
211
+ });
212
+ },
213
+ sortOrder: 90,
214
+ supportsDryRun: true,
215
+ usage: "wp-typia add ability <name> [--dry-run]",
216
+ visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
217
+ });
218
+
219
+ // src/cli-string-flags.ts
220
+ function readOptionalCliStringFlagValue(flags, name, mode) {
221
+ const value = flags[name];
222
+ if (value === undefined || value === null) {
223
+ return;
224
+ }
225
+ if (typeof value !== "string") {
226
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
227
+ }
228
+ const trimmed = value.trim();
229
+ if (trimmed.length === 0) {
230
+ if (mode === "strict") {
231
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
232
+ }
233
+ return;
234
+ }
235
+ return mode === "strict" ? value : trimmed;
236
+ }
237
+ function readOptionalLooseStringFlag(flags, name) {
238
+ return readOptionalCliStringFlagValue(flags, name, "loose");
239
+ }
240
+ function readOptionalStrictStringFlag(flags, name) {
241
+ return readOptionalCliStringFlagValue(flags, name, "strict");
242
+ }
243
+ function requireStrictStringFlag(flags, name, message) {
244
+ const value = readOptionalStrictStringFlag(flags, name);
245
+ if (!value) {
246
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
247
+ }
248
+ return value;
249
+ }
250
+ function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message) {
251
+ const leftValue = readOptionalStrictStringFlag(flags, leftName);
252
+ const rightValue = readOptionalStrictStringFlag(flags, rightName);
253
+ if (Boolean(leftValue) !== Boolean(rightValue)) {
254
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
255
+ }
256
+ return [leftValue, rightValue];
257
+ }
258
+
259
+ // src/add-kinds/admin-view.ts
260
+ var adminViewAddKindEntry = defineAddKindRegistryEntry({
261
+ completion: {
262
+ nextSteps: (values) => [
263
+ `Review src/admin-views/${values.adminViewSlug}/ and inc/admin-views/${values.adminViewSlug}.php.`,
264
+ "Run your workspace build or dev command to verify the generated DataViews admin screen."
265
+ ],
266
+ summaryLines: (values, projectDir) => [
267
+ `Admin view: ${values.adminViewSlug}`,
268
+ ...values.source ? [`Source: ${values.source}`] : [],
269
+ `Project directory: ${projectDir}`
270
+ ],
271
+ title: "Added DataViews admin screen"
272
+ },
273
+ description: "Add an opt-in DataViews-powered admin screen",
274
+ nameLabel: "Admin view name",
275
+ async prepareExecution(context) {
276
+ const name = requireAddKindName(context, "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].");
277
+ const source = readOptionalStrictStringFlag(context.flags, "source");
278
+ return createNamedExecutionPlan(context, {
279
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
280
+ adminViewName: name2,
281
+ cwd,
282
+ source
283
+ }),
284
+ getValues: (result) => ({
285
+ adminViewSlug: result.adminViewSlug,
286
+ ...result.source ? { source: result.source } : {}
287
+ }),
288
+ missingNameMessage: "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].",
289
+ name
290
+ });
291
+ },
292
+ sortOrder: 10,
293
+ supportsDryRun: true,
294
+ usage: "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]",
295
+ visibleFieldNames: () => NAME_SOURCE_VISIBLE_FIELDS
296
+ });
297
+
298
+ // src/add-kinds/ai-feature.ts
299
+ var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
300
+ completion: {
301
+ nextSteps: (values) => [
302
+ `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
303
+ "Run `wp-typia sync-rest` and `wp-typia sync ai` or your workspace build/dev command to verify the generated REST artifacts and AI schema."
304
+ ],
305
+ summaryLines: (values, projectDir) => [
306
+ `AI feature: ${values.aiFeatureSlug}`,
307
+ `Namespace: ${values.namespace}`,
308
+ `Project directory: ${projectDir}`
309
+ ],
310
+ title: "Added server-only AI feature"
311
+ },
312
+ description: "Add a server-owned WordPress AI feature endpoint",
313
+ nameLabel: "AI feature name",
314
+ async prepareExecution(context) {
315
+ const name = requireAddKindName(context, "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].");
316
+ const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
317
+ return createNamedExecutionPlan(context, {
318
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
319
+ aiFeatureName: name2,
320
+ cwd,
321
+ namespace
322
+ }),
323
+ getValues: (result) => ({
324
+ aiFeatureSlug: result.aiFeatureSlug,
325
+ namespace: result.namespace
326
+ }),
327
+ getWarnings: (result) => result.warnings,
328
+ missingNameMessage: "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].",
329
+ name,
330
+ warnLine: context.warnLine
331
+ });
332
+ },
333
+ sortOrder: 100,
334
+ supportsDryRun: true,
335
+ usage: "wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]",
336
+ visibleFieldNames: () => NAME_NAMESPACE_VISIBLE_FIELDS
337
+ });
338
+
339
+ // src/add-kinds/binding-source.ts
340
+ var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
341
+ completion: {
342
+ nextSteps: (values) => [
343
+ `Review src/bindings/${values.bindingSourceSlug}/server.php and src/bindings/${values.bindingSourceSlug}/editor.ts.`,
344
+ ...values.blockSlug && values.attributeName ? [
345
+ `Review src/blocks/${values.blockSlug}/block.json for the ${values.attributeName} bindable attribute.`
346
+ ] : [],
347
+ "Run your workspace build or dev command to verify the binding source hooks and editor registration."
348
+ ],
349
+ summaryLines: (values, projectDir) => [
350
+ `Binding source: ${values.bindingSourceSlug}`,
351
+ ...values.blockSlug && values.attributeName ? [`Target: ${values.blockSlug}.${values.attributeName}`] : [],
352
+ `Project directory: ${projectDir}`
353
+ ],
354
+ title: "Added binding source"
355
+ },
356
+ description: "Add a shared block bindings source",
357
+ nameLabel: "Binding source name",
358
+ async prepareExecution(context) {
359
+ const name = requireAddKindName(context, "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].");
360
+ const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
361
+ return createNamedExecutionPlan(context, {
362
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
363
+ attributeName,
364
+ bindingSourceName: name2,
365
+ blockName,
366
+ cwd
367
+ }),
368
+ getValues: (result) => ({
369
+ ...result.attributeName ? { attributeName: result.attributeName } : {},
370
+ ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
371
+ bindingSourceSlug: result.bindingSourceSlug
372
+ }),
373
+ missingNameMessage: "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>].",
374
+ name
375
+ });
376
+ },
377
+ sortOrder: 70,
378
+ supportsDryRun: true,
379
+ usage: "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--dry-run]",
380
+ visibleFieldNames: () => NAME_BLOCK_ATTRIBUTE_VISIBLE_FIELDS
381
+ });
382
+
383
+ // src/external-layer-prompt-options.ts
384
+ function formatExternalLayerSelectHint(option2) {
385
+ const details = [
386
+ option2.description,
387
+ option2.extends.length > 0 ? `extends ${option2.extends.join(", ")}` : undefined
388
+ ].filter((value) => typeof value === "string" && value.length > 0);
389
+ return details.length > 0 ? details.join(" \xB7 ") : undefined;
390
+ }
391
+ function toExternalLayerPromptOptions(options) {
392
+ return options.map((option2) => ({
393
+ hint: formatExternalLayerSelectHint(option2),
394
+ label: option2.id,
395
+ value: option2.id
396
+ }));
397
+ }
398
+
399
+ // src/add-kinds/block.ts
400
+ var blockAddKindEntry = defineAddKindRegistryEntry({
401
+ completion: {
402
+ nextSteps: () => [
403
+ "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
404
+ "Run your workspace build or dev command to verify the new scaffolded block family."
405
+ ],
406
+ summaryLines: (values, projectDir) => [
407
+ `Blocks: ${values.blockSlugs}`,
408
+ `Template family: ${values.templateId}`,
409
+ `Project directory: ${projectDir}`
410
+ ],
411
+ title: "Added workspace block"
412
+ },
413
+ description: "Add a real block slice",
414
+ hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
415
+ nameLabel: "Block name",
416
+ async prepareExecution(context) {
417
+ const name = requireAddKindName(context, "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]");
418
+ const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
419
+ const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
420
+ const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
421
+ const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
422
+ const alternateRenderTargets = readOptionalStrictStringFlag(context.flags, "alternate-render-targets");
423
+ const dataStorageMode = readOptionalStrictStringFlag(context.flags, "data-storage");
424
+ const innerBlocksPreset = readOptionalStrictStringFlag(context.flags, "inner-blocks-preset");
425
+ const persistencePolicy = readOptionalStrictStringFlag(context.flags, "persistence-policy");
426
+ const requestedTemplateId = readOptionalStrictStringFlag(context.flags, "template");
427
+ let resolvedTemplateId = requestedTemplateId ? assertAddBlockTemplateId(context, requestedTemplateId) : undefined;
428
+ if (!resolvedTemplateId && context.isInteractiveSession) {
429
+ const templatePrompt = await context.getOrCreatePrompt();
430
+ resolvedTemplateId = await templatePrompt.select("Select a block template", context.addRuntime.ADD_BLOCK_TEMPLATE_IDS.map((templateId) => ({
431
+ hint: `Scaffold the ${templateId} block family`,
432
+ label: templateId,
433
+ value: templateId
434
+ })), 1);
435
+ }
436
+ resolvedTemplateId ??= "basic";
437
+ return createNamedExecutionPlan(context, {
438
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockCommand({
439
+ alternateRenderTargets,
440
+ blockName: name2,
441
+ cwd,
442
+ dataStorageMode,
443
+ externalLayerId,
444
+ externalLayerSource,
445
+ innerBlocksPreset,
446
+ persistencePolicy,
447
+ selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
448
+ templateId: resolvedTemplateId
449
+ }),
450
+ getValues: (result) => ({
451
+ blockSlugs: result.blockSlugs.join(", "),
452
+ templateId: result.templateId
453
+ }),
454
+ getWarnings: (result) => result.warnings,
455
+ missingNameMessage: "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]",
456
+ name,
457
+ warnLine: context.warnLine
458
+ });
459
+ },
460
+ sortOrder: 20,
461
+ supportsDryRun: true,
462
+ 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]",
463
+ visibleFieldNames: ({ template }) => BLOCK_VISIBLE_FIELD_ORDER.filter((fieldName) => {
464
+ if (fieldName === "alternate-render-targets") {
465
+ return isAddPersistenceTemplate(template);
466
+ }
467
+ if (fieldName === "inner-blocks-preset") {
468
+ return template === "compound";
469
+ }
470
+ if (fieldName === "data-storage" || fieldName === "persistence-policy") {
471
+ return isAddPersistenceTemplate(template);
472
+ }
473
+ return true;
719
474
  })
475
+ });
476
+
477
+ // src/add-kinds/editor-plugin.ts
478
+ var editorPluginAddKindEntry = defineAddKindRegistryEntry({
479
+ completion: {
480
+ nextSteps: (values) => [
481
+ `Review src/editor-plugins/${values.editorPluginSlug}/.`,
482
+ "Run your workspace build or dev command to verify the new editor plugin registration."
483
+ ],
484
+ summaryLines: (values, projectDir) => [
485
+ `Editor plugin: ${values.editorPluginSlug}`,
486
+ `Slot: ${values.slot}`,
487
+ `Project directory: ${projectDir}`
488
+ ],
489
+ title: "Added editor plugin"
490
+ },
491
+ description: "Add a slot-aware document editor extension shell",
492
+ nameLabel: "Editor plugin name",
493
+ async prepareExecution(context) {
494
+ const name = requireAddKindName(context, "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].");
495
+ const slot = readOptionalStrictStringFlag(context.flags, "slot");
496
+ return createNamedExecutionPlan(context, {
497
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
498
+ cwd,
499
+ editorPluginName: name2,
500
+ slot
501
+ }),
502
+ getValues: (result) => ({
503
+ editorPluginSlug: result.editorPluginSlug,
504
+ slot: result.slot
505
+ }),
506
+ missingNameMessage: "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].",
507
+ name
508
+ });
509
+ },
510
+ sortOrder: 120,
511
+ supportsDryRun: true,
512
+ usage: "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>] [--dry-run]",
513
+ visibleFieldNames: () => NAME_SLOT_VISIBLE_FIELDS
514
+ });
515
+
516
+ // src/add-kinds/hooked-block.ts
517
+ var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
518
+ completion: {
519
+ nextSteps: (values) => [
520
+ `Review src/blocks/${values.blockSlug}/block.json for the new blockHooks entry.`,
521
+ "Run your workspace build or dev command to verify the updated hooked-block metadata."
522
+ ],
523
+ summaryLines: (values, projectDir) => [
524
+ `Block: ${values.blockSlug}`,
525
+ `Anchor: ${values.anchorBlockName}`,
526
+ `Position: ${values.position}`,
527
+ `Project directory: ${projectDir}`
528
+ ],
529
+ title: "Added blockHooks metadata"
530
+ },
531
+ description: "Add block.json hook metadata to an existing block",
532
+ nameLabel: "Target block",
533
+ async prepareExecution(context) {
534
+ const name = requireAddKindName(context, "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.");
535
+ const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
536
+ const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
537
+ return createNamedExecutionPlan(context, {
538
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddHookedBlockCommand({
539
+ anchorBlockName,
540
+ blockName: name2,
541
+ cwd,
542
+ position
543
+ }),
544
+ getValues: (result) => ({
545
+ anchorBlockName: result.anchorBlockName,
546
+ blockSlug: result.blockSlug,
547
+ position: result.position
548
+ }),
549
+ missingNameMessage: "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.",
550
+ name
551
+ });
552
+ },
553
+ sortOrder: 110,
554
+ supportsDryRun: true,
555
+ usage: "wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild> [--dry-run]",
556
+ visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
557
+ });
558
+
559
+ // src/add-kinds/pattern.ts
560
+ var patternAddKindEntry = defineAddKindRegistryEntry({
561
+ completion: {
562
+ nextSteps: (values) => [
563
+ `Review src/patterns/${values.patternSlug}.php.`,
564
+ "Run your workspace build or dev command to verify the new pattern registration."
565
+ ],
566
+ summaryLines: (values, projectDir) => [
567
+ `Pattern: ${values.patternSlug}`,
568
+ `Project directory: ${projectDir}`
569
+ ],
570
+ title: "Added workspace pattern"
571
+ },
572
+ description: "Add a PHP block pattern shell",
573
+ nameLabel: "Pattern name",
574
+ async prepareExecution(context) {
575
+ return createNamedExecutionPlan(context, {
576
+ execute: ({ cwd, name }) => context.addRuntime.runAddPatternCommand({
577
+ cwd,
578
+ patternName: name
579
+ }),
580
+ getValues: (result) => ({
581
+ patternSlug: result.patternSlug
582
+ }),
583
+ missingNameMessage: "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>."
584
+ });
585
+ },
586
+ sortOrder: 60,
587
+ supportsDryRun: true,
588
+ usage: "wp-typia add pattern <name> [--dry-run]",
589
+ visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
590
+ });
591
+
592
+ // src/add-kinds/rest-resource.ts
593
+ var restResourceAddKindEntry = defineAddKindRegistryEntry({
594
+ completion: {
595
+ nextSteps: (values) => [
596
+ `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
597
+ "Run your workspace build or dev command to verify the generated REST resource contract."
598
+ ],
599
+ summaryLines: (values, projectDir) => [
600
+ `REST resource: ${values.restResourceSlug}`,
601
+ `Namespace: ${values.namespace}`,
602
+ `Methods: ${values.methods}`,
603
+ `Project directory: ${projectDir}`
604
+ ],
605
+ title: "Added plugin-level REST resource"
606
+ },
607
+ description: "Add a plugin-level typed REST resource",
608
+ nameLabel: "REST resource name",
609
+ async prepareExecution(context) {
610
+ const name = requireAddKindName(context, "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>].");
611
+ const methods = readOptionalStrictStringFlag(context.flags, "methods");
612
+ const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
613
+ return createNamedExecutionPlan(context, {
614
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
615
+ cwd,
616
+ methods,
617
+ namespace,
618
+ restResourceName: name2
619
+ }),
620
+ getValues: (result) => ({
621
+ methods: result.methods.join(", "),
622
+ namespace: result.namespace,
623
+ restResourceSlug: result.restResourceSlug
624
+ }),
625
+ missingNameMessage: "`wp-typia add rest-resource` requires <name>. Usage: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>].",
626
+ name
627
+ });
628
+ },
629
+ sortOrder: 80,
630
+ supportsDryRun: true,
631
+ usage: "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]",
632
+ visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
633
+ });
634
+
635
+ // src/add-kinds/style.ts
636
+ var styleAddKindEntry = defineAddKindRegistryEntry({
637
+ completion: {
638
+ nextSteps: (values) => [
639
+ `Review src/blocks/${values.blockSlug}/styles/${values.styleSlug}.ts.`,
640
+ "Run your workspace build or dev command to verify the new block style registration."
641
+ ],
642
+ summaryLines: (values, projectDir) => [
643
+ `Block style: ${values.styleSlug}`,
644
+ `Target block: ${values.blockSlug}`,
645
+ `Project directory: ${projectDir}`
646
+ ],
647
+ title: "Added block style"
648
+ },
649
+ description: "Add a Block Styles registration to an existing block",
650
+ nameLabel: "Style name",
651
+ async prepareExecution(context) {
652
+ const name = requireAddKindName(context, "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.");
653
+ const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
654
+ return createNamedExecutionPlan(context, {
655
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
656
+ blockName: blockSlug,
657
+ cwd,
658
+ styleName: name2
659
+ }),
660
+ getValues: (result) => ({
661
+ blockSlug: result.blockSlug,
662
+ styleSlug: result.styleSlug
663
+ }),
664
+ missingNameMessage: "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.",
665
+ name
666
+ });
667
+ },
668
+ sortOrder: 40,
669
+ supportsDryRun: true,
670
+ usage: "wp-typia add style <name> --block <block-slug> [--dry-run]",
671
+ visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
672
+ });
673
+
674
+ // src/add-kinds/transform.ts
675
+ var transformAddKindEntry = defineAddKindRegistryEntry({
676
+ completion: {
677
+ nextSteps: (values) => [
678
+ `Review src/blocks/${values.blockSlug}/transforms/${values.transformSlug}.ts.`,
679
+ "Run your workspace build or dev command to verify the new block transform registration."
680
+ ],
681
+ summaryLines: (values, projectDir) => [
682
+ `Block transform: ${values.transformSlug}`,
683
+ `From: ${values.fromBlockName}`,
684
+ `To: ${values.toBlockName}`,
685
+ `Project directory: ${projectDir}`
686
+ ],
687
+ title: "Added block transform"
688
+ },
689
+ description: "Add a block-to-block transform into a workspace block",
690
+ nameLabel: "Transform name",
691
+ async prepareExecution(context) {
692
+ const name = requireAddKindName(context, "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.");
693
+ const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
694
+ const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
695
+ return createNamedExecutionPlan(context, {
696
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockTransformCommand({
697
+ cwd,
698
+ fromBlockName,
699
+ toBlockName,
700
+ transformName: name2
701
+ }),
702
+ getValues: (result) => ({
703
+ blockSlug: result.blockSlug,
704
+ fromBlockName: result.fromBlockName,
705
+ toBlockName: result.toBlockName,
706
+ transformSlug: result.transformSlug
707
+ }),
708
+ missingNameMessage: "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.",
709
+ name
710
+ });
711
+ },
712
+ sortOrder: 50,
713
+ supportsDryRun: true,
714
+ usage: "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]",
715
+ visibleFieldNames: () => NAME_FROM_TO_VISIBLE_FIELDS
716
+ });
717
+
718
+ // src/add-kinds/variation.ts
719
+ var variationAddKindEntry = defineAddKindRegistryEntry({
720
+ completion: {
721
+ nextSteps: (values) => [
722
+ `Review src/blocks/${values.blockSlug}/variations/${values.variationSlug}.ts.`,
723
+ "Run your workspace build or dev command to pick up the new variation."
724
+ ],
725
+ summaryLines: (values, projectDir) => [
726
+ `Variation: ${values.variationSlug}`,
727
+ `Target block: ${values.blockSlug}`,
728
+ `Project directory: ${projectDir}`
729
+ ],
730
+ title: "Added workspace variation"
731
+ },
732
+ description: "Add a variation to an existing block",
733
+ nameLabel: "Variation name",
734
+ async prepareExecution(context) {
735
+ const name = requireAddKindName(context, "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>");
736
+ const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
737
+ return createNamedExecutionPlan(context, {
738
+ execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
739
+ blockName: blockSlug,
740
+ cwd,
741
+ variationName: name2
742
+ }),
743
+ getValues: (result) => ({
744
+ blockSlug: result.blockSlug,
745
+ variationSlug: result.variationSlug
746
+ }),
747
+ missingNameMessage: "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>",
748
+ name
749
+ });
750
+ },
751
+ sortOrder: 30,
752
+ supportsDryRun: true,
753
+ usage: "wp-typia add variation <name> --block <block-slug> [--dry-run]",
754
+ visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
755
+ });
756
+
757
+ // src/add-kind-registry.ts
758
+ var ADD_KIND_REGISTRY = {
759
+ "admin-view": adminViewAddKindEntry,
760
+ block: blockAddKindEntry,
761
+ variation: variationAddKindEntry,
762
+ style: styleAddKindEntry,
763
+ transform: transformAddKindEntry,
764
+ pattern: patternAddKindEntry,
765
+ "binding-source": bindingSourceAddKindEntry,
766
+ "rest-resource": restResourceAddKindEntry,
767
+ ability: abilityAddKindEntry,
768
+ "ai-feature": aiFeatureAddKindEntry,
769
+ "hooked-block": hookedBlockAddKindEntry,
770
+ "editor-plugin": editorPluginAddKindEntry
720
771
  };
721
772
  function isAddKindId(value) {
722
773
  return typeof value === "string" && ADD_KIND_IDS.includes(value);
@@ -742,6 +793,24 @@ function supportsAddKindDryRun(kind) {
742
793
  return ADD_KIND_REGISTRY[kind].supportsDryRun;
743
794
  }
744
795
 
796
+ // src/cli-error-messages.ts
797
+ var MISSING_CREATE_PROJECT_DIR_DETAIL_LINES = [
798
+ "`wp-typia create` requires <project-dir>.",
799
+ "`--dry-run` still needs a logical project directory name because wp-typia derives slugs, package names, and planned file paths from it."
800
+ ];
801
+ function formatMissingAddKindDetailLine() {
802
+ return `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`;
803
+ }
804
+ function shouldPrintMissingAddKindHelp(options) {
805
+ if (typeof options.emitOutput === "boolean") {
806
+ return options.emitOutput;
807
+ }
808
+ return options.format !== "json";
809
+ }
810
+ function buildMissingCreateProjectDirDetailLines() {
811
+ return [...MISSING_CREATE_PROJECT_DIR_DETAIL_LINES];
812
+ }
813
+
745
814
  // src/runtime-bridge-add-dry-run.ts
746
815
  import fs2 from "fs";
747
816
  import { promises as fsp } from "fs";
@@ -946,6 +1015,13 @@ function stripLeadingOutputMarker(text, kind) {
946
1015
  return text.replace(new RegExp(`^(?:${markerPattern})\\s*`, "u"), "");
947
1016
  }
948
1017
 
1018
+ // src/print-block.ts
1019
+ function printBlock(printLine, lines) {
1020
+ for (const line of lines) {
1021
+ printLine(line);
1022
+ }
1023
+ }
1024
+
949
1025
  // src/runtime-bridge-output.ts
950
1026
  function printCompletionPayload(payload, options = {}) {
951
1027
  const printLine = options.printLine ?? console.log;
@@ -988,6 +1064,13 @@ function extractPlannedFiles(payload) {
988
1064
  return toNonEmptyArray(files);
989
1065
  }
990
1066
  var PROJECT_DIRECTORY_SUMMARY_PREFIX = "Project directory: ";
1067
+ function resolveCreateCompletionPackageManager(packageManager) {
1068
+ const parsedPackageManager = parsePackageManagerField(packageManager);
1069
+ if (parsedPackageManager) {
1070
+ return parsedPackageManager;
1071
+ }
1072
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
1073
+ }
991
1074
  function extractCompletionProjectDir(completion) {
992
1075
  const projectDir = completion?.summaryLines?.find((line) => line.startsWith(PROJECT_DIRECTORY_SUMMARY_PREFIX))?.slice(PROJECT_DIRECTORY_SUMMARY_PREFIX.length).trim();
993
1076
  return projectDir && projectDir.length > 0 ? projectDir : undefined;
@@ -1044,8 +1127,9 @@ function formatCreateProgressLine(payload, markerOptions) {
1044
1127
  return formatOutputMarker("progress", `${payload.title}: ${payload.detail}`, markerOptions);
1045
1128
  }
1046
1129
  function buildCreateCompletionPayload(flow, markerOptions) {
1130
+ const packageManager = resolveCreateCompletionPackageManager(flow.packageManager);
1047
1131
  const verificationSteps = [
1048
- formatPackageExecCommand(flow.packageManager, `wp-typia@${package_default.version}`, "doctor"),
1132
+ formatPackageExecCommand(packageManager, `wp-typia@${package_default.version}`, "doctor"),
1049
1133
  ...flow.optionalOnboarding.steps
1050
1134
  ];
1051
1135
  return {
@@ -1167,11 +1251,6 @@ function buildSyncDryRunPayload(options, markerOptions) {
1167
1251
  title: formatOutputMarker("dryRun", `Dry run for wp-typia sync${targetSuffix}`, markerOptions)
1168
1252
  };
1169
1253
  }
1170
- function printBlock(lines, printLine) {
1171
- for (const line of lines) {
1172
- printLine(line);
1173
- }
1174
- }
1175
1254
 
1176
1255
  // src/runtime-capabilities.ts
1177
1256
  function isInteractiveTerminal({
@@ -1343,7 +1422,7 @@ function runProjectScript(project, plannedCommand, options) {
1343
1422
  const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
1344
1423
  const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
1345
1424
  if (result.error || result.status !== 0) {
1346
- throw new Error(`\`${plannedCommand.displayCommand}\` failed.`, {
1425
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
1347
1426
  cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
1348
1427
  });
1349
1428
  }
@@ -1384,15 +1463,15 @@ async function executeSyncCommand({
1384
1463
  }
1385
1464
 
1386
1465
  // src/runtime-bridge.ts
1387
- var loadCliAddRuntime = () => import("./cli-add-1xvw17yg.js");
1466
+ var loadCliAddRuntime = () => import("./cli-add-6dn9h94t.js");
1388
1467
  var loadCliDiagnosticsRuntime = () => import("./cli-diagnostics-5dvztm7q.js");
1389
- var loadCliDoctorRuntime = () => import("./cli-doctor-bjv6z74k.js");
1390
- var loadCliInitRuntime = () => import("./cli-init-zdfrmp3y.js");
1468
+ var loadCliDoctorRuntime = () => import("./cli-doctor-564c43ay.js");
1469
+ var loadCliInitRuntime = () => import("./cli-init-znhqp8tr.js");
1391
1470
  var loadCliPromptRuntime = () => import("./cli-prompt-614tq57c.js");
1392
- var loadCliScaffoldRuntime = () => import("./cli-scaffold-pbb67zxg.js");
1471
+ var loadCliScaffoldRuntime = () => import("./cli-scaffold-6trxyyk6.js");
1393
1472
  var loadCliTemplatesRuntime = () => import("./cli-templates-hc71dfc2.js");
1394
- var loadCreateTemplateValidationRuntime = () => import("./create-template-validation-7k2752mz.js");
1395
- var loadMigrationsRuntime = () => import("./migrations-ads3j14z.js");
1473
+ var loadCreateTemplateValidationRuntime = () => import("./create-template-validation-rtec5sng.js");
1474
+ var loadMigrationsRuntime = () => import("./migrations-qc1r0yqe.js");
1396
1475
  async function wrapCliCommandError(command, error) {
1397
1476
  const { createCliCommandError } = await loadCliDiagnosticsRuntime();
1398
1477
  return createCliCommandError({ command, error });
@@ -1601,10 +1680,10 @@ async function executeAddCommand({
1601
1680
  const addRuntime = await loadCliAddRuntime();
1602
1681
  const isInteractiveSession = interactive ?? isInteractiveTerminal();
1603
1682
  if (!kind) {
1604
- if (emitOutput) {
1683
+ if (shouldPrintMissingAddKindHelp({ emitOutput })) {
1605
1684
  printLine(addRuntime.formatAddHelpText());
1606
1685
  }
1607
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`);
1686
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
1608
1687
  }
1609
1688
  if (!isAddKindId(kind)) {
1610
1689
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
@@ -1656,7 +1735,7 @@ async function executeTemplatesCommand({ flags }, printLine = console.log) {
1656
1735
  const subcommand = flags.subcommand ?? "list";
1657
1736
  if (subcommand === "list") {
1658
1737
  for (const template of listTemplates()) {
1659
- printBlock([formatTemplateSummary(template), formatTemplateFeatures(template)], printLine);
1738
+ printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
1660
1739
  }
1661
1740
  return;
1662
1741
  }
@@ -1668,7 +1747,7 @@ async function executeTemplatesCommand({ flags }, printLine = console.log) {
1668
1747
  if (!template) {
1669
1748
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
1670
1749
  }
1671
- printBlock([formatTemplateDetails(template)], printLine);
1750
+ printBlock(printLine, [formatTemplateDetails(template)]);
1672
1751
  return;
1673
1752
  }
1674
1753
  throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
@@ -2279,10 +2358,7 @@ var createCommand = defineCommand({
2279
2358
  emitCliDiagnosticFailure(args, {
2280
2359
  code: CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT,
2281
2360
  command: "create",
2282
- detailLines: [
2283
- "`wp-typia create` requires <project-dir>.",
2284
- "`--dry-run` still needs a logical project directory name because wp-typia derives slugs, package names, and planned file paths from it."
2285
- ]
2361
+ detailLines: buildMissingCreateProjectDirDetailLines()
2286
2362
  });
2287
2363
  return;
2288
2364
  }
@@ -2344,7 +2420,7 @@ var doctorCommand = defineCommand({
2344
2420
  const prefersStructuredOutput = prefersStructuredCliOutput(args);
2345
2421
  if (prefersStructuredOutput) {
2346
2422
  const [{ getDoctorChecks }, { getDoctorFailureDetailLines }] = await Promise.all([
2347
- import("./cli-doctor-bjv6z74k.js"),
2423
+ import("./cli-doctor-564c43ay.js"),
2348
2424
  import("./cli-diagnostics-5dvztm7q.js")
2349
2425
  ]);
2350
2426
  const checks = await getDoctorChecks(args.cwd);
@@ -3221,4 +3297,4 @@ export {
3221
3297
  wpTypiaCommands
3222
3298
  };
3223
3299
 
3224
- //# debugId=C86915DD4AD0BB9C64756E2164756E21
3300
+ //# debugId=1A737B9B812DF37F64756E2164756E21