@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,12 @@
1
+ /**
2
+ * Generic record type used for JSON-like plain-object inspection.
3
+ */
4
+ export type UnknownRecord = Record<string, unknown>;
5
+ /**
6
+ * Check whether a value is a plain object record.
7
+ *
8
+ * @param value Runtime value to inspect.
9
+ * @returns `true` when the value is a non-null plain object with an
10
+ * `Object.prototype` or `null` prototype.
11
+ */
12
+ export declare function isPlainObject(value: unknown): value is UnknownRecord;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Check whether a value is a plain object record.
3
+ *
4
+ * @param value Runtime value to inspect.
5
+ * @returns `true` when the value is a non-null plain object with an
6
+ * `Object.prototype` or `null` prototype.
7
+ */
8
+ export function isPlainObject(value) {
9
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
10
+ return false;
11
+ }
12
+ const prototype = Object.getPrototypeOf(value);
13
+ return prototype === Object.prototype || prototype === null;
14
+ }
@@ -0,0 +1,28 @@
1
+ export type PackageManagerId = "bun" | "npm" | "pnpm" | "yarn";
2
+ export interface PackageManagerDefinition {
3
+ id: PackageManagerId;
4
+ label: string;
5
+ packageManagerField: string;
6
+ installCommand: string;
7
+ frozenInstallCommand: string;
8
+ }
9
+ export declare const PACKAGE_MANAGER_IDS: PackageManagerId[];
10
+ export declare const PACKAGE_MANAGERS: Readonly<Record<PackageManagerId, PackageManagerDefinition>>;
11
+ export declare function getPackageManager(id: string): PackageManagerDefinition;
12
+ export declare function getPackageManagerSelectOptions(): Array<{
13
+ label: string;
14
+ value: PackageManagerId;
15
+ hint: string;
16
+ }>;
17
+ export declare function formatRunScript(packageManagerId: PackageManagerId, scriptName: string, extraArgs?: string): string;
18
+ export declare function formatInstallCommand(packageManagerId: PackageManagerId): string;
19
+ /**
20
+ * Format a package-manager-specific one-off package execution command.
21
+ *
22
+ * @param packageManagerId Package manager identifier.
23
+ * @param packageName Executable package name.
24
+ * @param extraArgs Optional extra CLI arguments appended after the package name.
25
+ * @returns Command string suitable for shell execution.
26
+ */
27
+ export declare function formatPackageExecCommand(packageManagerId: PackageManagerId, packageName: string, extraArgs?: string): string;
28
+ export declare function transformPackageManagerText(content: string, packageManagerId: PackageManagerId): string;
@@ -0,0 +1,156 @@
1
+ const PACKAGE_MANAGER_DATA = [
2
+ {
3
+ id: "bun",
4
+ label: "Bun",
5
+ packageManagerField: "bun@1.3.10",
6
+ installCommand: "bun install",
7
+ frozenInstallCommand: "bun install --frozen-lockfile",
8
+ },
9
+ {
10
+ id: "npm",
11
+ label: "npm",
12
+ packageManagerField: "npm@11.6.1",
13
+ installCommand: "npm install",
14
+ frozenInstallCommand: "npm ci",
15
+ },
16
+ {
17
+ id: "pnpm",
18
+ label: "pnpm",
19
+ packageManagerField: "pnpm@8.3.1",
20
+ installCommand: "pnpm install",
21
+ frozenInstallCommand: "pnpm install --frozen-lockfile",
22
+ },
23
+ {
24
+ id: "yarn",
25
+ label: "Yarn",
26
+ packageManagerField: "yarn@3.2.4",
27
+ installCommand: "yarn install",
28
+ frozenInstallCommand: "yarn install --frozen-lockfile",
29
+ },
30
+ ];
31
+ export const PACKAGE_MANAGER_IDS = PACKAGE_MANAGER_DATA.map((manager) => manager.id);
32
+ export const PACKAGE_MANAGERS = Object.freeze(Object.fromEntries(PACKAGE_MANAGER_DATA.map((manager) => [manager.id, manager])));
33
+ const DEV_INSTALL_FLAGS = {
34
+ bun: "add -d",
35
+ npm: "install --save-dev",
36
+ pnpm: "add -D",
37
+ yarn: "add -D",
38
+ };
39
+ const STOP_CHARS = new Set(["\n", "\r", "`", "\"", "'", ")", "]", "}", "!", ",", "."]);
40
+ export function getPackageManager(id) {
41
+ const manager = PACKAGE_MANAGERS[id];
42
+ if (!manager) {
43
+ throw new Error(`Unknown package manager "${id}". Expected one of: ${PACKAGE_MANAGER_IDS.join(", ")}`);
44
+ }
45
+ return manager;
46
+ }
47
+ export function getPackageManagerSelectOptions() {
48
+ return PACKAGE_MANAGER_DATA.map((manager) => ({
49
+ label: manager.label,
50
+ value: manager.id,
51
+ hint: manager.installCommand,
52
+ }));
53
+ }
54
+ export function formatRunScript(packageManagerId, scriptName, extraArgs = "") {
55
+ const args = extraArgs.trim();
56
+ if (packageManagerId === "bun") {
57
+ return args ? `bun run ${scriptName} ${args}` : `bun run ${scriptName}`;
58
+ }
59
+ if (packageManagerId === "npm") {
60
+ return args ? `npm run ${scriptName} -- ${args}` : `npm run ${scriptName}`;
61
+ }
62
+ if (packageManagerId === "pnpm") {
63
+ return args ? `pnpm run ${scriptName} ${args}` : `pnpm run ${scriptName}`;
64
+ }
65
+ return args ? `yarn run ${scriptName} ${args}` : `yarn run ${scriptName}`;
66
+ }
67
+ export function formatInstallCommand(packageManagerId) {
68
+ return getPackageManager(packageManagerId).installCommand;
69
+ }
70
+ /**
71
+ * Format a package-manager-specific one-off package execution command.
72
+ *
73
+ * @param packageManagerId Package manager identifier.
74
+ * @param packageName Executable package name.
75
+ * @param extraArgs Optional extra CLI arguments appended after the package name.
76
+ * @returns Command string suitable for shell execution.
77
+ */
78
+ export function formatPackageExecCommand(packageManagerId, packageName, extraArgs = "") {
79
+ const args = extraArgs.trim();
80
+ if (packageManagerId === "bun") {
81
+ return args ? `bunx ${packageName} ${args}` : `bunx ${packageName}`;
82
+ }
83
+ if (packageManagerId === "npm") {
84
+ return args ? `npx --yes ${packageName} ${args}` : `npx --yes ${packageName}`;
85
+ }
86
+ if (packageManagerId === "pnpm") {
87
+ return args ? `pnpm dlx ${packageName} ${args}` : `pnpm dlx ${packageName}`;
88
+ }
89
+ return args ? `yarn dlx ${packageName} ${args}` : `yarn dlx ${packageName}`;
90
+ }
91
+ function consumeCommandArguments(content, startIndex) {
92
+ let cursor = startIndex;
93
+ let args = "";
94
+ while (cursor < content.length) {
95
+ const current = content[cursor];
96
+ if (STOP_CHARS.has(current) ||
97
+ content.startsWith("&&", cursor) ||
98
+ content.startsWith("||", cursor) ||
99
+ current === ";") {
100
+ break;
101
+ }
102
+ args += current;
103
+ cursor += 1;
104
+ }
105
+ return {
106
+ args: args.trim(),
107
+ cursor,
108
+ };
109
+ }
110
+ function replaceBunRunCommands(content, packageManagerId) {
111
+ const marker = "bun run ";
112
+ let result = "";
113
+ let cursor = 0;
114
+ while (cursor < content.length) {
115
+ const index = content.indexOf(marker, cursor);
116
+ if (index === -1) {
117
+ result += content.slice(cursor);
118
+ break;
119
+ }
120
+ if (index > 0 && /[A-Za-z0-9_-]/.test(content[index - 1])) {
121
+ result += content.slice(cursor, index + marker.length);
122
+ cursor = index + marker.length;
123
+ continue;
124
+ }
125
+ result += content.slice(cursor, index);
126
+ const scriptNameStart = index + marker.length;
127
+ const scriptNameMatch = /^[A-Za-z0-9:_-]+/.exec(content.slice(scriptNameStart));
128
+ if (!scriptNameMatch) {
129
+ result += marker;
130
+ cursor = scriptNameStart;
131
+ continue;
132
+ }
133
+ const scriptName = scriptNameMatch[0];
134
+ const argsStart = scriptNameStart + scriptName.length;
135
+ const { args, cursor: nextCursor } = consumeCommandArguments(content, argsStart);
136
+ result += formatRunScript(packageManagerId, scriptName, args);
137
+ cursor = nextCursor;
138
+ }
139
+ return result;
140
+ }
141
+ function replaceDevDependencyInstalls(content, packageManagerId) {
142
+ return content.replace(/\bbun add -d ([^\s&|;`"'()]+)\b/g, (_, packageName) => {
143
+ if (packageManagerId === "bun") {
144
+ return `bun add -d ${packageName}`;
145
+ }
146
+ return `${packageManagerId} ${DEV_INSTALL_FLAGS[packageManagerId]} ${packageName}`;
147
+ });
148
+ }
149
+ export function transformPackageManagerText(content, packageManagerId) {
150
+ const manager = getPackageManager(packageManagerId);
151
+ return replaceDevDependencyInstalls(replaceBunRunCommands(content
152
+ .replace(/\bbun install --frozen-lockfile\b/g, manager.frozenInstallCommand)
153
+ .replace(/\bbun install\b/g, manager.installCommand), packageManagerId), packageManagerId)
154
+ .replace(/\s*&&\s*/g, " && ")
155
+ .replace(/\s*\|\|\s*/g, " || ");
156
+ }
@@ -0,0 +1,10 @@
1
+ interface PackageVersions {
2
+ apiClientPackageVersion: string;
3
+ blockRuntimePackageVersion: string;
4
+ blockTypesPackageVersion: string;
5
+ projectToolsPackageVersion: string;
6
+ restPackageVersion: string;
7
+ wpTypiaPackageVersion: string;
8
+ }
9
+ export declare function getPackageVersions(): PackageVersions;
10
+ export {};
@@ -0,0 +1,68 @@
1
+ import fs from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ import { PROJECT_TOOLS_PACKAGE_ROOT } from "./template-registry.js";
5
+ const require = createRequire(import.meta.url);
6
+ const DEFAULT_VERSION_RANGE = "^0.0.0";
7
+ let cachedPackageVersions = null;
8
+ function getErrorCode(error) {
9
+ return typeof error === "object" && error !== null && "code" in error
10
+ ? String(error.code)
11
+ : undefined;
12
+ }
13
+ function normalizeVersionRange(value) {
14
+ const trimmed = value?.trim();
15
+ if (!trimmed) {
16
+ return DEFAULT_VERSION_RANGE;
17
+ }
18
+ return /^[~^<>=]/.test(trimmed) ? trimmed : `^${trimmed}`;
19
+ }
20
+ function readPackageManifest(packageJsonPath) {
21
+ try {
22
+ return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
23
+ }
24
+ catch (error) {
25
+ if (getErrorCode(error) === "ENOENT") {
26
+ return null;
27
+ }
28
+ throw error;
29
+ }
30
+ }
31
+ function resolveInstalledPackageManifest(packageName) {
32
+ try {
33
+ return readPackageManifest(require.resolve(`${packageName}/package.json`));
34
+ }
35
+ catch (error) {
36
+ if (getErrorCode(error) === "MODULE_NOT_FOUND") {
37
+ return null;
38
+ }
39
+ throw error;
40
+ }
41
+ }
42
+ export function getPackageVersions() {
43
+ if (cachedPackageVersions) {
44
+ return cachedPackageVersions;
45
+ }
46
+ const createManifest = readPackageManifest(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json")) ??
47
+ resolveInstalledPackageManifest("@wp-typia/project-tools") ??
48
+ {};
49
+ const blockRuntimeManifest = readPackageManifest(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia-block-runtime", "package.json")) ??
50
+ resolveInstalledPackageManifest("@wp-typia/block-runtime") ??
51
+ {};
52
+ const wpTypiaManifest = readPackageManifest(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json")) ??
53
+ resolveInstalledPackageManifest("wp-typia") ??
54
+ {};
55
+ cachedPackageVersions = {
56
+ apiClientPackageVersion: normalizeVersionRange(createManifest.dependencies?.["@wp-typia/api-client"] ??
57
+ resolveInstalledPackageManifest("@wp-typia/api-client")?.version),
58
+ blockRuntimePackageVersion: normalizeVersionRange(createManifest.dependencies?.["@wp-typia/block-runtime"] ??
59
+ blockRuntimeManifest.version),
60
+ blockTypesPackageVersion: normalizeVersionRange(createManifest.dependencies?.["@wp-typia/block-types"] ??
61
+ resolveInstalledPackageManifest("@wp-typia/block-types")?.version),
62
+ projectToolsPackageVersion: normalizeVersionRange(createManifest.version),
63
+ restPackageVersion: normalizeVersionRange(createManifest.dependencies?.["@wp-typia/rest"] ??
64
+ resolveInstalledPackageManifest("@wp-typia/rest")?.version),
65
+ wpTypiaPackageVersion: normalizeVersionRange(wpTypiaManifest.version),
66
+ };
67
+ return cachedPackageVersions;
68
+ }
@@ -0,0 +1,32 @@
1
+ import type { PackageManagerId } from "./package-managers.js";
2
+ interface SyncOnboardingOptions {
3
+ compoundPersistenceEnabled?: boolean;
4
+ }
5
+ interface PhpRestExtensionOptions extends SyncOnboardingOptions {
6
+ slug: string;
7
+ }
8
+ /**
9
+ * Returns the optional sync script names to suggest for a template.
10
+ */
11
+ export declare function getOptionalSyncScriptNames(templateId: string, options?: SyncOnboardingOptions): string[];
12
+ /**
13
+ * Formats optional onboarding sync commands for the selected package manager.
14
+ */
15
+ export declare function getOptionalOnboardingSteps(packageManager: PackageManagerId, templateId: string, options?: SyncOnboardingOptions): string[];
16
+ /**
17
+ * Returns the onboarding note explaining when manual sync is optional.
18
+ */
19
+ export declare function getOptionalOnboardingNote(packageManager: PackageManagerId, templateId?: string): string;
20
+ /**
21
+ * Returns source-of-truth guidance for generated artifacts by template mode.
22
+ */
23
+ export declare function getTemplateSourceOfTruthNote(templateId: string, { compoundPersistenceEnabled }?: SyncOnboardingOptions): string;
24
+ /**
25
+ * Returns the generated-project extension workflow for compound child blocks.
26
+ */
27
+ export declare function getCompoundExtensionWorkflowSection(packageManager: PackageManagerId, templateId: string): string | null;
28
+ /**
29
+ * Returns scaffold-local guidance for the main PHP REST customization points.
30
+ */
31
+ export declare function getPhpRestExtensionPointsSection(templateId: string, { compoundPersistenceEnabled, slug }: PhpRestExtensionOptions): string | null;
32
+ export {};
@@ -0,0 +1,99 @@
1
+ import { formatRunScript } from "./package-managers.js";
2
+ import { getPrimaryDevelopmentScript } from "./local-dev-presets.js";
3
+ function templateHasPersistenceSync(templateId, { compoundPersistenceEnabled = false } = {}) {
4
+ return templateId === "persistence" || (templateId === "compound" && compoundPersistenceEnabled);
5
+ }
6
+ /**
7
+ * Returns the optional sync script names to suggest for a template.
8
+ */
9
+ export function getOptionalSyncScriptNames(templateId, options = {}) {
10
+ return templateHasPersistenceSync(templateId, options)
11
+ ? ["sync-types", "sync-rest"]
12
+ : ["sync-types"];
13
+ }
14
+ /**
15
+ * Formats optional onboarding sync commands for the selected package manager.
16
+ */
17
+ export function getOptionalOnboardingSteps(packageManager, templateId, options = {}) {
18
+ return getOptionalSyncScriptNames(templateId, options).map((scriptName) => formatRunScript(packageManager, scriptName));
19
+ }
20
+ /**
21
+ * Returns the onboarding note explaining when manual sync is optional.
22
+ */
23
+ export function getOptionalOnboardingNote(packageManager, templateId = "basic") {
24
+ const developmentScript = getPrimaryDevelopmentScript(templateId);
25
+ const failOnLossySyncCommand = formatRunScript(packageManager, "sync-types", "--fail-on-lossy");
26
+ const syncTypesCommand = formatRunScript(packageManager, "sync-types");
27
+ const typecheckCommand = formatRunScript(packageManager, "typecheck");
28
+ const strictSyncCommand = formatRunScript(packageManager, "sync-types", "--strict --report json");
29
+ return `${formatRunScript(packageManager, developmentScript)} ${developmentScript === "dev"
30
+ ? "watches the relevant sync scripts during local development."
31
+ : "remains the primary local entry point."} ${formatRunScript(packageManager, "start")} still runs one-shot syncs before starting, while ${formatRunScript(packageManager, "build")} and ${typecheckCommand} verify that generated metadata/schema artifacts are already current and fail if they are stale. Run the sync scripts manually when you want to refresh generated artifacts before build, typecheck, or commit. ${syncTypesCommand} stays warn-only by default; use \`${failOnLossySyncCommand}\` to fail only on lossy WordPress projections, or \`${strictSyncCommand}\` for a CI-friendly JSON report that fails on all warnings. They do not create migration history.`;
32
+ }
33
+ /**
34
+ * Returns source-of-truth guidance for generated artifacts by template mode.
35
+ */
36
+ export function getTemplateSourceOfTruthNote(templateId, { compoundPersistenceEnabled = false } = {}) {
37
+ if (templateId === "compound") {
38
+ const compoundBase = "`src/blocks/*/types.ts` files remain the source of truth for each block's `block.json`, `typia.manifest.json`, and `typia-validator.php`. Fresh scaffolds include starter `typia.manifest.json` files so editor imports resolve before the first sync.";
39
+ if (compoundPersistenceEnabled) {
40
+ return `${compoundBase} For persistence-enabled parents, \`src/blocks/*/api-types.ts\` files remain the source of truth for \`src/blocks/*/api-schemas/*\` when you run \`sync-rest\`.`;
41
+ }
42
+ return compoundBase;
43
+ }
44
+ if (templateId === "persistence") {
45
+ return "`src/types.ts` remains the source of truth for `block.json`, `typia.manifest.json`, and `typia-validator.php`. Fresh scaffolds include a starter `typia.manifest.json` so editor imports resolve before the first sync. `src/api-types.ts` remains the source of truth for `src/api-schemas/*` when you run `sync-rest`. This scaffold is intentionally server-rendered: `src/render.php` is the canonical frontend entry, and `src/save.tsx` returns `null` so PHP can inject post context, storage-backed state, and write-policy bootstrap data before hydration.";
46
+ }
47
+ return "`src/types.ts` remains the source of truth for `block.json`, `typia.manifest.json`, and `typia-validator.php`. Fresh scaffolds include a starter `typia.manifest.json` so editor imports resolve before the first sync. The basic scaffold stays static by design: it does not generate `render.php`, `src/save.tsx` always returns stable markup, and the generated webpack config keeps the current `@wordpress/scripts` CommonJS baseline.";
48
+ }
49
+ /**
50
+ * Returns the generated-project extension workflow for compound child blocks.
51
+ */
52
+ export function getCompoundExtensionWorkflowSection(packageManager, templateId) {
53
+ if (templateId !== "compound") {
54
+ return null;
55
+ }
56
+ return `## Compound Extension Workflow
57
+
58
+ \`\`\`bash
59
+ ${formatRunScript(packageManager, "add-child", '--slug faq-item --title "FAQ Item"')}
60
+ \`\`\`
61
+
62
+ This scaffolds a new hidden child block type, updates \`scripts/block-config.ts\` and \`src/blocks/*/children.ts\`, and leaves the default seeded child template unchanged.`;
63
+ }
64
+ function formatPhpRestExtensionPointsSection({ apiTypesPath, extraNote, mainPhpPath, mainPhpScope, }) {
65
+ const schemaJsonGlob = apiTypesPath.replace(/api-types\.ts$/u, "api-schemas/*.schema.json");
66
+ const perContractOpenApiGlob = apiTypesPath.replace(/api-types\.ts$/u, "api-schemas/*.openapi.json");
67
+ const aggregateOpenApiPath = apiTypesPath.replace(/api-types\.ts$/u, "api.openapi.json");
68
+ const lines = [
69
+ `- Edit \`${mainPhpPath}\` when you need to ${mainPhpScope}.`,
70
+ "- Edit `inc/rest-auth.php` or `inc/rest-public.php` when you need to customize write permissions or token/request-id/nonce checks for the selected policy.",
71
+ `- Keep \`${apiTypesPath}\` as the source of truth for request and response contracts, then regenerate \`${schemaJsonGlob}\`, per-contract \`${perContractOpenApiGlob}\`, and \`${aggregateOpenApiPath}\` with \`sync-rest\`.`,
72
+ "- Avoid hand-editing generated schema and OpenAPI artifacts unless you are debugging generated output; they are meant to be regenerated from TypeScript contracts.",
73
+ ];
74
+ if (typeof extraNote === "string" && extraNote.length > 0) {
75
+ lines.push(`- ${extraNote}`);
76
+ }
77
+ return `## PHP REST Extension Points\n\n${lines.join("\n")}`;
78
+ }
79
+ /**
80
+ * Returns scaffold-local guidance for the main PHP REST customization points.
81
+ */
82
+ export function getPhpRestExtensionPointsSection(templateId, { compoundPersistenceEnabled = false, slug }) {
83
+ if (templateId === "persistence") {
84
+ return formatPhpRestExtensionPointsSection({
85
+ apiTypesPath: "src/api-types.ts",
86
+ mainPhpPath: `${slug}.php`,
87
+ mainPhpScope: "change storage helpers, route handlers, response shaping, or route registration",
88
+ });
89
+ }
90
+ if (templateId === "compound" && compoundPersistenceEnabled) {
91
+ return formatPhpRestExtensionPointsSection({
92
+ apiTypesPath: `src/blocks/${slug}/api-types.ts`,
93
+ extraNote: "The hidden child block does not own REST routes or storage.",
94
+ mainPhpPath: `${slug}.php`,
95
+ mainPhpScope: "change parent-block storage helpers, route handlers, response shaping, or route registration",
96
+ });
97
+ }
98
+ return null;
99
+ }
@@ -0,0 +1,146 @@
1
+ import type { PackageManagerId } from "./package-managers.js";
2
+ import type { BuiltInTemplateId } from "./template-registry.js";
3
+ /**
4
+ * User-facing scaffold answers before template rendering.
5
+ *
6
+ * `namespace`, `textDomain`, and `phpPrefix` are normalized before use so
7
+ * callers can pass human-entered values while generated output stays
8
+ * predictable.
9
+ */
10
+ export interface ScaffoldAnswers {
11
+ author: string;
12
+ dataStorageMode?: DataStorageMode;
13
+ description: string;
14
+ /** Block namespace used in generated block names such as `namespace/slug`. */
15
+ namespace: string;
16
+ persistencePolicy?: PersistencePolicy;
17
+ /** Snake_case PHP symbol prefix used for generated functions, constants, and keys. */
18
+ phpPrefix?: string;
19
+ slug: string;
20
+ /** Kebab-case WordPress text domain used in block metadata and i18n strings. */
21
+ textDomain?: string;
22
+ title: string;
23
+ }
24
+ export declare const DATA_STORAGE_MODES: readonly ["post-meta", "custom-table"];
25
+ export type DataStorageMode = (typeof DATA_STORAGE_MODES)[number];
26
+ export declare const PERSISTENCE_POLICIES: readonly ["authenticated", "public"];
27
+ export type PersistencePolicy = (typeof PERSISTENCE_POLICIES)[number];
28
+ /**
29
+ * Normalized template variables shared by built-in and remote scaffold flows.
30
+ */
31
+ export interface ScaffoldTemplateVariables extends Record<string, string> {
32
+ apiClientPackageVersion: string;
33
+ author: string;
34
+ blockRuntimePackageVersion: string;
35
+ blockMetadataVersion: string;
36
+ blockTypesPackageVersion: string;
37
+ category: string;
38
+ icon: string;
39
+ compoundChildTitle: string;
40
+ compoundChildCategory: string;
41
+ compoundChildCssClassName: string;
42
+ compoundChildIcon: string;
43
+ compoundChildTitleJson: string;
44
+ compoundPersistenceEnabled: "false" | "true";
45
+ projectToolsPackageVersion: string;
46
+ cssClassName: string;
47
+ dashCase: string;
48
+ dataStorageMode: DataStorageMode;
49
+ description: string;
50
+ frontendCssClassName: string;
51
+ keyword: string;
52
+ namespace: string;
53
+ needsMigration: string;
54
+ pascalCase: string;
55
+ phpPrefix: string;
56
+ phpPrefixUpper: string;
57
+ isAuthenticatedPersistencePolicy: "false" | "true";
58
+ isPublicPersistencePolicy: "false" | "true";
59
+ publicWriteRequestIdDeclaration: string;
60
+ restPackageVersion: string;
61
+ restWriteAuthIntent: "authenticated" | "public-write-protected";
62
+ restWriteAuthMechanism: "public-signed-token" | "rest-nonce";
63
+ restWriteAuthMode: "authenticated-rest-nonce" | "public-signed-token";
64
+ slug: string;
65
+ slugCamelCase: string;
66
+ slugKebabCase: string;
67
+ slugSnakeCase: string;
68
+ textDomain: string;
69
+ textdomain: string;
70
+ title: string;
71
+ titleJson: string;
72
+ titleCase: string;
73
+ persistencePolicy: PersistencePolicy;
74
+ }
75
+ interface ResolveTemplateOptions {
76
+ isInteractive?: boolean;
77
+ selectTemplate?: () => Promise<BuiltInTemplateId>;
78
+ templateId?: string;
79
+ yes?: boolean;
80
+ }
81
+ interface ResolvePackageManagerOptions {
82
+ isInteractive?: boolean;
83
+ packageManager?: string;
84
+ selectPackageManager?: () => Promise<PackageManagerId>;
85
+ yes?: boolean;
86
+ }
87
+ interface CollectScaffoldAnswersOptions {
88
+ dataStorageMode?: DataStorageMode;
89
+ namespace?: string;
90
+ phpPrefix?: string;
91
+ projectName: string;
92
+ promptText?: (message: string, defaultValue: string, validate?: (value: string) => true | string) => Promise<string>;
93
+ persistencePolicy?: PersistencePolicy;
94
+ textDomain?: string;
95
+ templateId: string;
96
+ withTestPreset?: boolean;
97
+ withWpEnv?: boolean;
98
+ yes?: boolean;
99
+ }
100
+ interface InstallDependenciesOptions {
101
+ packageManager: PackageManagerId;
102
+ projectDir: string;
103
+ }
104
+ interface ScaffoldProjectOptions {
105
+ allowExistingDir?: boolean;
106
+ answers: ScaffoldAnswers;
107
+ cwd?: string;
108
+ dataStorageMode?: DataStorageMode;
109
+ installDependencies?: ((options: InstallDependenciesOptions) => Promise<void>) | undefined;
110
+ noInstall?: boolean;
111
+ packageManager: PackageManagerId;
112
+ persistencePolicy?: PersistencePolicy;
113
+ projectDir: string;
114
+ templateId: string;
115
+ variant?: string;
116
+ withMigrationUi?: boolean;
117
+ withTestPreset?: boolean;
118
+ withWpEnv?: boolean;
119
+ }
120
+ export interface ScaffoldProjectResult {
121
+ packageManager: PackageManagerId;
122
+ projectDir: string;
123
+ selectedVariant: string | null;
124
+ templateId: string;
125
+ variables: ScaffoldTemplateVariables;
126
+ warnings: string[];
127
+ }
128
+ /**
129
+ * Builds the generated WordPress wrapper CSS class for a scaffolded block.
130
+ *
131
+ * Returns `wp-block-{namespace}-{slug}` when a non-empty namespace is present,
132
+ * or `wp-block-{slug}` when the namespace is empty or undefined. Both inputs
133
+ * are normalized and validated with the same scaffold identifier rules used for
134
+ * block names.
135
+ */
136
+ export declare function buildBlockCssClassName(namespace: string | undefined, slug: string): string;
137
+ export declare function isDataStorageMode(value: string): value is DataStorageMode;
138
+ export declare function isPersistencePolicy(value: string): value is PersistencePolicy;
139
+ export declare function detectAuthor(): string;
140
+ export declare function getDefaultAnswers(projectName: string, templateId: string): ScaffoldAnswers;
141
+ export declare function resolveTemplateId({ templateId, yes, isInteractive, selectTemplate, }: ResolveTemplateOptions): Promise<string>;
142
+ export declare function resolvePackageManagerId({ packageManager, yes, isInteractive, selectPackageManager, }: ResolvePackageManagerOptions): Promise<PackageManagerId>;
143
+ export declare function collectScaffoldAnswers({ projectName, templateId, yes, dataStorageMode, namespace, persistencePolicy, phpPrefix, promptText, textDomain, }: CollectScaffoldAnswersOptions): Promise<ScaffoldAnswers>;
144
+ export declare function getTemplateVariables(templateId: string, answers: ScaffoldAnswers): ScaffoldTemplateVariables;
145
+ export declare function scaffoldProject({ projectDir, templateId, answers, dataStorageMode, persistencePolicy, packageManager, cwd, allowExistingDir, noInstall, installDependencies, variant, withMigrationUi, withTestPreset, withWpEnv, }: ScaffoldProjectOptions): Promise<ScaffoldProjectResult>;
146
+ export {};