@wp-typia/project-tools 0.22.2 → 0.22.4

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 (62) hide show
  1. package/dist/runtime/built-in-block-code-templates/interactivity.d.ts +1 -1
  2. package/dist/runtime/built-in-block-code-templates/interactivity.js +4 -2
  3. package/dist/runtime/cli-add-block-json.d.ts +31 -0
  4. package/dist/runtime/cli-add-block-json.js +65 -0
  5. package/dist/runtime/cli-add-collision.d.ts +129 -0
  6. package/dist/runtime/cli-add-collision.js +293 -0
  7. package/dist/runtime/cli-add-filesystem.d.ts +29 -0
  8. package/dist/runtime/cli-add-filesystem.js +77 -0
  9. package/dist/runtime/cli-add-help.d.ts +4 -0
  10. package/dist/runtime/cli-add-help.js +41 -0
  11. package/dist/runtime/cli-add-shared.d.ts +6 -255
  12. package/dist/runtime/cli-add-shared.js +6 -391
  13. package/dist/runtime/cli-add-types.d.ts +247 -0
  14. package/dist/runtime/cli-add-types.js +64 -0
  15. package/dist/runtime/cli-add-validation.d.ts +87 -0
  16. package/dist/runtime/cli-add-validation.js +147 -0
  17. package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +5 -0
  18. package/dist/runtime/cli-add-workspace-ability-scaffold.js +366 -0
  19. package/dist/runtime/cli-add-workspace-ability-templates.d.ts +34 -0
  20. package/dist/runtime/cli-add-workspace-ability-templates.js +500 -0
  21. package/dist/runtime/cli-add-workspace-ability-types.d.ts +27 -0
  22. package/dist/runtime/cli-add-workspace-ability-types.js +14 -0
  23. package/dist/runtime/cli-add-workspace-ability.js +12 -852
  24. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +35 -61
  25. package/dist/runtime/cli-add-workspace-ai-scaffold.d.ts +21 -0
  26. package/dist/runtime/cli-add-workspace-ai-scaffold.js +87 -0
  27. package/dist/runtime/cli-add-workspace-ai-templates.d.ts +4 -0
  28. package/dist/runtime/cli-add-workspace-ai-templates.js +607 -0
  29. package/dist/runtime/cli-add-workspace-ai.js +15 -688
  30. package/dist/runtime/cli-add-workspace-assets.js +7 -4
  31. package/dist/runtime/cli-add-workspace-mutation.d.ts +30 -0
  32. package/dist/runtime/cli-add-workspace-mutation.js +60 -0
  33. package/dist/runtime/cli-add-workspace.js +2 -98
  34. package/dist/runtime/cli-add.d.ts +2 -2
  35. package/dist/runtime/cli-add.js +2 -2
  36. package/dist/runtime/cli-doctor-workspace-bindings.d.ts +11 -0
  37. package/dist/runtime/cli-doctor-workspace-bindings.js +134 -0
  38. package/dist/runtime/cli-doctor-workspace-blocks.d.ts +11 -0
  39. package/dist/runtime/cli-doctor-workspace-blocks.js +439 -0
  40. package/dist/runtime/cli-doctor-workspace-features.d.ts +11 -0
  41. package/dist/runtime/cli-doctor-workspace-features.js +383 -0
  42. package/dist/runtime/cli-doctor-workspace-package.d.ts +18 -0
  43. package/dist/runtime/cli-doctor-workspace-package.js +59 -0
  44. package/dist/runtime/cli-doctor-workspace-shared.d.ts +69 -0
  45. package/dist/runtime/cli-doctor-workspace-shared.js +87 -0
  46. package/dist/runtime/cli-doctor-workspace.js +25 -1062
  47. package/dist/runtime/index.d.ts +2 -0
  48. package/dist/runtime/index.js +1 -0
  49. package/dist/runtime/migration-utils.d.ts +2 -1
  50. package/dist/runtime/migration-utils.js +3 -11
  51. package/dist/runtime/package-managers.d.ts +19 -0
  52. package/dist/runtime/package-managers.js +62 -0
  53. package/dist/runtime/template-source-cache.d.ts +59 -0
  54. package/dist/runtime/template-source-cache.js +160 -0
  55. package/dist/runtime/ts-source-masking.d.ts +28 -0
  56. package/dist/runtime/ts-source-masking.js +104 -0
  57. package/dist/runtime/typia-llm.d.ts +9 -1
  58. package/dist/runtime/typia-llm.js +20 -5
  59. package/dist/runtime/workspace-inventory.js +116 -59
  60. package/dist/runtime/workspace-project.d.ts +1 -1
  61. package/dist/runtime/workspace-project.js +2 -10
  62. package/package.json +4 -4
@@ -1,392 +1,7 @@
1
- import fs from "node:fs";
2
- import { promises as fsp } from "node:fs";
3
- import path from "node:path";
4
- import { parseScaffoldBlockMetadata } from "@wp-typia/block-runtime/blocks";
5
- import { HOOKED_BLOCK_ANCHOR_PATTERN, HOOKED_BLOCK_POSITION_IDS, } from "./hooked-blocks.js";
6
- import { toSnakeCase, } from "./string-case.js";
7
- import { WORKSPACE_TEMPLATE_PACKAGE, } from "./workspace-project.js";
8
1
  export { normalizeBlockSlug, } from "./scaffold-identifiers.js";
9
- /**
10
- * Supported top-level `wp-typia add` kinds exposed by the canonical CLI.
11
- */
12
- export const ADD_KIND_IDS = [
13
- "admin-view",
14
- "block",
15
- "variation",
16
- "style",
17
- "transform",
18
- "pattern",
19
- "binding-source",
20
- "rest-resource",
21
- "ability",
22
- "ai-feature",
23
- "hooked-block",
24
- "editor-plugin",
25
- ];
26
- /**
27
- * Supported plugin-level REST resource methods accepted by
28
- * `wp-typia add rest-resource --methods`.
29
- */
30
- export const REST_RESOURCE_METHOD_IDS = [
31
- "list",
32
- "read",
33
- "create",
34
- "update",
35
- "delete",
36
- ];
37
- /**
38
- * Supported editor-plugin shell surfaces accepted by
39
- * `wp-typia add editor-plugin --slot`.
40
- */
41
- export const EDITOR_PLUGIN_SLOT_IDS = ["sidebar", "document-setting-panel"];
42
- export const EDITOR_PLUGIN_SLOT_ALIASES = {
43
- PluginDocumentSettingPanel: "document-setting-panel",
44
- PluginSidebar: "sidebar",
45
- "document-setting-panel": "document-setting-panel",
46
- sidebar: "sidebar",
47
- };
48
- export function resolveEditorPluginSlotAlias(slot) {
49
- const trimmed = slot.trim();
50
- if (!Object.prototype.hasOwnProperty.call(EDITOR_PLUGIN_SLOT_ALIASES, trimmed)) {
51
- return undefined;
52
- }
53
- return EDITOR_PLUGIN_SLOT_ALIASES[trimmed];
54
- }
55
- /**
56
- * Supported built-in block families accepted by `wp-typia add block --template`.
57
- */
58
- export const ADD_BLOCK_TEMPLATE_IDS = [
59
- "basic",
60
- "interactivity",
61
- "persistence",
62
- "compound",
63
- ];
64
- const WORKSPACE_GENERATED_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
65
- export const REST_RESOURCE_NAMESPACE_PATTERN = /^[a-z][a-z0-9-]*(?:\/[a-z0-9-]+)+$/u;
66
- export function assertValidGeneratedSlug(label, slug, usage) {
67
- if (!slug) {
68
- throw new Error(`${label} is required. Use \`${usage}\`.`);
69
- }
70
- if (!WORKSPACE_GENERATED_SLUG_PATTERN.test(slug)) {
71
- throw new Error(`${label} must start with a letter and contain only lowercase letters, numbers, and hyphens.`);
72
- }
73
- return slug;
74
- }
75
- export function assertValidRestResourceNamespace(namespace) {
76
- const trimmed = namespace.trim();
77
- if (!trimmed) {
78
- throw new Error("REST resource namespace is required. Use `--namespace <vendor/v1>` or let the workspace default apply.");
79
- }
80
- if (!REST_RESOURCE_NAMESPACE_PATTERN.test(trimmed)) {
81
- throw new Error("REST resource namespace must use lowercase slash-separated segments like `demo-space/v1`.");
82
- }
83
- return trimmed;
84
- }
85
- export function resolveRestResourceNamespace(workspaceNamespace, namespace) {
86
- return assertValidRestResourceNamespace(namespace ?? `${workspaceNamespace}/v1`);
87
- }
88
- export function assertValidRestResourceMethods(methods) {
89
- const rawMethods = typeof methods === "string" && methods.trim().length > 0
90
- ? methods.split(",").map((value) => value.trim()).filter(Boolean)
91
- : ["list", "read", "create"];
92
- const normalizedMethods = Array.from(new Set(rawMethods));
93
- const invalidMethods = normalizedMethods.filter((method) => !REST_RESOURCE_METHOD_IDS.includes(method));
94
- if (invalidMethods.length > 0) {
95
- throw new Error(`REST resource methods must be a comma-separated list of: ${REST_RESOURCE_METHOD_IDS.join(", ")}.`);
96
- }
97
- if (normalizedMethods.length === 0) {
98
- throw new Error("REST resource methods must include at least one of: list, read, create, update, delete.");
99
- }
100
- return normalizedMethods;
101
- }
102
- export function assertValidHookedBlockPosition(position) {
103
- if (HOOKED_BLOCK_POSITION_IDS.includes(position)) {
104
- return position;
105
- }
106
- throw new Error(`Hook position must be one of: ${HOOKED_BLOCK_POSITION_IDS.join(", ")}.`);
107
- }
108
- export function getWorkspaceBootstrapPath(workspace) {
109
- const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
110
- return path.join(workspace.projectDir, `${workspaceBaseName}.php`);
111
- }
112
- export function buildWorkspacePhpPrefix(workspacePhpPrefix, slug) {
113
- return toSnakeCase(`${workspacePhpPrefix}_${slug}`);
114
- }
115
- export function isAddBlockTemplateId(value) {
116
- return ADD_BLOCK_TEMPLATE_IDS.includes(value);
117
- }
118
- export function quoteTsString(value) {
119
- return JSON.stringify(value);
120
- }
121
- /**
122
- * Apply a text transform to an existing file only when the contents change.
123
- */
124
- export async function patchFile(filePath, transform) {
125
- const currentSource = await fsp.readFile(filePath, "utf8");
126
- const nextSource = transform(currentSource);
127
- if (nextSource !== currentSource) {
128
- await fsp.writeFile(filePath, nextSource, "utf8");
129
- }
130
- }
131
- /**
132
- * Read a file when it exists and otherwise return `null`.
133
- */
134
- export async function readOptionalFile(filePath) {
135
- if (!fs.existsSync(filePath)) {
136
- return null;
137
- }
138
- return fsp.readFile(filePath, "utf8");
139
- }
140
- /**
141
- * Restore a file to its captured source, deleting it when the snapshot was `null`.
142
- */
143
- export async function restoreOptionalFile(filePath, source) {
144
- if (source === null) {
145
- await fsp.rm(filePath, { force: true });
146
- return;
147
- }
148
- await fsp.mkdir(path.dirname(filePath), { recursive: true });
149
- await fsp.writeFile(filePath, source, "utf8");
150
- }
151
- /**
152
- * Capture the current contents of a set of workspace files for rollback.
153
- */
154
- export async function snapshotWorkspaceFiles(filePaths) {
155
- const uniquePaths = Array.from(new Set(filePaths));
156
- return Promise.all(uniquePaths.map(async (filePath) => ({
157
- filePath,
158
- source: await readOptionalFile(filePath),
159
- })));
160
- }
161
- /**
162
- * Undo a partially applied workspace mutation from a captured snapshot.
163
- */
164
- export async function rollbackWorkspaceMutation(snapshot) {
165
- for (const targetPath of snapshot.targetPaths) {
166
- await fsp.rm(targetPath, { force: true, recursive: true });
167
- }
168
- for (const snapshotDir of snapshot.snapshotDirs) {
169
- await fsp.rm(snapshotDir, { force: true, recursive: true });
170
- }
171
- for (const { filePath, source } of snapshot.fileSources) {
172
- await restoreOptionalFile(filePath, source);
173
- }
174
- }
175
- export function resolveWorkspaceBlock(inventory, blockSlug) {
176
- const block = inventory.blocks.find((entry) => entry.slug === blockSlug);
177
- if (!block) {
178
- throw new Error(`Unknown workspace block "${blockSlug}". Choose one of: ${inventory.blocks.map((entry) => entry.slug).join(", ")}`);
179
- }
180
- return block;
181
- }
182
- export function assertValidHookAnchor(anchorBlockName) {
183
- const trimmed = anchorBlockName.trim();
184
- if (!trimmed) {
185
- throw new Error("`wp-typia add hooked-block` requires --anchor <anchor-block-name>.");
186
- }
187
- if (!HOOKED_BLOCK_ANCHOR_PATTERN.test(trimmed)) {
188
- throw new Error("`wp-typia add hooked-block` requires --anchor <anchor-block-name> to use the full `namespace/slug` block name format.");
189
- }
190
- return trimmed;
191
- }
192
- /**
193
- * Validate and normalize the editor plugin shell slot.
194
- *
195
- * @param slot Optional shell slot. Defaults to `sidebar`.
196
- * @returns The canonical editor plugin slot id.
197
- * @throws {Error} When the slot is not supported by the workspace scaffold.
198
- */
199
- export function assertValidEditorPluginSlot(slot = "sidebar") {
200
- const alias = resolveEditorPluginSlotAlias(slot);
201
- if (alias) {
202
- return alias;
203
- }
204
- throw new Error(`Editor plugin slot must be one of: ${EDITOR_PLUGIN_SLOT_IDS.join(", ")}. Legacy aliases: PluginSidebar, PluginDocumentSettingPanel.`);
205
- }
206
- export function readWorkspaceBlockJson(projectDir, blockSlug) {
207
- const blockJsonPath = path.join(projectDir, "src", "blocks", blockSlug, "block.json");
208
- if (!fs.existsSync(blockJsonPath)) {
209
- throw new Error(`Missing ${path.relative(projectDir, blockJsonPath)} for workspace block "${blockSlug}".`);
210
- }
211
- let blockJson;
212
- try {
213
- blockJson = parseScaffoldBlockMetadata(JSON.parse(fs.readFileSync(blockJsonPath, "utf8")));
214
- }
215
- catch (error) {
216
- throw new Error(error instanceof Error
217
- ? `Failed to parse ${path.relative(projectDir, blockJsonPath)}: ${error.message}`
218
- : `Failed to parse ${path.relative(projectDir, blockJsonPath)}.`);
219
- }
220
- return {
221
- blockJson,
222
- blockJsonPath,
223
- };
224
- }
225
- export function getMutableBlockHooks(blockJson, blockJsonRelativePath) {
226
- const blockHooks = blockJson.blockHooks;
227
- if (blockHooks === undefined) {
228
- const nextHooks = {};
229
- blockJson.blockHooks = nextHooks;
230
- return nextHooks;
231
- }
232
- if (!blockHooks || typeof blockHooks !== "object" || Array.isArray(blockHooks)) {
233
- throw new Error(`${blockJsonRelativePath} must define blockHooks as an object when present.`);
234
- }
235
- return blockHooks;
236
- }
237
- export function assertVariationDoesNotExist(projectDir, blockSlug, variationSlug, inventory) {
238
- const variationPath = path.join(projectDir, "src", "blocks", blockSlug, "variations", `${variationSlug}.ts`);
239
- if (fs.existsSync(variationPath)) {
240
- throw new Error(`A variation already exists at ${path.relative(projectDir, variationPath)}. Choose a different name.`);
241
- }
242
- if (inventory.variations.some((entry) => entry.block === blockSlug && entry.slug === variationSlug)) {
243
- throw new Error(`A variation inventory entry already exists for ${blockSlug}/${variationSlug}. Choose a different name.`);
244
- }
245
- }
246
- export function assertPatternDoesNotExist(projectDir, patternSlug, inventory) {
247
- const patternPath = path.join(projectDir, "src", "patterns", `${patternSlug}.php`);
248
- if (fs.existsSync(patternPath)) {
249
- throw new Error(`A pattern already exists at ${path.relative(projectDir, patternPath)}. Choose a different name.`);
250
- }
251
- if (inventory.patterns.some((entry) => entry.slug === patternSlug)) {
252
- throw new Error(`A pattern inventory entry already exists for ${patternSlug}. Choose a different name.`);
253
- }
254
- }
255
- export function assertBindingSourceDoesNotExist(projectDir, bindingSourceSlug, inventory) {
256
- const bindingSourceDir = path.join(projectDir, "src", "bindings", bindingSourceSlug);
257
- if (fs.existsSync(bindingSourceDir)) {
258
- throw new Error(`A binding source already exists at ${path.relative(projectDir, bindingSourceDir)}. Choose a different name.`);
259
- }
260
- if (inventory.bindingSources.some((entry) => entry.slug === bindingSourceSlug)) {
261
- throw new Error(`A binding source inventory entry already exists for ${bindingSourceSlug}. Choose a different name.`);
262
- }
263
- }
264
- export function assertRestResourceDoesNotExist(projectDir, restResourceSlug, inventory) {
265
- const restResourceDir = path.join(projectDir, "src", "rest", restResourceSlug);
266
- const restResourcePhpPath = path.join(projectDir, "inc", "rest", `${restResourceSlug}.php`);
267
- if (fs.existsSync(restResourceDir)) {
268
- throw new Error(`A REST resource already exists at ${path.relative(projectDir, restResourceDir)}. Choose a different name.`);
269
- }
270
- if (fs.existsSync(restResourcePhpPath)) {
271
- throw new Error(`A REST resource bootstrap already exists at ${path.relative(projectDir, restResourcePhpPath)}. Choose a different name.`);
272
- }
273
- if (inventory.restResources.some((entry) => entry.slug === restResourceSlug)) {
274
- throw new Error(`A REST resource inventory entry already exists for ${restResourceSlug}. Choose a different name.`);
275
- }
276
- }
277
- /**
278
- * Ensure a DataViews admin screen scaffold does not already exist on disk or in
279
- * the workspace inventory.
280
- *
281
- * @param projectDir Workspace root directory.
282
- * @param adminViewSlug Normalized admin screen slug.
283
- * @param inventory Parsed workspace inventory.
284
- * @throws {Error} When the directory, PHP bootstrap, or inventory entry already exists.
285
- */
286
- export function assertAdminViewDoesNotExist(projectDir, adminViewSlug, inventory) {
287
- const adminViewDir = path.join(projectDir, "src", "admin-views", adminViewSlug);
288
- const adminViewPhpPath = path.join(projectDir, "inc", "admin-views", `${adminViewSlug}.php`);
289
- if (fs.existsSync(adminViewDir)) {
290
- throw new Error(`An admin view already exists at ${path.relative(projectDir, adminViewDir)}. Choose a different name.`);
291
- }
292
- if (fs.existsSync(adminViewPhpPath)) {
293
- throw new Error(`An admin view bootstrap already exists at ${path.relative(projectDir, adminViewPhpPath)}. Choose a different name.`);
294
- }
295
- if (inventory.adminViews.some((entry) => entry.slug === adminViewSlug)) {
296
- throw new Error(`An admin view inventory entry already exists for ${adminViewSlug}. Choose a different name.`);
297
- }
298
- }
299
- /**
300
- * Ensure a workflow ability scaffold does not already exist on disk or in the
301
- * workspace inventory.
302
- *
303
- * The check covers the generated `src/abilities/<slug>` directory,
304
- * `inc/abilities/<slug>.php`, and any matching `inventory.abilities` entry.
305
- *
306
- * @param projectDir Workspace root directory.
307
- * @param abilitySlug Normalized workflow ability slug.
308
- * @param inventory Parsed workspace inventory.
309
- * @throws {Error} When the ability directory, PHP bootstrap, or inventory entry already exists.
310
- */
311
- export function assertAbilityDoesNotExist(projectDir, abilitySlug, inventory) {
312
- const abilityDir = path.join(projectDir, "src", "abilities", abilitySlug);
313
- const abilityPhpPath = path.join(projectDir, "inc", "abilities", `${abilitySlug}.php`);
314
- if (fs.existsSync(abilityDir)) {
315
- throw new Error(`An ability scaffold already exists at ${path.relative(projectDir, abilityDir)}. Choose a different name.`);
316
- }
317
- if (fs.existsSync(abilityPhpPath)) {
318
- throw new Error(`An ability bootstrap already exists at ${path.relative(projectDir, abilityPhpPath)}. Choose a different name.`);
319
- }
320
- if (inventory.abilities.some((entry) => entry.slug === abilitySlug)) {
321
- throw new Error(`An ability inventory entry already exists for ${abilitySlug}. Choose a different name.`);
322
- }
323
- }
324
- export function assertAiFeatureDoesNotExist(projectDir, aiFeatureSlug, inventory) {
325
- const aiFeatureDir = path.join(projectDir, "src", "ai-features", aiFeatureSlug);
326
- const aiFeaturePhpPath = path.join(projectDir, "inc", "ai-features", `${aiFeatureSlug}.php`);
327
- if (fs.existsSync(aiFeatureDir)) {
328
- throw new Error(`An AI feature already exists at ${path.relative(projectDir, aiFeatureDir)}. Choose a different name.`);
329
- }
330
- if (fs.existsSync(aiFeaturePhpPath)) {
331
- throw new Error(`An AI feature bootstrap already exists at ${path.relative(projectDir, aiFeaturePhpPath)}. Choose a different name.`);
332
- }
333
- if (inventory.aiFeatures.some((entry) => entry.slug === aiFeatureSlug)) {
334
- throw new Error(`An AI feature inventory entry already exists for ${aiFeatureSlug}. Choose a different name.`);
335
- }
336
- }
337
- /**
338
- * Ensure an editor plugin scaffold does not already exist on disk or in the
339
- * workspace inventory.
340
- *
341
- * @param projectDir Workspace root directory.
342
- * @param editorPluginSlug Normalized editor plugin slug.
343
- * @param inventory Parsed workspace inventory.
344
- * @throws {Error} When the directory or inventory entry already exists.
345
- */
346
- export function assertEditorPluginDoesNotExist(projectDir, editorPluginSlug, inventory) {
347
- const editorPluginDir = path.join(projectDir, "src", "editor-plugins", editorPluginSlug);
348
- if (fs.existsSync(editorPluginDir)) {
349
- throw new Error(`An editor plugin already exists at ${path.relative(projectDir, editorPluginDir)}. Choose a different name.`);
350
- }
351
- if (inventory.editorPlugins.some((entry) => entry.slug === editorPluginSlug)) {
352
- throw new Error(`An editor plugin inventory entry already exists for ${editorPluginSlug}. Choose a different name.`);
353
- }
354
- }
355
- /**
356
- * Returns help text for the canonical `wp-typia add` subcommands.
357
- */
358
- export function formatAddHelpText() {
359
- return `Usage:
360
- wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]
361
- wp-typia add block <name> [--template <${ADD_BLOCK_TEMPLATE_IDS.join("|")}>] [--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]
362
- wp-typia add variation <name> --block <block-slug> [--dry-run]
363
- wp-typia add style <name> --block <block-slug> [--dry-run]
364
- wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]
365
- wp-typia add pattern <name> [--dry-run]
366
- wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--dry-run]
367
- wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create,update,delete>] [--dry-run]
368
- wp-typia add ability <name> [--dry-run]
369
- wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]
370
- wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <${HOOKED_BLOCK_POSITION_IDS.join("|")}> [--dry-run]
371
- wp-typia add editor-plugin <name> [--slot <${EDITOR_PLUGIN_SLOT_IDS.join("|")}>] [--dry-run]
372
-
373
- Notes:
374
- \`wp-typia add\` runs only inside official ${WORKSPACE_TEMPLATE_PACKAGE} workspaces scaffolded via \`wp-typia create <project-dir> --template workspace\`.
375
- Pass \`--dry-run\` to preview the workspace files that would change without writing them.
376
- Interactive add flows let you choose a template when \`--template\` is omitted; non-interactive runs default to \`basic\`.
377
- \`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views/\`.
378
- Pass \`--source rest-resource:<slug>\` to reuse a list-capable REST resource.
379
- Pass \`--source core-data:postType/post\` or \`--source core-data:taxonomy/category\` to bind a WordPress-owned entity collection.
380
- Public installs currently gate this workflow until \`@wp-typia/dataviews\` is published to npm.
381
- \`query-loop\` is a create-time scaffold family. Use \`wp-typia create <project-dir> --template query-loop\` instead of \`wp-typia add block\`.
382
- \`add variation\` targets an existing block slug from \`scripts/block-config.ts\`.
383
- \`add style\` registers a Block Styles option for an existing generated block.
384
- \`add transform\` adds a block-to-block transform into an existing generated block.
385
- \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/\`.
386
- \`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`; pass \`--block\` and \`--attribute\` together to declare an end-to-end bindable attribute on an existing generated block.
387
- \`add rest-resource\` scaffolds plugin-level TypeScript REST contracts under \`src/rest/\` and PHP route glue under \`inc/rest/\`.
388
- \`add ability\` scaffolds typed workflow abilities under \`src/abilities/\` and server registration under \`inc/abilities/\`.
389
- \`add ai-feature\` scaffolds server-owned AI feature endpoints under \`src/ai-features/\` and PHP route glue under \`inc/ai-features/\`.
390
- \`add hooked-block\` patches an existing workspace block's \`block.json\` \`blockHooks\` metadata.
391
- \`add editor-plugin\` scaffolds a document-level editor extension under \`src/editor-plugins/\`; legacy aliases \`PluginSidebar\` and \`PluginDocumentSettingPanel\` resolve to \`sidebar\` and \`document-setting-panel\`.`;
392
- }
2
+ export * from "./cli-add-types.js";
3
+ export * from "./cli-add-validation.js";
4
+ export * from "./cli-add-filesystem.js";
5
+ export * from "./cli-add-block-json.js";
6
+ export * from "./cli-add-collision.js";
7
+ export * from "./cli-add-help.js";
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Supported top-level `wp-typia add` kinds exposed by the canonical CLI.
3
+ */
4
+ export declare const ADD_KIND_IDS: readonly ["admin-view", "block", "variation", "style", "transform", "pattern", "binding-source", "rest-resource", "ability", "ai-feature", "hooked-block", "editor-plugin"];
5
+ /**
6
+ * Union of supported top-level `wp-typia add` kind ids.
7
+ */
8
+ export type AddKindId = (typeof ADD_KIND_IDS)[number];
9
+ /**
10
+ * Supported plugin-level REST resource methods accepted by
11
+ * `wp-typia add rest-resource --methods`.
12
+ */
13
+ export declare const REST_RESOURCE_METHOD_IDS: readonly ["list", "read", "create", "update", "delete"];
14
+ /**
15
+ * Union of supported plugin-level REST resource method ids.
16
+ */
17
+ export type RestResourceMethodId = (typeof REST_RESOURCE_METHOD_IDS)[number];
18
+ /**
19
+ * Canonical editor-plugin shell surface ids accepted by
20
+ * `wp-typia add editor-plugin --slot`.
21
+ */
22
+ export declare const EDITOR_PLUGIN_SLOT_IDS: readonly ["sidebar", "document-setting-panel"];
23
+ /**
24
+ * Union of canonical editor-plugin shell surface ids.
25
+ */
26
+ export type EditorPluginSlotId = (typeof EDITOR_PLUGIN_SLOT_IDS)[number];
27
+ /**
28
+ * Legacy and canonical editor-plugin slot aliases keyed by user-facing input.
29
+ */
30
+ export declare const EDITOR_PLUGIN_SLOT_ALIASES: {
31
+ readonly PluginDocumentSettingPanel: "document-setting-panel";
32
+ readonly PluginSidebar: "sidebar";
33
+ readonly "document-setting-panel": "document-setting-panel";
34
+ readonly sidebar: "sidebar";
35
+ };
36
+ /**
37
+ * Resolve a user-provided editor-plugin slot alias to its canonical id.
38
+ *
39
+ * @param slot Raw slot value from CLI input.
40
+ * @returns The canonical slot id, or `undefined` when unsupported.
41
+ */
42
+ export declare function resolveEditorPluginSlotAlias(slot: string): EditorPluginSlotId | undefined;
43
+ /**
44
+ * Supported built-in block families accepted by `wp-typia add block --template`.
45
+ */
46
+ export declare const ADD_BLOCK_TEMPLATE_IDS: readonly ["basic", "interactivity", "persistence", "compound"];
47
+ /**
48
+ * Union of supported built-in block template ids.
49
+ */
50
+ export type AddBlockTemplateId = (typeof ADD_BLOCK_TEMPLATE_IDS)[number];
51
+ /**
52
+ * Options for `wp-typia add variation`.
53
+ *
54
+ * @property blockName Existing workspace block slug that owns the variation.
55
+ * @property cwd Working directory used to resolve the nearest official workspace.
56
+ * @property variationName Human-entered variation name normalized into a slug.
57
+ */
58
+ export interface RunAddVariationCommandOptions {
59
+ blockName: string;
60
+ cwd?: string;
61
+ variationName: string;
62
+ }
63
+ /**
64
+ * Options for `wp-typia add style`.
65
+ *
66
+ * @property blockName Existing workspace block slug that owns the style.
67
+ * @property cwd Working directory used to resolve the nearest official workspace.
68
+ * Defaults to `process.cwd()`.
69
+ * @property styleName Human-entered style name that will be normalized into the
70
+ * generated style slug.
71
+ */
72
+ export interface RunAddBlockStyleCommandOptions {
73
+ blockName: string;
74
+ cwd?: string;
75
+ styleName: string;
76
+ }
77
+ /**
78
+ * Options for `wp-typia add transform`.
79
+ *
80
+ * @property cwd Working directory used to resolve the nearest official workspace.
81
+ * Defaults to `process.cwd()`.
82
+ * @property fromBlockName Full `namespace/block` source block name accepted by
83
+ * WordPress block transform definitions.
84
+ * @property toBlockName Existing workspace block slug or full block name that
85
+ * owns the generated transform.
86
+ * @property transformName Human-entered transform name that will be normalized
87
+ * into the generated transform slug.
88
+ */
89
+ export interface RunAddBlockTransformCommandOptions {
90
+ cwd?: string;
91
+ fromBlockName: string;
92
+ toBlockName: string;
93
+ transformName: string;
94
+ }
95
+ /**
96
+ * Options for `wp-typia add pattern`.
97
+ *
98
+ * @property cwd Working directory used to resolve the nearest official workspace.
99
+ * @property patternName Human-entered pattern name normalized into a slug.
100
+ */
101
+ export interface RunAddPatternCommandOptions {
102
+ cwd?: string;
103
+ patternName: string;
104
+ }
105
+ /**
106
+ * Options for `wp-typia add binding-source`.
107
+ *
108
+ * @property attributeName Optional block attribute to bind when `blockName` is provided.
109
+ * @property blockName Optional existing workspace block slug or full block name.
110
+ * @property bindingSourceName Human-entered binding source name normalized into a slug.
111
+ * @property cwd Working directory used to resolve the nearest official workspace.
112
+ */
113
+ export interface RunAddBindingSourceCommandOptions {
114
+ attributeName?: string;
115
+ blockName?: string;
116
+ bindingSourceName: string;
117
+ cwd?: string;
118
+ }
119
+ /**
120
+ * Options for `wp-typia add rest-resource`.
121
+ *
122
+ * @property cwd Working directory used to resolve the nearest official workspace.
123
+ * @property methods Optional comma-separated REST method list.
124
+ * @property namespace Optional REST namespace, defaulting to the workspace namespace.
125
+ * @property restResourceName Human-entered resource name normalized into a slug.
126
+ */
127
+ export interface RunAddRestResourceCommandOptions {
128
+ cwd?: string;
129
+ methods?: string;
130
+ namespace?: string;
131
+ restResourceName: string;
132
+ }
133
+ /**
134
+ * Options for `wp-typia add admin-view`.
135
+ *
136
+ * @property adminViewName Human-entered admin screen name that will be
137
+ * normalized into the generated slug.
138
+ * @property cwd Working directory used to resolve the nearest official workspace.
139
+ * Defaults to `process.cwd()`.
140
+ * @property source Optional data source locator. `rest-resource:<slug>` wires
141
+ * the generated screen to an existing list-capable REST resource.
142
+ * `core-data:<kind>/<name>` binds the screen to a supported WordPress-owned
143
+ * entity collection such as `core-data:postType/post`.
144
+ */
145
+ export interface RunAddAdminViewCommandOptions {
146
+ adminViewName: string;
147
+ cwd?: string;
148
+ source?: string;
149
+ }
150
+ /**
151
+ * Options for `wp-typia add ability`.
152
+ *
153
+ * @property cwd Working directory used to resolve the nearest official workspace.
154
+ * Defaults to `process.cwd()`.
155
+ * @property abilityName Human-entered workflow ability name that will be
156
+ * normalized into the generated slug.
157
+ */
158
+ export interface RunAddAbilityCommandOptions {
159
+ abilityName: string;
160
+ cwd?: string;
161
+ }
162
+ /**
163
+ * Options for `wp-typia add ai-feature`.
164
+ *
165
+ * @property aiFeatureName Human-entered AI feature name normalized into a slug.
166
+ * @property cwd Working directory used to resolve the nearest official workspace.
167
+ * @property namespace Optional REST namespace, defaulting to the workspace namespace.
168
+ */
169
+ export interface RunAddAiFeatureCommandOptions {
170
+ aiFeatureName: string;
171
+ cwd?: string;
172
+ namespace?: string;
173
+ }
174
+ /**
175
+ * Options for `wp-typia add hooked-block`.
176
+ *
177
+ * @property anchorBlockName Full `namespace/block` anchor block name.
178
+ * @property blockName Existing workspace block slug that receives metadata.
179
+ * @property cwd Working directory used to resolve the nearest official workspace.
180
+ * @property position Hook position accepted by WordPress block hooks.
181
+ */
182
+ export interface RunAddHookedBlockCommandOptions {
183
+ anchorBlockName: string;
184
+ blockName: string;
185
+ cwd?: string;
186
+ position: string;
187
+ }
188
+ /**
189
+ * Options for `wp-typia add editor-plugin`.
190
+ *
191
+ * @property cwd Working directory used to resolve the nearest official workspace.
192
+ * Defaults to `process.cwd()`.
193
+ * @property editorPluginName Human-entered editor plugin name that will be
194
+ * normalized into the generated slug.
195
+ * @property slot Optional editor shell slot. Defaults to `sidebar`.
196
+ */
197
+ export interface RunAddEditorPluginCommandOptions {
198
+ cwd?: string;
199
+ editorPluginName: string;
200
+ slot?: string;
201
+ }
202
+ /**
203
+ * Options for `wp-typia add block`.
204
+ *
205
+ * @property alternateRenderTargets Optional comma-separated alternate render targets.
206
+ * @property blockName Human-entered block name normalized into a slug.
207
+ * @property cwd Working directory used to resolve the nearest official workspace.
208
+ * @property dataStorageMode Optional persistence storage mode.
209
+ * @property externalLayerId Optional external layer id to apply.
210
+ * @property externalLayerSource Optional local, GitHub, or npm external layer source.
211
+ * @property innerBlocksPreset Optional compound block inner blocks preset.
212
+ * @property persistencePolicy Optional persistence access policy.
213
+ * @property selectExternalLayerId Optional selector for interactive external layer choice.
214
+ * @property templateId Optional built-in block template id.
215
+ */
216
+ export interface RunAddBlockCommandOptions {
217
+ alternateRenderTargets?: string;
218
+ blockName: string;
219
+ cwd?: string;
220
+ dataStorageMode?: string;
221
+ externalLayerId?: string;
222
+ externalLayerSource?: string;
223
+ innerBlocksPreset?: string;
224
+ persistencePolicy?: string;
225
+ selectExternalLayerId?: (options: Array<{
226
+ description?: string;
227
+ extends: string[];
228
+ id: string;
229
+ }>) => Promise<string>;
230
+ templateId?: string;
231
+ }
232
+ /**
233
+ * Captured workspace mutation state used to roll back partial add operations.
234
+ */
235
+ export interface WorkspaceMutationSnapshot {
236
+ /** Snapshots of file contents taken before the mutation starts. */
237
+ fileSources: Array<{
238
+ /** Absolute file path recorded for rollback. */
239
+ filePath: string;
240
+ /** Previous file contents, or `null` when the file did not exist. */
241
+ source: string | null;
242
+ }>;
243
+ /** Snapshot directories created while seeding migration history. */
244
+ snapshotDirs: string[];
245
+ /** Files or directories created by the mutation that should be removed on rollback. */
246
+ targetPaths: string[];
247
+ }