wp-typia 0.24.3 → 0.24.5

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.
Files changed (58) hide show
  1. package/README.md +7 -5
  2. package/bin/wp-typia.js +24 -103
  3. package/{dist-bunli/node-cli.js → dist/cli.js} +5079 -3656
  4. package/package.json +9 -36
  5. package/bin/routing-metadata.generated.d.ts +0 -8
  6. package/bin/routing-metadata.generated.js +0 -93
  7. package/bin/runtime-routing.d.ts +0 -34
  8. package/bin/runtime-routing.js +0 -124
  9. package/dist-bunli/.bunli/commands.gen.js +0 -304333
  10. package/dist-bunli/.bunli/highlights-eq9cgrbb.scm +0 -604
  11. package/dist-bunli/.bunli/highlights-ghv9g403.scm +0 -205
  12. package/dist-bunli/.bunli/highlights-hk7bwhj4.scm +0 -284
  13. package/dist-bunli/.bunli/highlights-r812a2qc.scm +0 -150
  14. package/dist-bunli/.bunli/highlights-x6tmsnaa.scm +0 -115
  15. package/dist-bunli/.bunli/injections-73j83es3.scm +0 -27
  16. package/dist-bunli/.bunli/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  17. package/dist-bunli/.bunli/tree-sitter-markdown-411r6y9b.wasm +0 -0
  18. package/dist-bunli/.bunli/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  19. package/dist-bunli/.bunli/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  20. package/dist-bunli/.bunli/tree-sitter-zig-e78zbjpm.wasm +0 -0
  21. package/dist-bunli/agents-91fpdyyt.js +0 -12
  22. package/dist-bunli/chunk-bdqvmfwv-f5qmzmxg.js +0 -16825
  23. package/dist-bunli/cli-03j0axbt.js +0 -163
  24. package/dist-bunli/cli-1170yyve.js +0 -106
  25. package/dist-bunli/cli-377p86mf.js +0 -191
  26. package/dist-bunli/cli-4pzxbk4s.js +0 -1231
  27. package/dist-bunli/cli-6v0pcxw6.js +0 -314
  28. package/dist-bunli/cli-84c7wff4.js +0 -198
  29. package/dist-bunli/cli-8hxf9qw6.js +0 -198
  30. package/dist-bunli/cli-9fx0qgb7.js +0 -3680
  31. package/dist-bunli/cli-ac2ebaf8.js +0 -3
  32. package/dist-bunli/cli-add-mxxk5rep.js +0 -10660
  33. package/dist-bunli/cli-am5x7tb4.js +0 -192
  34. package/dist-bunli/cli-bajwv85z.js +0 -24
  35. package/dist-bunli/cli-ccax7s0s.js +0 -34
  36. package/dist-bunli/cli-cvxvcw7c.js +0 -46
  37. package/dist-bunli/cli-diagnostics-10drxh34.js +0 -34
  38. package/dist-bunli/cli-doctor-6fyxq940.js +0 -1446
  39. package/dist-bunli/cli-e4bwd81c.js +0 -1260
  40. package/dist-bunli/cli-fv4h3ydt.js +0 -173823
  41. package/dist-bunli/cli-hv2yedw2.js +0 -74591
  42. package/dist-bunli/cli-init-7avk42dh.js +0 -880
  43. package/dist-bunli/cli-kfm9mm68.js +0 -14679
  44. package/dist-bunli/cli-prompt-ncyg68rn.js +0 -12
  45. package/dist-bunli/cli-rdcga1bd.js +0 -135
  46. package/dist-bunli/cli-scaffold-0bb6pr3w.js +0 -538
  47. package/dist-bunli/cli-t73q5aqz.js +0 -103
  48. package/dist-bunli/cli-templates-g8t4fm11.js +0 -167
  49. package/dist-bunli/cli-tj7ajdvf.js +0 -2612
  50. package/dist-bunli/cli-tq730sqt.js +0 -344
  51. package/dist-bunli/cli-xnn9xjcy.js +0 -68
  52. package/dist-bunli/cli-z48frc8t.js +0 -229
  53. package/dist-bunli/cli.js +0 -2523
  54. package/dist-bunli/command-list-bgwaa2f4.js +0 -3920
  55. package/dist-bunli/create-template-validation-4fr851vg.js +0 -16
  56. package/dist-bunli/migrations-3vngdy51.js +0 -47
  57. package/dist-bunli/sync-k2k8svyc.js +0 -13
  58. package/dist-bunli/workspace-project-gmv2a71z.js +0 -22
@@ -1,3920 +0,0 @@
1
- // @bun
2
- import {
3
- ADD_OPTION_METADATA,
4
- CREATE_OPTION_METADATA,
5
- DOCTOR_OPTION_METADATA,
6
- INIT_OPTION_METADATA,
7
- MCP_OPTION_METADATA,
8
- MIGRATE_OPTION_METADATA,
9
- SYNC_OPTION_METADATA,
10
- TEMPLATES_OPTION_METADATA,
11
- WP_TYPIA_TOP_LEVEL_COMMAND_NAMES,
12
- buildCommandOptions,
13
- emitCliDiagnosticFailure,
14
- formatAddKindList,
15
- formatAddKindUsagePlaceholder,
16
- getAddBlockDefaults,
17
- getCreateDefaults,
18
- getMcpSchemaSources,
19
- package_default,
20
- prefersStructuredCliOutput,
21
- resolveCommandOptionValues
22
- } from "./cli-4pzxbk4s.js";
23
- import {
24
- Result,
25
- TaggedError,
26
- createKeyMatcher,
27
- defineCommand,
28
- exports_external,
29
- option,
30
- require_jsx_dev_runtime,
31
- require_react,
32
- useKeyboard,
33
- useRuntime
34
- } from "./cli-hv2yedw2.js";
35
- import"./cli-ac2ebaf8.js";
36
- import {
37
- createManagedTempRoot
38
- } from "./cli-t73q5aqz.js";
39
- import {
40
- ADD_KIND_IDS
41
- } from "./cli-bajwv85z.js";
42
- import {
43
- CLI_DIAGNOSTIC_CODES,
44
- createCliDiagnosticCodeError
45
- } from "./cli-tq730sqt.js";
46
- import {
47
- PACKAGE_MANAGER_IDS,
48
- formatInstallCommand,
49
- formatPackageExecCommand,
50
- formatRunScript,
51
- inferPackageManagerId,
52
- parsePackageManagerField
53
- } from "./cli-am5x7tb4.js";
54
- import"./cli-ccax7s0s.js";
55
- import {
56
- __require,
57
- __toESM
58
- } from "./cli-xnn9xjcy.js";
59
-
60
- // src/commands/add.ts
61
- var import_react34 = __toESM(require_react(), 1);
62
-
63
- // src/commands/output-adapters.ts
64
- var defaultPrintLine = (line) => {
65
- process.stdout.write(`${line}
66
- `);
67
- };
68
- var defaultWarnLine = (line) => {
69
- process.stderr.write(`${line}
70
- `);
71
- };
72
- function resolveCommandPrintLine(args) {
73
- return args.printLine ?? defaultPrintLine;
74
- }
75
- function resolveCommandOutputAdapters(args) {
76
- const adapters = args;
77
- return {
78
- printLine: adapters.printLine ?? defaultPrintLine,
79
- warnLine: adapters.warnLine ?? defaultWarnLine
80
- };
81
- }
82
-
83
- // src/render-loader.ts
84
- import fs from "fs";
85
- import { fileURLToPath } from "url";
86
- function resolveBundledModuleHref(baseUrl, candidates, options = {}) {
87
- for (const candidate of candidates) {
88
- const url = new URL(candidate, baseUrl);
89
- if (fs.existsSync(fileURLToPath(url))) {
90
- return url.href;
91
- }
92
- }
93
- const missingCandidates = candidates.map((candidate) => fileURLToPath(new URL(candidate, baseUrl)));
94
- const label = options.moduleLabel ?? "bundled wp-typia runtime module";
95
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_BUILD_ARTIFACT, [
96
- `Missing bundled build artifacts for ${label}.`,
97
- "None of the expected files were found:",
98
- ...missingCandidates.map((candidatePath) => `- ${candidatePath}`),
99
- "Run `bun run --filter wp-typia build` in a source checkout, or reinstall the published package/standalone binary if its bundled files are missing."
100
- ].join(`
101
- `));
102
- }
103
-
104
- // src/add-kind-registry-shared.ts
105
- var BLOCK_VISIBLE_FIELD_ORDER = [
106
- "kind",
107
- "name",
108
- "template",
109
- "alternate-render-targets",
110
- "inner-blocks-preset",
111
- "data-storage",
112
- "persistence-policy"
113
- ];
114
- var NAME_ONLY_VISIBLE_FIELDS = [
115
- "kind",
116
- "name"
117
- ];
118
- var PATTERN_CATALOG_VISIBLE_FIELDS = [
119
- "kind",
120
- "name",
121
- "scope",
122
- "section-role",
123
- "catalog-title",
124
- "tags",
125
- "thumbnail-url"
126
- ];
127
- var NAME_SOURCE_VISIBLE_FIELDS = [
128
- "kind",
129
- "name",
130
- "source"
131
- ];
132
- var NAME_TYPE_VISIBLE_FIELDS = [
133
- "kind",
134
- "name",
135
- "type"
136
- ];
137
- var NAME_BLOCK_ATTRIBUTE_POST_META_VISIBLE_FIELDS = [
138
- "kind",
139
- "name",
140
- "block",
141
- "attribute",
142
- "post-meta",
143
- "meta-path"
144
- ];
145
- var NAME_BLOCK_VISIBLE_FIELDS = [
146
- "kind",
147
- "name",
148
- "block"
149
- ];
150
- var NAME_SLOT_VISIBLE_FIELDS = [
151
- "kind",
152
- "name",
153
- "slot"
154
- ];
155
- var NAME_ANCHOR_POSITION_VISIBLE_FIELDS = [
156
- "kind",
157
- "name",
158
- "anchor",
159
- "position"
160
- ];
161
- var NAME_FROM_TO_VISIBLE_FIELDS = [
162
- "kind",
163
- "name",
164
- "from",
165
- "to"
166
- ];
167
- var NAME_NAMESPACE_METHODS_VISIBLE_FIELDS = [
168
- "kind",
169
- "name",
170
- "namespace",
171
- "methods"
172
- ];
173
- var NAME_NAMESPACE_VISIBLE_FIELDS = [
174
- "kind",
175
- "name",
176
- "namespace"
177
- ];
178
- var NAME_POST_TYPE_TYPE_VISIBLE_FIELDS = [
179
- "kind",
180
- "name",
181
- "post-type",
182
- "type"
183
- ];
184
- function requireAddKindName(context, message) {
185
- if (!context.name) {
186
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
187
- }
188
- return context.name;
189
- }
190
- function defineAddKindRegistryEntry(entry) {
191
- return entry;
192
- }
193
- function createNamedExecutionPlan(context, options) {
194
- const name = options.name ?? requireAddKindName(context, options.missingNameMessage);
195
- return {
196
- execute: (cwd) => options.execute({ cwd, name }),
197
- getValues: options.getValues,
198
- ...options.getWarnings ? { getWarnings: options.getWarnings } : {},
199
- ...options.warnLine ? { warnLine: options.warnLine } : {}
200
- };
201
- }
202
- function isAddPersistenceTemplate(template) {
203
- return template === "persistence" || template === "compound";
204
- }
205
- function formatAddBlockTemplateIds(addRuntime) {
206
- return addRuntime.ADD_BLOCK_TEMPLATE_IDS.join(", ");
207
- }
208
- function getMistypedAddBlockTemplateMessage(addRuntime, templateId) {
209
- const suggestion = addRuntime.suggestAddBlockTemplateId(templateId);
210
- if (!suggestion) {
211
- return null;
212
- }
213
- return `Unknown add-block template "${templateId}". Did you mean "${suggestion}"? Use \`--template ${suggestion}\`, or run \`wp-typia templates list\` to inspect available templates.`;
214
- }
215
- function assertAddBlockTemplateId(context, templateId) {
216
- if (templateId === "query-loop") {
217
- 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.");
218
- }
219
- if (context.addRuntime.isAddBlockTemplateId(templateId)) {
220
- return templateId;
221
- }
222
- const mistypedAddBlockTemplateMessage = getMistypedAddBlockTemplateMessage(context.addRuntime, templateId);
223
- if (mistypedAddBlockTemplateMessage) {
224
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, mistypedAddBlockTemplateMessage);
225
- }
226
- 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.`);
227
- }
228
-
229
- // src/add-kinds/ability.ts
230
- var ABILITY_MISSING_NAME_MESSAGE = "`wp-typia add ability` requires <name>. Usage: wp-typia add ability <name>.";
231
- var abilityAddKindEntry = defineAddKindRegistryEntry({
232
- completion: {
233
- nextSteps: (values) => [
234
- `Review src/abilities/${values.abilitySlug}/ and inc/abilities/${values.abilitySlug}.php.`,
235
- "Run `wp-typia sync` or `npm run sync-abilities -- --check` and then your workspace build/dev command to verify the generated workflow ability."
236
- ],
237
- summaryLines: (values, projectDir) => [
238
- `Ability: ${values.abilitySlug}`,
239
- `Project directory: ${projectDir}`
240
- ],
241
- title: "Added workflow ability"
242
- },
243
- description: "Add a typed server/client workflow ability scaffold",
244
- nameLabel: "Ability name",
245
- async prepareExecution(context) {
246
- return createNamedExecutionPlan(context, {
247
- execute: ({ cwd, name }) => context.addRuntime.runAddAbilityCommand({
248
- abilityName: name,
249
- cwd
250
- }),
251
- getValues: (result) => ({
252
- abilitySlug: result.abilitySlug
253
- }),
254
- getWarnings: (result) => result.warnings,
255
- missingNameMessage: ABILITY_MISSING_NAME_MESSAGE,
256
- warnLine: context.warnLine
257
- });
258
- },
259
- sortOrder: 90,
260
- supportsDryRun: true,
261
- usage: "wp-typia add ability <name> [--dry-run]",
262
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS
263
- });
264
-
265
- // src/cli-string-flags.ts
266
- function readOptionalCliStringFlagValue(flags, name, mode) {
267
- const value = flags[name];
268
- if (value === undefined || value === null) {
269
- return;
270
- }
271
- if (typeof value !== "string") {
272
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
273
- }
274
- const trimmed = value.trim();
275
- if (trimmed.length === 0) {
276
- if (mode === "strict") {
277
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `\`--${name}\` requires a value.`);
278
- }
279
- return;
280
- }
281
- return mode === "strict" ? value : trimmed;
282
- }
283
- function readOptionalLooseStringFlag(flags, name) {
284
- return readOptionalCliStringFlagValue(flags, name, "loose");
285
- }
286
- function readOptionalStrictStringFlag(flags, name) {
287
- return readOptionalCliStringFlagValue(flags, name, "strict");
288
- }
289
- function readOptionalDashedOrCamelStringFlag(flags, dashedName, camelName) {
290
- return readOptionalStrictStringFlag(flags, dashedName) ?? readOptionalStrictStringFlag(flags, camelName);
291
- }
292
- function requireStrictStringFlag(flags, name, message) {
293
- const value = readOptionalStrictStringFlag(flags, name);
294
- if (!value) {
295
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
296
- }
297
- return value;
298
- }
299
- function readOptionalPairedStrictStringFlags(flags, leftName, rightName, message) {
300
- const leftValue = readOptionalStrictStringFlag(flags, leftName);
301
- const rightValue = readOptionalStrictStringFlag(flags, rightName);
302
- if (Boolean(leftValue) !== Boolean(rightValue)) {
303
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
304
- }
305
- return [leftValue, rightValue];
306
- }
307
-
308
- // src/add-kinds/admin-view.ts
309
- var ADMIN_VIEW_MISSING_NAME_MESSAGE = "`wp-typia add admin-view` requires <name>. Usage: wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>].";
310
- var adminViewAddKindEntry = defineAddKindRegistryEntry({
311
- completion: {
312
- nextSteps: (values) => [
313
- `Review src/admin-views/${values.adminViewSlug}/ and inc/admin-views/${values.adminViewSlug}.php.`,
314
- "Run your workspace build or dev command to verify the generated DataViews admin screen."
315
- ],
316
- summaryLines: (values, projectDir) => [
317
- `Admin view: ${values.adminViewSlug}`,
318
- ...values.source ? [`Source: ${values.source}`] : [],
319
- `Project directory: ${projectDir}`
320
- ],
321
- title: "Added DataViews admin screen"
322
- },
323
- description: "Add an opt-in DataViews-powered admin screen",
324
- nameLabel: "Admin view name",
325
- async prepareExecution(context) {
326
- const name = requireAddKindName(context, ADMIN_VIEW_MISSING_NAME_MESSAGE);
327
- const source = readOptionalStrictStringFlag(context.flags, "source");
328
- return createNamedExecutionPlan(context, {
329
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAdminViewCommand({
330
- adminViewName: name2,
331
- cwd,
332
- source
333
- }),
334
- getValues: (result) => ({
335
- adminViewSlug: result.adminViewSlug,
336
- ...result.source ? { source: result.source } : {}
337
- }),
338
- missingNameMessage: ADMIN_VIEW_MISSING_NAME_MESSAGE,
339
- name,
340
- warnLine: context.warnLine
341
- });
342
- },
343
- sortOrder: 10,
344
- supportsDryRun: true,
345
- usage: "wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]",
346
- visibleFieldNames: () => NAME_SOURCE_VISIBLE_FIELDS
347
- });
348
-
349
- // src/add-kinds/ai-feature.ts
350
- var AI_FEATURE_MISSING_NAME_MESSAGE = "`wp-typia add ai-feature` requires <name>. Usage: wp-typia add ai-feature <name> [--namespace <vendor/v1>].";
351
- var aiFeatureAddKindEntry = defineAddKindRegistryEntry({
352
- completion: {
353
- nextSteps: (values) => [
354
- `Review src/ai-features/${values.aiFeatureSlug}/ and inc/ai-features/${values.aiFeatureSlug}.php.`,
355
- "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."
356
- ],
357
- summaryLines: (values, projectDir) => [
358
- `AI feature: ${values.aiFeatureSlug}`,
359
- `Namespace: ${values.namespace}`,
360
- `Project directory: ${projectDir}`
361
- ],
362
- title: "Added server-only AI feature"
363
- },
364
- description: "Add a server-owned WordPress AI feature endpoint",
365
- nameLabel: "AI feature name",
366
- async prepareExecution(context) {
367
- const name = requireAddKindName(context, AI_FEATURE_MISSING_NAME_MESSAGE);
368
- const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
369
- return createNamedExecutionPlan(context, {
370
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddAiFeatureCommand({
371
- aiFeatureName: name2,
372
- cwd,
373
- namespace
374
- }),
375
- getValues: (result) => ({
376
- aiFeatureSlug: result.aiFeatureSlug,
377
- namespace: result.namespace
378
- }),
379
- getWarnings: (result) => result.warnings,
380
- missingNameMessage: AI_FEATURE_MISSING_NAME_MESSAGE,
381
- name,
382
- warnLine: context.warnLine
383
- });
384
- },
385
- sortOrder: 100,
386
- supportsDryRun: true,
387
- usage: "wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]",
388
- visibleFieldNames: () => NAME_NAMESPACE_VISIBLE_FIELDS
389
- });
390
-
391
- // src/add-kinds/binding-source.ts
392
- var BINDING_SOURCE_MISSING_NAME_MESSAGE = "`wp-typia add binding-source` requires <name>. Usage: wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--from-post-meta <post-meta> --meta-path <field>].";
393
- var bindingSourceAddKindEntry = defineAddKindRegistryEntry({
394
- completion: {
395
- nextSteps: (values) => [
396
- `Review src/bindings/${values.bindingSourceSlug}/server.php and src/bindings/${values.bindingSourceSlug}/editor.ts.`,
397
- ...values.blockSlug && values.attributeName ? [
398
- `Review src/blocks/${values.blockSlug}/block.json for the ${values.attributeName} bindable attribute.`
399
- ] : [],
400
- ...values.postMetaSlug ? [
401
- `Run wp-typia sync-rest --check after editing ${values.schemaFile}.`
402
- ] : [],
403
- "Run your workspace build or dev command to verify the binding source hooks and editor registration."
404
- ],
405
- summaryLines: (values, projectDir) => [
406
- `Binding source: ${values.bindingSourceSlug}`,
407
- ...values.blockSlug && values.attributeName ? [`Target: ${values.blockSlug}.${values.attributeName}`] : [],
408
- ...values.postMetaSlug ? [
409
- `Post meta: ${values.postMetaSlug}`,
410
- `Meta field: ${values.metaPath}`
411
- ] : [],
412
- `Project directory: ${projectDir}`
413
- ],
414
- title: "Added binding source"
415
- },
416
- description: "Add a shared block bindings source",
417
- nameLabel: "Binding source name",
418
- async prepareExecution(context) {
419
- const name = requireAddKindName(context, BINDING_SOURCE_MISSING_NAME_MESSAGE);
420
- const [blockName, attributeName] = readOptionalPairedStrictStringFlags(context.flags, "block", "attribute", "`wp-typia add binding-source` requires --block and --attribute to be provided together.");
421
- const postMetaName = readOptionalDashedOrCamelStringFlag(context.flags, "from-post-meta", "fromPostMeta") ?? readOptionalDashedOrCamelStringFlag(context.flags, "post-meta", "postMeta");
422
- const metaPath = readOptionalDashedOrCamelStringFlag(context.flags, "meta-path", "metaPath");
423
- return createNamedExecutionPlan(context, {
424
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBindingSourceCommand({
425
- attributeName,
426
- bindingSourceName: name2,
427
- blockName,
428
- cwd,
429
- metaPath,
430
- postMetaName
431
- }),
432
- getValues: (result) => ({
433
- ...result.attributeName ? { attributeName: result.attributeName } : {},
434
- ...result.blockSlug ? { blockSlug: result.blockSlug } : {},
435
- bindingSourceSlug: result.bindingSourceSlug,
436
- ...result.metaKey ? { metaKey: result.metaKey } : {},
437
- ...result.metaPath ? { metaPath: result.metaPath } : {},
438
- ...result.postMetaSlug ? { postMetaSlug: result.postMetaSlug } : {},
439
- ...result.postType ? { postType: result.postType } : {},
440
- ...result.schemaFile ? { schemaFile: result.schemaFile } : {}
441
- }),
442
- missingNameMessage: BINDING_SOURCE_MISSING_NAME_MESSAGE,
443
- name,
444
- warnLine: context.warnLine
445
- });
446
- },
447
- sortOrder: 70,
448
- supportsDryRun: true,
449
- usage: "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--from-post-meta|--post-meta <post-meta> [--meta-path <field>]] [--dry-run]",
450
- visibleFieldNames: () => NAME_BLOCK_ATTRIBUTE_POST_META_VISIBLE_FIELDS
451
- });
452
-
453
- // src/external-layer-prompt-options.ts
454
- function formatExternalLayerSelectHint(option2) {
455
- const details = [
456
- option2.description,
457
- option2.extends.length > 0 ? `extends ${option2.extends.join(", ")}` : undefined
458
- ].filter((value) => typeof value === "string" && value.length > 0);
459
- return details.length > 0 ? details.join(" \xB7 ") : undefined;
460
- }
461
- function toExternalLayerPromptOptions(options) {
462
- return options.map((option2) => ({
463
- hint: formatExternalLayerSelectHint(option2),
464
- label: option2.id,
465
- value: option2.id
466
- }));
467
- }
468
-
469
- // src/add-kinds/block.ts
470
- var BLOCK_MISSING_NAME_MESSAGE = "`wp-typia add block` requires <name>. Usage: wp-typia add block <name> [--template <basic|interactivity|persistence|compound>]";
471
- var blockAddKindEntry = defineAddKindRegistryEntry({
472
- completion: {
473
- nextSteps: () => [
474
- "Review the generated sources under src/blocks/ and the updated scripts/block-config.ts entry.",
475
- "Run your workspace build or dev command to verify the new scaffolded block family."
476
- ],
477
- summaryLines: (values, projectDir) => [
478
- `Blocks: ${values.blockSlugs}`,
479
- `Template family: ${values.templateId}`,
480
- `Project directory: ${projectDir}`
481
- ],
482
- title: "Added workspace block"
483
- },
484
- description: "Add a real block slice",
485
- hiddenStringSubmitFields: ["external-layer-id", "external-layer-source"],
486
- nameLabel: "Block name",
487
- async prepareExecution(context) {
488
- const name = requireAddKindName(context, BLOCK_MISSING_NAME_MESSAGE);
489
- const externalLayerId = readOptionalStrictStringFlag(context.flags, "external-layer-id");
490
- const externalLayerSource = readOptionalStrictStringFlag(context.flags, "external-layer-source");
491
- const shouldPromptForLayerSelection = Boolean(externalLayerSource) && !Boolean(externalLayerId) && context.isInteractiveSession;
492
- const selectPrompt = shouldPromptForLayerSelection ? await context.getOrCreatePrompt() : undefined;
493
- const alternateRenderTargets = readOptionalStrictStringFlag(context.flags, "alternate-render-targets");
494
- const dataStorageMode = readOptionalStrictStringFlag(context.flags, "data-storage");
495
- const innerBlocksPreset = readOptionalStrictStringFlag(context.flags, "inner-blocks-preset");
496
- const persistencePolicy = readOptionalStrictStringFlag(context.flags, "persistence-policy");
497
- const requestedTemplateId = readOptionalStrictStringFlag(context.flags, "template");
498
- let resolvedTemplateId = requestedTemplateId ? assertAddBlockTemplateId(context, requestedTemplateId) : undefined;
499
- if (!resolvedTemplateId && context.isInteractiveSession) {
500
- const templatePrompt = await context.getOrCreatePrompt();
501
- resolvedTemplateId = await templatePrompt.select("Select a block template", context.addRuntime.ADD_BLOCK_TEMPLATE_IDS.map((templateId) => ({
502
- hint: `Scaffold the ${templateId} block family`,
503
- label: templateId,
504
- value: templateId
505
- })), 1);
506
- }
507
- resolvedTemplateId ??= "basic";
508
- return createNamedExecutionPlan(context, {
509
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockCommand({
510
- alternateRenderTargets,
511
- blockName: name2,
512
- cwd,
513
- dataStorageMode,
514
- externalLayerId,
515
- externalLayerSource,
516
- innerBlocksPreset,
517
- persistencePolicy,
518
- selectExternalLayerId: selectPrompt ? (options) => selectPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
519
- templateId: resolvedTemplateId
520
- }),
521
- getValues: (result) => ({
522
- blockSlugs: result.blockSlugs.join(", "),
523
- templateId: result.templateId
524
- }),
525
- getWarnings: (result) => result.warnings,
526
- missingNameMessage: BLOCK_MISSING_NAME_MESSAGE,
527
- name,
528
- warnLine: context.warnLine
529
- });
530
- },
531
- sortOrder: 20,
532
- supportsDryRun: true,
533
- 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]",
534
- visibleFieldNames: ({ template }) => BLOCK_VISIBLE_FIELD_ORDER.filter((fieldName) => {
535
- if (fieldName === "alternate-render-targets") {
536
- return isAddPersistenceTemplate(template);
537
- }
538
- if (fieldName === "inner-blocks-preset") {
539
- return template === "compound";
540
- }
541
- if (fieldName === "data-storage" || fieldName === "persistence-policy") {
542
- return isAddPersistenceTemplate(template);
543
- }
544
- return true;
545
- })
546
- });
547
-
548
- // src/add-kinds/contract.ts
549
- var CONTRACT_MISSING_NAME_MESSAGE = "`wp-typia add contract` requires <name>. Usage: wp-typia add contract <name> [--type <ExportedTypeName>].";
550
- var contractAddKindEntry = defineAddKindRegistryEntry({
551
- completion: {
552
- nextSteps: (values) => [
553
- `Edit ${values.typesFile} when the standalone wire shape changes.`,
554
- "Run `wp-typia sync-rest` or `wp-typia sync` to refresh the generated schema artifact."
555
- ],
556
- summaryLines: (values, projectDir) => [
557
- `Contract: ${values.contractSlug}`,
558
- `Source type: ${values.sourceTypeName}`,
559
- `Schema: ${values.schemaFile}`,
560
- `Project directory: ${projectDir}`
561
- ],
562
- title: "Added standalone contract"
563
- },
564
- description: "Add a standalone TypeScript schema contract",
565
- nameLabel: "Contract name",
566
- async prepareExecution(context) {
567
- const name = requireAddKindName(context, CONTRACT_MISSING_NAME_MESSAGE);
568
- const typeName = readOptionalStrictStringFlag(context.flags, "type");
569
- return createNamedExecutionPlan(context, {
570
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddContractCommand({
571
- contractName: name2,
572
- cwd,
573
- typeName
574
- }),
575
- getValues: (result) => ({
576
- contractSlug: result.contractSlug,
577
- schemaFile: result.schemaFile,
578
- sourceTypeName: result.sourceTypeName,
579
- typesFile: result.typesFile
580
- }),
581
- missingNameMessage: CONTRACT_MISSING_NAME_MESSAGE,
582
- name,
583
- warnLine: context.warnLine
584
- });
585
- },
586
- sortOrder: 75,
587
- supportsDryRun: true,
588
- usage: "wp-typia add contract <name> [--type <ExportedTypeName>] [--dry-run]",
589
- visibleFieldNames: () => NAME_TYPE_VISIBLE_FIELDS
590
- });
591
-
592
- // src/add-kinds/core-variation.ts
593
- var CORE_VARIATION_MISSING_NAME_MESSAGE = "`wp-typia add core-variation` requires <name>. Usage: wp-typia add core-variation <block-name> <name> or wp-typia add core-variation <name> --block <namespace/block>.";
594
- var CORE_VARIATION_MISSING_BLOCK_MESSAGE = "`wp-typia add core-variation` requires <block-name>. Usage: wp-typia add core-variation <block-name> <name> or wp-typia add core-variation <name> --block <namespace/block>.";
595
- var CORE_VARIATION_BLOCK_NAME_PATTERN = /^[^/\s]+\/[^/\s]+$/u;
596
- function formatCoreVariationMissingPositionalNameMessage(blockName) {
597
- return [
598
- `\`wp-typia add core-variation ${blockName}\` is missing <name>.`,
599
- "Usage: wp-typia add core-variation <block-name> <name>",
600
- "Alternative: wp-typia add core-variation <name> --block <namespace/block>"
601
- ].join(`
602
- `);
603
- }
604
- function resolveCoreVariationInputs(context) {
605
- const positionalTargetBlockName = context.positionalArgs?.[1];
606
- const positionalVariationName = context.positionalArgs?.[2];
607
- if (positionalVariationName) {
608
- if (!positionalTargetBlockName) {
609
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, CORE_VARIATION_MISSING_BLOCK_MESSAGE);
610
- }
611
- return {
612
- targetBlockName: positionalTargetBlockName,
613
- variationName: positionalVariationName
614
- };
615
- }
616
- const targetBlockFlag = readOptionalStrictStringFlag(context.flags, "block");
617
- const missingPositionalNameTarget = context.name !== undefined && positionalTargetBlockName === context.name && CORE_VARIATION_BLOCK_NAME_PATTERN.test(context.name) ? context.name : undefined;
618
- if (missingPositionalNameTarget && !targetBlockFlag) {
619
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, formatCoreVariationMissingPositionalNameMessage(missingPositionalNameTarget));
620
- }
621
- const variationName = requireAddKindName(context, CORE_VARIATION_MISSING_NAME_MESSAGE);
622
- if (!targetBlockFlag) {
623
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, CORE_VARIATION_MISSING_BLOCK_MESSAGE);
624
- }
625
- return {
626
- targetBlockName: targetBlockFlag,
627
- variationName
628
- };
629
- }
630
- var coreVariationAddKindEntry = defineAddKindRegistryEntry({
631
- completion: {
632
- nextSteps: (values) => [
633
- `Review ${values.variationFile}.`,
634
- "Run your workspace build or dev command to verify the editor-side variation registration."
635
- ],
636
- summaryLines: (values, projectDir) => [
637
- `Core variation: ${values.variationSlug}`,
638
- `Target block: ${values.targetBlockName}`,
639
- `Project directory: ${projectDir}`
640
- ],
641
- title: "Added core block variation"
642
- },
643
- description: "Add an editor-side variation for an existing core or external block",
644
- nameLabel: "Variation name",
645
- async prepareExecution(context) {
646
- const { targetBlockName, variationName } = resolveCoreVariationInputs(context);
647
- return createNamedExecutionPlan(context, {
648
- execute: ({ cwd, name }) => context.addRuntime.runAddCoreVariationCommand({
649
- cwd,
650
- targetBlockName,
651
- variationName: name
652
- }),
653
- getValues: (result) => ({
654
- targetBlockName: result.targetBlockName,
655
- variationFile: result.variationFile,
656
- variationSlug: result.variationSlug
657
- }),
658
- getWarnings: (result) => result.warnings,
659
- missingNameMessage: CORE_VARIATION_MISSING_NAME_MESSAGE,
660
- name: variationName,
661
- warnLine: context.warnLine
662
- });
663
- },
664
- sortOrder: 25,
665
- supportsDryRun: true,
666
- usage: `wp-typia add core-variation <block-name> <name> [--dry-run]
667
- Alias: wp-typia add core-variation <name> --block <namespace/block> [--dry-run]`,
668
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
669
- });
670
-
671
- // src/add-kinds/editor-plugin.ts
672
- var EDITOR_PLUGIN_MISSING_NAME_MESSAGE = "`wp-typia add editor-plugin` requires <name>. Usage: wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>].";
673
- var editorPluginAddKindEntry = defineAddKindRegistryEntry({
674
- completion: {
675
- nextSteps: (values) => [
676
- `Review src/editor-plugins/${values.editorPluginSlug}/.`,
677
- "Run your workspace build or dev command to verify the new editor plugin registration."
678
- ],
679
- summaryLines: (values, projectDir) => [
680
- `Editor plugin: ${values.editorPluginSlug}`,
681
- `Slot: ${values.slot}`,
682
- `Project directory: ${projectDir}`
683
- ],
684
- title: "Added editor plugin"
685
- },
686
- description: "Add a slot-aware document editor extension shell",
687
- nameLabel: "Editor plugin name",
688
- async prepareExecution(context) {
689
- const name = requireAddKindName(context, EDITOR_PLUGIN_MISSING_NAME_MESSAGE);
690
- const slot = readOptionalStrictStringFlag(context.flags, "slot");
691
- return createNamedExecutionPlan(context, {
692
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddEditorPluginCommand({
693
- cwd,
694
- editorPluginName: name2,
695
- slot
696
- }),
697
- getValues: (result) => ({
698
- editorPluginSlug: result.editorPluginSlug,
699
- slot: result.slot
700
- }),
701
- missingNameMessage: EDITOR_PLUGIN_MISSING_NAME_MESSAGE,
702
- name,
703
- warnLine: context.warnLine
704
- });
705
- },
706
- sortOrder: 120,
707
- supportsDryRun: true,
708
- usage: "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>] [--dry-run]",
709
- visibleFieldNames: () => NAME_SLOT_VISIBLE_FIELDS
710
- });
711
-
712
- // src/add-kinds/hooked-block.ts
713
- var HOOKED_BLOCK_MISSING_NAME_MESSAGE = "`wp-typia add hooked-block` requires <block-slug>. Usage: wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>.";
714
- var hookedBlockAddKindEntry = defineAddKindRegistryEntry({
715
- completion: {
716
- nextSteps: (values) => [
717
- `Review src/blocks/${values.blockSlug}/block.json for the new blockHooks entry.`,
718
- "Run your workspace build or dev command to verify the updated hooked-block metadata."
719
- ],
720
- summaryLines: (values, projectDir) => [
721
- `Block: ${values.blockSlug}`,
722
- `Anchor: ${values.anchorBlockName}`,
723
- `Position: ${values.position}`,
724
- `Project directory: ${projectDir}`
725
- ],
726
- title: "Added blockHooks metadata"
727
- },
728
- description: "Add block.json hook metadata to an existing block",
729
- nameLabel: "Target block",
730
- async prepareExecution(context) {
731
- const name = requireAddKindName(context, HOOKED_BLOCK_MISSING_NAME_MESSAGE);
732
- const anchorBlockName = requireStrictStringFlag(context.flags, "anchor", "`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
733
- const position = requireStrictStringFlag(context.flags, "position", "`wp-typia add hooked-block` requires --position <before|after|firstChild|lastChild>.");
734
- return createNamedExecutionPlan(context, {
735
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddHookedBlockCommand({
736
- anchorBlockName,
737
- blockName: name2,
738
- cwd,
739
- position
740
- }),
741
- getValues: (result) => ({
742
- anchorBlockName: result.anchorBlockName,
743
- blockSlug: result.blockSlug,
744
- position: result.position
745
- }),
746
- missingNameMessage: HOOKED_BLOCK_MISSING_NAME_MESSAGE,
747
- name,
748
- warnLine: context.warnLine
749
- });
750
- },
751
- sortOrder: 110,
752
- supportsDryRun: true,
753
- usage: "wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild> [--dry-run]",
754
- visibleFieldNames: () => NAME_ANCHOR_POSITION_VISIBLE_FIELDS
755
- });
756
-
757
- // src/add-kinds/integration-env.ts
758
- var INTEGRATION_ENV_MISSING_NAME_MESSAGE = "`wp-typia add integration-env` requires <name>. Usage: wp-typia add integration-env <name> [--wp-env] [--release-zip] [--service <none|docker-compose>].";
759
- var integrationEnvAddKindEntry = defineAddKindRegistryEntry({
760
- completion: {
761
- nextSteps: (values) => [
762
- `Review scripts/integration-smoke/${values.integrationEnvSlug}.mjs and docs/integration-env/${values.integrationEnvSlug}.md.`,
763
- "Copy `.env.example` to `.env`, adjust local URLs or credentials, then run the generated smoke script.",
764
- ...values.withWpEnv === "true" ? ["Run `npm run wp-env:start` before the smoke check when using the generated wp-env preset."] : [],
765
- ...values.withReleaseZip === "true" ? ["Run `npm run release:zip` after smoke checks pass to build a distributable plugin zip."] : []
766
- ],
767
- summaryLines: (values, projectDir) => [
768
- `Integration env: ${values.integrationEnvSlug}`,
769
- `wp-env preset: ${values.withWpEnv}`,
770
- `Release zip scripts: ${values.withReleaseZip}`,
771
- `Service starter: ${values.service}`,
772
- `Project directory: ${projectDir}`
773
- ],
774
- title: "Added integration environment starter"
775
- },
776
- description: "Add an opt-in local WordPress integration smoke environment starter",
777
- nameLabel: "Integration env name",
778
- async prepareExecution(context) {
779
- const service = readOptionalStrictStringFlag(context.flags, "service");
780
- const withReleaseZip = Boolean(context.flags["release-zip"]);
781
- const withWpEnv = Boolean(context.flags["wp-env"]);
782
- return createNamedExecutionPlan(context, {
783
- execute: ({ cwd, name }) => context.addRuntime.runAddIntegrationEnvCommand({
784
- cwd,
785
- integrationEnvName: name,
786
- service,
787
- withReleaseZip,
788
- withWpEnv
789
- }),
790
- getValues: (result) => ({
791
- integrationEnvSlug: result.integrationEnvSlug,
792
- service: result.service,
793
- withReleaseZip: String(result.withReleaseZip),
794
- withWpEnv: String(result.withWpEnv)
795
- }),
796
- getWarnings: (result) => result.warnings,
797
- missingNameMessage: INTEGRATION_ENV_MISSING_NAME_MESSAGE,
798
- warnLine: context.warnLine
799
- });
800
- },
801
- sortOrder: 25,
802
- supportsDryRun: true,
803
- usage: "wp-typia add integration-env <name> [--wp-env] [--release-zip] [--service <none|docker-compose>] [--dry-run]",
804
- visibleFieldNames: () => NAME_ONLY_VISIBLE_FIELDS,
805
- hiddenBooleanSubmitFields: ["wp-env", "release-zip"],
806
- hiddenStringSubmitFields: ["service"]
807
- });
808
-
809
- // src/add-kinds/pattern.ts
810
- var PATTERN_MISSING_NAME_MESSAGE = "`wp-typia add pattern` requires <name>. Usage: wp-typia add pattern <name>.";
811
- var patternAddKindEntry = defineAddKindRegistryEntry({
812
- completion: {
813
- nextSteps: (values) => [
814
- `Review ${values.contentFile}.`,
815
- "Run your workspace build or dev command to verify the new pattern registration."
816
- ],
817
- summaryLines: (values, projectDir) => [
818
- `Pattern: ${values.patternSlug}`,
819
- `Content file: ${values.contentFile}`,
820
- `Project directory: ${projectDir}`
821
- ],
822
- title: "Added workspace pattern"
823
- },
824
- description: "Add a PHP block pattern shell",
825
- hiddenStringSubmitFields: ["tag"],
826
- nameLabel: "Pattern name",
827
- async prepareExecution(context) {
828
- const name = requireAddKindName(context, PATTERN_MISSING_NAME_MESSAGE);
829
- const scope = resolvePatternScopeFlag(context);
830
- const sectionRole = resolvePatternSectionRoleFlag(context, scope);
831
- const catalogTitle = typeof context.flags["catalog-title"] === "string" ? context.flags["catalog-title"] : undefined;
832
- const tags = normalizePatternTagFlags(context.flags.tags, context.flags.tag);
833
- const thumbnailUrl = typeof context.flags["thumbnail-url"] === "string" ? context.flags["thumbnail-url"] : undefined;
834
- return {
835
- execute: (cwd) => context.addRuntime.runAddPatternCommand({
836
- catalogTitle,
837
- cwd,
838
- patternScope: scope,
839
- patternName: name,
840
- sectionRole,
841
- tags,
842
- thumbnailUrl
843
- }),
844
- getValues: (result) => ({
845
- contentFile: result.contentFile,
846
- patternSlug: result.patternSlug,
847
- patternScope: result.patternScope,
848
- ...result.sectionRole ? { sectionRole: result.sectionRole } : {}
849
- }),
850
- warnLine: context.warnLine
851
- };
852
- },
853
- sortOrder: 60,
854
- supportsDryRun: true,
855
- usage: "wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--catalog-title <title>] [--tags <tag,...>] [--tag <tag>...] [--thumbnail-url <url>] [--dry-run]",
856
- visibleFieldNames: () => PATTERN_CATALOG_VISIBLE_FIELDS
857
- });
858
- function createInvalidPatternArgumentError(message) {
859
- return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, message);
860
- }
861
- function createMissingPatternArgumentError(message) {
862
- return createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, message);
863
- }
864
- function resolvePatternScopeFlag(context) {
865
- const scope = readOptionalLooseStringFlag(context.flags, "scope");
866
- if (!scope) {
867
- return;
868
- }
869
- if (context.addRuntime.PATTERN_CATALOG_SCOPE_IDS.includes(scope)) {
870
- return scope;
871
- }
872
- throw createInvalidPatternArgumentError(`\`--scope\` must be one of: ${context.addRuntime.PATTERN_CATALOG_SCOPE_IDS.join(", ")}. Usage: wp-typia add pattern <name> --scope <full|section>.`);
873
- }
874
- function resolvePatternSectionRoleFlag(context, scope) {
875
- const sectionRole = readOptionalLooseStringFlag(context.flags, "section-role");
876
- if (scope === "section" && sectionRole === undefined) {
877
- throw createMissingPatternArgumentError("`wp-typia add pattern --scope section` requires --section-role <role> because section-scoped patterns need a typed catalog section role.");
878
- }
879
- if (scope !== "section" && sectionRole !== undefined) {
880
- throw createInvalidPatternArgumentError("`--section-role` only applies with `--scope section`. Use `--scope section --section-role <role>` or omit `--section-role` for full patterns.");
881
- }
882
- const normalizedSectionRole = sectionRole === undefined ? undefined : context.addRuntime.normalizeBlockSlug(sectionRole);
883
- if (normalizedSectionRole && !context.addRuntime.PATTERN_SECTION_ROLE_PATTERN.test(normalizedSectionRole)) {
884
- throw createInvalidPatternArgumentError("`--section-role` must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens. Section roles apply only with `--scope section`.");
885
- }
886
- if (sectionRole !== undefined && !normalizedSectionRole) {
887
- throw createInvalidPatternArgumentError("`--section-role` must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens. Section roles apply only with `--scope section`.");
888
- }
889
- return normalizedSectionRole;
890
- }
891
- function collectStringFlagValues(value) {
892
- if (typeof value === "string") {
893
- return [value];
894
- }
895
- if (Array.isArray(value)) {
896
- return value.filter((item) => typeof item === "string");
897
- }
898
- return [];
899
- }
900
- function normalizePatternTagFlags(tagsFlag, tagFlag) {
901
- const tags = [
902
- ...collectStringFlagValues(tagsFlag),
903
- ...collectStringFlagValues(tagFlag)
904
- ];
905
- return tags.length > 0 ? tags : undefined;
906
- }
907
-
908
- // src/add-kinds/post-meta.ts
909
- var POST_META_MISSING_NAME_MESSAGE = "`wp-typia add post-meta` requires <name>. Usage: wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>].";
910
- var POST_META_MISSING_POST_TYPE_MESSAGE = "`wp-typia add post-meta` requires --post-type <post-type>. Usage: wp-typia add post-meta <name> --post-type <post-type>.";
911
- var postMetaAddKindEntry = defineAddKindRegistryEntry({
912
- completion: {
913
- nextSteps: (values) => [
914
- `Edit ${values.typesFile} when the post meta shape changes.`,
915
- "Run `wp-typia sync-rest --check` to verify the generated meta schema is current.",
916
- `Smoke test ${values.metaKey} on the ${values.postType} post type in WordPress.`
917
- ],
918
- summaryLines: (values, projectDir) => [
919
- `Post meta contract: ${values.postMetaSlug}`,
920
- `Post type: ${values.postType}`,
921
- `Meta key: ${values.metaKey}`,
922
- `REST/editor exposure: ${values.showInRest}`,
923
- `Schema: ${values.schemaFile}`,
924
- `PHP: ${values.phpFile}`,
925
- `Project directory: ${projectDir}`
926
- ],
927
- title: "Added post meta contract"
928
- },
929
- description: "Add a typed WordPress post meta contract",
930
- hiddenBooleanSubmitFields: ["hide-from-rest"],
931
- hiddenStringSubmitFields: ["meta-key"],
932
- nameLabel: "Post meta name",
933
- async prepareExecution(context) {
934
- const name = requireAddKindName(context, POST_META_MISSING_NAME_MESSAGE);
935
- const hideFromRest = Boolean(context.flags["hide-from-rest"] ?? context.flags.hideFromRest);
936
- const metaKey = readOptionalDashedOrCamelStringFlag(context.flags, "meta-key", "metaKey");
937
- const postType = readOptionalDashedOrCamelStringFlag(context.flags, "post-type", "postType") ?? requireStrictStringFlag(context.flags, "post-type", POST_META_MISSING_POST_TYPE_MESSAGE);
938
- const typeName = readOptionalStrictStringFlag(context.flags, "type");
939
- return createNamedExecutionPlan(context, {
940
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddPostMetaCommand({
941
- cwd,
942
- hideFromRest,
943
- metaKey,
944
- postMetaName: name2,
945
- postType,
946
- typeName
947
- }),
948
- getValues: (result) => ({
949
- metaKey: result.metaKey,
950
- phpFile: result.phpFile,
951
- postMetaSlug: result.postMetaSlug,
952
- postType: result.postType,
953
- schemaFile: result.schemaFile,
954
- showInRest: result.showInRest ? "enabled" : "disabled",
955
- sourceTypeName: result.sourceTypeName,
956
- typesFile: result.typesFile
957
- }),
958
- missingNameMessage: POST_META_MISSING_NAME_MESSAGE,
959
- name,
960
- warnLine: context.warnLine
961
- });
962
- },
963
- sortOrder: 85,
964
- supportsDryRun: true,
965
- usage: "wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>] [--hide-from-rest] [--dry-run]",
966
- visibleFieldNames: () => NAME_POST_TYPE_TYPE_VISIBLE_FIELDS
967
- });
968
-
969
- // src/add-kinds/rest-resource.ts
970
- var REST_RESOURCE_GENERATED_USAGE = "Generated: wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--dry-run]";
971
- var REST_RESOURCE_MANUAL_USAGE = "Manual: wp-typia add rest-resource <name> --manual [--namespace <vendor/v1>] [--method <GET|POST|PUT|PATCH|DELETE>] [--auth <public|authenticated|public-write-protected>] [--path <route-pattern>|--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--query-type <Type>] [--body-type <Type>] [--response-type <Type>] [--secret-field <field>] [--secret-state-field|--secret-has-value-field <field>] [--secret-preserve-on-empty <true|false>] [--dry-run]";
972
- var REST_RESOURCE_USAGE = `${REST_RESOURCE_GENERATED_USAGE}
973
- ${REST_RESOURCE_MANUAL_USAGE}`;
974
- var REST_RESOURCE_MISSING_NAME_MESSAGE = [
975
- "`wp-typia add rest-resource` requires <name>. Usage:",
976
- ` ${REST_RESOURCE_GENERATED_USAGE}`,
977
- ` ${REST_RESOURCE_MANUAL_USAGE}`
978
- ].join(`
979
- `);
980
- var SECRET_PRESERVE_ON_EMPTY_TRUE_VALUES = new Set(["1", "true", "yes"]);
981
- var SECRET_PRESERVE_ON_EMPTY_FALSE_VALUES = new Set(["0", "false", "no"]);
982
- function readOptionalSecretPreserveOnEmptyFlag(flags) {
983
- const value = flags["secret-preserve-on-empty"] ?? flags.secretPreserveOnEmpty;
984
- if (value === undefined || value === null) {
985
- return;
986
- }
987
- if (typeof value === "boolean") {
988
- return value;
989
- }
990
- if (typeof value !== "string") {
991
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`--secret-preserve-on-empty` requires a value.");
992
- }
993
- const normalized = value.trim().toLowerCase();
994
- if (normalized.length === 0) {
995
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`--secret-preserve-on-empty` requires a value.");
996
- }
997
- if (SECRET_PRESERVE_ON_EMPTY_TRUE_VALUES.has(normalized)) {
998
- return true;
999
- }
1000
- if (SECRET_PRESERVE_ON_EMPTY_FALSE_VALUES.has(normalized)) {
1001
- return false;
1002
- }
1003
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "Manual REST contract --secret-preserve-on-empty must be true or false.");
1004
- }
1005
- var restResourceAddKindEntry = defineAddKindRegistryEntry({
1006
- completion: {
1007
- nextSteps: (values) => values.mode === "manual" ? [
1008
- `Review src/rest/${values.restResourceSlug}/ and edit the manual contract types to match the external route owner.`,
1009
- "Run sync-rest --check after changing the contract types to verify schemas, OpenAPI, and client artifacts."
1010
- ] : [
1011
- `Review src/rest/${values.restResourceSlug}/ and inc/rest/${values.restResourceSlug}.php.`,
1012
- "Run your workspace build or dev command to verify the generated REST resource contract."
1013
- ],
1014
- summaryLines: (values, projectDir) => [
1015
- `REST resource: ${values.restResourceSlug}`,
1016
- `Mode: ${values.mode}`,
1017
- `Namespace: ${values.namespace}`,
1018
- ...values.mode === "manual" ? [
1019
- `Route: ${values.method} /${values.namespace}${values.pathPattern}`,
1020
- `Auth: ${values.auth}`,
1021
- ...values.secretFieldName ? [
1022
- `Secret field: ${values.secretFieldName} -> ${values.secretStateFieldName}`,
1023
- `Secret preserve on empty: ${values.secretPreserveOnEmpty}`
1024
- ] : [],
1025
- ...values.permissionCallback ? [`Declared permission callback: ${values.permissionCallback}`] : [],
1026
- ...values.controllerClass ? [`Declared controller class: ${values.controllerClass}`] : [],
1027
- ...values.controllerExtends ? [`Declared controller base: ${values.controllerExtends}`] : []
1028
- ] : [
1029
- `Methods: ${values.methods}`,
1030
- ...values.routePattern ? [`Item route: /${values.namespace}${values.routePattern}`] : [],
1031
- ...values.permissionCallback ? [`Permission callback: ${values.permissionCallback}`] : [],
1032
- ...values.controllerClass ? [`Controller class: ${values.controllerClass}`] : []
1033
- ],
1034
- `Project directory: ${projectDir}`
1035
- ],
1036
- title: "Added REST resource contract"
1037
- },
1038
- description: "Add a generated or type-only REST resource contract",
1039
- hiddenBooleanSubmitFields: ["manual"],
1040
- hiddenStringSubmitFields: [
1041
- "auth",
1042
- "body-type",
1043
- "controller-class",
1044
- "controller-extends",
1045
- "method",
1046
- "path",
1047
- "permission-callback",
1048
- "query-type",
1049
- "response-type",
1050
- "route-pattern",
1051
- "secret-field",
1052
- "secret-has-value-field",
1053
- "secret-masked-response-field",
1054
- "secret-preserve-on-empty",
1055
- "secret-state-field"
1056
- ],
1057
- nameLabel: "REST resource name",
1058
- async prepareExecution(context) {
1059
- const name = requireAddKindName(context, REST_RESOURCE_MISSING_NAME_MESSAGE);
1060
- const auth = readOptionalStrictStringFlag(context.flags, "auth");
1061
- const bodyTypeName = readOptionalStrictStringFlag(context.flags, "body-type");
1062
- const controllerClass = readOptionalDashedOrCamelStringFlag(context.flags, "controller-class", "controllerClass");
1063
- const controllerExtends = readOptionalDashedOrCamelStringFlag(context.flags, "controller-extends", "controllerExtends");
1064
- const manual = Boolean(context.flags.manual);
1065
- const method = readOptionalStrictStringFlag(context.flags, "method");
1066
- const methods = readOptionalStrictStringFlag(context.flags, "methods");
1067
- const namespace = readOptionalStrictStringFlag(context.flags, "namespace");
1068
- const permissionCallback = readOptionalDashedOrCamelStringFlag(context.flags, "permission-callback", "permissionCallback");
1069
- const pathPattern = readOptionalStrictStringFlag(context.flags, "path");
1070
- const queryTypeName = readOptionalStrictStringFlag(context.flags, "query-type");
1071
- const responseTypeName = readOptionalStrictStringFlag(context.flags, "response-type");
1072
- const routePattern = readOptionalDashedOrCamelStringFlag(context.flags, "route-pattern", "routePattern");
1073
- const secretFieldName = readOptionalDashedOrCamelStringFlag(context.flags, "secret-field", "secretField");
1074
- const secretHasValueFieldName = readOptionalDashedOrCamelStringFlag(context.flags, "secret-has-value-field", "secretHasValueField");
1075
- const secretMaskedResponseFieldName = readOptionalDashedOrCamelStringFlag(context.flags, "secret-masked-response-field", "secretMaskedResponseField");
1076
- const secretPreserveOnEmpty = readOptionalSecretPreserveOnEmptyFlag(context.flags);
1077
- const secretStateFieldName = readOptionalDashedOrCamelStringFlag(context.flags, "secret-state-field", "secretStateField");
1078
- return createNamedExecutionPlan(context, {
1079
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddRestResourceCommand({
1080
- auth,
1081
- bodyTypeName,
1082
- controllerClass,
1083
- controllerExtends,
1084
- cwd,
1085
- manual,
1086
- method,
1087
- methods,
1088
- namespace,
1089
- permissionCallback,
1090
- pathPattern,
1091
- queryTypeName,
1092
- restResourceName: name2,
1093
- responseTypeName,
1094
- routePattern,
1095
- secretFieldName,
1096
- secretHasValueFieldName,
1097
- secretMaskedResponseFieldName,
1098
- secretPreserveOnEmpty,
1099
- secretStateFieldName
1100
- }),
1101
- getValues: (result) => ({
1102
- auth: result.auth ?? "",
1103
- controllerClass: result.controllerClass ?? "",
1104
- controllerExtends: result.controllerExtends ?? "",
1105
- method: result.method ?? "",
1106
- methods: result.methods.join(", "),
1107
- mode: result.mode,
1108
- namespace: result.namespace,
1109
- pathPattern: result.pathPattern ?? "",
1110
- permissionCallback: result.permissionCallback ?? "",
1111
- restResourceSlug: result.restResourceSlug,
1112
- routePattern: result.routePattern ?? "",
1113
- secretFieldName: result.secretFieldName ?? "",
1114
- secretPreserveOnEmpty: result.secretPreserveOnEmpty === undefined ? "" : String(result.secretPreserveOnEmpty),
1115
- secretStateFieldName: result.secretStateFieldName ?? ""
1116
- }),
1117
- missingNameMessage: REST_RESOURCE_MISSING_NAME_MESSAGE,
1118
- name,
1119
- warnLine: context.warnLine
1120
- });
1121
- },
1122
- sortOrder: 80,
1123
- supportsDryRun: true,
1124
- usage: REST_RESOURCE_USAGE,
1125
- visibleFieldNames: () => NAME_NAMESPACE_METHODS_VISIBLE_FIELDS
1126
- });
1127
-
1128
- // src/add-kinds/style.ts
1129
- var STYLE_MISSING_NAME_MESSAGE = "`wp-typia add style` requires <name>. Usage: wp-typia add style <name> --block <block-slug>.";
1130
- var styleAddKindEntry = defineAddKindRegistryEntry({
1131
- completion: {
1132
- nextSteps: (values) => [
1133
- `Review src/blocks/${values.blockSlug}/styles/${values.styleSlug}.ts.`,
1134
- "Run your workspace build or dev command to verify the new block style registration."
1135
- ],
1136
- summaryLines: (values, projectDir) => [
1137
- `Block style: ${values.styleSlug}`,
1138
- `Target block: ${values.blockSlug}`,
1139
- `Project directory: ${projectDir}`
1140
- ],
1141
- title: "Added block style"
1142
- },
1143
- description: "Add a Block Styles registration to an existing block",
1144
- nameLabel: "Style name",
1145
- async prepareExecution(context) {
1146
- const name = requireAddKindName(context, STYLE_MISSING_NAME_MESSAGE);
1147
- const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add style` requires --block <block-slug>.");
1148
- return createNamedExecutionPlan(context, {
1149
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockStyleCommand({
1150
- blockName: blockSlug,
1151
- cwd,
1152
- styleName: name2
1153
- }),
1154
- getValues: (result) => ({
1155
- blockSlug: result.blockSlug,
1156
- styleSlug: result.styleSlug
1157
- }),
1158
- missingNameMessage: STYLE_MISSING_NAME_MESSAGE,
1159
- name,
1160
- warnLine: context.warnLine
1161
- });
1162
- },
1163
- sortOrder: 40,
1164
- supportsDryRun: true,
1165
- usage: "wp-typia add style <name> --block <block-slug> [--dry-run]",
1166
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
1167
- });
1168
-
1169
- // src/add-kinds/transform.ts
1170
- var TRANSFORM_MISSING_NAME_MESSAGE = "`wp-typia add transform` requires <name>. Usage: wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>.";
1171
- var transformAddKindEntry = defineAddKindRegistryEntry({
1172
- completion: {
1173
- nextSteps: (values) => [
1174
- `Review src/blocks/${values.blockSlug}/transforms/${values.transformSlug}.ts.`,
1175
- "Run your workspace build or dev command to verify the new block transform registration."
1176
- ],
1177
- summaryLines: (values, projectDir) => [
1178
- `Block transform: ${values.transformSlug}`,
1179
- `From: ${values.fromBlockName}`,
1180
- `To: ${values.toBlockName}`,
1181
- `Project directory: ${projectDir}`
1182
- ],
1183
- title: "Added block transform"
1184
- },
1185
- description: "Add a block-to-block transform into a workspace block",
1186
- nameLabel: "Transform name",
1187
- async prepareExecution(context) {
1188
- const name = requireAddKindName(context, TRANSFORM_MISSING_NAME_MESSAGE);
1189
- const fromBlockName = requireStrictStringFlag(context.flags, "from", "`wp-typia add transform` requires --from <namespace/block>.");
1190
- const toBlockName = requireStrictStringFlag(context.flags, "to", "`wp-typia add transform` requires --to <block-slug|namespace/block-slug>.");
1191
- return createNamedExecutionPlan(context, {
1192
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddBlockTransformCommand({
1193
- cwd,
1194
- fromBlockName,
1195
- toBlockName,
1196
- transformName: name2
1197
- }),
1198
- getValues: (result) => ({
1199
- blockSlug: result.blockSlug,
1200
- fromBlockName: result.fromBlockName,
1201
- toBlockName: result.toBlockName,
1202
- transformSlug: result.transformSlug
1203
- }),
1204
- missingNameMessage: TRANSFORM_MISSING_NAME_MESSAGE,
1205
- name,
1206
- warnLine: context.warnLine
1207
- });
1208
- },
1209
- sortOrder: 50,
1210
- supportsDryRun: true,
1211
- usage: "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]",
1212
- visibleFieldNames: () => NAME_FROM_TO_VISIBLE_FIELDS
1213
- });
1214
-
1215
- // src/add-kinds/variation.ts
1216
- var VARIATION_MISSING_NAME_MESSAGE = "`wp-typia add variation` requires <name>. Usage: wp-typia add variation <name> --block <block-slug>";
1217
- var variationAddKindEntry = defineAddKindRegistryEntry({
1218
- completion: {
1219
- nextSteps: (values) => [
1220
- `Review src/blocks/${values.blockSlug}/variations/${values.variationSlug}.ts.`,
1221
- "Run your workspace build or dev command to pick up the new variation."
1222
- ],
1223
- summaryLines: (values, projectDir) => [
1224
- `Variation: ${values.variationSlug}`,
1225
- `Target block: ${values.blockSlug}`,
1226
- `Project directory: ${projectDir}`
1227
- ],
1228
- title: "Added workspace variation"
1229
- },
1230
- description: "Add a variation to an existing block",
1231
- nameLabel: "Variation name",
1232
- async prepareExecution(context) {
1233
- const name = requireAddKindName(context, VARIATION_MISSING_NAME_MESSAGE);
1234
- const blockSlug = requireStrictStringFlag(context.flags, "block", "`wp-typia add variation` requires --block <block-slug>.");
1235
- return createNamedExecutionPlan(context, {
1236
- execute: ({ cwd, name: name2 }) => context.addRuntime.runAddVariationCommand({
1237
- blockName: blockSlug,
1238
- cwd,
1239
- variationName: name2
1240
- }),
1241
- getValues: (result) => ({
1242
- blockSlug: result.blockSlug,
1243
- variationSlug: result.variationSlug
1244
- }),
1245
- missingNameMessage: VARIATION_MISSING_NAME_MESSAGE,
1246
- name,
1247
- warnLine: context.warnLine
1248
- });
1249
- },
1250
- sortOrder: 30,
1251
- supportsDryRun: true,
1252
- usage: "wp-typia add variation <name> --block <block-slug> [--dry-run]",
1253
- visibleFieldNames: () => NAME_BLOCK_VISIBLE_FIELDS
1254
- });
1255
-
1256
- // src/add-kind-registry.ts
1257
- var ADD_KIND_REGISTRY = {
1258
- "admin-view": adminViewAddKindEntry,
1259
- block: blockAddKindEntry,
1260
- "integration-env": integrationEnvAddKindEntry,
1261
- "core-variation": coreVariationAddKindEntry,
1262
- variation: variationAddKindEntry,
1263
- style: styleAddKindEntry,
1264
- transform: transformAddKindEntry,
1265
- pattern: patternAddKindEntry,
1266
- "binding-source": bindingSourceAddKindEntry,
1267
- contract: contractAddKindEntry,
1268
- "rest-resource": restResourceAddKindEntry,
1269
- "post-meta": postMetaAddKindEntry,
1270
- ability: abilityAddKindEntry,
1271
- "ai-feature": aiFeatureAddKindEntry,
1272
- "hooked-block": hookedBlockAddKindEntry,
1273
- "editor-plugin": editorPluginAddKindEntry
1274
- };
1275
- function isAddKindId(value) {
1276
- return typeof value === "string" && ADD_KIND_IDS.includes(value);
1277
- }
1278
- async function getAddKindExecutionPlan(kind, context) {
1279
- return ADD_KIND_REGISTRY[kind].prepareExecution(context);
1280
- }
1281
- function buildAddKindCompletionDetails(kind, options) {
1282
- const descriptor = ADD_KIND_REGISTRY[kind].completion;
1283
- return {
1284
- nextSteps: descriptor.nextSteps(options.values),
1285
- summaryLines: descriptor.summaryLines(options.values, options.projectDir),
1286
- title: descriptor.title
1287
- };
1288
- }
1289
- function supportsAddKindDryRun(kind) {
1290
- return ADD_KIND_REGISTRY[kind].supportsDryRun;
1291
- }
1292
-
1293
- // src/cli-error-messages.ts
1294
- var MISSING_CREATE_PROJECT_DIR_DETAIL_LINES = [
1295
- "`wp-typia create` requires <project-dir>.",
1296
- "`--dry-run` still needs a logical project directory name because wp-typia derives slugs, package names, and planned file paths from it."
1297
- ];
1298
- function formatMissingAddKindDetailLine() {
1299
- return `\`wp-typia add\` requires <kind>. Usage: wp-typia add ${formatAddKindUsagePlaceholder()} ...`;
1300
- }
1301
- function shouldPrintMissingAddKindHelp(options) {
1302
- if (typeof options.emitOutput === "boolean") {
1303
- return options.emitOutput;
1304
- }
1305
- return options.format !== "json";
1306
- }
1307
- function buildMissingCreateProjectDirDetailLines() {
1308
- return [...MISSING_CREATE_PROJECT_DIR_DETAIL_LINES];
1309
- }
1310
-
1311
- // src/runtime-bridge-add-dry-run.ts
1312
- import fs2 from "fs";
1313
- import { promises as fsp } from "fs";
1314
- import path from "path";
1315
- var SKIPPED_COPY_ROOT_ENTRIES = new Set([".git", "node_modules"]);
1316
- var SKIPPED_COMPARE_ROOT_ENTRIES = new Set([
1317
- ".git",
1318
- ".pnp.cjs",
1319
- ".pnp.loader.mjs",
1320
- "node_modules"
1321
- ]);
1322
- async function copyWorkspaceProject(sourceDir, targetDir) {
1323
- await fsp.cp(sourceDir, targetDir, {
1324
- filter: (sourcePath) => {
1325
- const relativePath = path.relative(sourceDir, sourcePath);
1326
- if (relativePath === "") {
1327
- return true;
1328
- }
1329
- const [rootEntry] = relativePath.split(path.sep);
1330
- return !SKIPPED_COPY_ROOT_ENTRIES.has(rootEntry ?? "");
1331
- },
1332
- recursive: true
1333
- });
1334
- }
1335
- function formatInstallMarkerError(error) {
1336
- if (error instanceof Error) {
1337
- return error.message;
1338
- }
1339
- return String(error);
1340
- }
1341
- function formatInstallMarkerFailures(failures) {
1342
- return failures.map((failure) => `${failure.operation}: ${failure.reason}`).join("; ");
1343
- }
1344
- function ensureWorkspaceInstallMarker({
1345
- fsAdapter = fs2,
1346
- sourceMarker,
1347
- targetMarker
1348
- }) {
1349
- const failures = [];
1350
- try {
1351
- fsAdapter.symlinkSync(sourceMarker, targetMarker);
1352
- return;
1353
- } catch (error) {
1354
- failures.push({
1355
- operation: "symlink",
1356
- reason: formatInstallMarkerError(error)
1357
- });
1358
- }
1359
- try {
1360
- fsAdapter.linkSync(sourceMarker, targetMarker);
1361
- return;
1362
- } catch (error) {
1363
- failures.push({
1364
- operation: "hard link",
1365
- reason: formatInstallMarkerError(error)
1366
- });
1367
- }
1368
- try {
1369
- fsAdapter.copyFileSync(sourceMarker, targetMarker);
1370
- return;
1371
- } catch (error) {
1372
- failures.push({
1373
- operation: "copy",
1374
- reason: formatInstallMarkerError(error)
1375
- });
1376
- }
1377
- throw new Error([
1378
- "Failed to prepare dry-run install marker.",
1379
- `Source: ${sourceMarker}`,
1380
- `Target: ${targetMarker}`,
1381
- `Fallback failures: ${formatInstallMarkerFailures(failures)}`
1382
- ].join(" "));
1383
- }
1384
- function ensureWorkspaceInstallMarkers(sourceDir, targetDir) {
1385
- const sourceNodeModules = path.join(sourceDir, "node_modules");
1386
- if (fs2.existsSync(sourceNodeModules)) {
1387
- fs2.symlinkSync(sourceNodeModules, path.join(targetDir, "node_modules"), "junction");
1388
- }
1389
- for (const marker of [".pnp.cjs", ".pnp.loader.mjs"]) {
1390
- const sourceMarker = path.join(sourceDir, marker);
1391
- if (!fs2.existsSync(sourceMarker)) {
1392
- continue;
1393
- }
1394
- const targetMarker = path.join(targetDir, marker);
1395
- ensureWorkspaceInstallMarker({ sourceMarker, targetMarker });
1396
- }
1397
- }
1398
- async function listWorkspaceFiles(rootDir) {
1399
- const files = new Map;
1400
- async function visit(currentDir) {
1401
- const entries = await fsp.readdir(currentDir, { withFileTypes: true });
1402
- for (const entry of entries) {
1403
- const absolutePath = path.join(currentDir, entry.name);
1404
- const relativePath = path.relative(rootDir, absolutePath);
1405
- const [rootEntry] = relativePath.split(path.sep);
1406
- if (SKIPPED_COMPARE_ROOT_ENTRIES.has(rootEntry ?? "")) {
1407
- continue;
1408
- }
1409
- if (entry.isDirectory()) {
1410
- await visit(absolutePath);
1411
- continue;
1412
- }
1413
- if (!entry.isFile()) {
1414
- continue;
1415
- }
1416
- files.set(relativePath.replace(path.sep === "\\" ? /\\/gu : /\//gu, "/"), await fsp.readFile(absolutePath));
1417
- }
1418
- }
1419
- await visit(rootDir);
1420
- return files;
1421
- }
1422
- function compareStrings(left, right) {
1423
- if (left < right) {
1424
- return -1;
1425
- }
1426
- if (left > right) {
1427
- return 1;
1428
- }
1429
- return 0;
1430
- }
1431
- async function collectWorkspaceFileOperations(sourceDir, simulatedDir) {
1432
- const [sourceFiles, simulatedFiles] = await Promise.all([
1433
- listWorkspaceFiles(sourceDir),
1434
- listWorkspaceFiles(simulatedDir)
1435
- ]);
1436
- const operations = [];
1437
- for (const [relativePath, simulatedSource] of simulatedFiles) {
1438
- const originalSource = sourceFiles.get(relativePath);
1439
- if (originalSource === undefined) {
1440
- operations.push(`write ${relativePath}`);
1441
- continue;
1442
- }
1443
- if (!originalSource.equals(simulatedSource)) {
1444
- operations.push(`update ${relativePath}`);
1445
- }
1446
- }
1447
- for (const relativePath of sourceFiles.keys()) {
1448
- if (!simulatedFiles.has(relativePath)) {
1449
- operations.push(`delete ${relativePath}`);
1450
- }
1451
- }
1452
- return operations.sort(compareStrings);
1453
- }
1454
- async function simulateWorkspaceAddDryRun({
1455
- cwd,
1456
- execute
1457
- }) {
1458
- const { resolveWorkspaceProject } = await import("./workspace-project-gmv2a71z.js");
1459
- const workspace = resolveWorkspaceProject(cwd);
1460
- const relativeCwd = path.relative(workspace.projectDir, path.resolve(cwd));
1461
- const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-add-plan-");
1462
- const simulatedProjectDir = path.join(tempRoot, "workspace");
1463
- try {
1464
- await copyWorkspaceProject(workspace.projectDir, simulatedProjectDir);
1465
- ensureWorkspaceInstallMarkers(workspace.projectDir, simulatedProjectDir);
1466
- const simulatedCwd = relativeCwd.length > 0 ? path.join(simulatedProjectDir, relativeCwd) : simulatedProjectDir;
1467
- const result = await execute(simulatedCwd);
1468
- const fileOperations = await collectWorkspaceFileOperations(workspace.projectDir, simulatedProjectDir);
1469
- return {
1470
- fileOperations,
1471
- result
1472
- };
1473
- } finally {
1474
- await cleanup();
1475
- }
1476
- }
1477
-
1478
- // src/string-utils.ts
1479
- function escapeRegExp(source) {
1480
- return source.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
1481
- }
1482
-
1483
- // src/output-markers.ts
1484
- var UNICODE_OUTPUT_MARKERS = {
1485
- dryRun: "\uD83E\uDDEA",
1486
- progress: "\u23F3",
1487
- success: "\u2705",
1488
- warning: "\u26A0\uFE0F"
1489
- };
1490
- var ASCII_OUTPUT_MARKERS = {
1491
- dryRun: "[dry-run]",
1492
- progress: "[...]",
1493
- success: "[ok]",
1494
- warning: "[!]"
1495
- };
1496
- var ASCII_ENV_TRUTHY_VALUES = new Set(["1", "on", "true", "yes"]);
1497
- var ASCII_ENV_FALSY_VALUES = new Set(["0", "off", "false", "no"]);
1498
- function readAsciiPreferenceFromEnv(env) {
1499
- const rawValue = env.WP_TYPIA_ASCII;
1500
- if (typeof rawValue !== "string") {
1501
- return;
1502
- }
1503
- const normalizedValue = rawValue.trim().toLowerCase();
1504
- if (ASCII_ENV_TRUTHY_VALUES.has(normalizedValue)) {
1505
- return true;
1506
- }
1507
- if (ASCII_ENV_FALSY_VALUES.has(normalizedValue)) {
1508
- return false;
1509
- }
1510
- return;
1511
- }
1512
- function hasNoColorPreference(env) {
1513
- return typeof env.NO_COLOR === "string" && env.NO_COLOR.length > 0;
1514
- }
1515
- function prefersAsciiOutput(options = {}) {
1516
- if (options.forceAscii) {
1517
- return true;
1518
- }
1519
- const env = options.env ?? process.env;
1520
- const envPreference = readAsciiPreferenceFromEnv(env);
1521
- if (envPreference !== undefined) {
1522
- return envPreference;
1523
- }
1524
- if (hasNoColorPreference(env)) {
1525
- return true;
1526
- }
1527
- const term = options.term ?? env.TERM;
1528
- if (term === "dumb") {
1529
- return true;
1530
- }
1531
- const locale = (env.LC_ALL ?? env.LC_CTYPE ?? env.LANG ?? "").toUpperCase();
1532
- if (locale.includes("UTF-8") || locale.includes("UTF8")) {
1533
- return false;
1534
- }
1535
- if (locale === "C" || locale === "POSIX") {
1536
- return true;
1537
- }
1538
- if (locale.includes("ASCII") || locale.includes("ANSI_X3") || locale.includes("8859")) {
1539
- return true;
1540
- }
1541
- return false;
1542
- }
1543
- function getOutputMarker(kind, options = {}) {
1544
- return prefersAsciiOutput(options) ? ASCII_OUTPUT_MARKERS[kind] : UNICODE_OUTPUT_MARKERS[kind];
1545
- }
1546
- function formatOutputMarker(kind, text, options = {}) {
1547
- return `${getOutputMarker(kind, options)} ${text}`;
1548
- }
1549
- function stripLeadingOutputMarker(text, kind) {
1550
- const markers = kind ? [UNICODE_OUTPUT_MARKERS[kind], ASCII_OUTPUT_MARKERS[kind]] : Array.from(new Set([
1551
- ...Object.values(UNICODE_OUTPUT_MARKERS),
1552
- ...Object.values(ASCII_OUTPUT_MARKERS)
1553
- ]));
1554
- const markerPattern = markers.map((marker) => escapeRegExp(marker)).join("|");
1555
- return text.replace(new RegExp(`^(?:${markerPattern})\\s*`, "u"), "");
1556
- }
1557
-
1558
- // src/runtime-output/init.ts
1559
- function buildInitCompletionPayload(plan, markerOptions) {
1560
- const changeLines = [
1561
- ...plan.packageChanges.addDevDependencies.map((dependency) => `devDependency ${dependency.action} ${dependency.name} -> ${dependency.requiredValue}`),
1562
- ...plan.packageChanges.packageManagerField ? [
1563
- `packageManager ${plan.packageChanges.packageManagerField.action} -> ${plan.packageChanges.packageManagerField.requiredValue}`
1564
- ] : [],
1565
- ...plan.packageChanges.scripts.map((script) => `script ${script.action} ${script.name} -> ${script.requiredValue}`),
1566
- ...plan.plannedFiles.map((filePlan) => `file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`),
1567
- ...plan.commandMode === "preview-only" ? plan.generatedArtifacts.map((artifactPath) => `generated artifact ${artifactPath}`) : []
1568
- ];
1569
- 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.";
1570
- const optionalTitle = plan.commandMode === "apply" ? `Applied adoption changes (${changeLines.length}):` : `Planned adoption changes (${changeLines.length}):`;
1571
- 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);
1572
- return {
1573
- nextSteps: plan.nextSteps,
1574
- optionalLines: changeLines,
1575
- optionalNote: plan.summary,
1576
- optionalTitle,
1577
- summaryLines: [
1578
- `Project directory: ${plan.projectDir}`,
1579
- `Detected layout: ${plan.detectedLayout.description}`,
1580
- ...plan.detectedLayout.blockNames.length > 0 ? [`Block targets: ${plan.detectedLayout.blockNames.join(", ")}`] : [],
1581
- `Package manager: ${plan.packageManager}`,
1582
- modeLine
1583
- ],
1584
- title,
1585
- warningLines: plan.notes
1586
- };
1587
- }
1588
-
1589
- // src/runtime-output/structured.ts
1590
- function toNonEmptyArray(values) {
1591
- return values && values.length > 0 ? values : undefined;
1592
- }
1593
- function extractPlannedFiles(payload) {
1594
- const files = payload.optionalLines?.map((line) => line.match(/^(?:delete|update|write)\s+(.+)$/u)?.[1]).filter((value) => typeof value === "string" && value.length > 0);
1595
- return toNonEmptyArray(files);
1596
- }
1597
- var PROJECT_DIRECTORY_SUMMARY_PREFIX = "Project directory: ";
1598
- function extractCompletionProjectDir(completion) {
1599
- const projectDir = completion?.summaryLines?.find((line) => line.startsWith(PROJECT_DIRECTORY_SUMMARY_PREFIX))?.slice(PROJECT_DIRECTORY_SUMMARY_PREFIX.length).trim();
1600
- return projectDir && projectDir.length > 0 ? projectDir : undefined;
1601
- }
1602
- function serializeCompletionPayload(payload) {
1603
- return {
1604
- nextSteps: toNonEmptyArray(payload.nextSteps),
1605
- optionalLines: toNonEmptyArray(payload.optionalLines),
1606
- optionalNote: payload.optionalNote,
1607
- optionalTitle: payload.optionalTitle,
1608
- preambleLines: toNonEmptyArray(payload.preambleLines),
1609
- summaryLines: toNonEmptyArray(payload.summaryLines),
1610
- title: stripLeadingOutputMarker(payload.title),
1611
- warningLines: toNonEmptyArray(payload.warningLines)
1612
- };
1613
- }
1614
- function buildStructuredCompletionSuccessPayload(command, completion, metadata = {}) {
1615
- const serializedCompletion = completion ? serializeCompletionPayload(completion) : undefined;
1616
- return {
1617
- ok: true,
1618
- data: {
1619
- ...metadata,
1620
- command,
1621
- ...serializedCompletion ? {
1622
- completion: serializedCompletion,
1623
- files: extractPlannedFiles(serializedCompletion)
1624
- } : {}
1625
- }
1626
- };
1627
- }
1628
- function buildStructuredInitSuccessPayload(plan) {
1629
- const completion = serializeCompletionPayload(buildInitCompletionPayload(plan));
1630
- const files = Array.from(new Set([
1631
- ...plan.plannedFiles.map((filePlan) => filePlan.path),
1632
- ...plan.commandMode === "preview-only" ? plan.generatedArtifacts : []
1633
- ]));
1634
- return {
1635
- ok: true,
1636
- data: {
1637
- command: "init",
1638
- completion,
1639
- detectedLayout: plan.detectedLayout,
1640
- files: toNonEmptyArray(files),
1641
- mode: plan.commandMode === "apply" ? "apply" : "preview",
1642
- packageManager: plan.packageManager,
1643
- plan,
1644
- projectDir: plan.projectDir,
1645
- status: plan.status,
1646
- summary: plan.summary
1647
- }
1648
- };
1649
- }
1650
- // src/runtime-output/create.ts
1651
- var LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN = new RegExp(`^(?:corepack\\s+)?(${PACKAGE_MANAGER_IDS.map(escapeRegExp).join("|")})(?=$|[@:/+\\s])`, "iu");
1652
- function parseCreateCompletionPackageManager(packageManager) {
1653
- const normalizedPackageManager = packageManager.trim();
1654
- const parsedPackageManager = parsePackageManagerField(normalizedPackageManager);
1655
- if (parsedPackageManager) {
1656
- return parsedPackageManager;
1657
- }
1658
- const looseMatch = LOOSE_CREATE_COMPLETION_PACKAGE_MANAGER_PATTERN.exec(normalizedPackageManager);
1659
- const loosePackageManager = looseMatch?.[1]?.toLowerCase();
1660
- return PACKAGE_MANAGER_IDS.includes(loosePackageManager) ? loosePackageManager : null;
1661
- }
1662
- function resolveCreateCompletionPackageManager(packageManager) {
1663
- const parsedPackageManager = parseCreateCompletionPackageManager(packageManager);
1664
- if (parsedPackageManager) {
1665
- return parsedPackageManager;
1666
- }
1667
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unsupported package manager "${packageManager}" in create completion payload. Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}.`);
1668
- }
1669
- function formatCreateProgressLine(payload, markerOptions) {
1670
- return formatOutputMarker("progress", `${payload.title}: ${payload.detail}`, markerOptions);
1671
- }
1672
- function buildCreateCompletionPayload(flow, markerOptions) {
1673
- const packageManager = resolveCreateCompletionPackageManager(flow.packageManager);
1674
- const verificationSteps = [
1675
- formatPackageExecCommand(packageManager, `wp-typia@${package_default.version}`, "doctor"),
1676
- ...flow.optionalOnboarding.steps
1677
- ];
1678
- return {
1679
- nextSteps: flow.nextSteps,
1680
- optionalLines: verificationSteps,
1681
- optionalNote: flow.optionalOnboarding.shortNote ?? flow.optionalOnboarding.note,
1682
- optionalTitle: "Verify and sync (optional):",
1683
- preambleLines: flow.result.selectedVariant ? [`Template variant: ${flow.result.selectedVariant}`] : undefined,
1684
- summaryLines: [`Project directory: ${flow.projectDir}`],
1685
- title: formatOutputMarker("success", `Created ${flow.result.variables.title} in ${flow.projectDir}`, markerOptions),
1686
- warningLines: flow.result.warnings
1687
- };
1688
- }
1689
- function buildCreateDryRunPayload(flow, markerOptions) {
1690
- let dependencyInstallLine;
1691
- switch (flow.plan.dependencyInstall) {
1692
- case "skipped-by-flag":
1693
- dependencyInstallLine = "Dependency install: already skipped via --no-install";
1694
- break;
1695
- case "would-install":
1696
- dependencyInstallLine = "Dependency install: would run during a real scaffold";
1697
- break;
1698
- }
1699
- return {
1700
- optionalLines: flow.plan.files.map((relativePath) => `write ${relativePath}`),
1701
- optionalNote: "No files were written because --dry-run was enabled. Re-run without --dry-run to materialize this scaffold.",
1702
- optionalTitle: `Planned files (${flow.plan.files.length}):`,
1703
- preambleLines: flow.result.selectedVariant ? [`Template variant: ${flow.result.selectedVariant}`] : undefined,
1704
- summaryLines: [
1705
- `Project directory: ${flow.projectDir}`,
1706
- `Template: ${flow.result.templateId}`,
1707
- `Package manager: ${flow.packageManager}`,
1708
- dependencyInstallLine
1709
- ],
1710
- title: formatOutputMarker("dryRun", `Dry run for ${flow.result.variables.title} at ${flow.projectDir}`, markerOptions),
1711
- warningLines: flow.result.warnings
1712
- };
1713
- }
1714
- // src/runtime-output/add.ts
1715
- function buildAddCompletionPayload(options, markerOptions) {
1716
- const verificationLines = [
1717
- formatPackageExecCommand(options.packageManager ?? inferPackageManagerId(options.projectDir), `wp-typia@${package_default.version}`, "doctor")
1718
- ];
1719
- const verificationNote = "Run doctor via your package manager for a quick inventory and generated-artifact check after the add workflow.";
1720
- const completion = buildAddKindCompletionDetails(options.kind, {
1721
- projectDir: options.projectDir,
1722
- values: options.values
1723
- });
1724
- return {
1725
- nextSteps: completion.nextSteps,
1726
- optionalLines: verificationLines,
1727
- optionalNote: verificationNote,
1728
- optionalTitle: "Verify workspace health (optional):",
1729
- summaryLines: completion.summaryLines,
1730
- title: formatOutputMarker("success", completion.title, markerOptions),
1731
- warningLines: options.warnings
1732
- };
1733
- }
1734
- function buildAddDryRunPayload(options, markerOptions) {
1735
- const normalizedTitle = stripLeadingOutputMarker(options.completion.title, "success").replace(/^Added\s*/u, "");
1736
- return {
1737
- optionalLines: options.fileOperations,
1738
- optionalNote: "No workspace files were changed because --dry-run was enabled. Re-run without --dry-run to apply this add command.",
1739
- optionalTitle: `Planned workspace updates (${options.fileOperations.length}):`,
1740
- preambleLines: options.completion.preambleLines,
1741
- summaryLines: options.completion.summaryLines,
1742
- title: formatOutputMarker("dryRun", `Dry run for ${normalizedTitle || "workspace add command"}`, markerOptions),
1743
- warningLines: options.completion.warningLines
1744
- };
1745
- }
1746
- // src/runtime-output/migrate.ts
1747
- function buildMigrationCompletionPayload(options, markerOptions) {
1748
- const summaryLines = options.lines.filter((line) => line.trim().length > 0);
1749
- return {
1750
- summaryLines,
1751
- title: formatOutputMarker("success", `Completed wp-typia migrate ${options.command}`, markerOptions)
1752
- };
1753
- }
1754
- // src/runtime-output/sync.ts
1755
- function buildSyncDryRunPayload(options, markerOptions) {
1756
- const targetSuffix = options.target === "ai" ? " ai" : "";
1757
- const targetSummary = options.target === "ai" ? "Sync target: AI artifacts only." : options.target === "default" ? "Sync target: generated project defaults." : undefined;
1758
- return {
1759
- optionalLines: options.plannedCommands.map((command) => command.displayCommand),
1760
- optionalNote: options.check ? `No sync scripts were executed because --dry-run was enabled. Re-run \`wp-typia sync${targetSuffix} --check\` to verify generated artifacts without rewriting them.` : `No sync scripts were executed because --dry-run was enabled. Re-run \`wp-typia sync${targetSuffix}\` without --dry-run to apply generated-file updates, or add --check to verify without rewriting.`,
1761
- optionalTitle: `Planned sync commands (${options.plannedCommands.length}):`,
1762
- summaryLines: [
1763
- `Project directory: ${options.projectDir}`,
1764
- `Package manager: ${options.packageManager}`,
1765
- ...targetSummary ? [targetSummary] : [],
1766
- options.check ? "Execution mode: would run generated sync scripts in verification mode." : "Execution mode: would run generated sync scripts in apply mode."
1767
- ],
1768
- title: formatOutputMarker("dryRun", `Dry run for wp-typia sync${targetSuffix}`, markerOptions)
1769
- };
1770
- }
1771
- // src/print-block.ts
1772
- function printBlock(printLine, lines) {
1773
- for (const line of lines) {
1774
- printLine(line);
1775
- }
1776
- }
1777
-
1778
- // src/runtime-output/print.ts
1779
- function printCompletionPayload(payload, options = {}) {
1780
- const printLine = options.printLine ?? console.log;
1781
- const warnLine = options.warnLine ?? printLine;
1782
- for (const line of payload.preambleLines ?? []) {
1783
- printLine(line);
1784
- }
1785
- for (const warning of payload.warningLines ?? []) {
1786
- warnLine(formatOutputMarker("warning", warning, options.markerOptions));
1787
- }
1788
- const hasDetails = (payload.summaryLines?.length ?? 0) > 0 || (payload.nextSteps?.length ?? 0) > 0 || (payload.optionalLines?.length ?? 0) > 0 || Boolean(payload.optionalNote);
1789
- const hasLeadingContext = (payload.preambleLines?.length ?? 0) > 0 || (payload.warningLines?.length ?? 0) > 0;
1790
- printLine(hasLeadingContext && hasDetails ? `
1791
- ${payload.title}` : payload.title);
1792
- for (const line of payload.summaryLines ?? []) {
1793
- printLine(line);
1794
- }
1795
- if ((payload.nextSteps?.length ?? 0) > 0) {
1796
- printLine("Next steps:");
1797
- for (const step of payload.nextSteps ?? []) {
1798
- printLine(` ${step}`);
1799
- }
1800
- }
1801
- if ((payload.optionalLines?.length ?? 0) > 0) {
1802
- printLine(`
1803
- ${payload.optionalTitle ?? "Optional:"}`);
1804
- for (const step of payload.optionalLines ?? []) {
1805
- printLine(` ${step}`);
1806
- }
1807
- }
1808
- if (payload.optionalNote) {
1809
- printLine(`Note: ${payload.optionalNote}`);
1810
- }
1811
- }
1812
- // src/runtime-capabilities.ts
1813
- function isInteractiveTerminal({
1814
- stdin = process.stdin,
1815
- stdout = process.stdout,
1816
- term = process.env.TERM
1817
- } = {}) {
1818
- return Boolean(stdin?.isTTY) && Boolean(stdout?.isTTY) && term !== "dumb";
1819
- }
1820
- function supportsInteractiveTui(options = {}) {
1821
- const hasBunRuntime = options.hasBunRuntime ?? typeof Bun !== "undefined";
1822
- return hasBunRuntime && isInteractiveTerminal(options);
1823
- }
1824
-
1825
- // src/runtime-bridge-shared.ts
1826
- var loadCliDiagnosticsRuntime = () => import("./cli-diagnostics-10drxh34.js");
1827
- async function wrapCliCommandError(command, error) {
1828
- const { createCliCommandError } = await loadCliDiagnosticsRuntime();
1829
- return createCliCommandError({ command, error });
1830
- }
1831
- function shouldWrapCliCommandError(options) {
1832
- if (options.emitOutput === false) {
1833
- return false;
1834
- }
1835
- if (options.renderLine) {
1836
- return false;
1837
- }
1838
- return true;
1839
- }
1840
- function emitCompletion(payload, options) {
1841
- if (options.emitOutput) {
1842
- printCompletionPayload(payload, {
1843
- printLine: options.printLine,
1844
- warnLine: options.warnLine
1845
- });
1846
- }
1847
- return payload;
1848
- }
1849
- function pushFlag(argv, name, value) {
1850
- if (value === undefined || value === null || value === false) {
1851
- return;
1852
- }
1853
- if (value === true) {
1854
- argv.push(`--${name}`);
1855
- return;
1856
- }
1857
- argv.push(`--${name}`, String(value));
1858
- }
1859
-
1860
- // src/runtime-bridge-add.ts
1861
- var loadCliAddRuntime = () => import("./cli-add-mxxk5rep.js");
1862
- var loadCliPromptRuntime = () => import("./cli-prompt-ncyg68rn.js");
1863
- async function executeWorkspaceAddWithOptionalDryRun(options) {
1864
- const simulated = options.dryRun ? await simulateWorkspaceAddDryRun({
1865
- cwd: options.cwd,
1866
- execute: options.execute
1867
- }) : null;
1868
- const result = simulated?.result ?? await options.execute(options.cwd);
1869
- const completion = options.buildCompletion(result);
1870
- if (!options.dryRun) {
1871
- return emitCompletion(completion, {
1872
- emitOutput: options.emitOutput ?? true,
1873
- printLine: options.printLine,
1874
- warnLine: options.warnLine
1875
- });
1876
- }
1877
- return emitCompletion(buildAddDryRunPayload({
1878
- completion,
1879
- fileOperations: simulated.fileOperations
1880
- }), {
1881
- emitOutput: options.emitOutput ?? true,
1882
- printLine: options.printLine,
1883
- warnLine: options.warnLine
1884
- });
1885
- }
1886
- function executePreparedAddKind(kind, context, plan) {
1887
- return executeWorkspaceAddWithOptionalDryRun({
1888
- buildCompletion: (result) => buildAddCompletionPayload({
1889
- kind,
1890
- projectDir: result.projectDir,
1891
- values: plan.getValues(result),
1892
- warnings: plan.getWarnings?.(result)
1893
- }),
1894
- cwd: context.cwd,
1895
- dryRun: context.dryRun,
1896
- emitOutput: context.emitOutput,
1897
- execute: plan.execute,
1898
- printLine: context.printLine,
1899
- warnLine: plan.warnLine
1900
- });
1901
- }
1902
- async function executePlannedAddKind(kind, executionContext, context) {
1903
- const plan = await getAddKindExecutionPlan(kind, executionContext);
1904
- return executePreparedAddKind(kind, context, plan);
1905
- }
1906
- async function executeAddCommand({
1907
- cwd,
1908
- emitOutput = true,
1909
- flags,
1910
- interactive,
1911
- kind,
1912
- name,
1913
- positionalArgs,
1914
- printLine = console.log,
1915
- prompt,
1916
- warnLine = console.warn
1917
- }) {
1918
- let activePrompt;
1919
- const dryRun = Boolean(flags["dry-run"]);
1920
- try {
1921
- const addRuntime = await loadCliAddRuntime();
1922
- const isInteractiveSession = interactive ?? isInteractiveTerminal();
1923
- if (!kind) {
1924
- if (shouldPrintMissingAddKindHelp({ emitOutput })) {
1925
- printLine(addRuntime.formatAddHelpText());
1926
- }
1927
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, formatMissingAddKindDetailLine());
1928
- }
1929
- if (!isAddKindId(kind)) {
1930
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown add kind "${kind}". Expected one of: ${formatAddKindList()}.`);
1931
- }
1932
- if (dryRun && !supportsAddKindDryRun(kind)) {
1933
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`wp-typia add ${kind}\` does not support \`--dry-run\` yet.`);
1934
- }
1935
- const executionContext = {
1936
- addRuntime,
1937
- cwd,
1938
- flags,
1939
- getOrCreatePrompt: async () => {
1940
- if (activePrompt) {
1941
- return activePrompt;
1942
- }
1943
- const { createReadlinePrompt } = await loadCliPromptRuntime();
1944
- activePrompt = prompt ?? createReadlinePrompt();
1945
- return activePrompt;
1946
- },
1947
- isInteractiveSession,
1948
- name,
1949
- positionalArgs,
1950
- warnLine
1951
- };
1952
- return await executePlannedAddKind(kind, executionContext, {
1953
- cwd,
1954
- dryRun,
1955
- emitOutput,
1956
- printLine
1957
- });
1958
- } catch (error) {
1959
- if (!shouldWrapCliCommandError({ emitOutput })) {
1960
- throw error;
1961
- }
1962
- throw await wrapCliCommandError("add", error);
1963
- } finally {
1964
- if (activePrompt && activePrompt !== prompt) {
1965
- activePrompt.close();
1966
- }
1967
- }
1968
- }
1969
- // src/runtime-bridge-create.ts
1970
- var loadCliPromptRuntime2 = () => import("./cli-prompt-ncyg68rn.js");
1971
- var loadCliScaffoldRuntime = () => import("./cli-scaffold-0bb6pr3w.js");
1972
- var loadCliTemplatesRuntime = () => import("./cli-templates-g8t4fm11.js");
1973
- var loadCreateTemplateValidationRuntime = () => import("./create-template-validation-4fr851vg.js");
1974
- var PACKAGE_MANAGER_PROMPT_OPTIONS = [
1975
- { label: "npm", value: "npm", hint: "Use npm" },
1976
- { label: "pnpm", value: "pnpm", hint: "Use pnpm" },
1977
- { label: "yarn", value: "yarn", hint: "Use yarn" },
1978
- { label: "bun", value: "bun", hint: "Use bun" }
1979
- ];
1980
- var DATA_STORAGE_PROMPT_OPTIONS = [
1981
- {
1982
- label: "custom-table",
1983
- value: "custom-table",
1984
- hint: "Dedicated custom table storage"
1985
- },
1986
- { label: "post-meta", value: "post-meta", hint: "Persist through post meta" }
1987
- ];
1988
- var PERSISTENCE_POLICY_PROMPT_OPTIONS = [
1989
- {
1990
- label: "authenticated",
1991
- value: "authenticated",
1992
- hint: "Authenticated write policy"
1993
- },
1994
- { label: "public", value: "public", hint: "Public token policy" }
1995
- ];
1996
- var BOOLEAN_PROMPT_OPTIONS = [
1997
- { label: "Yes", value: "yes", hint: "Enable this option" },
1998
- { label: "No", value: "no", hint: "Keep the default disabled state" }
1999
- ];
2000
- async function executeCreateCommand({
2001
- projectDir,
2002
- cwd,
2003
- emitOutput = true,
2004
- flags,
2005
- interactive,
2006
- onProgress,
2007
- printLine = console.log,
2008
- prompt,
2009
- warnLine = console.warn
2010
- }) {
2011
- let activePrompt;
2012
- try {
2013
- const requestedTemplateId = readOptionalLooseStringFlag(flags, "template");
2014
- const resolvedTemplateId = requestedTemplateId ? (await loadCreateTemplateValidationRuntime()).validateExplicitCreateTemplateId(requestedTemplateId) : undefined;
2015
- const [
2016
- { createReadlinePrompt },
2017
- { runScaffoldFlow },
2018
- { getTemplateSelectOptions }
2019
- ] = await Promise.all([
2020
- loadCliPromptRuntime2(),
2021
- loadCliScaffoldRuntime(),
2022
- loadCliTemplatesRuntime()
2023
- ]);
2024
- const shouldPrompt = interactive ?? (!Boolean(flags.yes) && isInteractiveTerminal());
2025
- activePrompt = shouldPrompt ? prompt ?? createReadlinePrompt() : undefined;
2026
- const scaffoldPrompt = activePrompt;
2027
- const shouldPromptForExternalLayerSelection = Boolean(scaffoldPrompt) && scaffoldPrompt !== prompt;
2028
- const effectiveYes = Boolean(flags.yes) || Boolean(flags["dry-run"]) && !Boolean(scaffoldPrompt);
2029
- const flow = await runScaffoldFlow({
2030
- alternateRenderTargets: readOptionalLooseStringFlag(flags, "alternate-render-targets"),
2031
- cwd,
2032
- dataStorageMode: readOptionalLooseStringFlag(flags, "data-storage"),
2033
- dryRun: Boolean(flags["dry-run"]),
2034
- externalLayerId: readOptionalLooseStringFlag(flags, "external-layer-id"),
2035
- externalLayerSource: readOptionalLooseStringFlag(flags, "external-layer-source"),
2036
- innerBlocksPreset: readOptionalLooseStringFlag(flags, "inner-blocks-preset"),
2037
- isInteractive: Boolean(scaffoldPrompt),
2038
- namespace: readOptionalLooseStringFlag(flags, "namespace"),
2039
- noInstall: Boolean(flags["no-install"]),
2040
- packageManager: readOptionalLooseStringFlag(flags, "package-manager"),
2041
- persistencePolicy: readOptionalLooseStringFlag(flags, "persistence-policy"),
2042
- phpPrefix: readOptionalLooseStringFlag(flags, "php-prefix"),
2043
- profile: readOptionalLooseStringFlag(flags, "profile"),
2044
- projectInput: projectDir,
2045
- onProgress: async (progress) => {
2046
- const payload2 = {
2047
- detail: progress.detail,
2048
- title: progress.title
2049
- };
2050
- onProgress?.(payload2);
2051
- if (emitOutput) {
2052
- printLine(formatCreateProgressLine(payload2));
2053
- }
2054
- },
2055
- promptText: scaffoldPrompt ? (message, defaultValue, validate) => scaffoldPrompt.text(message, defaultValue, validate) : undefined,
2056
- queryPostType: readOptionalLooseStringFlag(flags, "query-post-type"),
2057
- selectDataStorage: scaffoldPrompt ? () => scaffoldPrompt.select("Select a data storage mode", [...DATA_STORAGE_PROMPT_OPTIONS], 1) : undefined,
2058
- selectExternalLayerId: shouldPromptForExternalLayerSelection && scaffoldPrompt ? (options) => scaffoldPrompt.select("Select an external layer", toExternalLayerPromptOptions(options), 1) : undefined,
2059
- selectPackageManager: scaffoldPrompt ? () => scaffoldPrompt.select("Select a package manager", [...PACKAGE_MANAGER_PROMPT_OPTIONS], 1) : undefined,
2060
- selectPersistencePolicy: scaffoldPrompt ? () => scaffoldPrompt.select("Select a persistence policy", [...PERSISTENCE_POLICY_PROMPT_OPTIONS], 1) : undefined,
2061
- selectTemplate: scaffoldPrompt ? () => scaffoldPrompt.select("Select a template", getTemplateSelectOptions(), 1) : undefined,
2062
- selectWithMigrationUi: scaffoldPrompt ? async () => await scaffoldPrompt.select("Enable migration UI support?", [...BOOLEAN_PROMPT_OPTIONS], 2) === "yes" : undefined,
2063
- selectWithTestPreset: scaffoldPrompt ? async () => await scaffoldPrompt.select("Include the Playwright test preset?", [...BOOLEAN_PROMPT_OPTIONS], 2) === "yes" : undefined,
2064
- selectWithWpEnv: scaffoldPrompt ? async () => await scaffoldPrompt.select("Include a local wp-env preset?", [...BOOLEAN_PROMPT_OPTIONS], 2) === "yes" : undefined,
2065
- templateId: resolvedTemplateId,
2066
- textDomain: readOptionalLooseStringFlag(flags, "text-domain"),
2067
- variant: readOptionalLooseStringFlag(flags, "variant"),
2068
- withMigrationUi: flags["with-migration-ui"],
2069
- withTestPreset: flags["with-test-preset"],
2070
- withWpEnv: flags["with-wp-env"],
2071
- yes: effectiveYes
2072
- });
2073
- const payload = flow.dryRun && flow.plan ? buildCreateDryRunPayload({
2074
- packageManager: flow.packageManager,
2075
- plan: flow.plan,
2076
- projectDir: flow.projectDir,
2077
- result: flow.result
2078
- }) : buildCreateCompletionPayload(flow);
2079
- return emitCompletion(payload, { emitOutput, printLine, warnLine });
2080
- } catch (error) {
2081
- if (!shouldWrapCliCommandError({ emitOutput })) {
2082
- throw error;
2083
- }
2084
- throw await wrapCliCommandError("create", error);
2085
- } finally {
2086
- if (activePrompt && activePrompt !== prompt) {
2087
- activePrompt.close();
2088
- }
2089
- }
2090
- }
2091
- // src/runtime-bridge-doctor.ts
2092
- var loadCliDoctorRuntime = () => import("./cli-doctor-6fyxq940.js");
2093
- async function executeDoctorCommand(cwd, options = {}) {
2094
- try {
2095
- const { runDoctor } = await loadCliDoctorRuntime();
2096
- await runDoctor(cwd, { exitPolicy: options.exitPolicy });
2097
- } catch (error) {
2098
- throw await wrapCliCommandError("doctor", error);
2099
- }
2100
- }
2101
- // src/runtime-bridge-init.ts
2102
- import path2 from "path";
2103
- var loadCliInitRuntime = () => import("./cli-init-7avk42dh.js");
2104
- async function executeInitCommand({ apply, cwd, packageManager, projectDir }, options = {}) {
2105
- try {
2106
- const { runInitCommand } = await loadCliInitRuntime();
2107
- const resolvedProjectDir = projectDir ? path2.resolve(cwd, projectDir) : cwd;
2108
- const plan = await runInitCommand({
2109
- apply,
2110
- packageManager,
2111
- projectDir: resolvedProjectDir
2112
- });
2113
- const completion = buildInitCompletionPayload(plan);
2114
- if (options.emitOutput ?? true) {
2115
- printCompletionPayload(completion, {
2116
- printLine: options.printLine,
2117
- warnLine: options.warnLine
2118
- });
2119
- }
2120
- return plan;
2121
- } catch (error) {
2122
- if (!shouldWrapCliCommandError({ emitOutput: options.emitOutput })) {
2123
- throw error;
2124
- }
2125
- throw await wrapCliCommandError("init", error);
2126
- }
2127
- }
2128
- // src/runtime-bridge-migrate.ts
2129
- var loadMigrationsRuntime = () => import("./migrations-3vngdy51.js");
2130
- var defaultPrintLine2 = (line) => {
2131
- process.stdout.write(`${line}
2132
- `);
2133
- };
2134
- async function executeMigrateCommand({
2135
- command,
2136
- cwd,
2137
- flags,
2138
- printLine = defaultPrintLine2,
2139
- prompt,
2140
- renderLine
2141
- }) {
2142
- try {
2143
- const { formatMigrationHelpText, parseMigrationArgs, runMigrationCommand } = await loadMigrationsRuntime();
2144
- const outputLine = renderLine ?? printLine;
2145
- if (!command) {
2146
- const helpText = formatMigrationHelpText();
2147
- outputLine(helpText);
2148
- return;
2149
- }
2150
- const argv = [command];
2151
- pushFlag(argv, "all", flags.all);
2152
- pushFlag(argv, "force", flags.force);
2153
- pushFlag(argv, "current-migration-version", readOptionalLooseStringFlag(flags, "current-migration-version"));
2154
- pushFlag(argv, "migration-version", readOptionalLooseStringFlag(flags, "migration-version"));
2155
- pushFlag(argv, "from-migration-version", readOptionalLooseStringFlag(flags, "from-migration-version"));
2156
- pushFlag(argv, "to-migration-version", readOptionalLooseStringFlag(flags, "to-migration-version"));
2157
- pushFlag(argv, "iterations", readOptionalLooseStringFlag(flags, "iterations"));
2158
- pushFlag(argv, "seed", readOptionalLooseStringFlag(flags, "seed"));
2159
- const parsed = parseMigrationArgs(argv);
2160
- const lines = renderLine ? [] : null;
2161
- const captureLine = (line) => {
2162
- lines?.push(line);
2163
- outputLine(line);
2164
- };
2165
- const result = await runMigrationCommand(parsed, cwd, {
2166
- prompt,
2167
- renderLine: captureLine
2168
- });
2169
- if (renderLine) {
2170
- return result && typeof result === "object" && "cancelled" in result && result.cancelled === true ? undefined : buildMigrationCompletionPayload({
2171
- command: parsed.command ?? "plan",
2172
- lines: lines ?? []
2173
- });
2174
- }
2175
- if (result && typeof result === "object" && "cancelled" in result && result.cancelled === true) {
2176
- return;
2177
- }
2178
- } catch (error) {
2179
- if (!shouldWrapCliCommandError({ renderLine })) {
2180
- throw error;
2181
- }
2182
- throw await wrapCliCommandError("migrate", error);
2183
- }
2184
- }
2185
- // src/runtime-bridge-templates.ts
2186
- var loadCliTemplatesRuntime2 = () => import("./cli-templates-g8t4fm11.js");
2187
- async function executeTemplatesCommand({ flags }, printLine = console.log) {
2188
- const {
2189
- formatTemplateDetails,
2190
- formatTemplateFeatures,
2191
- formatTemplateSummary,
2192
- getTemplateById,
2193
- listTemplates
2194
- } = await loadCliTemplatesRuntime2();
2195
- const subcommand = flags.subcommand ?? "list";
2196
- if (subcommand === "list") {
2197
- for (const template of listTemplates()) {
2198
- printBlock(printLine, [formatTemplateSummary(template), formatTemplateFeatures(template)]);
2199
- }
2200
- return;
2201
- }
2202
- if (subcommand === "inspect") {
2203
- if (!flags.id) {
2204
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, "`wp-typia templates inspect` requires <template-id>.");
2205
- }
2206
- const template = getTemplateById(flags.id);
2207
- if (!template) {
2208
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unknown template "${flags.id}".`);
2209
- }
2210
- printBlock(printLine, [formatTemplateDetails(template)]);
2211
- return;
2212
- }
2213
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown templates subcommand "${subcommand}". Expected list or inspect.`);
2214
- }
2215
- async function listTemplatesForRuntime() {
2216
- const { listTemplates } = await loadCliTemplatesRuntime2();
2217
- return listTemplates();
2218
- }
2219
- // src/runtime-bridge-sync.ts
2220
- import { spawnSync } from "child_process";
2221
- import fs3 from "fs";
2222
- import path3 from "path";
2223
- var SYNC_INSTALL_MARKERS = [
2224
- "node_modules",
2225
- ".pnp.cjs",
2226
- ".pnp.loader.mjs"
2227
- ];
2228
- var LOCAL_SYNC_TOOL_PATTERN = /(^|[\s;&|()])(?:tsx|wp-scripts)(?=($|[\s;&|()]))/u;
2229
- var CAPTURED_SYNC_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
2230
- function resolveSyncExecutionTarget(subcommand) {
2231
- if (!subcommand) {
2232
- return "default";
2233
- }
2234
- if (subcommand === "ai") {
2235
- return "ai";
2236
- }
2237
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_COMMAND, `Unknown sync subcommand "${subcommand}". Expected one of: "ai".`);
2238
- }
2239
- function getSyncRootError(cwd) {
2240
- 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.`);
2241
- }
2242
- function readSyncPackageJson(packageJsonPath) {
2243
- const source = fs3.readFileSync(packageJsonPath, "utf8");
2244
- try {
2245
- return JSON.parse(source);
2246
- } catch (error) {
2247
- const message = error instanceof Error ? error.message : String(error);
2248
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Unable to parse ${packageJsonPath}: ${message}`, error instanceof Error ? { cause: error } : undefined);
2249
- }
2250
- }
2251
- function resolveSyncProjectContext(cwd) {
2252
- const packageJsonPath = path3.join(cwd, "package.json");
2253
- if (!fs3.existsSync(packageJsonPath)) {
2254
- throw getSyncRootError(cwd);
2255
- }
2256
- const packageJson = readSyncPackageJson(packageJsonPath);
2257
- const scripts = packageJson.scripts ?? {};
2258
- const syncScripts = {
2259
- sync: typeof scripts.sync === "string" ? {
2260
- command: scripts.sync,
2261
- scriptName: "sync"
2262
- } : undefined,
2263
- "sync-ai": typeof scripts["sync-ai"] === "string" ? {
2264
- command: scripts["sync-ai"],
2265
- scriptName: "sync-ai"
2266
- } : typeof scripts["sync-wordpress-ai"] === "string" ? {
2267
- command: scripts["sync-wordpress-ai"],
2268
- scriptName: "sync-wordpress-ai"
2269
- } : undefined,
2270
- "sync-rest": typeof scripts["sync-rest"] === "string" ? {
2271
- command: scripts["sync-rest"],
2272
- scriptName: "sync-rest"
2273
- } : undefined,
2274
- "sync-types": typeof scripts["sync-types"] === "string" ? {
2275
- command: scripts["sync-types"],
2276
- scriptName: "sync-types"
2277
- } : undefined
2278
- };
2279
- return {
2280
- cwd,
2281
- packageJsonPath,
2282
- packageManager: inferPackageManagerId(cwd, packageJson.packageManager),
2283
- scripts: syncScripts
2284
- };
2285
- }
2286
- function findInstalledDependencyMarkerDir(projectDir) {
2287
- let currentDir = path3.resolve(projectDir);
2288
- while (true) {
2289
- if (SYNC_INSTALL_MARKERS.some((marker) => fs3.existsSync(path3.join(currentDir, marker)))) {
2290
- return currentDir;
2291
- }
2292
- const parentDir = path3.dirname(currentDir);
2293
- if (parentDir === currentDir) {
2294
- return null;
2295
- }
2296
- currentDir = parentDir;
2297
- }
2298
- }
2299
- function scriptsLikelyNeedInstalledDependencies(project, target) {
2300
- const candidateScripts = target === "ai" ? [project.scripts["sync-ai"]] : project.scripts.sync ? [project.scripts.sync] : [
2301
- project.scripts["sync-types"],
2302
- project.scripts["sync-rest"],
2303
- project.scripts["sync-ai"]
2304
- ];
2305
- return candidateScripts.some((script) => script !== undefined && LOCAL_SYNC_TOOL_PATTERN.test(script.command));
2306
- }
2307
- function assertSyncDependenciesInstalled(project, target) {
2308
- if (!scriptsLikelyNeedInstalledDependencies(project, target)) {
2309
- return;
2310
- }
2311
- const markerDir = findInstalledDependencyMarkerDir(project.cwd);
2312
- if (markerDir) {
2313
- return;
2314
- }
2315
- 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\`.`);
2316
- }
2317
- function getPackageManagerRunInvocation(packageManager, scriptName, extraArgs) {
2318
- switch (packageManager) {
2319
- case "bun":
2320
- return { args: ["run", scriptName, ...extraArgs], command: "bun" };
2321
- case "npm":
2322
- return {
2323
- args: [
2324
- "run",
2325
- scriptName,
2326
- ...extraArgs.length > 0 ? ["--", ...extraArgs] : []
2327
- ],
2328
- command: "npm"
2329
- };
2330
- case "pnpm":
2331
- return { args: ["run", scriptName, ...extraArgs], command: "pnpm" };
2332
- case "yarn":
2333
- return { args: ["run", scriptName, ...extraArgs], command: "yarn" };
2334
- }
2335
- }
2336
- function createSyncPlannedCommand(project, scriptName, extraArgs) {
2337
- const script = project.scripts[scriptName];
2338
- if (!script) {
2339
- return null;
2340
- }
2341
- const invocation = getPackageManagerRunInvocation(project.packageManager, script.scriptName, extraArgs);
2342
- return {
2343
- args: invocation.args,
2344
- command: invocation.command,
2345
- displayCommand: formatRunScript(project.packageManager, script.scriptName, extraArgs.join(" ")),
2346
- scriptName: script.scriptName
2347
- };
2348
- }
2349
- function buildSyncPlannedCommands(project, extraArgs, target) {
2350
- if (target === "ai") {
2351
- const syncAiCommand2 = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2352
- if (!syncAiCommand2) {
2353
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define a \`sync-ai\` script for \`wp-typia sync ai\`.`);
2354
- }
2355
- return [syncAiCommand2];
2356
- }
2357
- if (project.scripts.sync) {
2358
- return [createSyncPlannedCommand(project, "sync", extraArgs)];
2359
- }
2360
- const syncTypesCommand = createSyncPlannedCommand(project, "sync-types", extraArgs);
2361
- if (!syncTypesCommand) {
2362
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING, `Expected ${project.packageJsonPath} to define either a \`sync\` or \`sync-types\` script.`);
2363
- }
2364
- const plannedCommands = [syncTypesCommand];
2365
- const syncRestCommand = createSyncPlannedCommand(project, "sync-rest", extraArgs);
2366
- if (syncRestCommand) {
2367
- plannedCommands.push(syncRestCommand);
2368
- }
2369
- const syncAiCommand = createSyncPlannedCommand(project, "sync-ai", extraArgs);
2370
- if (syncAiCommand) {
2371
- plannedCommands.push(syncAiCommand);
2372
- }
2373
- return plannedCommands;
2374
- }
2375
- function runProjectScript(project, plannedCommand, options) {
2376
- const result = spawnSync(plannedCommand.command, plannedCommand.args, {
2377
- cwd: project.cwd,
2378
- encoding: options.captureOutput ? "utf8" : undefined,
2379
- ...options.captureOutput ? { maxBuffer: CAPTURED_SYNC_OUTPUT_MAX_BUFFER } : {},
2380
- shell: process.platform === "win32",
2381
- stdio: options.captureOutput ? "pipe" : "inherit"
2382
- });
2383
- const stderr = options.captureOutput && typeof result.stderr === "string" ? result.stderr : undefined;
2384
- const stdout = options.captureOutput && typeof result.stdout === "string" ? result.stdout : undefined;
2385
- if (result.error || result.status !== 0) {
2386
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.COMMAND_EXECUTION, `\`${plannedCommand.displayCommand}\` failed.`, {
2387
- cause: result.error ?? (stderr ? new Error(stderr.trim()) : undefined)
2388
- });
2389
- }
2390
- return {
2391
- ...plannedCommand,
2392
- exitCode: result.status ?? 0,
2393
- ...stderr !== undefined ? { stderr } : {},
2394
- ...stdout !== undefined ? { stdout } : {}
2395
- };
2396
- }
2397
- async function executeSyncCommand({
2398
- captureOutput = false,
2399
- check = false,
2400
- cwd,
2401
- dryRun = false,
2402
- target = "default"
2403
- }) {
2404
- const project = resolveSyncProjectContext(cwd);
2405
- const extraArgs = check ? ["--check"] : [];
2406
- const plannedCommands = buildSyncPlannedCommands(project, extraArgs, target);
2407
- const result = {
2408
- check,
2409
- dryRun,
2410
- packageJsonPath: project.packageJsonPath,
2411
- packageManager: project.packageManager,
2412
- plannedCommands,
2413
- projectDir: project.cwd,
2414
- target
2415
- };
2416
- if (dryRun) {
2417
- return result;
2418
- }
2419
- assertSyncDependenciesInstalled(project, target);
2420
- result.executedCommands = plannedCommands.map((plannedCommand) => runProjectScript(project, plannedCommand, {
2421
- captureOutput
2422
- }));
2423
- return result;
2424
- }
2425
- // src/ui/lazy-flow.tsx
2426
- var import_react33 = __toESM(require_react(), 1);
2427
-
2428
- // src/ui/alternate-buffer-lifecycle.ts
2429
- var import_react32 = __toESM(require_react(), 1);
2430
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/utils/format.ts
2431
- var KEYWORDS = new Set([
2432
- "const",
2433
- "let",
2434
- "var",
2435
- "function",
2436
- "class",
2437
- "return",
2438
- "if",
2439
- "else",
2440
- "for",
2441
- "while",
2442
- "import",
2443
- "export",
2444
- "from",
2445
- "async",
2446
- "await",
2447
- "try",
2448
- "catch",
2449
- "throw",
2450
- "new",
2451
- "typeof",
2452
- "interface",
2453
- "type",
2454
- "enum",
2455
- "extends",
2456
- "implements",
2457
- "public",
2458
- "private",
2459
- "protected",
2460
- "def",
2461
- "fn",
2462
- "pub",
2463
- "use",
2464
- "mod",
2465
- "struct",
2466
- "impl",
2467
- "trait"
2468
- ]);
2469
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/form.tsx
2470
- var import_react2 = __toESM(require_react(), 1);
2471
-
2472
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/form-context.tsx
2473
- var import_react = __toESM(require_react(), 1);
2474
- var FormContext = import_react.createContext(null);
2475
-
2476
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/form.tsx
2477
- var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
2478
- var formKeymap = createKeyMatcher({
2479
- cancel: ["escape"],
2480
- nextField: ["tab"],
2481
- previousField: ["shift+tab"],
2482
- submitShortcut: ["ctrl+s"],
2483
- resetShortcut: ["ctrl+r"],
2484
- nextError: ["f8"],
2485
- previousError: ["shift+f8"],
2486
- submit: ["enter"]
2487
- });
2488
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/form-field.tsx
2489
- var import_react3 = __toESM(require_react(), 1);
2490
- var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
2491
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/select-field.tsx
2492
- var import_react4 = __toESM(require_react(), 1);
2493
- var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
2494
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/multi-select-field.tsx
2495
- var import_react5 = __toESM(require_react(), 1);
2496
- var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
2497
- var multiSelectKeymap = createKeyMatcher({
2498
- up: ["up", "k"],
2499
- down: ["down", "j"],
2500
- toggle: ["space"],
2501
- submit: ["enter"]
2502
- });
2503
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/number-field.tsx
2504
- var import_react6 = __toESM(require_react(), 1);
2505
- var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
2506
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/password-field.tsx
2507
- var import_react7 = __toESM(require_react(), 1);
2508
- var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
2509
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/textarea-field.tsx
2510
- var import_react8 = __toESM(require_react(), 1);
2511
- var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
2512
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/checkbox-field.tsx
2513
- var import_react9 = __toESM(require_react(), 1);
2514
- var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
2515
- var checkboxKeymap = createKeyMatcher({
2516
- toggle: ["space", "enter"]
2517
- });
2518
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/schema-form.tsx
2519
- var import_react10 = __toESM(require_react(), 1);
2520
- var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
2521
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/progress-bar.tsx
2522
- var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
2523
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/stack.tsx
2524
- var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
2525
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/panel.tsx
2526
- var jsx_dev_runtime12 = __toESM(require_jsx_dev_runtime(), 1);
2527
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/scroll-panel.tsx
2528
- var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
2529
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/card.tsx
2530
- var jsx_dev_runtime14 = __toESM(require_jsx_dev_runtime(), 1);
2531
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/alert.tsx
2532
- var jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
2533
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/badge.tsx
2534
- var jsx_dev_runtime16 = __toESM(require_jsx_dev_runtime(), 1);
2535
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/divider.tsx
2536
- var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
2537
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/key-value-list.tsx
2538
- var import_react11 = __toESM(require_react(), 1);
2539
- var jsx_dev_runtime18 = __toESM(require_jsx_dev_runtime(), 1);
2540
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/stat.tsx
2541
- var jsx_dev_runtime19 = __toESM(require_jsx_dev_runtime(), 1);
2542
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/container.tsx
2543
- var jsx_dev_runtime20 = __toESM(require_jsx_dev_runtime(), 1);
2544
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/grid.tsx
2545
- var import_react12 = __toESM(require_react(), 1);
2546
- var jsx_dev_runtime21 = __toESM(require_jsx_dev_runtime(), 1);
2547
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/section-header.tsx
2548
- var jsx_dev_runtime22 = __toESM(require_jsx_dev_runtime(), 1);
2549
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/empty-state.tsx
2550
- var jsx_dev_runtime23 = __toESM(require_jsx_dev_runtime(), 1);
2551
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/toast.tsx
2552
- var jsx_dev_runtime24 = __toESM(require_jsx_dev_runtime(), 1);
2553
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/modal.tsx
2554
- var import_react13 = __toESM(require_react(), 1);
2555
- var jsx_dev_runtime25 = __toESM(require_jsx_dev_runtime(), 1);
2556
- var modalKeymap = createKeyMatcher({
2557
- close: ["escape", "ctrl+c"],
2558
- trap: ["tab", "shift+tab"]
2559
- });
2560
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/tabs.tsx
2561
- var import_react15 = __toESM(require_react(), 1);
2562
- var jsx_dev_runtime26 = __toESM(require_jsx_dev_runtime(), 1);
2563
- var tabsKeymap = createKeyMatcher({
2564
- previous: ["left", "h"],
2565
- next: ["right", "l"]
2566
- });
2567
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/confirm.tsx
2568
- var import_react16 = __toESM(require_react(), 1);
2569
- var jsx_dev_runtime27 = __toESM(require_jsx_dev_runtime(), 1);
2570
- var confirmKeymap = createKeyMatcher({
2571
- toggle: ["left", "right", "h", "l", "tab"],
2572
- affirm: ["y"],
2573
- negate: ["n", "q"],
2574
- submit: ["enter"],
2575
- abort: ["escape"]
2576
- });
2577
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/menu.tsx
2578
- var import_react17 = __toESM(require_react(), 1);
2579
- var jsx_dev_runtime28 = __toESM(require_jsx_dev_runtime(), 1);
2580
- var menuKeymap = createKeyMatcher({
2581
- up: ["up", "k"],
2582
- down: ["down", "j"],
2583
- select: ["enter"]
2584
- });
2585
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/nav-list.tsx
2586
- var import_react18 = __toESM(require_react(), 1);
2587
- var jsx_dev_runtime29 = __toESM(require_jsx_dev_runtime(), 1);
2588
- var navKeymap = createKeyMatcher({
2589
- up: ["up", "k"],
2590
- down: ["down", "j"],
2591
- select: ["enter"]
2592
- });
2593
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/command-palette.tsx
2594
- var import_react19 = __toESM(require_react(), 1);
2595
- var jsx_dev_runtime30 = __toESM(require_jsx_dev_runtime(), 1);
2596
- var paletteKeymap = createKeyMatcher({
2597
- up: ["up", "k"],
2598
- down: ["down", "j"],
2599
- select: ["enter"]
2600
- });
2601
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/filter.tsx
2602
- var import_react20 = __toESM(require_react(), 1);
2603
- var jsx_dev_runtime31 = __toESM(require_jsx_dev_runtime(), 1);
2604
- var filterKeymap = createKeyMatcher({
2605
- up: ["up"],
2606
- down: ["down"],
2607
- toggle: ["tab"],
2608
- selectAll: ["ctrl+a"],
2609
- submit: ["enter"],
2610
- abort: ["escape"]
2611
- });
2612
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/data-table.tsx
2613
- var import_react21 = __toESM(require_react(), 1);
2614
- var jsx_dev_runtime32 = __toESM(require_jsx_dev_runtime(), 1);
2615
- var dataTableKeymap = createKeyMatcher({
2616
- sortPrevious: ["left", "h"],
2617
- sortNext: ["right", "l"],
2618
- rowPrevious: ["up", "k"],
2619
- rowNext: ["down", "j"],
2620
- select: ["enter"]
2621
- });
2622
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/sidebar-layout.tsx
2623
- var import_react22 = __toESM(require_react(), 1);
2624
- var jsx_dev_runtime33 = __toESM(require_jsx_dev_runtime(), 1);
2625
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/spinner.tsx
2626
- var import_react24 = __toESM(require_react(), 1);
2627
- var jsx_dev_runtime34 = __toESM(require_jsx_dev_runtime(), 1);
2628
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/pager.tsx
2629
- var import_react25 = __toESM(require_react(), 1);
2630
- var jsx_dev_runtime35 = __toESM(require_jsx_dev_runtime(), 1);
2631
- var pagerKeymap = createKeyMatcher({
2632
- scrollDown: ["down", "j"],
2633
- scrollUp: ["up", "k"],
2634
- halfPageDown: ["d"],
2635
- halfPageUp: ["u"],
2636
- top: ["g", "home"],
2637
- bottom: ["end"],
2638
- search: ["/"],
2639
- nextMatch: ["n"],
2640
- prevMatch: ["shift+n"],
2641
- quit: ["q", "escape"]
2642
- });
2643
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/choose.tsx
2644
- var import_react26 = __toESM(require_react(), 1);
2645
- var jsx_dev_runtime36 = __toESM(require_jsx_dev_runtime(), 1);
2646
- var chooseKeymap = createKeyMatcher({
2647
- up: ["up", "k"],
2648
- down: ["down", "j"],
2649
- pageUp: ["left", "h"],
2650
- pageDown: ["right", "l"],
2651
- home: ["g", "home"],
2652
- end: ["end", "G"],
2653
- toggle: ["space", "tab", "x"],
2654
- selectAll: ["a"],
2655
- submit: ["enter"],
2656
- abort: ["escape"]
2657
- });
2658
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/components/file-picker.tsx
2659
- var import_react27 = __toESM(require_react(), 1);
2660
- var jsx_dev_runtime37 = __toESM(require_jsx_dev_runtime(), 1);
2661
- var filePickerKeymap = createKeyMatcher({
2662
- up: ["up", "k"],
2663
- down: ["down", "j"],
2664
- enter: ["enter", "right", "l"],
2665
- back: ["backspace", "left", "h"],
2666
- toggleHidden: ["."],
2667
- quit: ["q", "escape"]
2668
- });
2669
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/interactive/index.tsx
2670
- var jsx_dev_runtime38 = __toESM(require_jsx_dev_runtime(), 1);
2671
- // ../../node_modules/.bun/@bunli+tui@0.6.0+df522c502ed1ba91/node_modules/@bunli/tui/src/charts/index.tsx
2672
- var import_react30 = __toESM(require_react(), 1);
2673
- var jsx_dev_runtime39 = __toESM(require_jsx_dev_runtime(), 1);
2674
- // src/ui/alternate-buffer-lifecycle.ts
2675
- function describeAlternateBufferFailure(context, error) {
2676
- const message = error instanceof Error ? error.message : String(error);
2677
- return `${context}: ${message}`;
2678
- }
2679
- function isAlternateBufferExitKey(key) {
2680
- return key.name === "q" || key.ctrl === true && key.name === "c";
2681
- }
2682
- function isAlternateBufferCompletionKey(key) {
2683
- return key.name === "enter" || key.sequence === "\r" || key.sequence === `
2684
- `;
2685
- }
2686
- function reportAlternateBufferFailure({
2687
- context,
2688
- error,
2689
- exit,
2690
- log = console.error
2691
- }) {
2692
- const message = describeAlternateBufferFailure(context, error);
2693
- exit();
2694
- log(message);
2695
- }
2696
- async function resolveLazyFlowComponent({
2697
- loader,
2698
- onLoaded,
2699
- onFailure,
2700
- isDisposed
2701
- }) {
2702
- try {
2703
- const module = await loader();
2704
- if (!isDisposed()) {
2705
- onLoaded(module.default);
2706
- }
2707
- } catch (error) {
2708
- if (!isDisposed()) {
2709
- onFailure(error);
2710
- }
2711
- }
2712
- }
2713
- function useAlternateBufferExitKeys(options = {}) {
2714
- const runtime = useRuntime();
2715
- const exit = options.exit ?? (() => runtime.exit());
2716
- const enabled = options.enabled ?? true;
2717
- useKeyboard((key) => {
2718
- if (!enabled) {
2719
- return;
2720
- }
2721
- if (isAlternateBufferExitKey(key)) {
2722
- exit();
2723
- }
2724
- });
2725
- }
2726
- function useAlternateBufferCompletionKeys(options = {}) {
2727
- const runtime = useRuntime();
2728
- const exit = options.exit ?? (() => runtime.exit());
2729
- const enabled = options.enabled ?? false;
2730
- useKeyboard((key) => {
2731
- if (!enabled) {
2732
- return;
2733
- }
2734
- if (isAlternateBufferCompletionKey(key) || isAlternateBufferExitKey(key)) {
2735
- exit();
2736
- }
2737
- });
2738
- }
2739
- function isAlternateBufferCompletionPayload(value) {
2740
- if (!value || typeof value !== "object" || Array.isArray(value)) {
2741
- return false;
2742
- }
2743
- const candidate = value;
2744
- return typeof candidate.title === "string" && candidate.title.trim().length > 0;
2745
- }
2746
- function useAlternateBufferLifecycle(context, options = {}) {
2747
- const runtime = useRuntime();
2748
- const [completion, setCompletion] = import_react32.useState(null);
2749
- const [progress, setProgress] = import_react32.useState(null);
2750
- const [status, setStatus] = import_react32.useState("editing");
2751
- const exit = import_react32.useCallback(() => {
2752
- runtime.exit();
2753
- }, [runtime]);
2754
- useAlternateBufferExitKeys({
2755
- enabled: (options.enableExitKeys ?? true) && status !== "completed",
2756
- exit
2757
- });
2758
- useAlternateBufferCompletionKeys({
2759
- enabled: status === "completed",
2760
- exit
2761
- });
2762
- const handleCancel = import_react32.useCallback(() => {
2763
- setCompletion(null);
2764
- setProgress(null);
2765
- setStatus("editing");
2766
- exit();
2767
- }, [exit]);
2768
- const handleFailure = import_react32.useCallback((error) => {
2769
- setCompletion(null);
2770
- setProgress(null);
2771
- setStatus("editing");
2772
- reportAlternateBufferFailure({
2773
- context,
2774
- error,
2775
- exit
2776
- });
2777
- }, [context, exit]);
2778
- const handleSubmit = import_react32.useCallback(async (action) => {
2779
- setCompletion(null);
2780
- setProgress(null);
2781
- setStatus("submitting");
2782
- try {
2783
- const result = await action();
2784
- if (isAlternateBufferCompletionPayload(result)) {
2785
- setCompletion(result);
2786
- setProgress(null);
2787
- setStatus("completed");
2788
- return;
2789
- }
2790
- exit();
2791
- } catch (error) {
2792
- setCompletion(null);
2793
- setProgress(null);
2794
- setStatus("editing");
2795
- reportAlternateBufferFailure({
2796
- context,
2797
- error,
2798
- exit
2799
- });
2800
- }
2801
- }, [context, exit]);
2802
- const reportProgress = import_react32.useCallback((payload) => {
2803
- setProgress(payload);
2804
- }, []);
2805
- return {
2806
- completion,
2807
- handleCancel,
2808
- handleFailure,
2809
- handleSubmit,
2810
- progress,
2811
- reportProgress,
2812
- status
2813
- };
2814
- }
2815
-
2816
- // src/ui/lazy-flow.tsx
2817
- function LazyFlow({ loader, props }) {
2818
- const [Component, setComponent] = import_react33.useState(null);
2819
- const { handleFailure } = useAlternateBufferLifecycle("wp-typia TUI flow failed", {
2820
- enableExitKeys: false
2821
- });
2822
- useAlternateBufferExitKeys({
2823
- enabled: Component === null
2824
- });
2825
- import_react33.useEffect(() => {
2826
- let disposed = false;
2827
- resolveLazyFlowComponent({
2828
- isDisposed: () => disposed,
2829
- loader,
2830
- onFailure: handleFailure,
2831
- onLoaded: (component) => {
2832
- setComponent(() => component);
2833
- }
2834
- });
2835
- return () => {
2836
- disposed = true;
2837
- };
2838
- }, [handleFailure, loader]);
2839
- if (!Component) {
2840
- return null;
2841
- }
2842
- return import_react33.createElement(Component, props);
2843
- }
2844
-
2845
- // src/commands/add.ts
2846
- function loadAddFlow() {
2847
- return import(resolveBundledModuleHref(import.meta.url, ["./ui/add-flow.js", "../ui/add-flow.js", "../ui/add-flow.tsx"], {
2848
- moduleLabel: "the add-flow UI"
2849
- })).then((module) => ({ default: module.AddFlow }));
2850
- }
2851
- var addOptions = buildCommandOptions(ADD_OPTION_METADATA);
2852
- function resolveAddCommandName(positional) {
2853
- if (positional[0] === "core-variation" && positional[2]) {
2854
- return positional[2];
2855
- }
2856
- return positional[1];
2857
- }
2858
- var addCommand = defineCommand({
2859
- defaultFormat: "toon",
2860
- description: "Extend an official wp-typia workspace with blocks, integration envs, variations, block styles, transforms, patterns, binding sources, standalone contracts, plugin-level REST resources, post meta contracts, workflow abilities, server-only AI features, editor plugins, or hooked blocks.",
2861
- handler: async (args) => {
2862
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
2863
- const { printLine, warnLine } = resolveCommandOutputAdapters(args);
2864
- try {
2865
- if (prefersStructuredOutput) {
2866
- const completion = await executeAddCommand({
2867
- cwd: args.cwd,
2868
- emitOutput: false,
2869
- flags: args.flags,
2870
- interactive: false,
2871
- kind: args.positional[0],
2872
- name: resolveAddCommandName(args.positional),
2873
- positionalArgs: args.positional,
2874
- printLine,
2875
- warnLine
2876
- });
2877
- args.output(buildStructuredCompletionSuccessPayload("add", completion, {
2878
- dryRun: Boolean(args.flags["dry-run"]),
2879
- kind: args.positional[0],
2880
- name: resolveAddCommandName(args.positional),
2881
- projectDir: extractCompletionProjectDir(completion) ?? args.cwd
2882
- }));
2883
- return;
2884
- }
2885
- await executeAddCommand({
2886
- cwd: args.cwd,
2887
- flags: args.flags,
2888
- kind: args.positional[0],
2889
- name: resolveAddCommandName(args.positional),
2890
- positionalArgs: args.positional,
2891
- printLine,
2892
- warnLine
2893
- });
2894
- } catch (error) {
2895
- emitCliDiagnosticFailure(args, {
2896
- command: "add",
2897
- error
2898
- });
2899
- }
2900
- },
2901
- name: "add",
2902
- options: addOptions,
2903
- ...supportsInteractiveTui() ? {
2904
- render: (args) => {
2905
- const config = args.context?.store?.wpTypiaUserConfig && typeof args.context.store.wpTypiaUserConfig === "object" ? getAddBlockDefaults(args.context.store.wpTypiaUserConfig) : {};
2906
- const initialValues = resolveCommandOptionValues(ADD_OPTION_METADATA, {
2907
- defaults: config,
2908
- flags: args.flags,
2909
- optionNames: Object.keys(ADD_OPTION_METADATA).filter((optionName) => optionName !== "dry-run")
2910
- });
2911
- return import_react34.createElement(LazyFlow, {
2912
- loader: loadAddFlow,
2913
- props: {
2914
- cwd: args.cwd,
2915
- initialValues: {
2916
- ...initialValues,
2917
- kind: args.positional[0] ?? "block",
2918
- name: resolveAddCommandName(args.positional) ?? "",
2919
- ...args.positional[0] === "core-variation" && args.positional[2] ? { block: args.positional[1] } : {},
2920
- position: initialValues.position ?? "after",
2921
- slot: initialValues.slot ?? "sidebar"
2922
- }
2923
- }
2924
- });
2925
- },
2926
- tui: {
2927
- renderer: {
2928
- bufferMode: "alternate"
2929
- }
2930
- }
2931
- } : {}
2932
- });
2933
-
2934
- // src/commands/create.ts
2935
- var import_react35 = __toESM(require_react(), 1);
2936
- function loadCreateFlow() {
2937
- return import(resolveBundledModuleHref(import.meta.url, [
2938
- "./ui/create-flow.js",
2939
- "../ui/create-flow.js",
2940
- "../ui/create-flow.tsx"
2941
- ], {
2942
- moduleLabel: "the create-flow UI"
2943
- })).then((module) => ({ default: module.CreateFlow }));
2944
- }
2945
- var createOptions = buildCommandOptions(CREATE_OPTION_METADATA);
2946
- var createCommand = defineCommand({
2947
- defaultFormat: "toon",
2948
- description: "Scaffold a new wp-typia project.",
2949
- handler: async (args) => {
2950
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
2951
- const { printLine, warnLine } = resolveCommandOutputAdapters(args);
2952
- const projectDir = args.positional[0];
2953
- if (!projectDir) {
2954
- emitCliDiagnosticFailure(args, {
2955
- code: CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT,
2956
- command: "create",
2957
- detailLines: buildMissingCreateProjectDirDetailLines()
2958
- });
2959
- return;
2960
- }
2961
- try {
2962
- const completion = await executeCreateCommand({
2963
- cwd: args.cwd,
2964
- emitOutput: !prefersStructuredOutput,
2965
- flags: args.flags,
2966
- interactive: prefersStructuredOutput ? false : undefined,
2967
- printLine,
2968
- projectDir,
2969
- warnLine
2970
- });
2971
- if (prefersStructuredOutput) {
2972
- args.output(buildStructuredCompletionSuccessPayload("create", completion, {
2973
- dryRun: Boolean(args.flags["dry-run"]),
2974
- projectDir: extractCompletionProjectDir(completion) ?? projectDir,
2975
- template: typeof args.flags.template === "string" ? args.flags.template : undefined
2976
- }));
2977
- }
2978
- } catch (error) {
2979
- emitCliDiagnosticFailure(args, {
2980
- command: "create",
2981
- error
2982
- });
2983
- }
2984
- },
2985
- name: "create",
2986
- options: createOptions,
2987
- ...supportsInteractiveTui() ? {
2988
- render: (args) => {
2989
- const config = args.context?.store?.wpTypiaUserConfig && typeof args.context.store.wpTypiaUserConfig === "object" ? getCreateDefaults(args.context.store.wpTypiaUserConfig) : {};
2990
- const initialValues = resolveCommandOptionValues(CREATE_OPTION_METADATA, {
2991
- defaults: config,
2992
- flags: args.flags
2993
- });
2994
- return import_react35.createElement(LazyFlow, {
2995
- loader: loadCreateFlow,
2996
- props: {
2997
- cwd: args.cwd,
2998
- initialValues: {
2999
- ...initialValues,
3000
- "project-dir": args.positional[0] ?? ""
3001
- }
3002
- }
3003
- });
3004
- },
3005
- tui: {
3006
- renderer: {
3007
- bufferMode: "alternate"
3008
- }
3009
- }
3010
- } : {}
3011
- });
3012
-
3013
- // src/commands/doctor.ts
3014
- var doctorCommand = defineCommand({
3015
- defaultFormat: "toon",
3016
- description: "Run repository and project diagnostics.",
3017
- handler: async (args) => {
3018
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
3019
- const doctorExitPolicy = args.flags["workspace-only"] ? "workspace-only" : "strict";
3020
- if (prefersStructuredOutput) {
3021
- const {
3022
- createDoctorRunSummary,
3023
- getDoctorChecks,
3024
- getDoctorExitFailureDetailLines
3025
- } = await import("./cli-doctor-6fyxq940.js");
3026
- const checks = await getDoctorChecks(args.cwd);
3027
- const summary = createDoctorRunSummary(checks, {
3028
- exitPolicy: doctorExitPolicy
3029
- });
3030
- if (summary.exitCode === 1) {
3031
- emitCliDiagnosticFailure(args, {
3032
- code: CLI_DIAGNOSTIC_CODES.DOCTOR_CHECK_FAILED,
3033
- command: "doctor",
3034
- detailLines: getDoctorExitFailureDetailLines(checks, {
3035
- exitPolicy: doctorExitPolicy
3036
- }),
3037
- extraOutput: { checks, summary },
3038
- summary: "One or more doctor checks failed."
3039
- });
3040
- return;
3041
- }
3042
- args.output({ checks, summary });
3043
- return;
3044
- }
3045
- try {
3046
- await executeDoctorCommand(args.cwd, { exitPolicy: doctorExitPolicy });
3047
- } catch (error) {
3048
- emitCliDiagnosticFailure(args, {
3049
- command: "doctor",
3050
- error
3051
- });
3052
- }
3053
- },
3054
- name: "doctor",
3055
- options: buildCommandOptions(DOCTOR_OPTION_METADATA)
3056
- });
3057
-
3058
- // src/commands/init.ts
3059
- var initCommand = defineCommand({
3060
- defaultFormat: "toon",
3061
- description: "Preview or apply the minimum wp-typia retrofit plan for an existing project.",
3062
- handler: async (args) => {
3063
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
3064
- const { printLine, warnLine } = resolveCommandOutputAdapters(args);
3065
- try {
3066
- const plan = await executeInitCommand({
3067
- apply: Boolean(args.flags.apply),
3068
- cwd: args.cwd,
3069
- packageManager: typeof args.flags["package-manager"] === "string" ? args.flags["package-manager"] : undefined,
3070
- projectDir: args.positional[0]
3071
- }, {
3072
- emitOutput: !prefersStructuredOutput,
3073
- printLine,
3074
- warnLine
3075
- });
3076
- if (prefersStructuredOutput) {
3077
- args.output(buildStructuredInitSuccessPayload(plan));
3078
- }
3079
- } catch (error) {
3080
- emitCliDiagnosticFailure(args, {
3081
- command: "init",
3082
- error
3083
- });
3084
- }
3085
- },
3086
- name: "init",
3087
- options: buildCommandOptions(INIT_OPTION_METADATA)
3088
- });
3089
-
3090
- // src/mcp.ts
3091
- import fs4 from "fs/promises";
3092
- import path4 from "path";
3093
-
3094
- // ../../node_modules/.bun/@bunli+plugin-mcp@0.2.5+ef72ce197b058209/node_modules/@bunli/plugin-mcp/src/errors.ts
3095
- class SchemaConversionError extends TaggedError("SchemaConversionError")() {
3096
- }
3097
-
3098
- class ConvertToolsError extends TaggedError("ConvertToolsError")() {
3099
- }
3100
-
3101
- class GenerateMCPTypesError extends TaggedError("GenerateMCPTypesError")() {
3102
- }
3103
-
3104
- class McpToolsProviderError extends TaggedError("McpToolsProviderError")() {
3105
- }
3106
-
3107
- // ../../node_modules/.bun/@bunli+plugin-mcp@0.2.5+ef72ce197b058209/node_modules/@bunli/plugin-mcp/src/schema-to-zod.ts
3108
- function jsonSchemaToZodSchema(schema, options = {}) {
3109
- return convertSchema(schema, options, "$");
3110
- }
3111
- function convertSchema(schema, options, path4) {
3112
- const { coerce = true } = options;
3113
- if (!schema || typeof schema !== "object") {
3114
- return Result.ok(exports_external.unknown());
3115
- }
3116
- if (schema.const !== undefined) {
3117
- return Result.ok(exports_external.literal(schema.const));
3118
- }
3119
- if (schema.enum && schema.enum.length > 0) {
3120
- const enumValues = schema.enum.filter((v) => v !== null);
3121
- if (enumValues.length > 0) {
3122
- if (enumValues.every((v) => typeof v === "string")) {
3123
- return Result.ok(exports_external.enum(enumValues));
3124
- }
3125
- const literals = enumValues.map((v) => exports_external.literal(v));
3126
- return unionFromSchemas(literals, path4);
3127
- }
3128
- }
3129
- if (schema.anyOf && schema.anyOf.length > 0) {
3130
- const schemas = mapSchemas(schema.anyOf, options, `${path4}.anyOf`);
3131
- if (Result.isError(schemas)) {
3132
- return schemas;
3133
- }
3134
- return unionFromSchemas(schemas.value, `${path4}.anyOf`);
3135
- }
3136
- if (schema.oneOf && schema.oneOf.length > 0) {
3137
- const schemas = mapSchemas(schema.oneOf, options, `${path4}.oneOf`);
3138
- if (Result.isError(schemas)) {
3139
- return schemas;
3140
- }
3141
- return unionFromSchemas(schemas.value, `${path4}.oneOf`);
3142
- }
3143
- const schemaType = Array.isArray(schema.type) ? schema.type[0] : schema.type;
3144
- switch (schemaType) {
3145
- case "string":
3146
- return buildStringSchema(schema, path4);
3147
- case "number":
3148
- case "integer":
3149
- return Result.ok(buildNumberSchema(schema, coerce));
3150
- case "boolean":
3151
- return Result.ok(buildBooleanSchema());
3152
- case "array":
3153
- return buildArraySchema(schema, options, path4);
3154
- case "object":
3155
- return buildObjectSchema(schema, options, path4);
3156
- case "null":
3157
- return Result.ok(exports_external.null());
3158
- default:
3159
- if (schema.properties) {
3160
- return buildObjectSchema(schema, options, path4);
3161
- }
3162
- if (schema.items) {
3163
- return buildArraySchema(schema, options, path4);
3164
- }
3165
- return Result.ok(exports_external.unknown());
3166
- }
3167
- }
3168
- function buildStringSchema(schema, path4) {
3169
- let zodSchema = exports_external.string();
3170
- if (schema.minLength !== undefined) {
3171
- zodSchema = zodSchema.min(schema.minLength);
3172
- }
3173
- if (schema.maxLength !== undefined) {
3174
- zodSchema = zodSchema.max(schema.maxLength);
3175
- }
3176
- if (schema.pattern) {
3177
- const pattern = schema.pattern;
3178
- const regexResult = Result.try({
3179
- try: () => new RegExp(pattern),
3180
- catch: (cause) => new SchemaConversionError({
3181
- path: path4,
3182
- message: `Invalid regex pattern "${pattern}"`,
3183
- cause
3184
- })
3185
- });
3186
- if (Result.isError(regexResult)) {
3187
- return regexResult;
3188
- }
3189
- zodSchema = zodSchema.regex(regexResult.value);
3190
- }
3191
- if (schema.format) {
3192
- switch (schema.format) {
3193
- case "email":
3194
- zodSchema = zodSchema.email();
3195
- break;
3196
- case "uri":
3197
- case "url":
3198
- zodSchema = zodSchema.url();
3199
- break;
3200
- case "uuid":
3201
- zodSchema = zodSchema.uuid();
3202
- break;
3203
- case "date-time":
3204
- zodSchema = zodSchema.datetime();
3205
- break;
3206
- case "date":
3207
- zodSchema = zodSchema.date();
3208
- break;
3209
- }
3210
- }
3211
- return Result.ok(zodSchema);
3212
- }
3213
- function buildNumberSchema(schema, coerce) {
3214
- let zodSchema = coerce ? exports_external.coerce.number() : exports_external.number();
3215
- if (schema.type === "integer" || Array.isArray(schema.type) && schema.type.includes("integer")) {
3216
- zodSchema = zodSchema.int();
3217
- }
3218
- if (schema.minimum !== undefined) {
3219
- zodSchema = zodSchema.min(schema.minimum);
3220
- }
3221
- if (schema.maximum !== undefined) {
3222
- zodSchema = zodSchema.max(schema.maximum);
3223
- }
3224
- if (schema.exclusiveMinimum !== undefined) {
3225
- zodSchema = zodSchema.gt(schema.exclusiveMinimum);
3226
- }
3227
- if (schema.exclusiveMaximum !== undefined) {
3228
- zodSchema = zodSchema.lt(schema.exclusiveMaximum);
3229
- }
3230
- if (schema.multipleOf !== undefined) {
3231
- zodSchema = zodSchema.multipleOf(schema.multipleOf);
3232
- }
3233
- return zodSchema;
3234
- }
3235
- function buildBooleanSchema() {
3236
- return exports_external.boolean();
3237
- }
3238
- function buildArraySchema(schema, options, path4) {
3239
- let itemSchema = exports_external.unknown();
3240
- if (schema.items) {
3241
- if (Array.isArray(schema.items)) {
3242
- if (schema.items.length > 0) {
3243
- const itemResult = convertSchema(schema.items[0], options, `${path4}.items[0]`);
3244
- if (Result.isError(itemResult)) {
3245
- return itemResult;
3246
- }
3247
- itemSchema = itemResult.value;
3248
- }
3249
- } else {
3250
- const itemResult = convertSchema(schema.items, options, `${path4}.items`);
3251
- if (Result.isError(itemResult)) {
3252
- return itemResult;
3253
- }
3254
- itemSchema = itemResult.value;
3255
- }
3256
- }
3257
- let zodSchema = exports_external.array(itemSchema);
3258
- if (schema.minItems !== undefined) {
3259
- zodSchema = zodSchema.min(schema.minItems);
3260
- }
3261
- if (schema.maxItems !== undefined) {
3262
- zodSchema = zodSchema.max(schema.maxItems);
3263
- }
3264
- return Result.ok(zodSchema);
3265
- }
3266
- function buildObjectSchema(schema, options, path4) {
3267
- if (!schema.properties) {
3268
- return Result.ok(exports_external.record(exports_external.string(), exports_external.unknown()));
3269
- }
3270
- const shape = {};
3271
- const requiredFields = new Set(schema.required || []);
3272
- for (const [propName, propSchema] of Object.entries(schema.properties)) {
3273
- const propResult = convertSchema(propSchema, options, `${path4}.properties.${propName}`);
3274
- if (Result.isError(propResult)) {
3275
- return propResult;
3276
- }
3277
- let propZodSchema = propResult.value;
3278
- if (propSchema.default !== undefined) {
3279
- propZodSchema = propZodSchema.default(propSchema.default);
3280
- }
3281
- if (!requiredFields.has(propName)) {
3282
- propZodSchema = propZodSchema.optional();
3283
- }
3284
- shape[propName] = propZodSchema;
3285
- }
3286
- return Result.ok(exports_external.object(shape));
3287
- }
3288
- function mapSchemas(schemas, options, path4) {
3289
- const zodSchemas = [];
3290
- for (let index = 0;index < schemas.length; index += 1) {
3291
- const converted = convertSchema(schemas[index], options, `${path4}[${index}]`);
3292
- if (Result.isError(converted)) {
3293
- return converted;
3294
- }
3295
- zodSchemas.push(converted.value);
3296
- }
3297
- return Result.ok(zodSchemas);
3298
- }
3299
- function unionFromSchemas(schemas, path4) {
3300
- if (schemas.length === 0) {
3301
- return Result.err(new SchemaConversionError({
3302
- path: path4,
3303
- message: `Cannot create union from an empty schema set at ${path4}`,
3304
- cause: new Error("Empty schema union")
3305
- }));
3306
- }
3307
- if (schemas.length === 1) {
3308
- return Result.ok(schemas[0]);
3309
- }
3310
- let unionSchema = exports_external.union([schemas[0], schemas[1]]);
3311
- for (let index = 2;index < schemas.length; index += 1) {
3312
- unionSchema = exports_external.union([unionSchema, schemas[index]]);
3313
- }
3314
- return Result.ok(unionSchema);
3315
- }
3316
-
3317
- // ../../node_modules/.bun/@bunli+plugin-mcp@0.2.5+ef72ce197b058209/node_modules/@bunli/plugin-mcp/src/utils.ts
3318
- function toKebabCase(str) {
3319
- return str.replace(/_/g, "-").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
3320
- }
3321
- function toCommandName(toolName, namespace) {
3322
- const kebabName = toKebabCase(toolName);
3323
- return namespace ? `${namespace}:${kebabName}` : kebabName;
3324
- }
3325
- function toFlagName(propName) {
3326
- return toKebabCase(propName);
3327
- }
3328
- function toPascalCase(str) {
3329
- return str.split(/[-:_]/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
3330
- }
3331
- function escapeString(str) {
3332
- return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
3333
- }
3334
-
3335
- // ../../node_modules/.bun/@bunli+plugin-mcp@0.2.5+ef72ce197b058209/node_modules/@bunli/plugin-mcp/src/converter.ts
3336
- function createCommandsFromMCPTools(tools, options) {
3337
- const commands = [];
3338
- for (const tool of tools) {
3339
- const converted = convertToolToCommand(tool, options);
3340
- if (Result.isError(converted)) {
3341
- return converted;
3342
- }
3343
- commands.push(converted.value);
3344
- }
3345
- return Result.ok(commands);
3346
- }
3347
- function convertToolToCommand(tool, options) {
3348
- const {
3349
- namespace,
3350
- createHandler,
3351
- commandName: customCommandName,
3352
- flagName: customFlagName
3353
- } = options;
3354
- const commandName = customCommandName ? customCommandName(tool.name) : toCommandName(tool.name, namespace);
3355
- const bunliOptionsResult = convertInputSchemaToOptions(tool.name, tool.inputSchema, customFlagName || toFlagName);
3356
- if (Result.isError(bunliOptionsResult)) {
3357
- return bunliOptionsResult;
3358
- }
3359
- const command = {
3360
- name: commandName,
3361
- description: tool.description || `Invoke MCP tool: ${tool.name}`,
3362
- options: bunliOptionsResult.value,
3363
- handler: createHandler(tool.name)
3364
- };
3365
- return Result.ok(command);
3366
- }
3367
- function convertInputSchemaToOptions(toolName, inputSchema, flagNameTransform) {
3368
- const bunliOptions = {};
3369
- if (!inputSchema?.properties) {
3370
- return Result.ok(bunliOptions);
3371
- }
3372
- const requiredFields = new Set(inputSchema.required || []);
3373
- for (const [propName, propSchema] of Object.entries(inputSchema.properties)) {
3374
- const schemaResult = jsonSchemaToZodSchema(propSchema, { coerce: true });
3375
- if (Result.isError(schemaResult)) {
3376
- return Result.err(new ConvertToolsError({
3377
- toolName,
3378
- message: `Failed to convert input schema field "${propName}" for tool "${toolName}"`,
3379
- cause: schemaResult.error
3380
- }));
3381
- }
3382
- let zodSchema = schemaResult.value;
3383
- if (propSchema.default !== undefined) {
3384
- zodSchema = zodSchema.default(propSchema.default);
3385
- }
3386
- if (!requiredFields.has(propName)) {
3387
- zodSchema = zodSchema.optional();
3388
- }
3389
- const flagName = flagNameTransform(propName);
3390
- const shortMatch = propSchema.description?.match(/^\[-([a-zA-Z])\]\s*/);
3391
- const short = shortMatch ? shortMatch[1] : undefined;
3392
- const description = shortMatch ? propSchema.description?.slice(shortMatch[0].length) : propSchema.description;
3393
- bunliOptions[flagName] = option(zodSchema, {
3394
- description,
3395
- short
3396
- });
3397
- }
3398
- return Result.ok(bunliOptions);
3399
- }
3400
- function extractCommandMetadata(tool, namespace, flagNameTransform = toFlagName) {
3401
- const commandName = toCommandName(tool.name, namespace);
3402
- const optionsMeta = {};
3403
- if (tool.inputSchema?.properties) {
3404
- const requiredFields = new Set(tool.inputSchema.required || []);
3405
- for (const [propName, propSchema] of Object.entries(tool.inputSchema.properties)) {
3406
- const flagName = flagNameTransform(propName);
3407
- const schemaType = Array.isArray(propSchema.type) ? propSchema.type[0] : propSchema.type;
3408
- const shortMatch = propSchema.description?.match(/^\[-([a-zA-Z])\]\s*/);
3409
- const short = shortMatch ? shortMatch[1] : undefined;
3410
- const description = shortMatch ? propSchema.description?.slice(shortMatch[0].length) : propSchema.description;
3411
- optionsMeta[flagName] = {
3412
- type: schemaType || "unknown",
3413
- required: requiredFields.has(propName) && propSchema.default === undefined,
3414
- description,
3415
- short,
3416
- hasDefault: propSchema.default !== undefined,
3417
- default: propSchema.default
3418
- };
3419
- if (propSchema.enum) {
3420
- optionsMeta[flagName].enumValues = propSchema.enum.filter((v) => typeof v === "string" || typeof v === "number");
3421
- }
3422
- if (propSchema.minimum !== undefined) {
3423
- optionsMeta[flagName].minimum = propSchema.minimum;
3424
- }
3425
- if (propSchema.maximum !== undefined) {
3426
- optionsMeta[flagName].maximum = propSchema.maximum;
3427
- }
3428
- }
3429
- }
3430
- return {
3431
- name: commandName,
3432
- toolName: tool.name,
3433
- namespace,
3434
- description: tool.description,
3435
- options: optionsMeta
3436
- };
3437
- }
3438
- // ../../node_modules/.bun/@bunli+plugin-mcp@0.2.5+ef72ce197b058209/node_modules/@bunli/plugin-mcp/src/codegen.ts
3439
- import { mkdir, writeFile } from "fs/promises";
3440
- import { join as join2 } from "path";
3441
- async function generateMCPTypes(options) {
3442
- const { tools, outputDir } = options;
3443
- return await Result.tryPromise({
3444
- try: async () => {
3445
- await mkdir(outputDir, { recursive: true });
3446
- for (const { namespace, tools: toolList } of tools) {
3447
- if (!toolList || toolList.length === 0)
3448
- continue;
3449
- const content = generateNamespaceTypes(namespace, toolList);
3450
- const fileName = `mcp-${namespace}.gen.ts`;
3451
- const filePath = join2(outputDir, fileName);
3452
- await writeFile(filePath, content, "utf-8");
3453
- }
3454
- const indexContent = generateIndexFile(tools);
3455
- await writeFile(join2(outputDir, "mcp-index.gen.ts"), indexContent, "utf-8");
3456
- },
3457
- catch: (cause) => new GenerateMCPTypesError({
3458
- outputDir,
3459
- message: `Failed to generate MCP types in ${outputDir}`,
3460
- cause
3461
- })
3462
- });
3463
- }
3464
- function generateNamespaceTypes(namespace, tools) {
3465
- const lines = [];
3466
- lines.push(`// This file was automatically generated by @bunli/plugin-mcp`);
3467
- lines.push(`// DO NOT EDIT - changes will be overwritten`);
3468
- lines.push(``);
3469
- lines.push(`import type { Command, Options, CLIOption } from '@bunli/core'`);
3470
- lines.push(`import { option } from '@bunli/core'`);
3471
- lines.push(`import { z } from 'zod'`);
3472
- lines.push(``);
3473
- const metadata = tools.map((tool) => extractCommandMetadata(tool, namespace));
3474
- for (const cmd of metadata) {
3475
- lines.push(generateCommandSchema(cmd));
3476
- lines.push(``);
3477
- }
3478
- lines.push(generateModuleAugmentation(namespace, metadata));
3479
- return lines.join(`
3480
- `);
3481
- }
3482
- function generateCommandSchema(cmd) {
3483
- const lines = [];
3484
- const baseName = toPascalCase(cmd.name);
3485
- lines.push(`// ${cmd.description || cmd.toolName}`);
3486
- lines.push(`export const ${baseName}Options = {`);
3487
- for (const [flagName, opt] of Object.entries(cmd.options)) {
3488
- const zodSchema = generateZodSchemaString(opt);
3489
- const metadata = [];
3490
- if (opt.description) {
3491
- metadata.push(`description: '${escapeString(opt.description)}'`);
3492
- }
3493
- if (opt.short) {
3494
- metadata.push(`short: '${opt.short}'`);
3495
- }
3496
- const metadataStr = metadata.length > 0 ? `, { ${metadata.join(", ")} }` : "";
3497
- lines.push(` '${flagName}': option(${zodSchema}${metadataStr}),`);
3498
- }
3499
- lines.push(`} as const`);
3500
- lines.push(``);
3501
- lines.push(`export type ${baseName}Flags = {`);
3502
- for (const [flagName, opt] of Object.entries(cmd.options)) {
3503
- const tsType = jsonSchemaTypeToTS(opt.type, opt.enumValues);
3504
- const optional = !opt.required ? "?" : "";
3505
- lines.push(` '${flagName}'${optional}: ${tsType}`);
3506
- }
3507
- lines.push(`}`);
3508
- return lines.join(`
3509
- `);
3510
- }
3511
- function generateZodSchemaString(opt) {
3512
- let schema;
3513
- if (opt.enumValues && opt.enumValues.length > 0) {
3514
- if (opt.enumValues.every((v) => typeof v === "string")) {
3515
- const values = opt.enumValues.map((v) => `'${escapeString(v)}'`).join(", ");
3516
- schema = `z.enum([${values}])`;
3517
- } else {
3518
- const literals = opt.enumValues.map((v) => typeof v === "string" ? `z.literal('${escapeString(v)}')` : `z.literal(${v})`).join(", ");
3519
- schema = `z.union([${literals}])`;
3520
- }
3521
- } else {
3522
- switch (opt.type) {
3523
- case "string":
3524
- schema = "z.string()";
3525
- break;
3526
- case "number":
3527
- schema = "z.coerce.number()";
3528
- break;
3529
- case "integer":
3530
- schema = "z.coerce.number().int()";
3531
- break;
3532
- case "boolean":
3533
- schema = "z.boolean()";
3534
- break;
3535
- case "array":
3536
- schema = "z.array(z.unknown())";
3537
- break;
3538
- case "object":
3539
- schema = "z.record(z.unknown())";
3540
- break;
3541
- default:
3542
- schema = "z.unknown()";
3543
- }
3544
- }
3545
- if (opt.minimum !== undefined) {
3546
- schema += `.min(${opt.minimum})`;
3547
- }
3548
- if (opt.maximum !== undefined) {
3549
- schema += `.max(${opt.maximum})`;
3550
- }
3551
- if (opt.hasDefault && opt.default !== undefined) {
3552
- const defaultVal = typeof opt.default === "string" ? `'${escapeString(opt.default)}'` : JSON.stringify(opt.default);
3553
- schema += `.default(${defaultVal})`;
3554
- }
3555
- if (!opt.required && !opt.hasDefault) {
3556
- schema += ".optional()";
3557
- }
3558
- return schema;
3559
- }
3560
- function jsonSchemaTypeToTS(type, enumValues) {
3561
- if (enumValues && enumValues.length > 0) {
3562
- return enumValues.map((v) => typeof v === "string" ? `'${escapeString(v)}'` : String(v)).join(" | ");
3563
- }
3564
- switch (type) {
3565
- case "string":
3566
- return "string";
3567
- case "number":
3568
- case "integer":
3569
- return "number";
3570
- case "boolean":
3571
- return "boolean";
3572
- case "array":
3573
- return "unknown[]";
3574
- case "object":
3575
- return "Record<string, unknown>";
3576
- case "null":
3577
- return "null";
3578
- default:
3579
- return "unknown";
3580
- }
3581
- }
3582
- function generateModuleAugmentation(namespace, metadata) {
3583
- const lines = [];
3584
- lines.push(`// Module augmentation for type-safe execute()`);
3585
- lines.push(`declare module '@bunli/core' {`);
3586
- lines.push(` interface RegisteredCommands {`);
3587
- for (const cmd of metadata) {
3588
- const baseName = toPascalCase(cmd.name);
3589
- lines.push(` '${cmd.name}': Command<typeof ${baseName}Options>`);
3590
- }
3591
- lines.push(` }`);
3592
- lines.push(`}`);
3593
- return lines.join(`
3594
- `);
3595
- }
3596
- function generateIndexFile(toolGroups) {
3597
- const lines = [];
3598
- lines.push(`// This file was automatically generated by @bunli/plugin-mcp`);
3599
- lines.push(`// DO NOT EDIT - changes will be overwritten`);
3600
- lines.push(``);
3601
- for (const { namespace } of toolGroups) {
3602
- if (!namespace)
3603
- continue;
3604
- lines.push(`export * from './mcp-${namespace}.gen.js'`);
3605
- }
3606
- return lines.join(`
3607
- `);
3608
- }
3609
- // src/mcp.ts
3610
- function isObject(value) {
3611
- return typeof value === "object" && value !== null && !Array.isArray(value);
3612
- }
3613
- function isTool(value) {
3614
- return isObject(value) && typeof value.name === "string" && (value.description === undefined || typeof value.description === "string");
3615
- }
3616
- function isToolGroup(value) {
3617
- return isObject(value) && typeof value.namespace === "string" && Array.isArray(value.tools) && value.tools.every(isTool);
3618
- }
3619
- function getErrorMessage(error) {
3620
- return error instanceof Error ? error.message : String(error);
3621
- }
3622
- function getErrorCauseOptions(error) {
3623
- return error instanceof Error ? { cause: error } : undefined;
3624
- }
3625
- async function readSchemaSource(cwd, source) {
3626
- const schemaPath = path4.resolve(cwd, source.path);
3627
- const raw = await fs4.readFile(schemaPath, "utf8");
3628
- let parsed;
3629
- try {
3630
- parsed = JSON.parse(raw);
3631
- } catch (error) {
3632
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Schema source "${source.path}" must contain valid JSON. ${getErrorMessage(error)}`, getErrorCauseOptions(error));
3633
- }
3634
- if (isToolGroup(parsed)) {
3635
- return parsed;
3636
- }
3637
- if (Array.isArray(parsed) && parsed.every(isTool)) {
3638
- return {
3639
- namespace: source.namespace,
3640
- tools: parsed
3641
- };
3642
- }
3643
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `Schema source "${source.path}" must contain either one MCPToolGroup object or an array of MCP tools.`);
3644
- }
3645
- async function loadMcpToolGroups(cwd, schemaSources) {
3646
- return Promise.all(schemaSources.map((source) => readSchemaSource(cwd, source)));
3647
- }
3648
- async function syncMcpSchemas(cwd, schemaSources, outputDir = path4.join(cwd, ".bunli", "mcp")) {
3649
- const groups = await loadMcpToolGroups(cwd, schemaSources);
3650
- const result = await generateMCPTypes({
3651
- outputDir,
3652
- tools: groups
3653
- });
3654
- if (Result.isError(result)) {
3655
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, getErrorMessage(result.error), getErrorCauseOptions(result.error));
3656
- }
3657
- const registry = groups.map((group) => ({
3658
- namespace: group.namespace,
3659
- tools: group.tools.map((tool) => extractCommandMetadata(tool, group.namespace))
3660
- }));
3661
- for (const group of groups) {
3662
- const convert = createCommandsFromMCPTools(group.tools, {
3663
- createHandler: () => async () => {},
3664
- namespace: group.namespace
3665
- });
3666
- if (Result.isError(convert)) {
3667
- throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, getErrorMessage(convert.error), getErrorCauseOptions(convert.error));
3668
- }
3669
- }
3670
- await fs4.mkdir(outputDir, { recursive: true });
3671
- await fs4.writeFile(path4.join(outputDir, "registry.json"), `${JSON.stringify(registry, null, 2)}
3672
- `, "utf8");
3673
- return {
3674
- commandCount: registry.reduce((count, group) => count + group.tools.length, 0),
3675
- groups,
3676
- outputDir
3677
- };
3678
- }
3679
-
3680
- // src/commands/mcp.ts
3681
- function printMcpToolGroupSummary(summary, printLine) {
3682
- for (const group of summary) {
3683
- printLine(`${group.namespace} (${group.toolCount})`);
3684
- for (const tool of group.tools) {
3685
- printLine(` - ${tool}`);
3686
- }
3687
- }
3688
- }
3689
- function printMcpSyncSummary(result, printLine) {
3690
- printLine(`Synced ${result.commandCount} MCP tools across ${result.groups.length} namespaces into ${result.outputDir}.`);
3691
- }
3692
- var mcpCommand = defineCommand({
3693
- defaultFormat: "json",
3694
- description: "Inspect or sync schema-driven MCP metadata for wp-typia.",
3695
- handler: async (args) => {
3696
- const subcommand = args.positional[0] ?? "list";
3697
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
3698
- const printLine = resolveCommandPrintLine(args);
3699
- const userConfig = args.context?.store?.wpTypiaUserConfig && typeof args.context.store.wpTypiaUserConfig === "object" ? args.context.store.wpTypiaUserConfig : {};
3700
- const schemaSources = getMcpSchemaSources(userConfig);
3701
- if (schemaSources.length === 0) {
3702
- emitCliDiagnosticFailure(args, {
3703
- code: CLI_DIAGNOSTIC_CODES.CONFIGURATION_MISSING,
3704
- command: "mcp",
3705
- detailLines: [
3706
- "No MCP schema sources are configured. Add `mcp.schemaSources` in ~/.config/wp-typia/config.json, .wp-typiarc(.json), or package.json#wp-typia."
3707
- ]
3708
- });
3709
- return;
3710
- }
3711
- try {
3712
- if (subcommand === "list") {
3713
- const groups = await loadMcpToolGroups(args.cwd, schemaSources);
3714
- const summary = groups.map((group) => ({
3715
- namespace: group.namespace,
3716
- toolCount: group.tools.length,
3717
- tools: group.tools.map((tool) => tool.name)
3718
- }));
3719
- if (prefersStructuredOutput) {
3720
- args.output({ groups: summary });
3721
- return;
3722
- }
3723
- printMcpToolGroupSummary(summary, printLine);
3724
- return;
3725
- }
3726
- if (subcommand === "sync") {
3727
- const outputDir = args.flags["output-dir"] ?? `${args.cwd}/.bunli/mcp`;
3728
- const result = await syncMcpSchemas(args.cwd, schemaSources, outputDir);
3729
- if (prefersStructuredOutput) {
3730
- args.output({ sync: result });
3731
- return;
3732
- }
3733
- printMcpSyncSummary(result, printLine);
3734
- return;
3735
- }
3736
- emitCliDiagnosticFailure(args, {
3737
- code: CLI_DIAGNOSTIC_CODES.INVALID_COMMAND,
3738
- command: "mcp",
3739
- detailLines: [
3740
- `Unknown mcp subcommand "${subcommand}". Expected list or sync.`
3741
- ]
3742
- });
3743
- } catch (error) {
3744
- emitCliDiagnosticFailure(args, {
3745
- command: "mcp",
3746
- error
3747
- });
3748
- }
3749
- },
3750
- name: "mcp",
3751
- options: buildCommandOptions(MCP_OPTION_METADATA)
3752
- });
3753
-
3754
- // src/commands/migrate.ts
3755
- var import_react36 = __toESM(require_react(), 1);
3756
- function loadMigrateFlow() {
3757
- return import(resolveBundledModuleHref(import.meta.url, [
3758
- "./ui/migrate-flow.js",
3759
- "../ui/migrate-flow.js",
3760
- "../ui/migrate-flow.tsx"
3761
- ], {
3762
- moduleLabel: "the migrate-flow UI"
3763
- })).then((module) => ({ default: module.MigrateFlow }));
3764
- }
3765
- var migrateOptions = buildCommandOptions(MIGRATE_OPTION_METADATA);
3766
- var migrateCommand = defineCommand({
3767
- defaultFormat: "toon",
3768
- description: "Run migration workflows for migration-capable wp-typia projects.",
3769
- handler: async (args) => {
3770
- const printLine = resolveCommandPrintLine(args);
3771
- try {
3772
- await executeMigrateCommand({
3773
- command: args.positional[0],
3774
- cwd: args.cwd,
3775
- flags: args.flags,
3776
- printLine
3777
- });
3778
- } catch (error) {
3779
- emitCliDiagnosticFailure(args, {
3780
- command: "migrate",
3781
- error
3782
- });
3783
- }
3784
- },
3785
- name: "migrate",
3786
- options: migrateOptions,
3787
- ...supportsInteractiveTui() ? {
3788
- render: (args) => {
3789
- const initialValues = resolveCommandOptionValues(MIGRATE_OPTION_METADATA, {
3790
- flags: args.flags
3791
- });
3792
- return import_react36.createElement(LazyFlow, {
3793
- loader: loadMigrateFlow,
3794
- props: {
3795
- cwd: args.cwd,
3796
- initialValues: {
3797
- ...initialValues,
3798
- command: args.positional[0] ?? "plan",
3799
- "to-migration-version": initialValues["to-migration-version"] ?? "current"
3800
- }
3801
- }
3802
- });
3803
- },
3804
- tui: {
3805
- renderer: {
3806
- bufferMode: "alternate"
3807
- }
3808
- }
3809
- } : {}
3810
- });
3811
-
3812
- // src/commands/sync.ts
3813
- var syncCommand = defineCommand({
3814
- description: "Run the generated-project sync workflow from a scaffolded project or official workspace root.",
3815
- handler: async (args) => {
3816
- const check = Boolean(args.flags.check);
3817
- const dryRun = Boolean(args.flags["dry-run"]);
3818
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
3819
- try {
3820
- const target = resolveSyncExecutionTarget(args.positional[0]);
3821
- const sync = await executeSyncCommand({
3822
- captureOutput: prefersStructuredOutput && !dryRun,
3823
- check,
3824
- cwd: args.cwd,
3825
- dryRun,
3826
- target
3827
- });
3828
- if (prefersStructuredOutput) {
3829
- args.output({ sync });
3830
- return;
3831
- }
3832
- if (dryRun) {
3833
- printCompletionPayload(buildSyncDryRunPayload({
3834
- check: sync.check,
3835
- packageManager: sync.packageManager,
3836
- plannedCommands: sync.plannedCommands,
3837
- projectDir: sync.projectDir,
3838
- target: sync.target
3839
- }));
3840
- }
3841
- } catch (error) {
3842
- emitCliDiagnosticFailure(args, {
3843
- command: "sync",
3844
- error
3845
- });
3846
- }
3847
- },
3848
- name: "sync",
3849
- options: buildCommandOptions(SYNC_OPTION_METADATA)
3850
- });
3851
-
3852
- // src/commands/templates.ts
3853
- var templatesCommand = defineCommand({
3854
- defaultFormat: "json",
3855
- description: "Inspect built-in and external scaffold templates.",
3856
- handler: async (args) => {
3857
- const subcommand = args.positional[0] ?? "list";
3858
- const id = args.positional[1] ?? args.flags.id;
3859
- const effectiveSubcommand = subcommand === "list" && typeof id === "string" && id.length > 0 ? "inspect" : subcommand;
3860
- const prefersStructuredOutput = prefersStructuredCliOutput(args);
3861
- const printLine = resolveCommandPrintLine(args);
3862
- try {
3863
- if (prefersStructuredOutput) {
3864
- const templates = await listTemplatesForRuntime();
3865
- if (effectiveSubcommand === "list") {
3866
- args.output({ templates });
3867
- return;
3868
- }
3869
- if (effectiveSubcommand === "inspect" && id) {
3870
- const { getTemplateById } = await import("./cli-templates-g8t4fm11.js");
3871
- let template;
3872
- try {
3873
- template = getTemplateById(id);
3874
- } catch (lookupError) {
3875
- const message = lookupError instanceof Error ? lookupError.message : String(lookupError);
3876
- if (!message.startsWith("Unknown template")) {
3877
- throw lookupError;
3878
- }
3879
- emitCliDiagnosticFailure(args, {
3880
- code: CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT,
3881
- command: "templates",
3882
- detailLines: [`Unknown template "${id}".`]
3883
- });
3884
- return;
3885
- }
3886
- args.output({ template });
3887
- return;
3888
- }
3889
- }
3890
- await executeTemplatesCommand({
3891
- flags: { id, subcommand: effectiveSubcommand }
3892
- }, printLine);
3893
- } catch (error) {
3894
- emitCliDiagnosticFailure(args, {
3895
- command: "templates",
3896
- error
3897
- });
3898
- }
3899
- },
3900
- name: "templates",
3901
- options: buildCommandOptions(TEMPLATES_OPTION_METADATA)
3902
- });
3903
-
3904
- // src/command-list.ts
3905
- var WP_TYPIA_COMMANDS_BY_NAME = {
3906
- add: addCommand,
3907
- create: createCommand,
3908
- doctor: doctorCommand,
3909
- init: initCommand,
3910
- mcp: mcpCommand,
3911
- migrate: migrateCommand,
3912
- sync: syncCommand,
3913
- templates: templatesCommand
3914
- };
3915
- var wpTypiaCommands = WP_TYPIA_TOP_LEVEL_COMMAND_NAMES.map((commandName) => WP_TYPIA_COMMANDS_BY_NAME[commandName]);
3916
- export {
3917
- wpTypiaCommands
3918
- };
3919
-
3920
- //# debugId=F41601669F8057C564756E2164756E21