@wp-typia/project-tools 0.11.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 (187) hide show
  1. package/README.md +32 -0
  2. package/dist/runtime/cli-add.d.ts +38 -0
  3. package/dist/runtime/cli-add.js +561 -0
  4. package/dist/runtime/cli-core.d.ts +25 -0
  5. package/dist/runtime/cli-core.js +25 -0
  6. package/dist/runtime/cli-doctor.d.ts +34 -0
  7. package/dist/runtime/cli-doctor.js +131 -0
  8. package/dist/runtime/cli-help.d.ts +9 -0
  9. package/dist/runtime/cli-help.js +37 -0
  10. package/dist/runtime/cli-prompt.d.ts +21 -0
  11. package/dist/runtime/cli-prompt.js +53 -0
  12. package/dist/runtime/cli-scaffold.d.ts +79 -0
  13. package/dist/runtime/cli-scaffold.js +206 -0
  14. package/dist/runtime/cli-templates.d.ts +30 -0
  15. package/dist/runtime/cli-templates.js +61 -0
  16. package/dist/runtime/index.d.ts +9 -0
  17. package/dist/runtime/index.js +7 -0
  18. package/dist/runtime/json-utils.d.ts +10 -0
  19. package/dist/runtime/json-utils.js +12 -0
  20. package/dist/runtime/local-dev-presets.d.ts +26 -0
  21. package/dist/runtime/local-dev-presets.js +132 -0
  22. package/dist/runtime/metadata-analysis.d.ts +11 -0
  23. package/dist/runtime/metadata-analysis.js +285 -0
  24. package/dist/runtime/metadata-model.d.ts +84 -0
  25. package/dist/runtime/metadata-model.js +59 -0
  26. package/dist/runtime/metadata-parser.d.ts +53 -0
  27. package/dist/runtime/metadata-parser.js +794 -0
  28. package/dist/runtime/metadata-php-render.d.ts +29 -0
  29. package/dist/runtime/metadata-php-render.js +549 -0
  30. package/dist/runtime/metadata-projection.d.ts +7 -0
  31. package/dist/runtime/metadata-projection.js +233 -0
  32. package/dist/runtime/migration-constants.d.ts +15 -0
  33. package/dist/runtime/migration-constants.js +16 -0
  34. package/dist/runtime/migration-diff.d.ts +2 -0
  35. package/dist/runtime/migration-diff.js +537 -0
  36. package/dist/runtime/migration-fixtures.d.ts +8 -0
  37. package/dist/runtime/migration-fixtures.js +94 -0
  38. package/dist/runtime/migration-fuzz-plan.d.ts +2 -0
  39. package/dist/runtime/migration-fuzz-plan.js +50 -0
  40. package/dist/runtime/migration-manifest.d.ts +19 -0
  41. package/dist/runtime/migration-manifest.js +129 -0
  42. package/dist/runtime/migration-project.d.ts +94 -0
  43. package/dist/runtime/migration-project.js +1101 -0
  44. package/dist/runtime/migration-render.d.ts +11 -0
  45. package/dist/runtime/migration-render.js +741 -0
  46. package/dist/runtime/migration-risk.d.ts +4 -0
  47. package/dist/runtime/migration-risk.js +52 -0
  48. package/dist/runtime/migration-types.d.ts +249 -0
  49. package/dist/runtime/migration-types.js +1 -0
  50. package/dist/runtime/migration-ui-capability.d.ts +17 -0
  51. package/dist/runtime/migration-ui-capability.js +190 -0
  52. package/dist/runtime/migration-utils.d.ts +69 -0
  53. package/dist/runtime/migration-utils.js +246 -0
  54. package/dist/runtime/migrations.d.ts +249 -0
  55. package/dist/runtime/migrations.js +1061 -0
  56. package/dist/runtime/object-utils.d.ts +12 -0
  57. package/dist/runtime/object-utils.js +14 -0
  58. package/dist/runtime/package-managers.d.ts +28 -0
  59. package/dist/runtime/package-managers.js +156 -0
  60. package/dist/runtime/package-versions.d.ts +10 -0
  61. package/dist/runtime/package-versions.js +68 -0
  62. package/dist/runtime/scaffold-onboarding.d.ts +32 -0
  63. package/dist/runtime/scaffold-onboarding.js +99 -0
  64. package/dist/runtime/scaffold.d.ts +146 -0
  65. package/dist/runtime/scaffold.js +612 -0
  66. package/dist/runtime/schema-core.d.ts +267 -0
  67. package/dist/runtime/schema-core.js +597 -0
  68. package/dist/runtime/starter-manifests.d.ts +25 -0
  69. package/dist/runtime/starter-manifests.js +383 -0
  70. package/dist/runtime/string-case.d.ts +36 -0
  71. package/dist/runtime/string-case.js +69 -0
  72. package/dist/runtime/template-builtins.d.ts +38 -0
  73. package/dist/runtime/template-builtins.js +72 -0
  74. package/dist/runtime/template-defaults.d.ts +75 -0
  75. package/dist/runtime/template-defaults.js +65 -0
  76. package/dist/runtime/template-registry.d.ts +36 -0
  77. package/dist/runtime/template-registry.js +94 -0
  78. package/dist/runtime/template-render.d.ts +24 -0
  79. package/dist/runtime/template-render.js +113 -0
  80. package/dist/runtime/template-source.d.ts +71 -0
  81. package/dist/runtime/template-source.js +821 -0
  82. package/dist/runtime/typia-tags.d.ts +1 -0
  83. package/dist/runtime/typia-tags.js +1 -0
  84. package/package.json +79 -0
  85. package/templates/_shared/base/languages/.gitkeep +1 -0
  86. package/templates/_shared/base/package.json.mustache +41 -0
  87. package/templates/_shared/base/scripts/sync-types-to-block-json.ts.mustache +118 -0
  88. package/templates/_shared/base/src/hooks.ts.mustache +19 -0
  89. package/templates/_shared/base/src/validator-toolkit.ts.mustache +31 -0
  90. package/templates/_shared/base/tsconfig.json.mustache +21 -0
  91. package/templates/_shared/base/webpack.config.js.mustache +99 -0
  92. package/templates/_shared/base/{{slugKebabCase}}.php.mustache +53 -0
  93. package/templates/_shared/compound/core/package.json.mustache +45 -0
  94. package/templates/_shared/compound/core/scripts/add-compound-child.ts.mustache +559 -0
  95. package/templates/_shared/compound/core/scripts/block-config.ts.mustache +13 -0
  96. package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +53 -0
  97. package/templates/_shared/compound/core/webpack.config.js.mustache +141 -0
  98. package/templates/_shared/compound/core/{{slugKebabCase}}.php.mustache +51 -0
  99. package/templates/_shared/compound/persistence/package.json.mustache +50 -0
  100. package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +59 -0
  101. package/templates/_shared/compound/persistence/scripts/sync-rest-contracts.ts.mustache +101 -0
  102. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/api-types.ts.mustache +21 -0
  103. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/api-validators.ts.mustache +32 -0
  104. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/api.ts.mustache +68 -0
  105. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/block.json.mustache +52 -0
  106. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/data.ts.mustache +192 -0
  107. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/edit.tsx.mustache +123 -0
  108. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/hooks.ts.mustache +11 -0
  109. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/interactivity.ts.mustache +132 -0
  110. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/render.php.mustache +158 -0
  111. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/save.tsx.mustache +3 -0
  112. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/types.ts.mustache +56 -0
  113. package/templates/_shared/compound/persistence/src/blocks/{{slugKebabCase}}/validators.ts.mustache +32 -0
  114. package/templates/_shared/compound/persistence-auth/{{slugKebabCase}}.php.mustache +294 -0
  115. package/templates/_shared/compound/persistence-public/{{slugKebabCase}}.php.mustache +312 -0
  116. package/templates/_shared/migration-ui/common/src/admin/migration-dashboard.tsx +394 -0
  117. package/templates/_shared/migration-ui/common/src/migration-detector.ts +9 -0
  118. package/templates/_shared/migration-ui/common/src/migrations/helpers.ts +490 -0
  119. package/templates/_shared/migration-ui/common/src/migrations/index.ts +886 -0
  120. package/templates/_shared/persistence/auth/{{slugKebabCase}}.php.mustache +290 -0
  121. package/templates/_shared/persistence/core/package.json.mustache +46 -0
  122. package/templates/_shared/persistence/core/scripts/sync-rest-contracts.ts.mustache +113 -0
  123. package/templates/_shared/persistence/core/scripts/sync-types-to-block-json.ts.mustache +125 -0
  124. package/templates/_shared/persistence/core/src/api-types.ts.mustache +21 -0
  125. package/templates/_shared/persistence/core/src/api-validators.ts.mustache +32 -0
  126. package/templates/_shared/persistence/core/src/api.ts.mustache +68 -0
  127. package/templates/_shared/persistence/core/src/data.ts.mustache +192 -0
  128. package/templates/_shared/persistence/core/src/index.tsx.mustache +25 -0
  129. package/templates/_shared/persistence/core/src/interactivity.ts.mustache +134 -0
  130. package/templates/_shared/persistence/core/src/save.tsx.mustache +5 -0
  131. package/templates/_shared/persistence/core/src/validators.ts.mustache +32 -0
  132. package/templates/_shared/persistence/core/{{slugKebabCase}}.php.mustache +336 -0
  133. package/templates/_shared/persistence/public/{{slugKebabCase}}.php.mustache +308 -0
  134. package/templates/_shared/presets/test-preset/.wp-env.test.json.mustache +16 -0
  135. package/templates/_shared/presets/test-preset/playwright.config.ts.mustache +22 -0
  136. package/templates/_shared/presets/test-preset/scripts/wait-for-wp-env.mjs.mustache +102 -0
  137. package/templates/_shared/presets/test-preset/scripts/wp-env-utils.cjs.mustache +32 -0
  138. package/templates/_shared/presets/test-preset/tests/e2e/smoke.spec.ts.mustache +34 -0
  139. package/templates/_shared/presets/wp-env/.wp-env.json.mustache +16 -0
  140. package/templates/_shared/rest-helpers/auth/inc/rest-auth.php.mustache +37 -0
  141. package/templates/_shared/rest-helpers/public/inc/rest-public.php.mustache +314 -0
  142. package/templates/_shared/rest-helpers/shared/inc/rest-shared.php.mustache +58 -0
  143. package/templates/_shared/workspace/persistence-auth/inc/rest-auth.php.mustache +36 -0
  144. package/templates/_shared/workspace/persistence-auth/inc/rest-shared.php.mustache +55 -0
  145. package/templates/_shared/workspace/persistence-auth/server.php.mustache +237 -0
  146. package/templates/_shared/workspace/persistence-public/inc/rest-public.php.mustache +273 -0
  147. package/templates/_shared/workspace/persistence-public/inc/rest-shared.php.mustache +55 -0
  148. package/templates/_shared/workspace/persistence-public/server.php.mustache +252 -0
  149. package/templates/basic/src/block.json.mustache +51 -0
  150. package/templates/basic/src/edit.tsx.mustache +128 -0
  151. package/templates/basic/src/editor.scss.mustache +8 -0
  152. package/templates/basic/src/hooks.ts.mustache +18 -0
  153. package/templates/basic/src/index.tsx.mustache +45 -0
  154. package/templates/basic/src/save.tsx.mustache +30 -0
  155. package/templates/basic/src/style.scss.mustache +40 -0
  156. package/templates/basic/src/types.ts.mustache +56 -0
  157. package/templates/basic/src/validators.ts.mustache +26 -0
  158. package/templates/compound/src/blocks/{{slugKebabCase}}/block.json.mustache +37 -0
  159. package/templates/compound/src/blocks/{{slugKebabCase}}/children.ts.mustache +25 -0
  160. package/templates/compound/src/blocks/{{slugKebabCase}}/edit.tsx.mustache +93 -0
  161. package/templates/compound/src/blocks/{{slugKebabCase}}/hooks.ts.mustache +11 -0
  162. package/templates/compound/src/blocks/{{slugKebabCase}}/index.tsx.mustache +25 -0
  163. package/templates/compound/src/blocks/{{slugKebabCase}}/save.tsx.mustache +32 -0
  164. package/templates/compound/src/blocks/{{slugKebabCase}}/style.scss.mustache +31 -0
  165. package/templates/compound/src/blocks/{{slugKebabCase}}/types.ts.mustache +13 -0
  166. package/templates/compound/src/blocks/{{slugKebabCase}}/validators.ts.mustache +17 -0
  167. package/templates/compound/src/blocks/{{slugKebabCase}}-item/block.json.mustache +35 -0
  168. package/templates/compound/src/blocks/{{slugKebabCase}}-item/edit.tsx.mustache +50 -0
  169. package/templates/compound/src/blocks/{{slugKebabCase}}-item/hooks.ts.mustache +11 -0
  170. package/templates/compound/src/blocks/{{slugKebabCase}}-item/index.tsx.mustache +25 -0
  171. package/templates/compound/src/blocks/{{slugKebabCase}}-item/save.tsx.mustache +24 -0
  172. package/templates/compound/src/blocks/{{slugKebabCase}}-item/types.ts.mustache +12 -0
  173. package/templates/compound/src/blocks/{{slugKebabCase}}-item/validators.ts.mustache +17 -0
  174. package/templates/interactivity/package.json.mustache +42 -0
  175. package/templates/interactivity/src/block.json.mustache +73 -0
  176. package/templates/interactivity/src/edit.tsx.mustache +270 -0
  177. package/templates/interactivity/src/index.tsx.mustache +32 -0
  178. package/templates/interactivity/src/interactivity.ts.mustache +152 -0
  179. package/templates/interactivity/src/save.tsx.mustache +101 -0
  180. package/templates/interactivity/src/style.scss.mustache +60 -0
  181. package/templates/interactivity/src/types.ts.mustache +32 -0
  182. package/templates/interactivity/src/validators.ts.mustache +36 -0
  183. package/templates/persistence/src/block.json.mustache +52 -0
  184. package/templates/persistence/src/edit.tsx.mustache +165 -0
  185. package/templates/persistence/src/render.php.mustache +126 -0
  186. package/templates/persistence/src/style.scss.mustache +46 -0
  187. package/templates/persistence/src/types.ts.mustache +55 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Public runtime helper barrel consumed by the canonical `wp-typia` package.
3
+ *
4
+ * These exports do not make `@wp-typia/project-tools` the CLI owner again. Command
5
+ * taxonomy, help text ownership, and published bin responsibility stay in
6
+ * `packages/wp-typia`.
7
+ *
8
+ * Import `formatAddHelpText`, `runAddBlockCommand`,
9
+ * `createAddPlaceholderMessage`, and `seedWorkspaceMigrationProject` for
10
+ * explicit `wp-typia add` flows,
11
+ * `getDoctorChecks`, `runDoctor`, and `DoctorCheck` for diagnostics,
12
+ * `formatHelpText` for top-level CLI usage output, scaffold helpers such as
13
+ * `createReadlinePrompt`, `getNextSteps`, `getOptionalOnboarding`,
14
+ * `runScaffoldFlow`, and `ReadlinePrompt` for interactive project creation,
15
+ * and template helpers such as `formatTemplateDetails`,
16
+ * `formatTemplateFeatures`, `formatTemplateSummary`, `getTemplateById`,
17
+ * `getTemplateSelectOptions`, `listTemplates`, and `isBuiltInTemplateId` for
18
+ * template inspection flows.
19
+ */
20
+ export { getDoctorChecks, runDoctor } from "./cli-doctor.js";
21
+ export { createAddPlaceholderMessage, formatAddHelpText, runAddBlockCommand, seedWorkspaceMigrationProject } from "./cli-add.js";
22
+ export { formatHelpText } from "./cli-help.js";
23
+ export { getNextSteps, getOptionalOnboarding, runScaffoldFlow, } from "./cli-scaffold.js";
24
+ export { createReadlinePrompt } from "./cli-prompt.js";
25
+ export { formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getTemplateById, getTemplateSelectOptions, isBuiltInTemplateId, listTemplates, } from "./cli-templates.js";
@@ -0,0 +1,34 @@
1
+ /**
2
+ * One doctor check rendered by the CLI diagnostics flow.
3
+ */
4
+ export interface DoctorCheck {
5
+ /** Human-readable status detail rendered next to the label. */
6
+ detail: string;
7
+ /** Short label for the dependency, directory, or template check. */
8
+ label: string;
9
+ /** Final pass/fail status for this diagnostic row. */
10
+ status: "pass" | "fail";
11
+ }
12
+ interface RunDoctorOptions {
13
+ renderLine?: (check: DoctorCheck) => void;
14
+ }
15
+ /**
16
+ * Collect all runtime doctor checks for the current environment.
17
+ *
18
+ * The returned array includes command availability checks, directory
19
+ * writability checks, and built-in template asset checks in display order.
20
+ *
21
+ * @param cwd Working directory to validate for writability.
22
+ * @returns Ordered doctor check rows ready for CLI rendering.
23
+ */
24
+ export declare function getDoctorChecks(cwd: string): Promise<DoctorCheck[]>;
25
+ /**
26
+ * Run doctor checks, render each line, and fail when any check does not pass.
27
+ *
28
+ * @param cwd Working directory to validate.
29
+ * @param options Optional renderer override for each emitted check row.
30
+ * @returns The completed list of doctor checks.
31
+ * @throws {Error} When one or more checks fail.
32
+ */
33
+ export declare function runDoctor(cwd: string, { renderLine, }?: RunDoctorOptions): Promise<DoctorCheck[]>;
34
+ export {};
@@ -0,0 +1,131 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { execFileSync } from "node:child_process";
5
+ import { access, constants as fsConstants, rm, writeFile } from "node:fs/promises";
6
+ import { getBuiltInTemplateLayerDirs } from "./template-builtins.js";
7
+ import { listTemplates } from "./template-registry.js";
8
+ function readCommandVersion(command, args = ["--version"]) {
9
+ try {
10
+ return execFileSync(command, args, {
11
+ encoding: "utf8",
12
+ stdio: ["ignore", "pipe", "ignore"],
13
+ }).trim();
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ function compareMajorVersion(actualVersion, minimumMajor) {
20
+ const parsed = Number.parseInt(actualVersion.replace(/^v/, "").split(".")[0] ?? "", 10);
21
+ return Number.isFinite(parsed) && parsed >= minimumMajor;
22
+ }
23
+ async function checkWritableDirectory(directory) {
24
+ try {
25
+ await access(directory, fsConstants.W_OK);
26
+ return true;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ async function checkTempDirectory() {
33
+ const tempFile = path.join(os.tmpdir(), `wp-typia-${Date.now()}.tmp`);
34
+ try {
35
+ await writeFile(tempFile, "ok", "utf8");
36
+ await rm(tempFile, { force: true });
37
+ return true;
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ /**
44
+ * Collect all runtime doctor checks for the current environment.
45
+ *
46
+ * The returned array includes command availability checks, directory
47
+ * writability checks, and built-in template asset checks in display order.
48
+ *
49
+ * @param cwd Working directory to validate for writability.
50
+ * @returns Ordered doctor check rows ready for CLI rendering.
51
+ */
52
+ export async function getDoctorChecks(cwd) {
53
+ const checks = [];
54
+ const bunVersion = readCommandVersion("bun");
55
+ const nodeVersion = readCommandVersion("node");
56
+ const gitVersion = readCommandVersion("git");
57
+ const cwdWritable = await checkWritableDirectory(cwd);
58
+ const tempWritable = await checkTempDirectory();
59
+ checks.push({
60
+ status: bunVersion && compareMajorVersion(bunVersion, 1) ? "pass" : "fail",
61
+ label: "Bun",
62
+ detail: bunVersion ? `Detected ${bunVersion}` : "Not available",
63
+ });
64
+ checks.push({
65
+ status: nodeVersion && compareMajorVersion(nodeVersion, 20) ? "pass" : "fail",
66
+ label: "Node",
67
+ detail: nodeVersion ? `Detected ${nodeVersion}` : "Not available",
68
+ });
69
+ checks.push({
70
+ status: gitVersion ? "pass" : "fail",
71
+ label: "git",
72
+ detail: gitVersion ?? "Not available",
73
+ });
74
+ checks.push({
75
+ status: cwdWritable ? "pass" : "fail",
76
+ label: "Current directory",
77
+ detail: cwdWritable ? "Writable" : "Not writable",
78
+ });
79
+ checks.push({
80
+ status: tempWritable ? "pass" : "fail",
81
+ label: "Temp directory",
82
+ detail: tempWritable ? "Writable" : "Not writable",
83
+ });
84
+ for (const template of listTemplates()) {
85
+ const layerDirs = template.id === "persistence"
86
+ ? Array.from(new Set([
87
+ ...getBuiltInTemplateLayerDirs(template.id, { persistencePolicy: "authenticated" }),
88
+ ...getBuiltInTemplateLayerDirs(template.id, { persistencePolicy: "public" }),
89
+ ]))
90
+ : template.id === "compound"
91
+ ? Array.from(new Set([
92
+ ...getBuiltInTemplateLayerDirs(template.id),
93
+ ...getBuiltInTemplateLayerDirs(template.id, {
94
+ persistenceEnabled: true,
95
+ persistencePolicy: "authenticated",
96
+ }),
97
+ ...getBuiltInTemplateLayerDirs(template.id, {
98
+ persistenceEnabled: true,
99
+ persistencePolicy: "public",
100
+ }),
101
+ ]))
102
+ : getBuiltInTemplateLayerDirs(template.id);
103
+ const hasAssets = layerDirs.every((layerDir) => fs.existsSync(layerDir)) &&
104
+ layerDirs.some((layerDir) => fs.existsSync(path.join(layerDir, "package.json.mustache"))) &&
105
+ layerDirs.some((layerDir) => fs.existsSync(path.join(layerDir, "src")));
106
+ checks.push({
107
+ status: hasAssets ? "pass" : "fail",
108
+ label: `Template ${template.id}`,
109
+ detail: hasAssets ? layerDirs.join(" + ") : "Missing core template assets",
110
+ });
111
+ }
112
+ return checks;
113
+ }
114
+ /**
115
+ * Run doctor checks, render each line, and fail when any check does not pass.
116
+ *
117
+ * @param cwd Working directory to validate.
118
+ * @param options Optional renderer override for each emitted check row.
119
+ * @returns The completed list of doctor checks.
120
+ * @throws {Error} When one or more checks fail.
121
+ */
122
+ export async function runDoctor(cwd, { renderLine = (check) => console.log(`${check.status.toUpperCase()} ${check.label}: ${check.detail}`), } = {}) {
123
+ const checks = await getDoctorChecks(cwd);
124
+ for (const check of checks) {
125
+ renderLine(check);
126
+ }
127
+ if (checks.some((check) => check.status === "fail")) {
128
+ throw new Error("Doctor found one or more failing checks.");
129
+ }
130
+ return checks;
131
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Return the canonical CLI usage text for `wp-typia`.
3
+ *
4
+ * The rendered help includes the current built-in template ids and supported
5
+ * package manager ids from the runtime registry.
6
+ *
7
+ * @returns Human-readable help text for CLI usage output.
8
+ */
9
+ export declare function formatHelpText(): string;
@@ -0,0 +1,37 @@
1
+ import { PACKAGE_MANAGER_IDS } from "./package-managers.js";
2
+ import { TEMPLATE_IDS } from "./template-registry.js";
3
+ /**
4
+ * Return the canonical CLI usage text for `wp-typia`.
5
+ *
6
+ * The rendered help includes the current built-in template ids and supported
7
+ * package manager ids from the runtime registry.
8
+ *
9
+ * @returns Human-readable help text for CLI usage output.
10
+ */
11
+ export function formatHelpText() {
12
+ return `Usage:
13
+ wp-typia create <project-dir> [--template <basic|interactivity>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
14
+ 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] [--no-install] [--package-manager <id>]
15
+ 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] [--no-install] [--package-manager <id>]
16
+ wp-typia create <project-dir> [--template persistence] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
17
+ wp-typia create <project-dir> [--template compound] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
18
+ wp-typia <project-dir> [create flags...]
19
+ wp-typia add block <name> --template <basic|interactivity|persistence|compound> [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>]
20
+ wp-typia add variation
21
+ wp-typia add pattern
22
+ wp-typia migrate <init|snapshot|diff|scaffold|verify|doctor|fixtures|fuzz> [...]
23
+ wp-typia templates list
24
+ wp-typia templates inspect <id>
25
+ wp-typia doctor
26
+ wp-typia mcp <list|sync>
27
+ wp-typia skills <list|sync>
28
+ wp-typia completions <bash|zsh|fish|powershell>
29
+
30
+ Built-in templates: ${TEMPLATE_IDS.join(", ")}
31
+ Package managers: ${PACKAGE_MANAGER_IDS.join(", ")}
32
+ Notes:
33
+ \`wp-typia create\` is the canonical scaffold command.
34
+ \`wp-typia <project-dir>\` remains a backward-compatible alias to \`create\`.
35
+ \`add variation\` and \`add pattern\` are reserved placeholders in this release.
36
+ \`migrate\` is the canonical migration command; \`migrations\` is no longer supported.`;
37
+ }
@@ -0,0 +1,21 @@
1
+ type ValidateInput = (value: string) => boolean | string;
2
+ interface PromptOption<T extends string> {
3
+ hint?: string;
4
+ label: string;
5
+ value: T;
6
+ }
7
+ /**
8
+ * Prompt adapter used by CLI scaffold flows and migration wizard flows.
9
+ */
10
+ export interface ReadlinePrompt {
11
+ close(): void;
12
+ select<T extends string>(message: string, options: PromptOption<T>[], defaultValue?: number): Promise<T>;
13
+ text(message: string, defaultValue: string, validate?: ValidateInput): Promise<string>;
14
+ }
15
+ /**
16
+ * Create the default readline-backed prompt implementation for the CLI.
17
+ *
18
+ * @returns A prompt adapter that reads from stdin and writes to stdout.
19
+ */
20
+ export declare function createReadlinePrompt(): ReadlinePrompt;
21
+ export {};
@@ -0,0 +1,53 @@
1
+ import readline from "node:readline";
2
+ /**
3
+ * Create the default readline-backed prompt implementation for the CLI.
4
+ *
5
+ * @returns A prompt adapter that reads from stdin and writes to stdout.
6
+ */
7
+ export function createReadlinePrompt() {
8
+ const rl = readline.createInterface({
9
+ input: process.stdin,
10
+ output: process.stdout,
11
+ });
12
+ return {
13
+ async text(message, defaultValue, validate) {
14
+ const suffix = defaultValue ? ` (${defaultValue})` : "";
15
+ const answer = await new Promise((resolve) => {
16
+ rl.question(`${message}${suffix}: `, resolve);
17
+ });
18
+ const value = String(answer).trim() || defaultValue;
19
+ if (validate) {
20
+ const result = validate(value);
21
+ if (result !== true) {
22
+ console.error(`❌ ${typeof result === "string" ? result : "Invalid input"}`);
23
+ return this.text(message, defaultValue, validate);
24
+ }
25
+ }
26
+ return value;
27
+ },
28
+ async select(message, options, defaultValue = 1) {
29
+ if (options.length === 0) {
30
+ throw new Error(`select() requires at least one option for prompt: ${message}`);
31
+ }
32
+ console.log(message);
33
+ options.forEach((option, index) => {
34
+ const hint = option.hint ? ` - ${option.hint}` : "";
35
+ console.log(` ${index + 1}. ${option.label}${hint}`);
36
+ });
37
+ const answer = await this.text("Choice", String(defaultValue));
38
+ const numericChoice = Number(answer);
39
+ if (!Number.isNaN(numericChoice) && options[numericChoice - 1]) {
40
+ return options[numericChoice - 1].value;
41
+ }
42
+ const directChoice = options.find((option) => option.value === answer);
43
+ if (directChoice) {
44
+ return directChoice.value;
45
+ }
46
+ console.error(`❌ Invalid selection: ${answer}`);
47
+ return this.select(message, options, defaultValue);
48
+ },
49
+ close() {
50
+ rl.close();
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,79 @@
1
+ import { collectScaffoldAnswers, scaffoldProject } from "./scaffold.js";
2
+ import type { DataStorageMode, PersistencePolicy } from "./scaffold.js";
3
+ import type { PackageManagerId } from "./package-managers.js";
4
+ import type { TemplateDefinition } from "./template-registry.js";
5
+ interface GetNextStepsOptions {
6
+ noInstall: boolean;
7
+ packageManager: PackageManagerId;
8
+ projectDir: string;
9
+ projectInput: string;
10
+ templateId: string;
11
+ }
12
+ interface GetOptionalOnboardingOptions {
13
+ packageManager: PackageManagerId;
14
+ templateId: string;
15
+ compoundPersistenceEnabled?: boolean;
16
+ }
17
+ interface OptionalOnboardingGuidance {
18
+ note: string;
19
+ steps: string[];
20
+ }
21
+ interface RunScaffoldFlowOptions {
22
+ allowExistingDir?: boolean;
23
+ cwd?: string;
24
+ dataStorageMode?: string;
25
+ installDependencies?: Parameters<typeof scaffoldProject>[0]["installDependencies"];
26
+ isInteractive?: boolean;
27
+ namespace?: string;
28
+ noInstall?: boolean;
29
+ packageManager?: string;
30
+ phpPrefix?: string;
31
+ projectInput: string;
32
+ promptText?: Parameters<typeof collectScaffoldAnswers>[0]["promptText"];
33
+ selectDataStorage?: () => Promise<DataStorageMode>;
34
+ selectPackageManager?: () => Promise<PackageManagerId>;
35
+ selectPersistencePolicy?: () => Promise<PersistencePolicy>;
36
+ selectTemplate?: () => Promise<TemplateDefinition["id"]>;
37
+ selectWithMigrationUi?: () => Promise<boolean>;
38
+ selectWithTestPreset?: () => Promise<boolean>;
39
+ selectWithWpEnv?: () => Promise<boolean>;
40
+ templateId?: string;
41
+ textDomain?: string;
42
+ variant?: string;
43
+ persistencePolicy?: string;
44
+ withMigrationUi?: boolean;
45
+ withTestPreset?: boolean;
46
+ withWpEnv?: boolean;
47
+ yes?: boolean;
48
+ }
49
+ /**
50
+ * Build the printed next-step commands for a scaffolded project.
51
+ *
52
+ * @param options Project location and package-manager details used to format
53
+ * next-step commands.
54
+ * @returns Ordered shell commands shown after scaffolding succeeds.
55
+ */
56
+ export declare function getNextSteps({ projectInput, projectDir, packageManager, noInstall, templateId, }: GetNextStepsOptions): string[];
57
+ /**
58
+ * Compute optional onboarding guidance shown after scaffolding completes.
59
+ *
60
+ * @param options Package-manager and template context for optional guidance.
61
+ * @returns Optional onboarding note and step list.
62
+ */
63
+ export declare function getOptionalOnboarding({ packageManager, templateId, compoundPersistenceEnabled, }: GetOptionalOnboardingOptions): OptionalOnboardingGuidance;
64
+ /**
65
+ * Resolve scaffold options, prompts, and follow-up steps for one CLI run.
66
+ *
67
+ * @param options CLI/runtime inputs used to collect answers and scaffold a
68
+ * project.
69
+ * @returns The scaffold result together with next-step guidance.
70
+ */
71
+ export declare function runScaffoldFlow({ projectInput, cwd, templateId, dataStorageMode, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, yes, noInstall, isInteractive, allowExistingDir, selectTemplate, selectDataStorage, selectPersistencePolicy, selectPackageManager, promptText, installDependencies, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }: RunScaffoldFlowOptions): Promise<{
72
+ optionalOnboarding: OptionalOnboardingGuidance;
73
+ projectDir: string;
74
+ projectInput: string;
75
+ packageManager: PackageManagerId;
76
+ result: import("./scaffold.js").ScaffoldProjectResult;
77
+ nextSteps: string[];
78
+ }>;
79
+ export {};
@@ -0,0 +1,206 @@
1
+ import path from "node:path";
2
+ import { collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, resolvePackageManagerId, resolveTemplateId, scaffoldProject, } from "./scaffold.js";
3
+ import { formatInstallCommand, formatRunScript, } from "./package-managers.js";
4
+ import { getPrimaryDevelopmentScript } from "./local-dev-presets.js";
5
+ import { getOptionalOnboardingNote, getOptionalOnboardingSteps, } from "./scaffold-onboarding.js";
6
+ import { isBuiltInTemplateId } from "./template-registry.js";
7
+ const OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE = "@wp-typia/create-workspace-template";
8
+ function templateUsesPersistenceSettings(templateId, options) {
9
+ if (templateId === "persistence") {
10
+ return true;
11
+ }
12
+ if (templateId !== "compound") {
13
+ return false;
14
+ }
15
+ return Boolean(options.dataStorageMode || options.persistencePolicy);
16
+ }
17
+ function parseSelectableValue(label, value, isValue, allowedValues) {
18
+ if (isValue(value)) {
19
+ return value;
20
+ }
21
+ throw new Error(`Unsupported ${label} "${value}". Expected one of: ${allowedValues.join(", ")}`);
22
+ }
23
+ async function resolveOptionalSelection({ defaultValue, explicitValue, isInteractive, isValue, label, allowedValues, select, shouldResolve = true, yes, }) {
24
+ if (!shouldResolve) {
25
+ return undefined;
26
+ }
27
+ if (explicitValue) {
28
+ return parseSelectableValue(label, explicitValue, isValue, allowedValues);
29
+ }
30
+ if (yes) {
31
+ return defaultValue;
32
+ }
33
+ if (isInteractive && select) {
34
+ return select();
35
+ }
36
+ return defaultValue;
37
+ }
38
+ async function resolveOptionalBooleanFlag({ defaultValue = false, disabled = false, explicitValue, isInteractive, select, yes, }) {
39
+ if (disabled) {
40
+ return defaultValue;
41
+ }
42
+ if (typeof explicitValue === "boolean") {
43
+ return explicitValue;
44
+ }
45
+ if (yes) {
46
+ return defaultValue;
47
+ }
48
+ if (isInteractive && select) {
49
+ return select();
50
+ }
51
+ return defaultValue;
52
+ }
53
+ function quoteShellValue(value) {
54
+ if (!value.startsWith("-") &&
55
+ /^[A-Za-z0-9._/@:-]+(?:\/[A-Za-z0-9._@:-]+)*$/.test(value)) {
56
+ return value;
57
+ }
58
+ return `'${value.replace(/'/g, `'\"'\"'`)}'`;
59
+ }
60
+ /**
61
+ * Build the printed next-step commands for a scaffolded project.
62
+ *
63
+ * @param options Project location and package-manager details used to format
64
+ * next-step commands.
65
+ * @returns Ordered shell commands shown after scaffolding succeeds.
66
+ */
67
+ export function getNextSteps({ projectInput, projectDir, packageManager, noInstall, templateId, }) {
68
+ const cdTarget = path.isAbsolute(projectInput) ? projectDir : projectInput;
69
+ const steps = [`cd ${quoteShellValue(cdTarget)}`];
70
+ if (noInstall) {
71
+ steps.push(formatInstallCommand(packageManager));
72
+ }
73
+ steps.push(formatRunScript(packageManager, getPrimaryDevelopmentScript(templateId)));
74
+ return steps;
75
+ }
76
+ /**
77
+ * Compute optional onboarding guidance shown after scaffolding completes.
78
+ *
79
+ * @param options Package-manager and template context for optional guidance.
80
+ * @returns Optional onboarding note and step list.
81
+ */
82
+ export function getOptionalOnboarding({ packageManager, templateId, compoundPersistenceEnabled = false, }) {
83
+ return {
84
+ note: getOptionalOnboardingNote(packageManager, templateId),
85
+ steps: getOptionalOnboardingSteps(packageManager, templateId, {
86
+ compoundPersistenceEnabled,
87
+ }),
88
+ };
89
+ }
90
+ /**
91
+ * Resolve scaffold options, prompts, and follow-up steps for one CLI run.
92
+ *
93
+ * @param options CLI/runtime inputs used to collect answers and scaffold a
94
+ * project.
95
+ * @returns The scaffold result together with next-step guidance.
96
+ */
97
+ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templateId, dataStorageMode, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, yes = false, noInstall = false, isInteractive = false, allowExistingDir = false, selectTemplate, selectDataStorage, selectPersistencePolicy, selectPackageManager, promptText, installDependencies = undefined, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }) {
98
+ if (!projectInput) {
99
+ throw new Error("Project directory is required. Usage: wp-typia create <project-dir> (or wp-typia <project-dir>).");
100
+ }
101
+ const resolvedTemplateId = await resolveTemplateId({
102
+ templateId,
103
+ yes,
104
+ isInteractive,
105
+ selectTemplate,
106
+ });
107
+ const shouldResolvePersistence = templateUsesPersistenceSettings(resolvedTemplateId, {
108
+ dataStorageMode,
109
+ persistencePolicy,
110
+ });
111
+ const resolvedDataStorage = await resolveOptionalSelection({
112
+ allowedValues: DATA_STORAGE_MODES,
113
+ defaultValue: "custom-table",
114
+ explicitValue: dataStorageMode,
115
+ isInteractive,
116
+ isValue: isDataStorageMode,
117
+ label: "data storage mode",
118
+ select: selectDataStorage,
119
+ shouldResolve: shouldResolvePersistence,
120
+ yes,
121
+ });
122
+ const resolvedPersistencePolicy = await resolveOptionalSelection({
123
+ allowedValues: PERSISTENCE_POLICIES,
124
+ defaultValue: "authenticated",
125
+ explicitValue: persistencePolicy,
126
+ isInteractive,
127
+ isValue: isPersistencePolicy,
128
+ label: "persistence policy",
129
+ select: selectPersistencePolicy,
130
+ shouldResolve: shouldResolvePersistence,
131
+ yes,
132
+ });
133
+ const resolvedPackageManager = await resolvePackageManagerId({
134
+ packageManager,
135
+ yes,
136
+ isInteractive,
137
+ selectPackageManager,
138
+ });
139
+ const resolvedWithWpEnv = await resolveOptionalBooleanFlag({
140
+ explicitValue: withWpEnv,
141
+ isInteractive,
142
+ select: selectWithWpEnv,
143
+ yes,
144
+ });
145
+ const resolvedWithTestPreset = await resolveOptionalBooleanFlag({
146
+ explicitValue: withTestPreset,
147
+ isInteractive,
148
+ select: selectWithTestPreset,
149
+ yes,
150
+ });
151
+ const resolvedWithMigrationUi = await resolveOptionalBooleanFlag({
152
+ disabled: !isBuiltInTemplateId(resolvedTemplateId) &&
153
+ resolvedTemplateId !== OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE,
154
+ explicitValue: withMigrationUi,
155
+ isInteractive,
156
+ select: selectWithMigrationUi,
157
+ yes,
158
+ });
159
+ const projectDir = path.resolve(cwd, projectInput);
160
+ const projectName = path.basename(projectDir);
161
+ const answers = await collectScaffoldAnswers({
162
+ dataStorageMode: resolvedDataStorage,
163
+ namespace,
164
+ persistencePolicy: resolvedPersistencePolicy,
165
+ phpPrefix,
166
+ projectName,
167
+ templateId: resolvedTemplateId,
168
+ textDomain,
169
+ yes,
170
+ promptText,
171
+ });
172
+ const result = await scaffoldProject({
173
+ answers,
174
+ allowExistingDir,
175
+ cwd,
176
+ dataStorageMode: resolvedDataStorage,
177
+ installDependencies,
178
+ noInstall,
179
+ packageManager: resolvedPackageManager,
180
+ persistencePolicy: resolvedPersistencePolicy,
181
+ projectDir,
182
+ templateId: resolvedTemplateId,
183
+ variant,
184
+ withMigrationUi: resolvedWithMigrationUi,
185
+ withTestPreset: resolvedWithTestPreset,
186
+ withWpEnv: resolvedWithWpEnv,
187
+ });
188
+ return {
189
+ optionalOnboarding: getOptionalOnboarding({
190
+ packageManager: resolvedPackageManager,
191
+ templateId: resolvedTemplateId,
192
+ compoundPersistenceEnabled: result.variables.compoundPersistenceEnabled === "true",
193
+ }),
194
+ projectDir,
195
+ projectInput,
196
+ packageManager: resolvedPackageManager,
197
+ result,
198
+ nextSteps: getNextSteps({
199
+ projectInput,
200
+ projectDir,
201
+ packageManager: resolvedPackageManager,
202
+ noInstall,
203
+ templateId: resolvedTemplateId,
204
+ }),
205
+ };
206
+ }
@@ -0,0 +1,30 @@
1
+ import { getTemplateById, getTemplateSelectOptions, isBuiltInTemplateId, listTemplates } from "./template-registry.js";
2
+ import type { TemplateDefinition } from "./template-registry.js";
3
+ /**
4
+ * Format one line of template list output for a built-in template.
5
+ *
6
+ * @param template Template metadata including `id` and `description`.
7
+ * @returns One-line summary text for `templates list`.
8
+ */
9
+ export declare function formatTemplateSummary(template: TemplateDefinition): string;
10
+ /**
11
+ * Format the feature hint line shown under a template summary.
12
+ *
13
+ * @param template Template metadata including the `features` list.
14
+ * @returns Indented feature text for CLI list output.
15
+ */
16
+ export declare function formatTemplateFeatures(template: TemplateDefinition): string;
17
+ /**
18
+ * Format the detailed template description for `templates inspect`.
19
+ *
20
+ * This expands special layer combinations for the `persistence` and `compound`
21
+ * templates and returns a multi-line block including category, overlay path,
22
+ * resolved layers, and feature labels.
23
+ *
24
+ * @param template Template metadata including `id`, `defaultCategory`,
25
+ * `templateDir`, and `features`.
26
+ * @returns Multi-line template details text for CLI output.
27
+ */
28
+ export declare function formatTemplateDetails(template: TemplateDefinition): string;
29
+ export { getTemplateById, getTemplateSelectOptions, listTemplates };
30
+ export { isBuiltInTemplateId };