@wp-typia/project-tools 0.22.10 → 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 (155) 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-collision.d.ts +25 -0
  5. package/dist/runtime/cli-add-collision.js +76 -0
  6. package/dist/runtime/cli-add-help.js +12 -2
  7. package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
  8. package/dist/runtime/cli-add-kind-ids.js +3 -0
  9. package/dist/runtime/cli-add-types.d.ts +129 -0
  10. package/dist/runtime/cli-add-types.js +26 -0
  11. package/dist/runtime/cli-add-validation.d.ts +97 -1
  12. package/dist/runtime/cli-add-validation.js +313 -1
  13. package/dist/runtime/cli-add-workspace-ability-scaffold.js +4 -1
  14. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +79 -20
  15. package/dist/runtime/cli-add-workspace-admin-view-source.js +11 -2
  16. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.d.ts +34 -0
  17. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.js +483 -0
  18. package/dist/runtime/cli-add-workspace-admin-view-templates-default.d.ts +30 -0
  19. package/dist/runtime/cli-add-workspace-admin-view-templates-default.js +310 -0
  20. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.d.ts +25 -0
  21. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.js +124 -0
  22. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.d.ts +34 -0
  23. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.js +370 -0
  24. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.d.ts +49 -0
  25. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.js +259 -0
  26. package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +19 -10
  27. package/dist/runtime/cli-add-workspace-admin-view-templates.js +31 -971
  28. package/dist/runtime/cli-add-workspace-admin-view-types.d.ts +21 -0
  29. package/dist/runtime/cli-add-workspace-admin-view-types.js +22 -0
  30. package/dist/runtime/cli-add-workspace-ai-anchors.js +125 -32
  31. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +17 -1
  32. package/dist/runtime/cli-add-workspace-contract-source-emitters.d.ts +15 -0
  33. package/dist/runtime/cli-add-workspace-contract-source-emitters.js +42 -0
  34. package/dist/runtime/cli-add-workspace-contract.d.ts +15 -0
  35. package/dist/runtime/cli-add-workspace-contract.js +65 -0
  36. package/dist/runtime/cli-add-workspace-integration-env.d.ts +26 -0
  37. package/dist/runtime/cli-add-workspace-integration-env.js +428 -0
  38. package/dist/runtime/cli-add-workspace-post-meta-anchors.d.ts +23 -0
  39. package/dist/runtime/cli-add-workspace-post-meta-anchors.js +244 -0
  40. package/dist/runtime/cli-add-workspace-post-meta-source-emitters.d.ts +63 -0
  41. package/dist/runtime/cli-add-workspace-post-meta-source-emitters.js +179 -0
  42. package/dist/runtime/cli-add-workspace-post-meta.d.ts +15 -0
  43. package/dist/runtime/cli-add-workspace-post-meta.js +107 -0
  44. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +9 -0
  45. package/dist/runtime/cli-add-workspace-rest-anchors.js +326 -21
  46. package/dist/runtime/cli-add-workspace-rest-generated.d.ts +9 -0
  47. package/dist/runtime/cli-add-workspace-rest-generated.js +158 -0
  48. package/dist/runtime/cli-add-workspace-rest-manual.d.ts +8 -0
  49. package/dist/runtime/cli-add-workspace-rest-manual.js +279 -0
  50. package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +24 -0
  51. package/dist/runtime/cli-add-workspace-rest-php-templates.js +678 -0
  52. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +98 -2
  53. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +323 -29
  54. package/dist/runtime/cli-add-workspace-rest-types.d.ts +108 -0
  55. package/dist/runtime/cli-add-workspace-rest-types.js +1 -0
  56. package/dist/runtime/cli-add-workspace-rest.d.ts +3 -7
  57. package/dist/runtime/cli-add-workspace-rest.js +34 -481
  58. package/dist/runtime/cli-add-workspace.d.ts +15 -0
  59. package/dist/runtime/cli-add-workspace.js +15 -0
  60. package/dist/runtime/cli-add.d.ts +1 -1
  61. package/dist/runtime/cli-add.js +1 -1
  62. package/dist/runtime/cli-core.d.ts +3 -2
  63. package/dist/runtime/cli-core.js +3 -2
  64. package/dist/runtime/cli-diagnostics.d.ts +3 -1
  65. package/dist/runtime/cli-diagnostics.js +17 -5
  66. package/dist/runtime/cli-doctor-environment.js +1 -3
  67. package/dist/runtime/cli-doctor-workspace-bindings.js +4 -1
  68. package/dist/runtime/cli-doctor-workspace-block-addons.d.ts +12 -0
  69. package/dist/runtime/cli-doctor-workspace-block-addons.js +134 -0
  70. package/dist/runtime/cli-doctor-workspace-block-iframe.d.ts +9 -0
  71. package/dist/runtime/cli-doctor-workspace-block-iframe.js +228 -0
  72. package/dist/runtime/cli-doctor-workspace-block-metadata.d.ts +11 -0
  73. package/dist/runtime/cli-doctor-workspace-block-metadata.js +111 -0
  74. package/dist/runtime/cli-doctor-workspace-blocks.js +6 -424
  75. package/dist/runtime/cli-doctor-workspace-features-abilities.d.ts +11 -0
  76. package/dist/runtime/cli-doctor-workspace-features-abilities.js +112 -0
  77. package/dist/runtime/cli-doctor-workspace-features-admin-views.d.ts +11 -0
  78. package/dist/runtime/cli-doctor-workspace-features-admin-views.js +128 -0
  79. package/dist/runtime/cli-doctor-workspace-features-ai.d.ts +11 -0
  80. package/dist/runtime/cli-doctor-workspace-features-ai.js +57 -0
  81. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.d.ts +11 -0
  82. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.js +80 -0
  83. package/dist/runtime/cli-doctor-workspace-features-post-meta.d.ts +11 -0
  84. package/dist/runtime/cli-doctor-workspace-features-post-meta.js +77 -0
  85. package/dist/runtime/cli-doctor-workspace-features-rest.d.ts +11 -0
  86. package/dist/runtime/cli-doctor-workspace-features-rest.js +120 -0
  87. package/dist/runtime/cli-doctor-workspace-features.js +14 -369
  88. package/dist/runtime/cli-doctor-workspace-package.d.ts +25 -3
  89. package/dist/runtime/cli-doctor-workspace-package.js +35 -13
  90. package/dist/runtime/cli-doctor-workspace-shared.d.ts +2 -0
  91. package/dist/runtime/cli-doctor-workspace-shared.js +2 -0
  92. package/dist/runtime/cli-doctor-workspace.js +8 -3
  93. package/dist/runtime/cli-doctor.d.ts +52 -3
  94. package/dist/runtime/cli-doctor.js +79 -8
  95. package/dist/runtime/cli-help.js +10 -0
  96. package/dist/runtime/cli-init-package-json.js +4 -2
  97. package/dist/runtime/cli-init-templates.js +11 -1
  98. package/dist/runtime/cli-prompt.d.ts +16 -2
  99. package/dist/runtime/cli-prompt.js +29 -12
  100. package/dist/runtime/cli-scaffold.d.ts +2 -1
  101. package/dist/runtime/cli-scaffold.js +19 -10
  102. package/dist/runtime/contract-artifacts.d.ts +14 -0
  103. package/dist/runtime/contract-artifacts.js +15 -0
  104. package/dist/runtime/external-template-guards.js +4 -6
  105. package/dist/runtime/index.d.ts +2 -2
  106. package/dist/runtime/index.js +1 -1
  107. package/dist/runtime/json-utils.d.ts +62 -4
  108. package/dist/runtime/json-utils.js +78 -4
  109. package/dist/runtime/local-dev-presets.js +4 -1
  110. package/dist/runtime/migration-ui-capability.js +4 -1
  111. package/dist/runtime/migration-utils.js +4 -1
  112. package/dist/runtime/package-managers.js +6 -1
  113. package/dist/runtime/package-versions.js +6 -1
  114. package/dist/runtime/rest-resource-artifacts.d.ts +57 -1
  115. package/dist/runtime/rest-resource-artifacts.js +97 -1
  116. package/dist/runtime/scaffold-bootstrap.js +7 -2
  117. package/dist/runtime/scaffold-package-manager-files.js +5 -1
  118. package/dist/runtime/scaffold-repository-reference.js +4 -2
  119. package/dist/runtime/scaffold-template-variables.js +2 -1
  120. package/dist/runtime/scaffold.d.ts +18 -1
  121. package/dist/runtime/scaffold.js +55 -2
  122. package/dist/runtime/temp-roots.js +4 -1
  123. package/dist/runtime/template-layers.js +4 -1
  124. package/dist/runtime/template-registry.js +9 -3
  125. package/dist/runtime/template-render.d.ts +1 -1
  126. package/dist/runtime/template-render.js +1 -1
  127. package/dist/runtime/template-source-cache-markers.d.ts +37 -0
  128. package/dist/runtime/template-source-cache-markers.js +125 -0
  129. package/dist/runtime/template-source-cache.d.ts +1 -4
  130. package/dist/runtime/template-source-cache.js +16 -122
  131. package/dist/runtime/template-source-contracts.d.ts +2 -0
  132. package/dist/runtime/template-source-external.d.ts +4 -2
  133. package/dist/runtime/template-source-external.js +4 -2
  134. package/dist/runtime/template-source-normalization.js +2 -1
  135. package/dist/runtime/template-source-remote.d.ts +8 -4
  136. package/dist/runtime/template-source-remote.js +26 -9
  137. package/dist/runtime/template-source-seeds.js +10 -3
  138. package/dist/runtime/workspace-inventory-mutations.js +54 -4
  139. package/dist/runtime/workspace-inventory-parser-entries.d.ts +17 -0
  140. package/dist/runtime/workspace-inventory-parser-entries.js +157 -0
  141. package/dist/runtime/workspace-inventory-parser-validation.d.ts +104 -0
  142. package/dist/runtime/workspace-inventory-parser-validation.js +34 -0
  143. package/dist/runtime/workspace-inventory-parser.d.ts +3 -44
  144. package/dist/runtime/workspace-inventory-parser.js +7 -464
  145. package/dist/runtime/workspace-inventory-read.d.ts +9 -2
  146. package/dist/runtime/workspace-inventory-read.js +9 -2
  147. package/dist/runtime/workspace-inventory-section-descriptors.d.ts +19 -0
  148. package/dist/runtime/workspace-inventory-section-descriptors.js +435 -0
  149. package/dist/runtime/workspace-inventory-templates.d.ts +16 -1
  150. package/dist/runtime/workspace-inventory-templates.js +75 -4
  151. package/dist/runtime/workspace-inventory-types.d.ts +52 -2
  152. package/dist/runtime/workspace-inventory.d.ts +2 -2
  153. package/dist/runtime/workspace-inventory.js +1 -1
  154. package/dist/runtime/workspace-project.js +4 -6
  155. package/package.json +2 -2
@@ -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,31 @@ 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.
35
84
  * @returns The completed list of doctor checks.
36
- * @throws {Error} When one or more checks fail.
85
+ * @throws {Error} When one or more failed checks contribute to the exit code under the active policy.
37
86
  */
38
87
  export declare function runDoctor(cwd: string, options?: RunDoctorOptions): Promise<DoctorCheck[]>;
39
88
  export {};
@@ -1,6 +1,33 @@
1
- import { CLI_DIAGNOSTIC_CODES, createCliCommandError, formatDoctorCheckLine, formatDoctorSummaryLine, getDoctorFailureDetailLines, } from "./cli-diagnostics.js";
1
+ import { CLI_DIAGNOSTIC_CODES, createCliCommandError, formatDoctorCheckLine, formatDoctorSummaryLine, } from "./cli-diagnostics.js";
2
2
  import { getEnvironmentDoctorChecks } from "./cli-doctor-environment.js";
3
3
  import { getWorkspaceDoctorChecks } from "./cli-doctor-workspace.js";
4
+ const DEFAULT_DOCTOR_EXIT_POLICY = "strict";
5
+ function annotateDoctorChecks(checks, scope) {
6
+ return checks.map((check) => ({
7
+ ...check,
8
+ scope: check.scope ?? scope,
9
+ }));
10
+ }
11
+ function resolveDoctorExitPolicy(options) {
12
+ return options.exitPolicy ?? DEFAULT_DOCTOR_EXIT_POLICY;
13
+ }
14
+ function doesCheckContributeToExit(check, exitPolicy) {
15
+ if (check.status !== "fail") {
16
+ return false;
17
+ }
18
+ if (exitPolicy === "strict") {
19
+ return true;
20
+ }
21
+ return check.scope === "workspace";
22
+ }
23
+ function toFailureSummary(check, severity) {
24
+ return {
25
+ ...(check.code ? { code: check.code } : {}),
26
+ label: check.label,
27
+ scope: check.scope ?? "unknown",
28
+ severity,
29
+ };
30
+ }
4
31
  /**
5
32
  * Collect all runtime doctor checks for the current environment.
6
33
  *
@@ -14,19 +41,62 @@ import { getWorkspaceDoctorChecks } from "./cli-doctor-workspace.js";
14
41
  */
15
42
  export async function getDoctorChecks(cwd) {
16
43
  return [
17
- ...(await getEnvironmentDoctorChecks(cwd)),
18
- ...(await getWorkspaceDoctorChecks(cwd)),
44
+ ...annotateDoctorChecks(await getEnvironmentDoctorChecks(cwd), "environment"),
45
+ ...annotateDoctorChecks(await getWorkspaceDoctorChecks(cwd), "workspace"),
19
46
  ];
20
47
  }
21
48
  /**
22
- * Run doctor checks, render each line, and fail when any check does not pass.
49
+ * Return failed rows that contribute to the process exit code for one policy.
50
+ */
51
+ export function getDoctorExitFailureChecks(checks, options = {}) {
52
+ const exitPolicy = resolveDoctorExitPolicy(options);
53
+ return checks.filter((check) => doesCheckContributeToExit(check, exitPolicy));
54
+ }
55
+ /**
56
+ * Format only exit-contributing doctor failures for structured diagnostics.
57
+ */
58
+ export function getDoctorExitFailureDetailLines(checks, options = {}) {
59
+ return getDoctorExitFailureChecks(checks, options).map((check) => `${check.label}: ${check.detail}`);
60
+ }
61
+ /**
62
+ * Build the stable JSON summary for one doctor run.
63
+ */
64
+ export function createDoctorRunSummary(checks, options = {}) {
65
+ const exitPolicy = resolveDoctorExitPolicy(options);
66
+ const failedChecks = checks.filter((check) => check.status === "fail");
67
+ const exitFailureChecks = failedChecks.filter((check) => doesCheckContributeToExit(check, exitPolicy));
68
+ const advisoryFailureChecks = failedChecks.filter((check) => !doesCheckContributeToExit(check, exitPolicy));
69
+ const warnings = checks.filter((check) => check.status === "warn").length;
70
+ return {
71
+ advisoryFailureCount: advisoryFailureChecks.length,
72
+ advisoryFailures: advisoryFailureChecks.map((check) => toFailureSummary(check, "advisory")),
73
+ exitCode: exitFailureChecks.length > 0 ? 1 : 0,
74
+ exitFailureCount: exitFailureChecks.length,
75
+ exitFailures: exitFailureChecks.map((check) => toFailureSummary(check, "error")),
76
+ exitPolicy,
77
+ failed: failedChecks.length,
78
+ passed: checks.length - failedChecks.length - warnings,
79
+ total: checks.length,
80
+ warnings,
81
+ };
82
+ }
83
+ /**
84
+ * Run doctor checks, render each line, and fail when one or more failed checks
85
+ * contribute to the exit code under the active exit policy.
86
+ *
87
+ * The default `strict` policy treats every failed row as exit-contributing.
88
+ * The `workspace-only` policy only fails on workspace-scoped rows so
89
+ * environment/runtime failures remain advisory for CI gates that only care
90
+ * about generated workspace artifacts.
23
91
  *
24
92
  * @param cwd Working directory to validate.
25
- * @param options Optional renderer override for each emitted check row.
93
+ * @param options Optional renderer overrides and exit-policy selection.
94
+ * @param options.exitPolicy Policy deciding which failed checks contribute to the process exit code.
26
95
  * @returns The completed list of doctor checks.
27
- * @throws {Error} When one or more checks fail.
96
+ * @throws {Error} When one or more failed checks contribute to the exit code under the active policy.
28
97
  */
29
98
  export async function runDoctor(cwd, options = {}) {
99
+ const exitPolicy = resolveDoctorExitPolicy(options);
30
100
  const renderLine = options.renderLine ?? ((check) => console.log(formatDoctorCheckLine(check)));
31
101
  const renderSummaryLine = options.renderSummaryLine ??
32
102
  (options.renderLine ? () => undefined : (summaryLine) => console.log(summaryLine));
@@ -34,8 +104,9 @@ export async function runDoctor(cwd, options = {}) {
34
104
  for (const check of checks) {
35
105
  renderLine(check);
36
106
  }
37
- renderSummaryLine(formatDoctorSummaryLine(checks));
38
- const failureDetailLines = getDoctorFailureDetailLines(checks);
107
+ const exitFailureChecks = getDoctorExitFailureChecks(checks, { exitPolicy });
108
+ renderSummaryLine(formatDoctorSummaryLine(checks, { exitFailureChecks }));
109
+ const failureDetailLines = getDoctorExitFailureDetailLines(checks, { exitPolicy });
39
110
  if (failureDetailLines.length > 0) {
40
111
  throw createCliCommandError({
41
112
  code: CLI_DIAGNOSTIC_CODES.DOCTOR_CHECK_FAILED,
@@ -11,6 +11,7 @@ import { TEMPLATE_IDS } from "./template-registry.js";
11
11
  export function formatHelpText() {
12
12
  return `Usage:
13
13
  wp-typia create <project-dir> [--template <basic|interactivity>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
14
+ wp-typia create <project-dir> [--template workspace] [--profile <plugin-qa>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
14
15
  wp-typia create <project-dir> [--template query-loop] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--query-post-type <post-type>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
15
16
  wp-typia create <project-dir> [--template <./path|github:owner/repo/path[#ref]>] [--variant <name>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
16
17
  wp-typia create <project-dir> [--template <npm-package>] [--variant <name>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
@@ -20,12 +21,15 @@ export function formatHelpText() {
20
21
  wp-typia init [project-dir] [--apply] [--package-manager <id>]
21
22
  wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>]
22
23
  wp-typia add block <name> [--template <basic|interactivity|persistence|compound>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--inner-blocks-preset <freeform|ordered|horizontal|locked-structure>] [--alternate-render-targets <email,mjml,plain-text>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>]
24
+ wp-typia add integration-env <name> [--wp-env] [--release-zip] [--service <none|docker-compose>]
23
25
  wp-typia add variation <name> --block <block-slug>
24
26
  wp-typia add style <name> --block <block-slug>
25
27
  wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>
26
28
  wp-typia add pattern <name>
27
29
  wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>]
28
30
  wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <method[,method...]>]
31
+ wp-typia add rest-resource <name> --manual [--namespace <vendor/v1>] [--method <GET|POST|PUT|PATCH|DELETE>] [--auth <public|authenticated|public-write-protected>] [--path <route-pattern>|--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--query-type <Type>] [--body-type <Type>] [--response-type <Type>] [--secret-field <field>] [--secret-state-field|--secret-has-value-field <field>] [--secret-preserve-on-empty <true|false>]
32
+ wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>] [--hide-from-rest]
29
33
  wp-typia add ability <name>
30
34
  wp-typia add ai-feature <name> [--namespace <vendor/v1>]
31
35
  wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>]
@@ -48,11 +52,15 @@ Notes:
48
52
  \`wp-typia <project-dir>\` remains a backward-compatible alias to \`create\` when \`<project-dir>\` is the only positional argument.
49
53
  \`wp-typia init\` previews the minimum retrofit sync surface by default; rerun with \`--apply\` to write package.json updates and generated helper scripts.
50
54
  Use \`--template workspace\` as shorthand for \`@wp-typia/create-workspace-template\`, the official empty workspace scaffold behind \`wp-typia add ...\`.
55
+ Use \`--profile plugin-qa\` with \`--template workspace\` when a plugin needs local wp-env smoke checks, \`.env.example\`, and release zip scripts from day one; omit it for the minimal workspace shell.
51
56
  Interactive add flows let you choose a template when \`--template\` is omitted; non-interactive runs default to \`basic\`.
52
57
  \`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views/\`.
53
58
  Pass \`--source rest-resource:<slug>\` to reuse a list-capable REST resource.
54
59
  Pass \`--source core-data:postType/post\` or \`--source core-data:taxonomy/category\` to bind a WordPress-owned entity collection.
55
60
  Generated admin-view workspaces add \`@wp-typia/dataviews\` and the needed WordPress DataViews packages as opt-in dependencies.
61
+ \`add integration-env\` generates an opt-in local smoke starter under \`scripts/integration-smoke/\`, updates \`.env.example\`, and can add \`@wordpress/env\` plus \`.wp-env.json\` when \`--wp-env\` is passed.
62
+ Pass \`--release-zip\` to add \`release:zip\`, \`release:zip:check\`, and \`qa:check\` scripts for plugin QA packaging.
63
+ Pass \`--service docker-compose\` to include a placeholder local service stack that can be adapted to project-specific dependencies.
56
64
  \`query-loop\` is create-only. Use \`wp-typia create <project-dir> --template query-loop\`; \`wp-typia add block\` accepts only basic, interactivity, persistence, and compound families.
57
65
  \`add variation\` uses an existing workspace block from \`scripts/block-config.ts\`.
58
66
  \`add style\` registers a Block Styles option for an existing generated block.
@@ -60,6 +68,8 @@ Notes:
60
68
  \`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/\`.
61
69
  \`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`; pass \`--block\` and \`--attribute\` together to declare a bindable generated-block attribute.
62
70
  \`add rest-resource\` scaffolds plugin-level TypeScript REST contracts under \`src/rest/\` and PHP route glue under \`inc/rest/\`.
71
+ \`add rest-resource --manual\` tracks an external/provider REST route with typed schemas, OpenAPI, clients, and drift checks without generating PHP route/controller files while still allowing route-owner metadata such as permission callbacks and controller classes. Settings contracts can add \`--secret-field\` plus \`--secret-preserve-on-empty\` to model write-only credentials and preserve blank submissions.
72
+ \`add post-meta\` scaffolds typed post meta contracts under \`src/post-meta/\`, emits schema artifacts, and wires generated \`register_post_meta()\` helpers under \`inc/post-meta/\`.
63
73
  \`add ability\` scaffolds typed workflow abilities under \`src/abilities/\` and server registration under \`inc/abilities/\`.
64
74
  \`add ai-feature\` scaffolds server-owned AI feature endpoints under \`src/ai-features/\` and PHP route glue under \`inc/ai-features/\`.
65
75
  \`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\`.
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { CLI_DIAGNOSTIC_CODES, createCliDiagnosticCodeError, } from "./cli-diagnostics.js";
4
4
  import { getPackageManager, transformPackageManagerText, } from "./package-managers.js";
5
5
  import { getPackageVersions } from "./package-versions.js";
6
+ import { readJsonFileSync } from "./json-utils.js";
6
7
  import { parseWorkspacePackageManagerId } from "./workspace-project.js";
7
8
  const BASE_RETROFIT_SCRIPTS = {
8
9
  sync: "tsx scripts/sync-project.ts",
@@ -22,9 +23,10 @@ export function readProjectPackageJson(projectDir) {
22
23
  if (!fs.existsSync(packageJsonPath)) {
23
24
  return null;
24
25
  }
25
- const source = fs.readFileSync(packageJsonPath, "utf8");
26
26
  try {
27
- return JSON.parse(source);
27
+ return readJsonFileSync(packageJsonPath, {
28
+ context: "project package manifest",
29
+ });
28
30
  }
29
31
  catch (error) {
30
32
  const message = error instanceof Error ? error.message : String(error);
@@ -182,6 +182,16 @@ function getSyncScriptEnv() {
182
182
  \treturn env;
183
183
  }
184
184
 
185
+ function getOptionalNodeErrorCode( error: unknown ): string | undefined {
186
+ \treturn typeof error === 'object' && error !== null && 'code' in error
187
+ \t\t? String( ( error as { code: unknown } ).code )
188
+ \t\t: undefined;
189
+ }
190
+
191
+ function isFileNotFoundError( error: unknown ): boolean {
192
+ \treturn getOptionalNodeErrorCode( error ) === 'ENOENT';
193
+ }
194
+
185
195
  function runSyncScript( scriptPath: string, options: SyncCliOptions ) {
186
196
  \tconst args = [ scriptPath ];
187
197
  \tif ( options.check ) {
@@ -196,7 +206,7 @@ function runSyncScript( scriptPath: string, options: SyncCliOptions ) {
196
206
  \t} );
197
207
 
198
208
  \tif ( result.error ) {
199
- \t\tif ( ( result.error as NodeJS.ErrnoException ).code === 'ENOENT' ) {
209
+ \t\tif ( isFileNotFoundError( result.error ) ) {
200
210
  \t\t\tthrow new Error(
201
211
  \t\t\t\t'Unable to resolve \`tsx\` for project sync. Install project dependencies or rerun the command through your package manager.'
202
212
  \t\t\t);
@@ -1,4 +1,5 @@
1
1
  type ValidateInput = (value: string) => boolean | string;
2
+ export type PromptLinePrinter = (line: string) => void;
2
3
  interface PromptOption<T extends string> {
3
4
  hint?: string;
4
5
  label: string;
@@ -12,6 +13,15 @@ export interface ReadlinePrompt {
12
13
  select<T extends string>(message: string, options: PromptOption<T>[], defaultValue?: number): Promise<T>;
13
14
  text(message: string, defaultValue: string, validate?: ValidateInput): Promise<string>;
14
15
  }
16
+ /**
17
+ * Output adapters used by prompt rendering and validation feedback.
18
+ */
19
+ export interface ReadlinePromptOutput {
20
+ /** Render one informational prompt line. */
21
+ printLine?: PromptLinePrinter;
22
+ /** Render one validation or selection error line. */
23
+ errorLine?: PromptLinePrinter;
24
+ }
15
25
  /**
16
26
  * Adapter interface for readline-style prompt interactions.
17
27
  *
@@ -33,14 +43,18 @@ export interface ReadlineQuestionAdapter {
33
43
  /**
34
44
  * Create the default readline-backed prompt implementation for the CLI.
35
45
  *
46
+ * @param output Optional line printers for prompt and validation output.
36
47
  * @returns A prompt adapter that reads from stdin and writes to stdout.
37
48
  */
38
- export declare function createReadlinePrompt(): ReadlinePrompt;
49
+ export declare function createReadlinePrompt(output?: ReadlinePromptOutput): ReadlinePrompt;
39
50
  /**
40
51
  * Build a prompt adapter around a supplied readline-style question interface.
41
52
  *
42
53
  * This keeps the production CLI path unchanged while letting tests validate
43
54
  * retry behavior without stubbing global stdin/stdout.
55
+ *
56
+ * @param rl Readline-compatible question adapter.
57
+ * @param output Optional line printers for prompt and validation output.
44
58
  */
45
- export declare function createReadlinePromptWithInterface(rl: ReadlineQuestionAdapter): ReadlinePrompt;
59
+ export declare function createReadlinePromptWithInterface(rl: ReadlineQuestionAdapter, output?: ReadlinePromptOutput): ReadlinePrompt;
46
60
  export {};
@@ -2,22 +2,27 @@ import readline from "node:readline";
2
2
  /**
3
3
  * Create the default readline-backed prompt implementation for the CLI.
4
4
  *
5
+ * @param output Optional line printers for prompt and validation output.
5
6
  * @returns A prompt adapter that reads from stdin and writes to stdout.
6
7
  */
7
- export function createReadlinePrompt() {
8
+ export function createReadlinePrompt(output = {}) {
8
9
  const rl = readline.createInterface({
9
10
  input: process.stdin,
10
11
  output: process.stdout,
11
12
  });
12
- return createReadlinePromptWithInterface(rl);
13
+ return createReadlinePromptWithInterface(rl, output);
13
14
  }
14
15
  /**
15
16
  * Build a prompt adapter around a supplied readline-style question interface.
16
17
  *
17
18
  * This keeps the production CLI path unchanged while letting tests validate
18
19
  * retry behavior without stubbing global stdin/stdout.
20
+ *
21
+ * @param rl Readline-compatible question adapter.
22
+ * @param output Optional line printers for prompt and validation output.
19
23
  */
20
- export function createReadlinePromptWithInterface(rl) {
24
+ export function createReadlinePromptWithInterface(rl, output = {}) {
25
+ const { errorLine, printLine } = resolveReadlinePromptOutput(output);
21
26
  const askQuestion = (query) => new Promise((resolve) => {
22
27
  rl.question(query, resolve);
23
28
  });
@@ -28,7 +33,7 @@ export function createReadlinePromptWithInterface(rl) {
28
33
  if (validate) {
29
34
  const result = validate(value);
30
35
  if (result !== true) {
31
- console.error(formatValidationError(message, result, defaultValue));
36
+ errorLine(formatValidationError(message, result, defaultValue));
32
37
  continue;
33
38
  }
34
39
  }
@@ -40,7 +45,7 @@ export function createReadlinePromptWithInterface(rl) {
40
45
  throw new Error(`select() requires at least one option for prompt: ${message}`);
41
46
  }
42
47
  const resolvedDefaultIndex = getResolvedDefaultIndex(options, defaultValue);
43
- renderSelectPrompt(message, options, resolvedDefaultIndex);
48
+ renderSelectPrompt(message, options, resolvedDefaultIndex, printLine);
44
49
  while (true) {
45
50
  const answer = normalizePromptAnswer(await askQuestion(formatChoicePrompt(resolvedDefaultIndex)));
46
51
  if (answer.length === 0) {
@@ -51,10 +56,10 @@ export function createReadlinePromptWithInterface(rl) {
51
56
  return selection.value;
52
57
  }
53
58
  if (isPromptHelpToken(answer)) {
54
- renderSelectPrompt(message, options, resolvedDefaultIndex);
59
+ renderSelectPrompt(message, options, resolvedDefaultIndex, printLine);
55
60
  continue;
56
61
  }
57
- console.error(formatInvalidSelectionError(answer, options, resolvedDefaultIndex));
62
+ errorLine(formatInvalidSelectionError(answer, options, resolvedDefaultIndex));
58
63
  }
59
64
  },
60
65
  close() {
@@ -62,6 +67,18 @@ export function createReadlinePromptWithInterface(rl) {
62
67
  },
63
68
  };
64
69
  }
70
+ function resolveReadlinePromptOutput({ errorLine, printLine, }) {
71
+ return {
72
+ errorLine: errorLine ?? writePromptErrorLine,
73
+ printLine: printLine ?? writePromptLine,
74
+ };
75
+ }
76
+ function writePromptLine(line) {
77
+ process.stdout.write(`${line}\n`);
78
+ }
79
+ function writePromptErrorLine(line) {
80
+ process.stderr.write(`${line}\n`);
81
+ }
65
82
  function normalizePromptAnswer(value) {
66
83
  return String(value).trim();
67
84
  }
@@ -84,17 +101,17 @@ function formatValidationError(message, result, defaultValue) {
84
101
  function formatChoicePrompt(defaultIndex) {
85
102
  return `Choice [default: ${defaultIndex + 1}, ? for options]: `;
86
103
  }
87
- function renderSelectPrompt(message, options, defaultIndex) {
88
- console.log(message);
89
- console.log(" Enter a number, option label, or option value. Press Enter to keep the default, or type ? to list choices again.");
104
+ function renderSelectPrompt(message, options, defaultIndex, printLine) {
105
+ printLine(message);
106
+ printLine(" Enter a number, option label, or option value. Press Enter to keep the default, or type ? to list choices again.");
90
107
  options.forEach((option, index) => {
91
108
  const defaultMarker = index === defaultIndex ? " (default)" : "";
92
109
  const valueHint = normalizePromptToken(option.label) === normalizePromptToken(option.value)
93
110
  ? ""
94
111
  : ` [${option.value}]`;
95
- console.log(` ${index + 1}. ${option.label}${valueHint}${defaultMarker}`);
112
+ printLine(` ${index + 1}. ${option.label}${valueHint}${defaultMarker}`);
96
113
  if (option.hint) {
97
- console.log(` ${option.hint}`);
114
+ printLine(` ${option.hint}`);
98
115
  }
99
116
  });
100
117
  }
@@ -41,6 +41,7 @@ interface RunScaffoldFlowOptions {
41
41
  onProgress?: ((event: ScaffoldProgressEvent) => void | Promise<void>) | undefined;
42
42
  packageManager?: string;
43
43
  phpPrefix?: string;
44
+ profile?: string;
44
45
  projectInput: string;
45
46
  promptText?: Parameters<typeof collectScaffoldAnswers>[0]["promptText"];
46
47
  queryPostType?: string;
@@ -83,7 +84,7 @@ export declare function getOptionalOnboarding({ availableScripts, packageManager
83
84
  * project.
84
85
  * @returns The scaffold result together with next-step guidance.
85
86
  */
86
- export declare function runScaffoldFlow({ projectInput, cwd, templateId, alternateRenderTargets, dataStorageMode, dryRun, externalLayerId, externalLayerSource, innerBlocksPreset, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, queryPostType, yes, noInstall, onProgress, isInteractive, allowExistingDir, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }: RunScaffoldFlowOptions): Promise<{
87
+ export declare function runScaffoldFlow({ projectInput, cwd, templateId, alternateRenderTargets, dataStorageMode, dryRun, externalLayerId, externalLayerSource, innerBlocksPreset, persistencePolicy, packageManager, namespace, profile, textDomain, phpPrefix, queryPostType, yes, noInstall, onProgress, isInteractive, allowExistingDir, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }: RunScaffoldFlowOptions): Promise<{
87
88
  dryRun: boolean;
88
89
  optionalOnboarding: OptionalOnboardingGuidance;
89
90
  plan: ScaffoldDryRunPlan | undefined;
@@ -1,6 +1,6 @@
1
1
  import { promises as fsp } from "node:fs";
2
2
  import path from "node:path";
3
- import { collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, resolvePackageManagerId, resolveTemplateId, scaffoldProject, } from "./scaffold.js";
3
+ import { collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, resolveCreateProfileId, isPersistencePolicy, resolvePackageManagerId, resolveTemplateId, scaffoldProject, } from "./scaffold.js";
4
4
  import { parseAlternateRenderTargets } from "./alternate-render-targets.js";
5
5
  import { parseCompoundInnerBlocksPreset } from "./compound-inner-blocks.js";
6
6
  import { isCompoundPersistenceEnabled } from "./scaffold-template-variable-groups.js";
@@ -10,6 +10,7 @@ import { createManagedTempRoot } from "./temp-roots.js";
10
10
  import { getOptionalOnboardingNote, getOptionalOnboardingShortNote, getOptionalOnboardingSteps, } from "./scaffold-onboarding.js";
11
11
  import { formatNonEmptyTargetDirectoryError } from "./scaffold-bootstrap.js";
12
12
  import { pathExists } from "./fs-async.js";
13
+ import { readJsonFile } from "./json-utils.js";
13
14
  import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, isBuiltInTemplateId, } from "./template-registry.js";
14
15
  import { resolveOptionalInteractiveExternalLayerId, } from "./external-layer-selection.js";
15
16
  import { assertBuiltInTemplateVariantAllowed, resolveLocalCliPathOption, normalizeOptionalCliString, } from "./cli-validation.js";
@@ -40,7 +41,7 @@ async function assertDryRunTargetDirectoryReady(projectDir, allowExistingDir) {
40
41
  throw new Error(formatNonEmptyTargetDirectoryError(projectDir));
41
42
  }
42
43
  }
43
- async function buildScaffoldDryRunPlan({ allowExistingDir, alternateRenderTargets, answers, cwd, dataStorageMode, externalLayerId, externalLayerSource, externalLayerSourceLabel, installDependencies, noInstall, onProgress, packageManager, persistencePolicy, projectDir, templateId, variant, withMigrationUi, withTestPreset, withWpEnv, }) {
44
+ async function buildScaffoldDryRunPlan({ allowExistingDir, alternateRenderTargets, answers, cwd, dataStorageMode, externalLayerId, externalLayerSource, externalLayerSourceLabel, installDependencies, noInstall, onProgress, packageManager, persistencePolicy, profile, projectDir, templateId, variant, withMigrationUi, withTestPreset, withWpEnv, }) {
44
45
  await assertDryRunTargetDirectoryReady(projectDir, allowExistingDir);
45
46
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-scaffold-plan-");
46
47
  const previewProjectDir = path.join(tempRoot, "preview-project");
@@ -59,6 +60,7 @@ async function buildScaffoldDryRunPlan({ allowExistingDir, alternateRenderTarget
59
60
  onProgress,
60
61
  packageManager,
61
62
  persistencePolicy,
63
+ profile,
62
64
  projectDir: previewProjectDir,
63
65
  templateId,
64
66
  variant,
@@ -272,7 +274,7 @@ export function getOptionalOnboarding({ availableScripts, packageManager, templa
272
274
  * project.
273
275
  * @returns The scaffold result together with next-step guidance.
274
276
  */
275
- export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templateId, alternateRenderTargets, dataStorageMode, dryRun = false, externalLayerId, externalLayerSource, innerBlocksPreset, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, queryPostType, yes = false, noInstall = false, onProgress, isInteractive = false, allowExistingDir = false, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies = undefined, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }) {
277
+ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templateId, alternateRenderTargets, dataStorageMode, dryRun = false, externalLayerId, externalLayerSource, innerBlocksPreset, persistencePolicy, packageManager, namespace, profile, textDomain, phpPrefix, queryPostType, yes = false, noInstall = false, onProgress, isInteractive = false, allowExistingDir = false, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies = undefined, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }) {
276
278
  const normalizedExternalLayerId = normalizeOptionalCliString(externalLayerId);
277
279
  const normalizedExternalLayerSource = resolveLocalCliPathOption({
278
280
  cwd,
@@ -286,6 +288,7 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
286
288
  isInteractive,
287
289
  selectTemplate,
288
290
  });
291
+ const resolvedProfile = resolveCreateProfileId(profile);
289
292
  validateCreateFlagContract({
290
293
  alternateRenderTargets,
291
294
  dataStorageMode,
@@ -339,12 +342,14 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
339
342
  isInteractive,
340
343
  selectPackageManager,
341
344
  });
342
- const resolvedWithWpEnv = await resolveOptionalBooleanFlag({
343
- explicitValue: withWpEnv,
344
- isInteractive,
345
- select: selectWithWpEnv,
346
- yes,
347
- });
345
+ const resolvedWithWpEnv = resolvedProfile === "plugin-qa"
346
+ ? true
347
+ : await resolveOptionalBooleanFlag({
348
+ explicitValue: withWpEnv,
349
+ isInteractive,
350
+ select: selectWithWpEnv,
351
+ yes,
352
+ });
348
353
  const resolvedWithTestPreset = await resolveOptionalBooleanFlag({
349
354
  explicitValue: withTestPreset,
350
355
  isInteractive,
@@ -391,6 +396,7 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
391
396
  onProgress,
392
397
  packageManager: resolvedPackageManager,
393
398
  persistencePolicy: resolvedPersistencePolicy,
399
+ profile: resolvedProfile,
394
400
  projectDir,
395
401
  templateId: resolvedTemplateId,
396
402
  variant,
@@ -414,6 +420,7 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
414
420
  onProgress,
415
421
  packageManager: resolvedPackageManager,
416
422
  persistencePolicy: resolvedPersistencePolicy,
423
+ profile: resolvedProfile,
417
424
  projectDir,
418
425
  templateId: resolvedTemplateId,
419
426
  variant,
@@ -425,7 +432,9 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
425
432
  let availableScripts;
426
433
  if (!dryRun) {
427
434
  try {
428
- const parsedPackageJson = JSON.parse(await fsp.readFile(path.join(projectDir, "package.json"), "utf8"));
435
+ const parsedPackageJson = await readJsonFile(path.join(projectDir, "package.json"), {
436
+ context: "generated package manifest",
437
+ });
429
438
  const scripts = parsedPackageJson.scripts &&
430
439
  typeof parsedPackageJson.scripts === "object" &&
431
440
  !Array.isArray(parsedPackageJson.scripts)
@@ -0,0 +1,14 @@
1
+ interface SyncStandaloneContractArtifactsOptions {
2
+ projectDir: string;
3
+ schemaFile: string;
4
+ sourceTypeName: string;
5
+ typesFile: string;
6
+ }
7
+ /**
8
+ * Generate the JSON Schema artifact for a standalone TypeScript contract.
9
+ *
10
+ * @param options Workspace-relative type/schema paths plus the exported source
11
+ * type name.
12
+ */
13
+ export declare function syncStandaloneContractArtifacts({ projectDir, schemaFile, sourceTypeName, typesFile, }: SyncStandaloneContractArtifactsOptions): Promise<void>;
14
+ export {};
@@ -0,0 +1,15 @@
1
+ import { syncTypeSchemas, } from "@wp-typia/block-runtime/metadata-core";
2
+ /**
3
+ * Generate the JSON Schema artifact for a standalone TypeScript contract.
4
+ *
5
+ * @param options Workspace-relative type/schema paths plus the exported source
6
+ * type name.
7
+ */
8
+ export async function syncStandaloneContractArtifacts({ projectDir, schemaFile, sourceTypeName, typesFile, }) {
9
+ await syncTypeSchemas({
10
+ jsonSchemaFile: schemaFile,
11
+ projectRoot: projectDir,
12
+ sourceTypeName,
13
+ typesFile,
14
+ });
15
+ }
@@ -1,4 +1,5 @@
1
1
  import fs from "node:fs";
2
+ import { safeJsonParse } from "./json-utils.js";
2
3
  export const TEMPLATE_SOURCE_TIMEOUT_CODE = "template-source-timeout";
3
4
  export const TEMPLATE_SOURCE_TOO_LARGE_CODE = "template-source-too-large";
4
5
  const DEFAULT_EXTERNAL_TEMPLATE_TIMEOUT_MS = 20000;
@@ -120,12 +121,9 @@ async function readResponseBodyWithLimit(response, options) {
120
121
  }
121
122
  export async function readJsonResponseWithLimit(response, options) {
122
123
  const buffer = await readResponseBodyWithLimit(response, options);
123
- try {
124
- return JSON.parse(buffer.toString("utf8"));
125
- }
126
- catch (error) {
127
- throw new Error(`Failed to parse ${options.label}: ${error instanceof Error ? error.message : String(error)}`);
128
- }
124
+ return safeJsonParse(buffer.toString("utf8"), {
125
+ context: options.label,
126
+ });
129
127
  }
130
128
  export async function readBufferResponseWithLimit(response, options) {
131
129
  return readResponseBodyWithLimit(response, options);
@@ -38,5 +38,5 @@ export { TEMPLATE_IDS, TEMPLATE_REGISTRY, getTemplateById, getTemplateSelectOpti
38
38
  export { EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV, pruneExternalTemplateCache, } from "./template-source-cache.js";
39
39
  export type { ExternalTemplateCachePruneOptions, ExternalTemplateCachePruneResult, } from "./template-source-cache.js";
40
40
  export { STALE_TEMP_ROOT_MAX_AGE_MS, WP_TYPIA_TEMP_ROOT_PREFIX, cleanupManagedTempRoot, cleanupStaleTempRoots, createManagedTempRoot, getTrackedTempRoots, } from "./temp-roots.js";
41
- export { createReadlinePrompt, createCliCommandError, createCliDiagnosticCodeError, CliDiagnosticError, CLI_DIAGNOSTIC_CODES, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, getWorkspaceBlockSelectOptionsAsync, HOOKED_BLOCK_POSITION_IDS, EDITOR_PLUGIN_SLOT_IDS, isCliDiagnosticError, runAddAdminViewCommand, runAddAbilityCommand, runAddAiFeatureCommand, runAddBindingSourceCommand, runAddBlockCommand, runAddBlockStyleCommand, runAddBlockTransformCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runDoctor, runAddVariationCommand, runScaffoldFlow, } from "./cli-core.js";
42
- export type { CliDiagnosticCode, CliDiagnosticCodeError, CliDiagnosticMessage, DoctorCheck, EditorPluginSlotId, HookedBlockPositionId, ReadlinePrompt, WorkspaceBlockSelectOption, } from "./cli-core.js";
41
+ export { createReadlinePrompt, createDoctorRunSummary, createCliCommandError, createCliDiagnosticCodeError, CliDiagnosticError, CLI_DIAGNOSTIC_CODES, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorExitFailureChecks, getDoctorExitFailureDetailLines, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, getWorkspaceBlockSelectOptionsAsync, HOOKED_BLOCK_POSITION_IDS, EDITOR_PLUGIN_SLOT_IDS, isCliDiagnosticError, runAddAdminViewCommand, runAddAbilityCommand, runAddAiFeatureCommand, runAddBindingSourceCommand, runAddBlockCommand, runAddBlockStyleCommand, runAddBlockTransformCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddPostMetaCommand, runDoctor, runAddVariationCommand, runScaffoldFlow, } from "./cli-core.js";
42
+ export type { CliDiagnosticCode, CliDiagnosticCodeError, CliDiagnosticMessage, DoctorCheck, DoctorCheckScope, DoctorExitPolicy, DoctorFailureSummary, DoctorRunSummary, EditorPluginSlotId, HookedBlockPositionId, ReadlinePrompt, WorkspaceBlockSelectOption, } from "./cli-core.js";
@@ -29,4 +29,4 @@ export { clearPackageVersionsCache, getPackageVersions, invalidatePackageVersion
29
29
  export { TEMPLATE_IDS, TEMPLATE_REGISTRY, getTemplateById, getTemplateSelectOptions, listTemplates, } from "./template-registry.js";
30
30
  export { EXTERNAL_TEMPLATE_CACHE_TTL_DAYS_ENV, pruneExternalTemplateCache, } from "./template-source-cache.js";
31
31
  export { STALE_TEMP_ROOT_MAX_AGE_MS, WP_TYPIA_TEMP_ROOT_PREFIX, cleanupManagedTempRoot, cleanupStaleTempRoots, createManagedTempRoot, getTrackedTempRoots, } from "./temp-roots.js";
32
- export { createReadlinePrompt, createCliCommandError, createCliDiagnosticCodeError, CliDiagnosticError, CLI_DIAGNOSTIC_CODES, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, getWorkspaceBlockSelectOptionsAsync, HOOKED_BLOCK_POSITION_IDS, EDITOR_PLUGIN_SLOT_IDS, isCliDiagnosticError, runAddAdminViewCommand, runAddAbilityCommand, runAddAiFeatureCommand, runAddBindingSourceCommand, runAddBlockCommand, runAddBlockStyleCommand, runAddBlockTransformCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runDoctor, runAddVariationCommand, runScaffoldFlow, } from "./cli-core.js";
32
+ export { createReadlinePrompt, createDoctorRunSummary, createCliCommandError, createCliDiagnosticCodeError, CliDiagnosticError, CLI_DIAGNOSTIC_CODES, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorExitFailureChecks, getDoctorExitFailureDetailLines, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, getWorkspaceBlockSelectOptionsAsync, HOOKED_BLOCK_POSITION_IDS, EDITOR_PLUGIN_SLOT_IDS, isCliDiagnosticError, runAddAdminViewCommand, runAddAbilityCommand, runAddAiFeatureCommand, runAddBindingSourceCommand, runAddBlockCommand, runAddBlockStyleCommand, runAddBlockTransformCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddPostMetaCommand, runDoctor, runAddVariationCommand, runScaffoldFlow, } from "./cli-core.js";