@wp-typia/project-tools 0.23.0 → 0.23.1

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 (109) hide show
  1. package/dist/runtime/ai-feature-artifacts.js +4 -1
  2. package/dist/runtime/block-generator-service-spec.js +2 -1
  3. package/dist/runtime/cli-add-block-json.js +5 -1
  4. package/dist/runtime/cli-add-help.js +4 -3
  5. package/dist/runtime/cli-add-types.d.ts +18 -6
  6. package/dist/runtime/cli-add-validation.d.ts +7 -0
  7. package/dist/runtime/cli-add-validation.js +9 -0
  8. package/dist/runtime/cli-add-workspace-ability-scaffold.js +4 -1
  9. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +5 -1
  10. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.d.ts +34 -0
  11. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.js +483 -0
  12. package/dist/runtime/cli-add-workspace-admin-view-templates-default.d.ts +30 -0
  13. package/dist/runtime/cli-add-workspace-admin-view-templates-default.js +310 -0
  14. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.d.ts +25 -0
  15. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.js +124 -0
  16. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.d.ts +34 -0
  17. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.js +370 -0
  18. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.d.ts +49 -0
  19. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.js +259 -0
  20. package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +18 -27
  21. package/dist/runtime/cli-add-workspace-admin-view-templates.js +30 -1326
  22. package/dist/runtime/cli-add-workspace-ai-anchors.js +4 -1
  23. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +17 -1
  24. package/dist/runtime/cli-add-workspace-integration-env.d.ts +3 -1
  25. package/dist/runtime/cli-add-workspace-integration-env.js +42 -5
  26. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +8 -0
  27. package/dist/runtime/cli-add-workspace-rest-anchors.js +41 -0
  28. package/dist/runtime/cli-add-workspace-rest-generated.d.ts +9 -0
  29. package/dist/runtime/cli-add-workspace-rest-generated.js +158 -0
  30. package/dist/runtime/cli-add-workspace-rest-manual.d.ts +8 -0
  31. package/dist/runtime/cli-add-workspace-rest-manual.js +279 -0
  32. package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +24 -0
  33. package/dist/runtime/cli-add-workspace-rest-php-templates.js +678 -0
  34. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +8 -0
  35. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +25 -4
  36. package/dist/runtime/cli-add-workspace-rest-types.d.ts +108 -0
  37. package/dist/runtime/cli-add-workspace-rest-types.js +1 -0
  38. package/dist/runtime/cli-add-workspace-rest.d.ts +3 -20
  39. package/dist/runtime/cli-add-workspace-rest.js +33 -788
  40. package/dist/runtime/cli-core.d.ts +1 -1
  41. package/dist/runtime/cli-core.js +1 -1
  42. package/dist/runtime/cli-diagnostics.d.ts +3 -1
  43. package/dist/runtime/cli-diagnostics.js +17 -5
  44. package/dist/runtime/cli-doctor-workspace-bindings.js +4 -1
  45. package/dist/runtime/cli-doctor-workspace-block-addons.d.ts +12 -0
  46. package/dist/runtime/cli-doctor-workspace-block-addons.js +134 -0
  47. package/dist/runtime/cli-doctor-workspace-block-iframe.d.ts +9 -0
  48. package/dist/runtime/cli-doctor-workspace-block-iframe.js +228 -0
  49. package/dist/runtime/cli-doctor-workspace-block-metadata.d.ts +11 -0
  50. package/dist/runtime/cli-doctor-workspace-block-metadata.js +111 -0
  51. package/dist/runtime/cli-doctor-workspace-blocks.js +6 -424
  52. package/dist/runtime/cli-doctor-workspace-features-abilities.d.ts +11 -0
  53. package/dist/runtime/cli-doctor-workspace-features-abilities.js +112 -0
  54. package/dist/runtime/cli-doctor-workspace-features-admin-views.d.ts +11 -0
  55. package/dist/runtime/cli-doctor-workspace-features-admin-views.js +128 -0
  56. package/dist/runtime/cli-doctor-workspace-features-ai.d.ts +11 -0
  57. package/dist/runtime/cli-doctor-workspace-features-ai.js +57 -0
  58. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.d.ts +11 -0
  59. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.js +80 -0
  60. package/dist/runtime/cli-doctor-workspace-features-post-meta.d.ts +11 -0
  61. package/dist/runtime/cli-doctor-workspace-features-post-meta.js +77 -0
  62. package/dist/runtime/cli-doctor-workspace-features-rest.d.ts +11 -0
  63. package/dist/runtime/cli-doctor-workspace-features-rest.js +120 -0
  64. package/dist/runtime/cli-doctor-workspace-features.js +14 -487
  65. package/dist/runtime/cli-doctor.d.ts +52 -3
  66. package/dist/runtime/cli-doctor.js +79 -8
  67. package/dist/runtime/cli-help.js +6 -3
  68. package/dist/runtime/cli-init-package-json.js +4 -2
  69. package/dist/runtime/cli-prompt.d.ts +16 -2
  70. package/dist/runtime/cli-prompt.js +29 -12
  71. package/dist/runtime/cli-scaffold.d.ts +2 -1
  72. package/dist/runtime/cli-scaffold.js +19 -10
  73. package/dist/runtime/external-template-guards.js +4 -6
  74. package/dist/runtime/index.d.ts +2 -2
  75. package/dist/runtime/index.js +1 -1
  76. package/dist/runtime/json-utils.d.ts +62 -4
  77. package/dist/runtime/json-utils.js +78 -4
  78. package/dist/runtime/local-dev-presets.js +4 -1
  79. package/dist/runtime/migration-ui-capability.js +4 -1
  80. package/dist/runtime/migration-utils.js +4 -1
  81. package/dist/runtime/package-managers.js +6 -1
  82. package/dist/runtime/package-versions.js +6 -1
  83. package/dist/runtime/scaffold-bootstrap.js +7 -2
  84. package/dist/runtime/scaffold-package-manager-files.js +5 -1
  85. package/dist/runtime/scaffold-repository-reference.js +4 -2
  86. package/dist/runtime/scaffold-template-variables.js +2 -1
  87. package/dist/runtime/scaffold.d.ts +18 -1
  88. package/dist/runtime/scaffold.js +55 -2
  89. package/dist/runtime/temp-roots.js +4 -1
  90. package/dist/runtime/template-layers.js +4 -1
  91. package/dist/runtime/template-registry.js +9 -3
  92. package/dist/runtime/template-source-contracts.d.ts +2 -0
  93. package/dist/runtime/template-source-normalization.js +2 -1
  94. package/dist/runtime/template-source-remote.js +18 -5
  95. package/dist/runtime/template-source-seeds.js +10 -3
  96. package/dist/runtime/workspace-inventory-mutations.js +2 -1
  97. package/dist/runtime/workspace-inventory-parser-entries.d.ts +17 -0
  98. package/dist/runtime/workspace-inventory-parser-entries.js +157 -0
  99. package/dist/runtime/workspace-inventory-parser-validation.d.ts +104 -0
  100. package/dist/runtime/workspace-inventory-parser-validation.js +34 -0
  101. package/dist/runtime/workspace-inventory-parser.d.ts +3 -45
  102. package/dist/runtime/workspace-inventory-parser.js +3 -581
  103. package/dist/runtime/workspace-inventory-section-descriptors.d.ts +19 -0
  104. package/dist/runtime/workspace-inventory-section-descriptors.js +435 -0
  105. package/dist/runtime/workspace-inventory-templates.d.ts +1 -1
  106. package/dist/runtime/workspace-inventory-templates.js +1 -0
  107. package/dist/runtime/workspace-inventory-types.d.ts +1 -0
  108. package/dist/runtime/workspace-project.js +4 -6
  109. package/package.json +2 -2
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { getPackageVersions } from "./package-versions.js";
4
4
  import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
5
5
  import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
6
+ import { readJsonFile } from "./json-utils.js";
6
7
  import { hasPhpFunctionDefinition } from "./php-utils.js";
7
8
  const AI_FEATURE_SERVER_GLOB = "/inc/ai-features/*.php";
8
9
  /**
@@ -43,7 +44,9 @@ function ${registerFunctionName}() {
43
44
  */
44
45
  export async function ensureAiFeaturePackageScripts(workspace) {
45
46
  const packageJsonPath = path.join(workspace.projectDir, "package.json");
46
- const packageJson = JSON.parse(await fsp.readFile(packageJsonPath, "utf8"));
47
+ const packageJson = await readJsonFile(packageJsonPath, {
48
+ context: "workspace package manifest",
49
+ });
47
50
  const nextScripts = {
48
51
  ...(packageJson.scripts ?? {}),
49
52
  "sync-ai": packageJson.scripts?.["sync-ai"] ?? "tsx scripts/sync-ai-features.ts",
@@ -397,7 +397,23 @@ async function reconcileGeneratedArtifact( options: {
397
397
  }
398
398
 
399
399
  async function loadJsonDocument( filePath: string ) {
400
- \tconst decoded = JSON.parse( await readFile( filePath, 'utf8' ) ) as unknown;
400
+ \tlet source: string;
401
+ \ttry {
402
+ \t\tsource = await readFile( filePath, 'utf8' );
403
+ \t} catch ( error ) {
404
+ \t\tthrow new Error(
405
+ \t\t\t\`Failed to read AI schema document at \${ filePath }: \${ error instanceof Error ? error.message : String( error ) }\`
406
+ \t\t);
407
+ \t}
408
+
409
+ \tlet decoded: unknown;
410
+ \ttry {
411
+ \t\tdecoded = JSON.parse( source ) as unknown;
412
+ \t} catch ( error ) {
413
+ \t\tthrow new Error(
414
+ \t\t\t\`Failed to parse AI schema document at \${ filePath }: \${ error instanceof Error ? error.message : String( error ) }\`
415
+ \t\t);
416
+ \t}
401
417
  \tif ( ! decoded || typeof decoded !== 'object' || Array.isArray( decoded ) ) {
402
418
  \t\tthrow new Error( \`Expected \${ filePath } to decode to a JSON object.\` );
403
419
  \t}
@@ -8,6 +8,7 @@ import { type IntegrationEnvServiceId, type RunAddIntegrationEnvCommandOptions }
8
8
  * @property service Canonical local service starter id selected for the scaffold.
9
9
  * @property warnings Optional non-fatal preservation notices for existing files
10
10
  * or scripts.
11
+ * @property withReleaseZip Whether release zip packaging scripts were added.
11
12
  * @property withWpEnv Whether the generated scaffold included the wp-env preset.
12
13
  */
13
14
  export interface RunAddIntegrationEnvCommandResult {
@@ -15,10 +16,11 @@ export interface RunAddIntegrationEnvCommandResult {
15
16
  projectDir: string;
16
17
  service: IntegrationEnvServiceId;
17
18
  warnings?: string[];
19
+ withReleaseZip: boolean;
18
20
  withWpEnv: boolean;
19
21
  }
20
22
  /**
21
23
  * Add an opt-in local WordPress integration environment starter to an official
22
24
  * workspace.
23
25
  */
24
- export declare function runAddIntegrationEnvCommand({ cwd, integrationEnvName, service, withWpEnv, }: RunAddIntegrationEnvCommandOptions): Promise<RunAddIntegrationEnvCommandResult>;
26
+ export declare function runAddIntegrationEnvCommand({ cwd, integrationEnvName, service, withReleaseZip, withWpEnv, }: RunAddIntegrationEnvCommandOptions): Promise<RunAddIntegrationEnvCommandResult>;
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { assertValidGeneratedSlug, assertValidIntegrationEnvService, normalizeBlockSlug, } from "./cli-add-shared.js";
4
4
  import { formatRunScript, } from "./package-managers.js";
5
5
  import { pathExists, readOptionalUtf8File } from "./fs-async.js";
6
+ import { readJsonFile } from "./json-utils.js";
6
7
  import { executeWorkspaceMutationPlan } from "./cli-add-workspace-mutation.js";
7
8
  import { resolveWorkspaceProject } from "./workspace-project.js";
8
9
  import { toTitleCase } from "./string-case.js";
@@ -136,6 +137,11 @@ const baseUrl = new URL(
136
137
  );
137
138
  const serviceUrl = getEnv("WP_TYPIA_SERVICE_URL", "").trim();
138
139
 
140
+ // Extend this starter with project-specific generated REST clients or schema
141
+ // checks as the workspace grows. For example, read JSON schemas under
142
+ // src/rest/<resource>/api-schemas or import TS clients through a tsx-powered
143
+ // smoke runner when you need authenticated route coverage.
144
+
139
145
  await assertJsonEndpoint(
140
146
  "WordPress REST index",
141
147
  resolveEndpointUrl(baseUrl, "wp-json/"),
@@ -171,7 +177,7 @@ function buildEnvExampleSource(service) {
171
177
  "",
172
178
  ].join("\n");
173
179
  }
174
- function buildIntegrationEnvReadmeSource({ integrationEnvSlug, service, withWpEnv, }) {
180
+ function buildIntegrationEnvReadmeSource({ integrationEnvSlug, service, withReleaseZip, withWpEnv, }) {
175
181
  const title = toTitleCase(integrationEnvSlug);
176
182
  const setupSteps = [
177
183
  "Copy `.env.example` to `.env` and adjust the URLs or credentials for your local project.",
@@ -190,6 +196,11 @@ function buildIntegrationEnvReadmeSource({ integrationEnvSlug, service, withWpEn
190
196
  "Set `WP_TYPIA_SERVICE_URL` only when your integration smoke needs a local service dependency.",
191
197
  ]),
192
198
  `Run \`npm run smoke:${integrationEnvSlug}\` to execute the starter smoke check.`,
199
+ ...(withReleaseZip
200
+ ? [
201
+ "Run `npm run release:zip` after smoke checks pass to build a distributable plugin zip.",
202
+ ]
203
+ : []),
193
204
  ];
194
205
  return `# ${title} Integration Environment
195
206
 
@@ -211,6 +222,7 @@ ${setupSteps.map((step, index) => `${index + 1}. ${step}`).join("\n")}
211
222
  emulator containers.
212
223
  - Keep the smoke script focused on high-signal integration checks so CI and
213
224
  local debugging stay fast.
225
+ ${withReleaseZip ? "- Treat `release:zip:check` as a CI guard before packaging release artifacts.\n" : ""}
214
226
  `;
215
227
  }
216
228
  async function appendMissingLines(filePath, lines) {
@@ -249,11 +261,13 @@ function addScriptIfMissing({ scriptName, scripts, scriptValue, warnings, }) {
249
261
  }
250
262
  async function mutatePackageJson(projectDir, mutate) {
251
263
  const packageJsonPath = path.join(projectDir, "package.json");
252
- const packageJson = JSON.parse(await fsp.readFile(packageJsonPath, "utf8"));
264
+ const packageJson = await readJsonFile(packageJsonPath, {
265
+ context: "integration env package manifest",
266
+ });
253
267
  mutate(packageJson);
254
268
  await fsp.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}\n`, "utf8");
255
269
  }
256
- function addIntegrationEnvPackageJsonEntries({ integrationEnvSlug, packageManager, packageJson, service, warnings, withWpEnv, }) {
270
+ function addIntegrationEnvPackageJsonEntries({ integrationEnvSlug, packageManager, packageJson, withReleaseZip, service, warnings, withWpEnv, }) {
257
271
  const devDependencies = {
258
272
  ...(packageJson.devDependencies ?? {}),
259
273
  };
@@ -296,6 +310,26 @@ function addIntegrationEnvPackageJsonEntries({ integrationEnvSlug, packageManage
296
310
  warnings,
297
311
  });
298
312
  }
313
+ if (withReleaseZip) {
314
+ addScriptIfMissing({
315
+ scriptName: "release:zip",
316
+ scriptValue: `${formatRunScript(packageManager, "sync-rest:package")} && ${formatRunScript(packageManager, "build")} && wp-scripts plugin-zip`,
317
+ scripts,
318
+ warnings,
319
+ });
320
+ addScriptIfMissing({
321
+ scriptName: "release:zip:check",
322
+ scriptValue: `${formatRunScript(packageManager, "sync-rest:package:check")} && ${formatRunScript(packageManager, "build")}`,
323
+ scripts,
324
+ warnings,
325
+ });
326
+ addScriptIfMissing({
327
+ scriptName: "qa:check",
328
+ scriptValue: `${formatRunScript(packageManager, "wp-typia:doctor:workspace")} && ${formatRunScript(packageManager, "release:zip:check")}`,
329
+ scripts,
330
+ warnings,
331
+ });
332
+ }
299
333
  if (service === "docker-compose") {
300
334
  addScriptIfMissing({
301
335
  scriptName: "service:start",
@@ -316,9 +350,9 @@ function addIntegrationEnvPackageJsonEntries({ integrationEnvSlug, packageManage
316
350
  * Add an opt-in local WordPress integration environment starter to an official
317
351
  * workspace.
318
352
  */
319
- export async function runAddIntegrationEnvCommand({ cwd = process.cwd(), integrationEnvName, service, withWpEnv = false, }) {
353
+ export async function runAddIntegrationEnvCommand({ cwd = process.cwd(), integrationEnvName, service, withReleaseZip = false, withWpEnv = false, }) {
320
354
  const workspace = resolveWorkspaceProject(cwd);
321
- const integrationEnvSlug = assertValidGeneratedSlug("Integration environment name", normalizeBlockSlug(integrationEnvName), "wp-typia add integration-env <name> [--wp-env]");
355
+ const integrationEnvSlug = assertValidGeneratedSlug("Integration environment name", normalizeBlockSlug(integrationEnvName), "wp-typia add integration-env <name> [--wp-env] [--release-zip]");
322
356
  const serviceId = assertValidIntegrationEnvService(service);
323
357
  const warnings = [];
324
358
  const packageJsonPath = path.join(workspace.projectDir, "package.json");
@@ -351,6 +385,7 @@ export async function runAddIntegrationEnvCommand({ cwd = process.cwd(), integra
351
385
  await writeNewScaffoldFile(docsPath, buildIntegrationEnvReadmeSource({
352
386
  integrationEnvSlug,
353
387
  service: serviceId,
388
+ withReleaseZip,
354
389
  withWpEnv,
355
390
  }));
356
391
  await appendMissingLines(envExamplePath, [
@@ -376,6 +411,7 @@ export async function runAddIntegrationEnvCommand({ cwd = process.cwd(), integra
376
411
  packageManager: workspace.packageManager,
377
412
  packageJson,
378
413
  service: serviceId,
414
+ withReleaseZip,
379
415
  warnings,
380
416
  withWpEnv,
381
417
  }));
@@ -386,6 +422,7 @@ export async function runAddIntegrationEnvCommand({ cwd = process.cwd(), integra
386
422
  projectDir: workspace.projectDir,
387
423
  service: serviceId,
388
424
  warnings: warnings.length > 0 ? warnings : undefined,
425
+ withReleaseZip,
389
426
  withWpEnv,
390
427
  };
391
428
  }
@@ -1,4 +1,12 @@
1
1
  import type { WorkspaceProject } from "./workspace-project.js";
2
+ /**
3
+ * Ensure the workspace bootstrap loads the shared REST schema helper file.
4
+ *
5
+ * @param workspace Resolved workspace project metadata and PHP prefix.
6
+ * @returns A promise that resolves after the bootstrap is patched.
7
+ * @throws When an existing loader does not reference `inc/rest-schema.php`.
8
+ */
9
+ export declare function ensureRestSchemaHelperBootstrapAnchors(workspace: WorkspaceProject): Promise<void>;
2
10
  export declare function ensureRestResourceBootstrapAnchors(workspace: WorkspaceProject): Promise<void>;
3
11
  export declare function ensureContractSyncScriptAnchors(workspace: WorkspaceProject): Promise<void>;
4
12
  export declare function ensureRestResourceSyncScriptAnchors(workspace: WorkspaceProject): Promise<void>;
@@ -3,6 +3,47 @@ import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
3
3
  import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
4
4
  import { hasPhpFunctionDefinition } from "./php-utils.js";
5
5
  const REST_RESOURCE_SERVER_GLOB = "/inc/rest/*.php";
6
+ const REST_SCHEMA_HELPER_PATH = "/inc/rest-schema.php";
7
+ /**
8
+ * Ensure the workspace bootstrap loads the shared REST schema helper file.
9
+ *
10
+ * @param workspace Resolved workspace project metadata and PHP prefix.
11
+ * @returns A promise that resolves after the bootstrap is patched.
12
+ * @throws When an existing loader does not reference `inc/rest-schema.php`.
13
+ */
14
+ export async function ensureRestSchemaHelperBootstrapAnchors(workspace) {
15
+ const bootstrapPath = getWorkspaceBootstrapPath(workspace);
16
+ await patchFile(bootstrapPath, (source) => {
17
+ let nextSource = source;
18
+ const loadFunctionName = `${workspace.workspace.phpPrefix}_load_rest_schema_helpers`;
19
+ const loadCall = `${loadFunctionName}();`;
20
+ const helperFunction = `
21
+
22
+ function ${loadFunctionName}() {
23
+ \t$helper_path = __DIR__ . '${REST_SCHEMA_HELPER_PATH}';
24
+ \tif ( is_readable( $helper_path ) ) {
25
+ \t\trequire_once $helper_path;
26
+ \t}
27
+ }
28
+
29
+ ${loadCall}
30
+ `;
31
+ if (!hasPhpFunctionDefinition(nextSource, loadFunctionName)) {
32
+ nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, helperFunction);
33
+ }
34
+ else if (!nextSource.includes(REST_SCHEMA_HELPER_PATH)) {
35
+ throw new Error([
36
+ `Unable to patch ${path.basename(bootstrapPath)} in ensureRestSchemaHelperBootstrapAnchors.`,
37
+ `The existing ${loadFunctionName}() definition does not include ${REST_SCHEMA_HELPER_PATH}.`,
38
+ "Restore the generated bootstrap shape or load inc/rest-schema.php manually before retrying.",
39
+ ].join(" "));
40
+ }
41
+ else if (!nextSource.includes(loadCall)) {
42
+ nextSource = appendPhpSnippetBeforeClosingTag(nextSource, loadCall);
43
+ }
44
+ return nextSource;
45
+ });
46
+ }
6
47
  export async function ensureRestResourceBootstrapAnchors(workspace) {
7
48
  const bootstrapPath = getWorkspaceBootstrapPath(workspace);
8
49
  await patchFile(bootstrapPath, (source) => {
@@ -0,0 +1,9 @@
1
+ import { type GeneratedRestResourceScaffoldOptions, type RunAddRestResourceCommandResult } from "./cli-add-workspace-rest-types.js";
2
+ /**
3
+ * Scaffold generated TypeScript, PHP, schema, and inventory files for a
4
+ * workspace-owned REST resource.
5
+ *
6
+ * @param options Resolved workspace and raw generated-mode command options.
7
+ * @returns Resolved scaffold metadata for the generated REST resource.
8
+ */
9
+ export declare function scaffoldGeneratedRestResource({ controllerClass, controllerExtends, methods, namespace, permissionCallback, restResourceSlug, routePattern, workspace, }: GeneratedRestResourceScaffoldOptions): Promise<RunAddRestResourceCommandResult>;
@@ -0,0 +1,158 @@
1
+ import { promises as fsp } from "node:fs";
2
+ import path from "node:path";
3
+ import { ensureBlockConfigCanAddRestManifests } from "./cli-add-block-legacy-validator.js";
4
+ import { assertValidRestResourceMethods, getWorkspaceBootstrapPath, resolveGeneratedRestResourceRoutePattern, resolveOptionalPhpCallbackReference, resolveOptionalPhpClassReference, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
5
+ import { ensureRestResourceBootstrapAnchors, ensureRestSchemaHelperBootstrapAnchors, ensureRestResourceSyncScriptAnchors, } from "./cli-add-workspace-rest-anchors.js";
6
+ import { buildRestResourcePhpSource, buildWorkspaceRestSchemaHelperPhpSource, } from "./cli-add-workspace-rest-php-templates.js";
7
+ import { buildRestResourceApiSource, buildRestResourceConfigEntry, buildRestResourceDataSource, buildRestResourceTypesSource, buildRestResourceValidatorsSource, } from "./cli-add-workspace-rest-source-emitters.js";
8
+ import { hasPhpFunctionDefinition } from "./php-utils.js";
9
+ import { syncRestResourceArtifacts } from "./rest-resource-artifacts.js";
10
+ import { toPascalCase, toTitleCase } from "./string-case.js";
11
+ import { appendWorkspaceInventoryEntries } from "./workspace-inventory.js";
12
+ async function ensureWorkspaceRestSchemaHelperFile(helperFilePath, phpPrefix) {
13
+ let currentSource = null;
14
+ try {
15
+ currentSource = await fsp.readFile(helperFilePath, "utf8");
16
+ }
17
+ catch (error) {
18
+ if (error.code !== "ENOENT") {
19
+ throw error;
20
+ }
21
+ }
22
+ if (currentSource === null) {
23
+ await fsp.mkdir(path.dirname(helperFilePath), { recursive: true });
24
+ await fsp.writeFile(helperFilePath, buildWorkspaceRestSchemaHelperPhpSource(phpPrefix), "utf8");
25
+ return;
26
+ }
27
+ const requiredFunctions = [
28
+ `${phpPrefix}_load_rest_schema`,
29
+ `${phpPrefix}_prepare_rest_schema_for_wordpress`,
30
+ `${phpPrefix}_get_wordpress_rest_schema`,
31
+ `${phpPrefix}_validate_and_sanitize_rest_payload`,
32
+ ];
33
+ const missingFunctions = requiredFunctions.filter((functionName) => !hasPhpFunctionDefinition(currentSource, functionName));
34
+ if (missingFunctions.length > 0) {
35
+ throw new Error([
36
+ `Existing ${path.relative(process.cwd(), helperFilePath)} is missing generated REST schema helper functions: ${missingFunctions.join(", ")}.`,
37
+ "Restore the generated inc/rest-schema.php helper or add these functions manually before retrying.",
38
+ ].join(" "));
39
+ }
40
+ }
41
+ /**
42
+ * Scaffold generated TypeScript, PHP, schema, and inventory files for a
43
+ * workspace-owned REST resource.
44
+ *
45
+ * @param options Resolved workspace and raw generated-mode command options.
46
+ * @returns Resolved scaffold metadata for the generated REST resource.
47
+ */
48
+ export async function scaffoldGeneratedRestResource({ controllerClass, controllerExtends, methods, namespace, permissionCallback, restResourceSlug, routePattern, workspace, }) {
49
+ const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
50
+ const syncRestScriptPath = path.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
51
+ const restResourceDir = path.join(workspace.projectDir, "src", "rest", restResourceSlug);
52
+ const typesFilePath = path.join(restResourceDir, "api-types.ts");
53
+ const validatorsFilePath = path.join(restResourceDir, "api-validators.ts");
54
+ const apiFilePath = path.join(restResourceDir, "api.ts");
55
+ const resolvedMethods = assertValidRestResourceMethods(methods);
56
+ const resolvedRoutePattern = resolveGeneratedRestResourceRoutePattern(restResourceSlug, routePattern);
57
+ const hasCustomRoutePattern = typeof routePattern === "string" && routePattern.trim().length > 0;
58
+ const resolvedPermissionCallback = resolveOptionalPhpCallbackReference("Generated REST resource permission callback", permissionCallback);
59
+ const resolvedControllerClass = resolveOptionalPhpClassReference("Generated REST resource controller class", controllerClass);
60
+ const resolvedControllerExtends = resolveOptionalPhpClassReference("Generated REST resource controller base class", controllerExtends);
61
+ if (resolvedControllerExtends && !resolvedControllerClass) {
62
+ throw new Error("Generated REST resource controller base class requires --controller-class.");
63
+ }
64
+ const bootstrapPath = getWorkspaceBootstrapPath(workspace);
65
+ const dataFilePath = path.join(restResourceDir, "data.ts");
66
+ const restSchemaHelperPath = path.join(workspace.projectDir, "inc", "rest-schema.php");
67
+ const phpFilePath = path.join(workspace.projectDir, "inc", "rest", `${restResourceSlug}.php`);
68
+ const mutationSnapshot = {
69
+ fileSources: await snapshotWorkspaceFiles([
70
+ blockConfigPath,
71
+ bootstrapPath,
72
+ restSchemaHelperPath,
73
+ syncRestScriptPath,
74
+ ]),
75
+ snapshotDirs: [],
76
+ targetPaths: [restResourceDir, restSchemaHelperPath, phpFilePath],
77
+ };
78
+ try {
79
+ await fsp.mkdir(restResourceDir, { recursive: true });
80
+ await fsp.mkdir(path.dirname(phpFilePath), { recursive: true });
81
+ await ensureWorkspaceRestSchemaHelperFile(restSchemaHelperPath, workspace.workspace.phpPrefix);
82
+ await ensureRestSchemaHelperBootstrapAnchors(workspace);
83
+ await ensureRestResourceBootstrapAnchors(workspace);
84
+ await ensureRestResourceSyncScriptAnchors(workspace);
85
+ await fsp.writeFile(typesFilePath, buildRestResourceTypesSource(restResourceSlug, resolvedMethods), "utf8");
86
+ await fsp.writeFile(validatorsFilePath, buildRestResourceValidatorsSource(restResourceSlug, resolvedMethods), "utf8");
87
+ await fsp.writeFile(apiFilePath, buildRestResourceApiSource(restResourceSlug, resolvedMethods), "utf8");
88
+ await fsp.writeFile(dataFilePath, buildRestResourceDataSource(restResourceSlug, resolvedMethods), "utf8");
89
+ await fsp.writeFile(phpFilePath, buildRestResourcePhpSource(restResourceSlug, namespace, workspace.workspace.phpPrefix, resolvedMethods, {
90
+ ...(resolvedControllerClass
91
+ ? { controllerClass: resolvedControllerClass }
92
+ : {}),
93
+ ...(resolvedControllerExtends
94
+ ? { controllerExtends: resolvedControllerExtends }
95
+ : {}),
96
+ ...(resolvedPermissionCallback
97
+ ? { permissionCallback: resolvedPermissionCallback }
98
+ : {}),
99
+ routePattern: resolvedRoutePattern,
100
+ }), "utf8");
101
+ await syncRestResourceArtifacts({
102
+ clientFile: `src/rest/${restResourceSlug}/api-client.ts`,
103
+ methods: resolvedMethods,
104
+ outputDir: restResourceDir,
105
+ projectDir: workspace.projectDir,
106
+ typesFile: `src/rest/${restResourceSlug}/api-types.ts`,
107
+ validatorsFile: `src/rest/${restResourceSlug}/api-validators.ts`,
108
+ variables: {
109
+ namespace,
110
+ pascalCase: toPascalCase(restResourceSlug),
111
+ ...(hasCustomRoutePattern ? { routePattern: resolvedRoutePattern } : {}),
112
+ slugKebabCase: restResourceSlug,
113
+ title: toTitleCase(restResourceSlug),
114
+ },
115
+ });
116
+ await appendWorkspaceInventoryEntries(workspace.projectDir, {
117
+ restResourceEntries: [
118
+ buildRestResourceConfigEntry({
119
+ ...(resolvedControllerClass
120
+ ? { controllerClass: resolvedControllerClass }
121
+ : {}),
122
+ ...(resolvedControllerExtends
123
+ ? { controllerExtends: resolvedControllerExtends }
124
+ : {}),
125
+ methods: resolvedMethods,
126
+ namespace,
127
+ ...(resolvedPermissionCallback
128
+ ? { permissionCallback: resolvedPermissionCallback }
129
+ : {}),
130
+ restResourceSlug,
131
+ ...(hasCustomRoutePattern ? { routePattern: resolvedRoutePattern } : {}),
132
+ }),
133
+ ],
134
+ transformSource: ensureBlockConfigCanAddRestManifests,
135
+ });
136
+ return {
137
+ ...(resolvedControllerClass
138
+ ? { controllerClass: resolvedControllerClass }
139
+ : {}),
140
+ ...(resolvedControllerExtends
141
+ ? { controllerExtends: resolvedControllerExtends }
142
+ : {}),
143
+ methods: resolvedMethods,
144
+ mode: "generated",
145
+ namespace,
146
+ ...(resolvedPermissionCallback
147
+ ? { permissionCallback: resolvedPermissionCallback }
148
+ : {}),
149
+ projectDir: workspace.projectDir,
150
+ restResourceSlug,
151
+ ...(hasCustomRoutePattern ? { routePattern: resolvedRoutePattern } : {}),
152
+ };
153
+ }
154
+ catch (error) {
155
+ await rollbackWorkspaceMutation(mutationSnapshot);
156
+ throw error;
157
+ }
158
+ }
@@ -0,0 +1,8 @@
1
+ import { type ManualRestContractScaffoldOptions, type RunAddRestResourceCommandResult } from "./cli-add-workspace-rest-types.js";
2
+ /**
3
+ * Scaffold a type-only external REST contract for workspace consumers.
4
+ *
5
+ * @param options Resolved workspace and raw manual-mode command options.
6
+ * @returns Resolved scaffold metadata for the manual REST contract.
7
+ */
8
+ export declare function scaffoldManualRestContract({ auth, bodyTypeName, controllerClass, controllerExtends, method, namespace, pathPattern, permissionCallback, queryTypeName, responseTypeName, restResourceSlug, routePattern, secretFieldName, secretHasValueFieldName, secretMaskedResponseFieldName, secretPreserveOnEmpty, secretStateFieldName, workspace, }: ManualRestContractScaffoldOptions): Promise<RunAddRestResourceCommandResult>;