@wp-typia/project-tools 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) 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/built-in-block-non-ts-basic-artifacts.d.ts +9 -0
  4. package/dist/runtime/built-in-block-non-ts-basic-artifacts.js +84 -0
  5. package/dist/runtime/built-in-block-non-ts-compound-artifacts.d.ts +9 -0
  6. package/dist/runtime/built-in-block-non-ts-compound-artifacts.js +36 -0
  7. package/dist/runtime/built-in-block-non-ts-compound-templates.d.ts +23 -0
  8. package/dist/runtime/built-in-block-non-ts-compound-templates.js +453 -0
  9. package/dist/runtime/built-in-block-non-ts-family-artifacts.d.ts +8 -26
  10. package/dist/runtime/built-in-block-non-ts-family-artifacts.js +8 -1034
  11. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.d.ts +9 -0
  12. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.js +83 -0
  13. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.d.ts +9 -0
  14. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.js +33 -0
  15. package/dist/runtime/built-in-block-non-ts-persistence-templates.d.ts +23 -0
  16. package/dist/runtime/built-in-block-non-ts-persistence-templates.js +395 -0
  17. package/dist/runtime/cli-add-block-json.js +5 -1
  18. package/dist/runtime/cli-add-collision.js +8 -0
  19. package/dist/runtime/cli-add-help.js +14 -10
  20. package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
  21. package/dist/runtime/cli-add-kind-ids.js +1 -0
  22. package/dist/runtime/cli-add-types.d.ts +45 -6
  23. package/dist/runtime/cli-add-types.js +2 -0
  24. package/dist/runtime/cli-add-validation.d.ts +7 -0
  25. package/dist/runtime/cli-add-validation.js +9 -0
  26. package/dist/runtime/cli-add-workspace-ability-anchors.d.ts +24 -0
  27. package/dist/runtime/cli-add-workspace-ability-anchors.js +294 -0
  28. package/dist/runtime/cli-add-workspace-ability-registry.d.ts +10 -0
  29. package/dist/runtime/cli-add-workspace-ability-registry.js +51 -0
  30. package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +1 -1
  31. package/dist/runtime/cli-add-workspace-ability-scaffold.js +5 -308
  32. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +6 -2
  33. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.d.ts +34 -0
  34. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.js +483 -0
  35. package/dist/runtime/cli-add-workspace-admin-view-templates-default.d.ts +30 -0
  36. package/dist/runtime/cli-add-workspace-admin-view-templates-default.js +310 -0
  37. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.d.ts +25 -0
  38. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.js +124 -0
  39. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.d.ts +34 -0
  40. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.js +370 -0
  41. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.d.ts +49 -0
  42. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.js +259 -0
  43. package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +18 -27
  44. package/dist/runtime/cli-add-workspace-admin-view-templates.js +30 -1326
  45. package/dist/runtime/cli-add-workspace-ai-anchors.d.ts +4 -4
  46. package/dist/runtime/cli-add-workspace-ai-anchors.js +8 -233
  47. package/dist/runtime/cli-add-workspace-ai-scaffold.js +4 -2
  48. package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +1 -4
  49. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +1 -129
  50. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.d.ts +5 -0
  51. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.js +236 -0
  52. package/dist/runtime/cli-add-workspace-ai-sync-script-source.d.ts +4 -0
  53. package/dist/runtime/cli-add-workspace-ai-sync-script-source.js +145 -0
  54. package/dist/runtime/cli-add-workspace-assets.d.ts +6 -63
  55. package/dist/runtime/cli-add-workspace-assets.js +6 -950
  56. package/dist/runtime/cli-add-workspace-binding-source-anchors.d.ts +23 -0
  57. package/dist/runtime/cli-add-workspace-binding-source-anchors.js +112 -0
  58. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.d.ts +33 -0
  59. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.js +436 -0
  60. package/dist/runtime/cli-add-workspace-binding-source-types.d.ts +20 -0
  61. package/dist/runtime/cli-add-workspace-binding-source-types.js +1 -0
  62. package/dist/runtime/cli-add-workspace-binding-source.d.ts +40 -0
  63. package/dist/runtime/cli-add-workspace-binding-source.js +275 -0
  64. package/dist/runtime/cli-add-workspace-block-style.d.ts +22 -0
  65. package/dist/runtime/cli-add-workspace-block-style.js +148 -0
  66. package/dist/runtime/cli-add-workspace-block-transform.d.ts +32 -0
  67. package/dist/runtime/cli-add-workspace-block-transform.js +197 -0
  68. package/dist/runtime/cli-add-workspace-contract.js +1 -1
  69. package/dist/runtime/cli-add-workspace-core-variation.d.ts +20 -0
  70. package/dist/runtime/cli-add-workspace-core-variation.js +322 -0
  71. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.d.ts +37 -0
  72. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.js +206 -0
  73. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.d.ts +47 -0
  74. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.js +219 -0
  75. package/dist/runtime/cli-add-workspace-editor-plugin.d.ts +22 -0
  76. package/dist/runtime/cli-add-workspace-editor-plugin.js +78 -0
  77. package/dist/runtime/cli-add-workspace-hooked-block.d.ts +23 -0
  78. package/dist/runtime/cli-add-workspace-hooked-block.js +57 -0
  79. package/dist/runtime/cli-add-workspace-integration-env-files.d.ts +33 -0
  80. package/dist/runtime/cli-add-workspace-integration-env-files.js +65 -0
  81. package/dist/runtime/cli-add-workspace-integration-env-package-json.d.ts +38 -0
  82. package/dist/runtime/cli-add-workspace-integration-env-package-json.js +122 -0
  83. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.d.ts +44 -0
  84. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.js +262 -0
  85. package/dist/runtime/cli-add-workspace-integration-env.d.ts +3 -1
  86. package/dist/runtime/cli-add-workspace-integration-env.js +10 -313
  87. package/dist/runtime/cli-add-workspace-pattern-anchors.d.ts +10 -0
  88. package/dist/runtime/cli-add-workspace-pattern-anchors.js +95 -0
  89. package/dist/runtime/cli-add-workspace-pattern-options.d.ts +20 -0
  90. package/dist/runtime/cli-add-workspace-pattern-options.js +113 -0
  91. package/dist/runtime/cli-add-workspace-pattern-source-emitters.d.ts +20 -0
  92. package/dist/runtime/cli-add-workspace-pattern-source-emitters.js +57 -0
  93. package/dist/runtime/cli-add-workspace-pattern.d.ts +42 -0
  94. package/dist/runtime/cli-add-workspace-pattern.js +99 -0
  95. package/dist/runtime/cli-add-workspace-post-meta.js +1 -1
  96. package/dist/runtime/cli-add-workspace-registration-hooks.d.ts +50 -0
  97. package/dist/runtime/cli-add-workspace-registration-hooks.js +162 -0
  98. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +9 -4
  99. package/dist/runtime/cli-add-workspace-rest-anchors.js +9 -428
  100. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.d.ts +17 -0
  101. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.js +108 -0
  102. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.d.ts +9 -0
  103. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.js +142 -0
  104. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.d.ts +51 -0
  105. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.js +415 -0
  106. package/dist/runtime/cli-add-workspace-rest-generated.d.ts +9 -0
  107. package/dist/runtime/cli-add-workspace-rest-generated.js +160 -0
  108. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.d.ts +80 -0
  109. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.js +238 -0
  110. package/dist/runtime/cli-add-workspace-rest-manual.d.ts +8 -0
  111. package/dist/runtime/cli-add-workspace-rest-manual.js +266 -0
  112. package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +18 -0
  113. package/dist/runtime/cli-add-workspace-rest-php-templates.js +359 -0
  114. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.d.ts +33 -0
  115. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.js +145 -0
  116. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.d.ts +9 -0
  117. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.js +162 -0
  118. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.d.ts +7 -0
  119. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.js +193 -0
  120. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +5 -91
  121. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +5 -642
  122. package/dist/runtime/cli-add-workspace-rest-source-utils.d.ts +17 -0
  123. package/dist/runtime/cli-add-workspace-rest-source-utils.js +50 -0
  124. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.d.ts +56 -0
  125. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.js +122 -0
  126. package/dist/runtime/cli-add-workspace-rest-types.d.ts +108 -0
  127. package/dist/runtime/cli-add-workspace-rest-types.js +1 -0
  128. package/dist/runtime/cli-add-workspace-rest.d.ts +3 -20
  129. package/dist/runtime/cli-add-workspace-rest.js +33 -788
  130. package/dist/runtime/cli-add-workspace-variation.d.ts +22 -0
  131. package/dist/runtime/cli-add-workspace-variation.js +162 -0
  132. package/dist/runtime/cli-add-workspace.d.ts +42 -107
  133. package/dist/runtime/cli-add-workspace.js +42 -674
  134. package/dist/runtime/cli-add.d.ts +3 -3
  135. package/dist/runtime/cli-add.js +2 -2
  136. package/dist/runtime/cli-core.d.ts +3 -2
  137. package/dist/runtime/cli-core.js +2 -2
  138. package/dist/runtime/cli-diagnostics.d.ts +3 -1
  139. package/dist/runtime/cli-diagnostics.js +17 -5
  140. package/dist/runtime/cli-doctor-workspace-bindings.js +63 -1
  141. package/dist/runtime/cli-doctor-workspace-block-addons.d.ts +12 -0
  142. package/dist/runtime/cli-doctor-workspace-block-addons.js +162 -0
  143. package/dist/runtime/cli-doctor-workspace-block-iframe.d.ts +9 -0
  144. package/dist/runtime/cli-doctor-workspace-block-iframe.js +228 -0
  145. package/dist/runtime/cli-doctor-workspace-block-metadata.d.ts +11 -0
  146. package/dist/runtime/cli-doctor-workspace-block-metadata.js +111 -0
  147. package/dist/runtime/cli-doctor-workspace-blocks.js +6 -424
  148. package/dist/runtime/cli-doctor-workspace-features-abilities.d.ts +11 -0
  149. package/dist/runtime/cli-doctor-workspace-features-abilities.js +112 -0
  150. package/dist/runtime/cli-doctor-workspace-features-admin-views.d.ts +11 -0
  151. package/dist/runtime/cli-doctor-workspace-features-admin-views.js +128 -0
  152. package/dist/runtime/cli-doctor-workspace-features-ai.d.ts +11 -0
  153. package/dist/runtime/cli-doctor-workspace-features-ai.js +57 -0
  154. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.d.ts +11 -0
  155. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.js +80 -0
  156. package/dist/runtime/cli-doctor-workspace-features-post-meta.d.ts +11 -0
  157. package/dist/runtime/cli-doctor-workspace-features-post-meta.js +77 -0
  158. package/dist/runtime/cli-doctor-workspace-features-rest.d.ts +11 -0
  159. package/dist/runtime/cli-doctor-workspace-features-rest.js +120 -0
  160. package/dist/runtime/cli-doctor-workspace-features.js +14 -487
  161. package/dist/runtime/cli-doctor.d.ts +54 -3
  162. package/dist/runtime/cli-doctor.js +92 -10
  163. package/dist/runtime/cli-help.js +12 -7
  164. package/dist/runtime/cli-init-package-json.js +4 -2
  165. package/dist/runtime/cli-prompt.d.ts +16 -2
  166. package/dist/runtime/cli-prompt.js +29 -12
  167. package/dist/runtime/cli-scaffold.d.ts +2 -1
  168. package/dist/runtime/cli-scaffold.js +19 -10
  169. package/dist/runtime/external-template-guards.js +4 -6
  170. package/dist/runtime/index.d.ts +6 -3
  171. package/dist/runtime/index.js +4 -2
  172. package/dist/runtime/json-utils.d.ts +62 -4
  173. package/dist/runtime/json-utils.js +78 -4
  174. package/dist/runtime/local-dev-presets.js +6 -2
  175. package/dist/runtime/migration-ui-capability.js +4 -1
  176. package/dist/runtime/migration-utils.js +4 -1
  177. package/dist/runtime/package-managers.js +6 -1
  178. package/dist/runtime/package-versions.d.ts +1 -0
  179. package/dist/runtime/package-versions.js +16 -3
  180. package/dist/runtime/pattern-catalog.d.ts +122 -0
  181. package/dist/runtime/pattern-catalog.js +471 -0
  182. package/dist/runtime/post-meta-binding-fields.d.ts +46 -0
  183. package/dist/runtime/post-meta-binding-fields.js +135 -0
  184. package/dist/runtime/scaffold-bootstrap.js +7 -2
  185. package/dist/runtime/scaffold-package-manager-files.js +5 -1
  186. package/dist/runtime/scaffold-repository-reference.js +4 -2
  187. package/dist/runtime/scaffold-template-variables.js +2 -1
  188. package/dist/runtime/scaffold.d.ts +18 -1
  189. package/dist/runtime/scaffold.js +55 -2
  190. package/dist/runtime/temp-roots.js +4 -1
  191. package/dist/runtime/template-layers.js +4 -1
  192. package/dist/runtime/template-registry.js +9 -3
  193. package/dist/runtime/template-source-contracts.d.ts +2 -0
  194. package/dist/runtime/template-source-normalization.js +2 -1
  195. package/dist/runtime/template-source-remote.js +18 -5
  196. package/dist/runtime/template-source-seeds.js +10 -3
  197. package/dist/runtime/typia-llm-json-schema.d.ts +24 -0
  198. package/dist/runtime/typia-llm-json-schema.js +33 -0
  199. package/dist/runtime/typia-llm-openapi-constraints.d.ts +20 -0
  200. package/dist/runtime/typia-llm-openapi-constraints.js +254 -0
  201. package/dist/runtime/typia-llm-projection.d.ts +25 -0
  202. package/dist/runtime/typia-llm-projection.js +58 -0
  203. package/dist/runtime/typia-llm-render.d.ts +21 -0
  204. package/dist/runtime/typia-llm-render.js +252 -0
  205. package/dist/runtime/typia-llm-sync.d.ts +10 -0
  206. package/dist/runtime/typia-llm-sync.js +63 -0
  207. package/dist/runtime/typia-llm-types.d.ts +197 -0
  208. package/dist/runtime/typia-llm-types.js +1 -0
  209. package/dist/runtime/typia-llm.d.ts +9 -255
  210. package/dist/runtime/typia-llm.js +5 -634
  211. package/dist/runtime/workspace-inventory-mutations.js +15 -1
  212. package/dist/runtime/workspace-inventory-parser-entries.d.ts +17 -0
  213. package/dist/runtime/workspace-inventory-parser-entries.js +157 -0
  214. package/dist/runtime/workspace-inventory-parser-validation.d.ts +104 -0
  215. package/dist/runtime/workspace-inventory-parser-validation.js +34 -0
  216. package/dist/runtime/workspace-inventory-parser.d.ts +3 -45
  217. package/dist/runtime/workspace-inventory-parser.js +3 -581
  218. package/dist/runtime/workspace-inventory-section-descriptors.d.ts +19 -0
  219. package/dist/runtime/workspace-inventory-section-descriptors.js +443 -0
  220. package/dist/runtime/workspace-inventory-templates.d.ts +3 -3
  221. package/dist/runtime/workspace-inventory-templates.js +10 -1
  222. package/dist/runtime/workspace-inventory-types.d.ts +10 -1
  223. package/dist/runtime/workspace-project.js +4 -6
  224. package/package.json +8 -3
  225. package/templates/_shared/compound/core/scripts/block-config.ts.mustache +22 -0
  226. package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +103 -2
  227. package/templates/_shared/compound/core/src/inner-blocks-templates.ts.mustache +13 -0
  228. package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +22 -1
@@ -1,441 +1,9 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { EDITOR_PLUGIN_SLOT_IDS, MANUAL_REST_CONTRACT_AUTH_IDS, MANUAL_REST_CONTRACT_HTTP_METHOD_IDS, REST_RESOURCE_METHOD_IDS, REST_RESOURCE_NAMESPACE_PATTERN, assertValidPostMetaPostType, isGeneratedRestResourceRoutePatternCompatible, resolveEditorPluginSlotAlias, } from "./cli-add-shared.js";
4
- import { hasAdminViewManualSettingsRouteParameters, isAdminViewManualSettingsRestResource, } from "./cli-add-workspace-admin-view-types.js";
5
- import { checkExistingFiles, createDoctorCheck, resolveWorkspaceBootstrapPath, WORKSPACE_ABILITY_EDITOR_ASSET, WORKSPACE_ABILITY_EDITOR_SCRIPT, WORKSPACE_ABILITY_GLOB, WORKSPACE_ADMIN_VIEW_ASSET, WORKSPACE_ADMIN_VIEW_GLOB, WORKSPACE_ADMIN_VIEW_SCRIPT, WORKSPACE_ADMIN_VIEW_STYLE, WORKSPACE_AI_FEATURE_GLOB, WORKSPACE_EDITOR_PLUGIN_EDITOR_ASSET, WORKSPACE_EDITOR_PLUGIN_EDITOR_SCRIPT, WORKSPACE_EDITOR_PLUGIN_EDITOR_STYLE, WORKSPACE_POST_META_GLOB, WORKSPACE_REST_RESOURCE_GLOB, } from "./cli-doctor-workspace-shared.js";
6
- import { escapeRegex } from "./php-utils.js";
7
- function isManualRestResource(restResource) {
8
- return restResource.mode === "manual";
9
- }
10
- function getWorkspaceRestResourceRequiredFiles(restResource) {
11
- const schemaNames = new Set();
12
- if (isManualRestResource(restResource)) {
13
- schemaNames.add("query");
14
- if (restResource.bodyTypeName) {
15
- schemaNames.add("request");
16
- }
17
- schemaNames.add("response");
18
- return Array.from(new Set([
19
- restResource.apiFile,
20
- ...Array.from(schemaNames, (schemaName) => path.join(path.dirname(restResource.typesFile), "api-schemas", `${schemaName}.schema.json`)),
21
- restResource.clientFile,
22
- restResource.openApiFile,
23
- restResource.typesFile,
24
- restResource.validatorsFile,
25
- ]));
26
- }
27
- if (restResource.methods.includes("list")) {
28
- schemaNames.add("list-query");
29
- schemaNames.add("list-response");
30
- }
31
- if (restResource.methods.includes("read")) {
32
- schemaNames.add("read-query");
33
- schemaNames.add("read-response");
34
- }
35
- if (restResource.methods.includes("create")) {
36
- schemaNames.add("create-request");
37
- schemaNames.add("create-response");
38
- }
39
- if (restResource.methods.includes("update")) {
40
- schemaNames.add("update-query");
41
- schemaNames.add("update-request");
42
- schemaNames.add("update-response");
43
- }
44
- if (restResource.methods.includes("delete")) {
45
- schemaNames.add("delete-query");
46
- schemaNames.add("delete-response");
47
- }
48
- return Array.from(new Set([
49
- restResource.apiFile,
50
- ...Array.from(schemaNames, (schemaName) => path.join(path.dirname(restResource.typesFile), "api-schemas", `${schemaName}.schema.json`)),
51
- restResource.clientFile,
52
- ...(restResource.dataFile ? [restResource.dataFile] : []),
53
- restResource.openApiFile,
54
- ...(restResource.phpFile ? [restResource.phpFile] : []),
55
- restResource.typesFile,
56
- restResource.validatorsFile,
57
- ]));
58
- }
59
- function checkWorkspaceRestResourceConfig(restResource) {
60
- const hasNamespace = REST_RESOURCE_NAMESPACE_PATTERN.test(restResource.namespace);
61
- if (isManualRestResource(restResource)) {
62
- const hasAuth = restResource.auth == null ||
63
- MANUAL_REST_CONTRACT_AUTH_IDS.includes(restResource.auth);
64
- const hasMethod = typeof restResource.method === "string" &&
65
- MANUAL_REST_CONTRACT_HTTP_METHOD_IDS.includes(restResource.method);
66
- const hasPathPattern = typeof restResource.pathPattern === "string" &&
67
- restResource.pathPattern.startsWith("/") &&
68
- restResource.pathPattern.length > 1;
69
- return createDoctorCheck(`REST resource config ${restResource.slug}`, hasNamespace && hasAuth && hasMethod && hasPathPattern ? "pass" : "fail", hasNamespace && hasAuth && hasMethod && hasPathPattern
70
- ? `Manual REST contract ${restResource.method} /${restResource.namespace}${restResource.pathPattern}`
71
- : "Manual REST contract namespace, auth, method, or path pattern is invalid");
72
- }
73
- const hasMethods = restResource.methods.length > 0 &&
74
- restResource.methods.every((method) => REST_RESOURCE_METHOD_IDS.includes(method));
75
- const hasGeneratedFiles = typeof restResource.dataFile === "string" &&
76
- restResource.dataFile.length > 0 &&
77
- typeof restResource.phpFile === "string" &&
78
- restResource.phpFile.length > 0;
79
- const hasRoutePattern = restResource.routePattern == null ||
80
- (typeof restResource.routePattern === "string" &&
81
- restResource.routePattern.startsWith("/") &&
82
- restResource.routePattern.length > 1 &&
83
- !/\s/u.test(restResource.routePattern) &&
84
- isGeneratedRestResourceRoutePatternCompatible(restResource.routePattern));
85
- return createDoctorCheck(`REST resource config ${restResource.slug}`, hasNamespace && hasMethods && hasGeneratedFiles && hasRoutePattern
86
- ? "pass"
87
- : "fail", hasNamespace && hasMethods && hasGeneratedFiles && hasRoutePattern
88
- ? `REST resource namespace ${restResource.namespace} with methods ${restResource.methods.join(", ")}`
89
- : "REST resource namespace, methods, dataFile, phpFile, or routePattern are invalid");
90
- }
91
- function checkWorkspaceRestResourceBootstrap(projectDir, packageName, phpPrefix) {
92
- const bootstrapPath = resolveWorkspaceBootstrapPath(projectDir, packageName);
93
- if (!fs.existsSync(bootstrapPath)) {
94
- return createDoctorCheck("REST resource bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
95
- }
96
- const source = fs.readFileSync(bootstrapPath, "utf8");
97
- const registerFunctionName = `${phpPrefix}_register_rest_resources`;
98
- const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
99
- const hasServerGlob = source.includes(WORKSPACE_REST_RESOURCE_GLOB);
100
- const hasRegisterHook = source.includes(registerHook);
101
- return createDoctorCheck("REST resource bootstrap", hasServerGlob && hasRegisterHook ? "pass" : "fail", hasServerGlob && hasRegisterHook
102
- ? "REST resource PHP loader hook is present"
103
- : "Missing REST resource PHP require glob or init hook");
104
- }
105
- function getWorkspacePostMetaRequiredFiles(postMeta) {
106
- return Array.from(new Set([
107
- postMeta.phpFile,
108
- postMeta.schemaFile,
109
- postMeta.typesFile,
110
- ]));
111
- }
112
- function checkWorkspacePostMetaConfig(postMeta) {
113
- let hasPostType = false;
114
- try {
115
- hasPostType = assertValidPostMetaPostType(postMeta.postType) === postMeta.postType;
116
- }
117
- catch {
118
- hasPostType = false;
119
- }
120
- const hasMetaKey = typeof postMeta.metaKey === "string" &&
121
- postMeta.metaKey.trim().length > 0 &&
122
- !/\s/u.test(postMeta.metaKey);
123
- const hasRestExposure = typeof postMeta.showInRest === "boolean";
124
- return createDoctorCheck(`Post meta config ${postMeta.slug}`, hasPostType && hasMetaKey && hasRestExposure ? "pass" : "fail", hasPostType && hasMetaKey && hasRestExposure
125
- ? `Post meta ${postMeta.metaKey} targets ${postMeta.postType}`
126
- : "Post meta postType, metaKey, or showInRest configuration is invalid");
127
- }
128
- function checkWorkspacePostMetaBootstrap(projectDir, packageName, phpPrefix) {
129
- const bootstrapPath = resolveWorkspaceBootstrapPath(projectDir, packageName);
130
- if (!fs.existsSync(bootstrapPath)) {
131
- return createDoctorCheck("Post meta bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
132
- }
133
- const source = fs.readFileSync(bootstrapPath, "utf8");
134
- const registerFunctionName = `${phpPrefix}_register_post_meta_contracts`;
135
- const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
136
- const hasServerGlob = source.includes(WORKSPACE_POST_META_GLOB);
137
- const hasRegisterHook = source.includes(registerHook);
138
- return createDoctorCheck("Post meta bootstrap", hasServerGlob && hasRegisterHook ? "pass" : "fail", hasServerGlob && hasRegisterHook
139
- ? "Post meta PHP loader hook is present"
140
- : "Missing post meta PHP require glob or init hook");
141
- }
142
- function checkWorkspacePostMetaPhp(projectDir, postMeta) {
143
- const phpPath = path.join(projectDir, postMeta.phpFile);
144
- if (!fs.existsSync(phpPath)) {
145
- return createDoctorCheck(`Post meta PHP ${postMeta.slug}`, "fail", `Missing ${postMeta.phpFile}`);
146
- }
147
- const source = fs.readFileSync(phpPath, "utf8");
148
- const hasRegisterPostMeta = source.includes("register_post_meta");
149
- const hasPostType = source.includes(postMeta.postType);
150
- const hasMetaKey = source.includes(postMeta.metaKey);
151
- const hasSchemaFile = source.includes(postMeta.schemaFile);
152
- const hasRestExposure = source.includes("'show_in_rest'");
153
- return createDoctorCheck(`Post meta PHP ${postMeta.slug}`, hasRegisterPostMeta && hasPostType && hasMetaKey && hasSchemaFile && hasRestExposure
154
- ? "pass"
155
- : "fail", hasRegisterPostMeta && hasPostType && hasMetaKey && hasSchemaFile && hasRestExposure
156
- ? "Post meta registration, schema path, and REST exposure flag are wired"
157
- : "Missing register_post_meta, post type, meta key, schema path, or show_in_rest wiring");
158
- }
159
- function getWorkspaceAbilityRequiredFiles(ability) {
160
- return Array.from(new Set([
161
- ability.clientFile,
162
- ability.configFile,
163
- ability.dataFile,
164
- ability.inputSchemaFile,
165
- ability.outputSchemaFile,
166
- ability.phpFile,
167
- ability.typesFile,
168
- ]));
169
- }
170
- function checkWorkspaceAbilityConfig(projectDir, ability) {
171
- const configPath = path.join(projectDir, ability.configFile);
172
- if (!fs.existsSync(configPath)) {
173
- return createDoctorCheck(`Ability config ${ability.slug}`, "fail", `Missing ${ability.configFile}`);
174
- }
175
- try {
176
- const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
177
- const abilityId = typeof config.abilityId === "string" ? config.abilityId.trim() : "";
178
- const categorySlug = typeof config.category?.slug === "string"
179
- ? config.category.slug.trim()
180
- : "";
181
- const hasValidAbilityId = /^[a-z0-9-]+\/[a-z0-9-]+$/u.test(abilityId);
182
- const hasValidCategorySlug = /^[a-z0-9-]+$/u.test(categorySlug);
183
- return createDoctorCheck(`Ability config ${ability.slug}`, hasValidAbilityId && hasValidCategorySlug ? "pass" : "fail", hasValidAbilityId && hasValidCategorySlug
184
- ? `Ability id ${abilityId} in category ${categorySlug} is valid`
185
- : "Ability config must define a valid abilityId (`namespace/ability-name`) and category.slug.");
186
- }
187
- catch (error) {
188
- return createDoctorCheck(`Ability config ${ability.slug}`, "fail", error instanceof Error ? error.message : String(error));
189
- }
190
- }
191
- function checkWorkspaceAbilityBootstrap(projectDir, packageName, phpPrefix) {
192
- const bootstrapPath = resolveWorkspaceBootstrapPath(projectDir, packageName);
193
- if (!fs.existsSync(bootstrapPath)) {
194
- return createDoctorCheck("Ability bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
195
- }
196
- const source = fs.readFileSync(bootstrapPath, "utf8");
197
- const loadFunctionName = `${phpPrefix}_load_workflow_abilities`;
198
- const enqueueFunctionName = `${phpPrefix}_enqueue_workflow_abilities`;
199
- const loadHook = `add_action( 'plugins_loaded', '${loadFunctionName}' );`;
200
- const adminEnqueueHook = `add_action( 'admin_enqueue_scripts', '${enqueueFunctionName}' );`;
201
- const editorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${enqueueFunctionName}' );`;
202
- const hasLoaderHook = source.includes(loadHook);
203
- const hasAdminEnqueueHook = source.includes(adminEnqueueHook);
204
- const hasEditorEnqueueHook = source.includes(editorEnqueueHook);
205
- const hasServerGlob = source.includes(WORKSPACE_ABILITY_GLOB);
206
- const hasEditorScript = source.includes(WORKSPACE_ABILITY_EDITOR_SCRIPT);
207
- const hasEditorAsset = source.includes(WORKSPACE_ABILITY_EDITOR_ASSET);
208
- const hasScriptModuleEnqueue = source.includes("wp_enqueue_script_module");
209
- return createDoctorCheck("Ability bootstrap", hasLoaderHook &&
210
- hasAdminEnqueueHook &&
211
- hasEditorEnqueueHook &&
212
- hasServerGlob &&
213
- hasEditorScript &&
214
- hasEditorAsset &&
215
- hasScriptModuleEnqueue
216
- ? "pass"
217
- : "fail", hasLoaderHook &&
218
- hasAdminEnqueueHook &&
219
- hasEditorEnqueueHook &&
220
- hasServerGlob &&
221
- hasEditorScript &&
222
- hasEditorAsset &&
223
- hasScriptModuleEnqueue
224
- ? "Ability loader and admin/editor script-module bootstrap hooks are present"
225
- : "Missing ability loader hook, script-module enqueue, or build/abilities asset references");
226
- }
227
- function checkWorkspaceAbilityIndex(projectDir, abilities) {
228
- const indexRelativePath = [
229
- path.join("src", "abilities", "index.ts"),
230
- path.join("src", "abilities", "index.js"),
231
- ].find((relativePath) => fs.existsSync(path.join(projectDir, relativePath)));
232
- if (!indexRelativePath) {
233
- return createDoctorCheck("Abilities index", "fail", "Missing src/abilities/index.ts or src/abilities/index.js");
234
- }
235
- const indexPath = path.join(projectDir, indexRelativePath);
236
- const source = fs.readFileSync(indexPath, "utf8");
237
- const missingExports = abilities.filter((ability) => {
238
- const exportPattern = new RegExp(`^\\s*export\\s+(?:\\*\\s+from|\\{[^}]+\\}\\s+from)\\s+['"\`]\\./${escapeRegex(ability.slug)}\\/client['"\`]`, "mu");
239
- return !exportPattern.test(source);
240
- });
241
- return createDoctorCheck("Abilities index", missingExports.length === 0 ? "pass" : "fail", missingExports.length === 0
242
- ? "Ability client helpers are aggregated"
243
- : `Missing ability exports for: ${missingExports.map((entry) => entry.slug).join(", ")}`);
244
- }
245
- function getWorkspaceAiFeatureRequiredFiles(aiFeature) {
246
- return Array.from(new Set([
247
- aiFeature.aiSchemaFile,
248
- aiFeature.apiFile,
249
- path.join(path.dirname(aiFeature.typesFile), "api-schemas", "feature-request.schema.json"),
250
- path.join(path.dirname(aiFeature.typesFile), "api-schemas", "feature-response.schema.json"),
251
- path.join(path.dirname(aiFeature.typesFile), "api-schemas", "feature-result.schema.json"),
252
- aiFeature.clientFile,
253
- aiFeature.dataFile,
254
- aiFeature.openApiFile,
255
- aiFeature.phpFile,
256
- aiFeature.typesFile,
257
- aiFeature.validatorsFile,
258
- ]));
259
- }
260
- function checkWorkspaceAiFeatureConfig(aiFeature) {
261
- const hasNamespace = REST_RESOURCE_NAMESPACE_PATTERN.test(aiFeature.namespace);
262
- return createDoctorCheck(`AI feature config ${aiFeature.slug}`, hasNamespace ? "pass" : "fail", hasNamespace
263
- ? `AI feature namespace ${aiFeature.namespace} is valid`
264
- : "AI feature namespace is invalid");
265
- }
266
- function checkWorkspaceAiFeatureBootstrap(projectDir, packageName, phpPrefix) {
267
- const bootstrapPath = resolveWorkspaceBootstrapPath(projectDir, packageName);
268
- if (!fs.existsSync(bootstrapPath)) {
269
- return createDoctorCheck("AI feature bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
270
- }
271
- const source = fs.readFileSync(bootstrapPath, "utf8");
272
- const registerFunctionName = `${phpPrefix}_register_ai_features`;
273
- const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
274
- const hasServerGlob = source.includes(WORKSPACE_AI_FEATURE_GLOB);
275
- const hasRegisterHook = source.includes(registerHook);
276
- return createDoctorCheck("AI feature bootstrap", hasServerGlob && hasRegisterHook ? "pass" : "fail", hasServerGlob && hasRegisterHook
277
- ? "AI feature PHP loader hook is present"
278
- : "Missing AI feature PHP require glob or init hook");
279
- }
280
- function getWorkspaceEditorPluginRequiredFiles(editorPlugin) {
281
- const editorPluginDir = path.join("src", "editor-plugins", editorPlugin.slug);
282
- const surfaceFile = editorPlugin.slot === "PluginSidebar"
283
- ? path.join(editorPluginDir, "Sidebar.tsx")
284
- : path.join(editorPluginDir, "Surface.tsx");
285
- return Array.from(new Set([
286
- editorPlugin.file,
287
- surfaceFile,
288
- path.join(editorPluginDir, "data.ts"),
289
- path.join(editorPluginDir, "types.ts"),
290
- path.join(editorPluginDir, "style.scss"),
291
- ]));
292
- }
293
- function checkWorkspaceEditorPluginConfig(editorPlugin) {
294
- const normalizedSlot = resolveEditorPluginSlotAlias(editorPlugin.slot);
295
- const isValidSlot = Boolean(normalizedSlot);
296
- return createDoctorCheck(`Editor plugin config ${editorPlugin.slug}`, isValidSlot ? "pass" : "fail", isValidSlot
297
- ? `Editor plugin slot ${editorPlugin.slot} is supported as ${normalizedSlot}`
298
- : `Unsupported editor plugin slot "${editorPlugin.slot}". Expected one of: ${EDITOR_PLUGIN_SLOT_IDS.join(", ")} or legacy aliases PluginSidebar, PluginDocumentSettingPanel.`);
299
- }
300
- function checkWorkspaceEditorPluginBootstrap(projectDir, packageName, phpPrefix) {
301
- const bootstrapPath = resolveWorkspaceBootstrapPath(projectDir, packageName);
302
- if (!fs.existsSync(bootstrapPath)) {
303
- return createDoctorCheck("Editor plugin bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
304
- }
305
- const source = fs.readFileSync(bootstrapPath, "utf8");
306
- const enqueueFunctionName = `${phpPrefix}_enqueue_editor_plugins_editor`;
307
- const enqueueHook = `add_action( 'enqueue_block_editor_assets', '${enqueueFunctionName}' );`;
308
- const hasEditorEnqueueHook = source.includes(enqueueHook);
309
- const hasEditorScript = source.includes(WORKSPACE_EDITOR_PLUGIN_EDITOR_SCRIPT);
310
- const hasEditorAsset = source.includes(WORKSPACE_EDITOR_PLUGIN_EDITOR_ASSET);
311
- const hasEditorStyle = source.includes(WORKSPACE_EDITOR_PLUGIN_EDITOR_STYLE);
312
- return createDoctorCheck("Editor plugin bootstrap", hasEditorEnqueueHook && hasEditorScript && hasEditorAsset && hasEditorStyle ? "pass" : "fail", hasEditorEnqueueHook && hasEditorScript && hasEditorAsset && hasEditorStyle
313
- ? "Editor plugin enqueue hook is present"
314
- : "Missing editor plugin enqueue hook or build/editor-plugins script/style asset references");
315
- }
316
- function checkWorkspaceEditorPluginIndex(projectDir, editorPlugins) {
317
- const indexRelativePath = [
318
- path.join("src", "editor-plugins", "index.ts"),
319
- path.join("src", "editor-plugins", "index.js"),
320
- ].find((relativePath) => fs.existsSync(path.join(projectDir, relativePath)));
321
- if (!indexRelativePath) {
322
- return createDoctorCheck("Editor plugins index", "fail", "Missing src/editor-plugins/index.ts or src/editor-plugins/index.js");
323
- }
324
- const indexPath = path.join(projectDir, indexRelativePath);
325
- const source = fs.readFileSync(indexPath, "utf8");
326
- const missingImports = editorPlugins.filter((editorPlugin) => {
327
- const importPattern = new RegExp(`['"\`]\\./${escapeRegex(editorPlugin.slug)}(?:/[^'"\`]*)?['"\`]`, "u");
328
- return !importPattern.test(source);
329
- });
330
- return createDoctorCheck("Editor plugins index", missingImports.length === 0 ? "pass" : "fail", missingImports.length === 0
331
- ? "Editor plugin registrations are aggregated"
332
- : `Missing editor plugin imports for: ${missingImports
333
- .map((entry) => entry.slug)
334
- .join(", ")}`);
335
- }
336
- function getWorkspaceAdminViewRequiredFiles(adminView) {
337
- const adminViewDir = path.join("src", "admin-views", adminView.slug);
338
- return Array.from(new Set([
339
- adminView.file,
340
- adminView.phpFile,
341
- path.join(adminViewDir, "Screen.tsx"),
342
- path.join(adminViewDir, "config.ts"),
343
- path.join(adminViewDir, "data.ts"),
344
- path.join(adminViewDir, "style.scss"),
345
- path.join(adminViewDir, "types.ts"),
346
- ]));
347
- }
348
- function checkWorkspaceAdminViewConfig(adminView, inventory) {
349
- if (adminView.source === undefined) {
350
- return createDoctorCheck(`Admin view config ${adminView.slug}`, "pass", "Admin view uses a replaceable local fetcher");
351
- }
352
- const source = adminView.source.trim();
353
- const restSourceMatch = /^rest-resource:([a-z][a-z0-9-]*)$/u.exec(source);
354
- const coreDataSourceMatch = /^core-data:(postType|taxonomy)\/([a-z0-9][a-z0-9_-]*)$/u.exec(source);
355
- const restResourceSlug = restSourceMatch?.[1];
356
- const restResource = restResourceSlug
357
- ? inventory.restResources.find((entry) => entry.slug === restResourceSlug)
358
- : undefined;
359
- const isListCapableRestResource = Boolean(restResource?.methods.includes("list"));
360
- const isManualSettingsRestResource = isAdminViewManualSettingsRestResource(restResource);
361
- const hasManualSettingsRouteParameters = isManualSettingsRestResource &&
362
- hasAdminViewManualSettingsRouteParameters(restResource);
363
- const isValid = isListCapableRestResource ||
364
- (isManualSettingsRestResource && !hasManualSettingsRouteParameters) ||
365
- Boolean(coreDataSourceMatch);
366
- const failDetail = hasManualSettingsRouteParameters
367
- ? `Admin view source ${source} uses route parameters or regex groups and cannot scaffold a singleton settings form`
368
- : "Admin view source must use rest-resource:<slug> with a list-capable REST resource, a manual settings contract with a body type, or core-data:<postType|taxonomy>/<name>";
369
- return createDoctorCheck(`Admin view config ${adminView.slug}`, isValid ? "pass" : "fail", isValid
370
- ? `Admin view source ${source} is ${isManualSettingsRestResource
371
- ? "settings-form capable"
372
- : coreDataSourceMatch
373
- ? "core-data capable"
374
- : "list-capable"}`
375
- : failDetail);
376
- }
377
- function checkWorkspaceAdminViewBootstrap(projectDir, packageName, phpPrefix) {
378
- const bootstrapPath = resolveWorkspaceBootstrapPath(projectDir, packageName);
379
- if (!fs.existsSync(bootstrapPath)) {
380
- return createDoctorCheck("Admin view bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
381
- }
382
- const source = fs.readFileSync(bootstrapPath, "utf8");
383
- const loadFunctionName = `${phpPrefix}_load_admin_views`;
384
- const loadHook = `add_action( 'plugins_loaded', '${loadFunctionName}' );`;
385
- const hasLoaderHook = source.includes(loadHook);
386
- const hasServerGlob = source.includes(WORKSPACE_ADMIN_VIEW_GLOB);
387
- return createDoctorCheck("Admin view bootstrap", hasLoaderHook && hasServerGlob ? "pass" : "fail", hasLoaderHook && hasServerGlob
388
- ? "Admin view PHP loader hook is present"
389
- : "Missing admin view PHP require glob or plugins_loaded hook");
390
- }
391
- function checkWorkspaceAdminViewIndex(projectDir, adminViews) {
392
- const indexRelativePath = [
393
- path.join("src", "admin-views", "index.ts"),
394
- path.join("src", "admin-views", "index.js"),
395
- ].find((relativePath) => fs.existsSync(path.join(projectDir, relativePath)));
396
- if (!indexRelativePath) {
397
- return createDoctorCheck("Admin views index", "fail", "Missing src/admin-views/index.ts or src/admin-views/index.js");
398
- }
399
- const indexPath = path.join(projectDir, indexRelativePath);
400
- const source = fs.readFileSync(indexPath, "utf8");
401
- const missingImports = adminViews.filter((adminView) => {
402
- const importPattern = new RegExp(`['"\`]\\./${escapeRegex(adminView.slug)}(?:/[^'"\`]*)?['"\`]`, "u");
403
- return !importPattern.test(source);
404
- });
405
- return createDoctorCheck("Admin views index", missingImports.length === 0 ? "pass" : "fail", missingImports.length === 0
406
- ? "Admin view registrations are aggregated"
407
- : `Missing admin view imports for: ${missingImports
408
- .map((entry) => entry.slug)
409
- .join(", ")}`);
410
- }
411
- function checkWorkspaceAdminViewPhp(projectDir, adminView) {
412
- const phpPath = path.join(projectDir, adminView.phpFile);
413
- if (!fs.existsSync(phpPath)) {
414
- return createDoctorCheck(`Admin view PHP ${adminView.slug}`, "fail", `Missing ${adminView.phpFile}`);
415
- }
416
- const source = fs.readFileSync(phpPath, "utf8");
417
- const hasAdminMenu = source.includes("add_submenu_page");
418
- const hasAdminEnqueue = source.includes("admin_enqueue_scripts");
419
- const hasScript = source.includes(WORKSPACE_ADMIN_VIEW_SCRIPT);
420
- const hasAsset = source.includes(WORKSPACE_ADMIN_VIEW_ASSET);
421
- const hasStyle = source.includes(WORKSPACE_ADMIN_VIEW_STYLE);
422
- const hasComponentsStyleDependency = source.includes("'wp-components'");
423
- return createDoctorCheck(`Admin view PHP ${adminView.slug}`, hasAdminMenu &&
424
- hasAdminEnqueue &&
425
- hasScript &&
426
- hasAsset &&
427
- hasStyle &&
428
- hasComponentsStyleDependency
429
- ? "pass"
430
- : "fail", hasAdminMenu &&
431
- hasAdminEnqueue &&
432
- hasScript &&
433
- hasAsset &&
434
- hasStyle &&
435
- hasComponentsStyleDependency
436
- ? "Admin menu, script, style, and wp-components style dependency are wired"
437
- : "Missing admin menu, enqueue hook, build/admin-views asset reference, or wp-components style dependency");
438
- }
1
+ import { getWorkspaceAbilityDoctorChecks, } from "./cli-doctor-workspace-features-abilities.js";
2
+ import { getWorkspaceAdminViewDoctorChecks, } from "./cli-doctor-workspace-features-admin-views.js";
3
+ import { getWorkspaceAiFeatureDoctorChecks, } from "./cli-doctor-workspace-features-ai.js";
4
+ import { getWorkspaceEditorPluginDoctorChecks, } from "./cli-doctor-workspace-features-editor-plugins.js";
5
+ import { getWorkspacePostMetaDoctorChecks, } from "./cli-doctor-workspace-features-post-meta.js";
6
+ import { getWorkspaceRestResourceDoctorChecks, } from "./cli-doctor-workspace-features-rest.js";
439
7
  /**
440
8
  * Collect workspace doctor checks for REST resources, abilities, AI features, editor plugins, and admin views.
441
9
  *
@@ -444,53 +12,12 @@ function checkWorkspaceAdminViewPhp(projectDir, adminView) {
444
12
  * @returns Ordered `DoctorCheck[]` rows for extracted workspace feature diagnostics.
445
13
  */
446
14
  export function getWorkspaceFeatureDoctorChecks(workspace, inventory) {
447
- const checks = [];
448
- if (inventory.restResources.some((restResource) => !isManualRestResource(restResource))) {
449
- checks.push(checkWorkspaceRestResourceBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
450
- }
451
- for (const restResource of inventory.restResources) {
452
- checks.push(checkWorkspaceRestResourceConfig(restResource));
453
- checks.push(checkExistingFiles(workspace.projectDir, `REST resource ${restResource.slug}`, getWorkspaceRestResourceRequiredFiles(restResource)));
454
- }
455
- if (inventory.postMeta.length > 0) {
456
- checks.push(checkWorkspacePostMetaBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
457
- }
458
- for (const postMeta of inventory.postMeta) {
459
- checks.push(checkWorkspacePostMetaConfig(postMeta));
460
- checks.push(checkExistingFiles(workspace.projectDir, `Post meta ${postMeta.slug}`, getWorkspacePostMetaRequiredFiles(postMeta)));
461
- checks.push(checkWorkspacePostMetaPhp(workspace.projectDir, postMeta));
462
- }
463
- if (inventory.abilities.length > 0) {
464
- checks.push(checkWorkspaceAbilityBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
465
- checks.push(checkWorkspaceAbilityIndex(workspace.projectDir, inventory.abilities));
466
- }
467
- for (const ability of inventory.abilities) {
468
- checks.push(checkWorkspaceAbilityConfig(workspace.projectDir, ability));
469
- checks.push(checkExistingFiles(workspace.projectDir, `Ability ${ability.slug}`, getWorkspaceAbilityRequiredFiles(ability)));
470
- }
471
- if (inventory.aiFeatures.length > 0) {
472
- checks.push(checkWorkspaceAiFeatureBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
473
- }
474
- for (const aiFeature of inventory.aiFeatures) {
475
- checks.push(checkWorkspaceAiFeatureConfig(aiFeature));
476
- checks.push(checkExistingFiles(workspace.projectDir, `AI feature ${aiFeature.slug}`, getWorkspaceAiFeatureRequiredFiles(aiFeature)));
477
- }
478
- if (inventory.editorPlugins.length > 0) {
479
- checks.push(checkWorkspaceEditorPluginBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
480
- checks.push(checkWorkspaceEditorPluginIndex(workspace.projectDir, inventory.editorPlugins));
481
- }
482
- for (const editorPlugin of inventory.editorPlugins) {
483
- checks.push(checkExistingFiles(workspace.projectDir, `Editor plugin ${editorPlugin.slug}`, getWorkspaceEditorPluginRequiredFiles(editorPlugin)));
484
- checks.push(checkWorkspaceEditorPluginConfig(editorPlugin));
485
- }
486
- if (inventory.adminViews.length > 0) {
487
- checks.push(checkWorkspaceAdminViewBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
488
- checks.push(checkWorkspaceAdminViewIndex(workspace.projectDir, inventory.adminViews));
489
- }
490
- for (const adminView of inventory.adminViews) {
491
- checks.push(checkWorkspaceAdminViewConfig(adminView, inventory));
492
- checks.push(checkExistingFiles(workspace.projectDir, `Admin view ${adminView.slug}`, getWorkspaceAdminViewRequiredFiles(adminView)));
493
- checks.push(checkWorkspaceAdminViewPhp(workspace.projectDir, adminView));
494
- }
495
- return checks;
15
+ return [
16
+ ...getWorkspaceRestResourceDoctorChecks(workspace, inventory.restResources),
17
+ ...getWorkspacePostMetaDoctorChecks(workspace, inventory.postMeta),
18
+ ...getWorkspaceAbilityDoctorChecks(workspace, inventory.abilities),
19
+ ...getWorkspaceAiFeatureDoctorChecks(workspace, inventory.aiFeatures),
20
+ ...getWorkspaceEditorPluginDoctorChecks(workspace, inventory.editorPlugins),
21
+ ...getWorkspaceAdminViewDoctorChecks(workspace, inventory),
22
+ ];
496
23
  }
@@ -1,3 +1,7 @@
1
+ /** Scope bucket used by doctor exit policies and JSON summaries. */
2
+ export type DoctorCheckScope = "environment" | "workspace";
3
+ /** Policy used to decide which failed checks should fail the process. */
4
+ export type DoctorExitPolicy = "strict" | "workspace-only";
1
5
  /**
2
6
  * One doctor check rendered by the CLI diagnostics flow.
3
7
  */
@@ -8,13 +12,39 @@ export interface DoctorCheck {
8
12
  detail: string;
9
13
  /** Short label for the dependency, directory, or template check. */
10
14
  label: string;
15
+ /** Scope bucket used by machine-readable summaries and exit-code policies. */
16
+ scope?: DoctorCheckScope;
11
17
  /** Final pass/fail/warn status for this diagnostic row. */
12
18
  status: "pass" | "fail" | "warn";
13
19
  }
20
+ /** One failed row classified against the active doctor exit policy. */
21
+ export interface DoctorFailureSummary {
22
+ code?: string;
23
+ label: string;
24
+ scope: DoctorCheckScope | "unknown";
25
+ severity: "advisory" | "error";
26
+ }
27
+ /** Stable JSON summary for `wp-typia doctor --format json`. */
28
+ export interface DoctorRunSummary {
29
+ advisoryFailureCount: number;
30
+ advisoryFailures: DoctorFailureSummary[];
31
+ exitCode: 0 | 1;
32
+ exitFailureCount: number;
33
+ exitFailures: DoctorFailureSummary[];
34
+ exitPolicy: DoctorExitPolicy;
35
+ failed: number;
36
+ passed: number;
37
+ total: number;
38
+ warnings: number;
39
+ }
14
40
  interface RunDoctorOptions {
41
+ exitPolicy?: DoctorExitPolicy;
15
42
  renderLine?: (check: DoctorCheck) => void;
16
43
  renderSummaryLine?: (summaryLine: string) => void;
17
44
  }
45
+ interface DoctorSummaryOptions {
46
+ exitPolicy?: DoctorExitPolicy;
47
+ }
18
48
  /**
19
49
  * Collect all runtime doctor checks for the current environment.
20
50
  *
@@ -28,12 +58,33 @@ interface RunDoctorOptions {
28
58
  */
29
59
  export declare function getDoctorChecks(cwd: string): Promise<DoctorCheck[]>;
30
60
  /**
31
- * Run doctor checks, render each line, and fail when any check does not pass.
61
+ * Return failed rows that contribute to the process exit code for one policy.
62
+ */
63
+ export declare function getDoctorExitFailureChecks(checks: readonly DoctorCheck[], options?: DoctorSummaryOptions): DoctorCheck[];
64
+ /**
65
+ * Format only exit-contributing doctor failures for structured diagnostics.
66
+ */
67
+ export declare function getDoctorExitFailureDetailLines(checks: readonly DoctorCheck[], options?: DoctorSummaryOptions): string[];
68
+ /**
69
+ * Build the stable JSON summary for one doctor run.
70
+ */
71
+ export declare function createDoctorRunSummary(checks: readonly DoctorCheck[], options?: DoctorSummaryOptions): DoctorRunSummary;
72
+ /**
73
+ * Run doctor checks, render each line, and fail when one or more failed checks
74
+ * contribute to the exit code under the active exit policy.
75
+ *
76
+ * The default `strict` policy treats every failed row as exit-contributing.
77
+ * The `workspace-only` policy only fails on workspace-scoped rows so
78
+ * environment/runtime failures remain advisory for CI gates that only care
79
+ * about generated workspace artifacts.
32
80
  *
33
81
  * @param cwd Working directory to validate.
34
- * @param options Optional renderer override for each emitted check row.
82
+ * @param options Optional renderer overrides and exit-policy selection.
83
+ * @param options.exitPolicy Policy deciding which failed checks contribute to the process exit code.
84
+ * @param options.renderLine Optional renderer for each check row. Defaults to the stdout line printer.
85
+ * @param options.renderSummaryLine Optional renderer for the summary row. Defaults to the stdout line printer unless a custom `renderLine` suppresses implicit summary output.
35
86
  * @returns The completed list of doctor checks.
36
- * @throws {Error} When one or more checks fail.
87
+ * @throws {Error} When one or more failed checks contribute to the exit code under the active policy.
37
88
  */
38
89
  export declare function runDoctor(cwd: string, options?: RunDoctorOptions): Promise<DoctorCheck[]>;
39
90
  export {};