@wp-typia/project-tools 0.20.2 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/runtime/cli-add-shared.d.ts +73 -5
  2. package/dist/runtime/cli-add-shared.js +58 -11
  3. package/dist/runtime/cli-add-workspace-ability.js +11 -57
  4. package/dist/runtime/cli-add-workspace-admin-view.d.ts +23 -0
  5. package/dist/runtime/cli-add-workspace-admin-view.js +872 -0
  6. package/dist/runtime/cli-add-workspace-ai-anchors.js +2 -5
  7. package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +0 -4
  8. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +7 -17
  9. package/dist/runtime/cli-add-workspace-ai.js +4 -6
  10. package/dist/runtime/cli-add-workspace-assets.d.ts +13 -5
  11. package/dist/runtime/cli-add-workspace-assets.js +290 -106
  12. package/dist/runtime/cli-add-workspace-rest-anchors.js +2 -5
  13. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +0 -1
  14. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +7 -14
  15. package/dist/runtime/cli-add-workspace-rest.js +4 -6
  16. package/dist/runtime/cli-add-workspace.d.ts +58 -1
  17. package/dist/runtime/cli-add-workspace.js +588 -18
  18. package/dist/runtime/cli-add.d.ts +1 -1
  19. package/dist/runtime/cli-add.js +1 -1
  20. package/dist/runtime/cli-core.d.ts +8 -5
  21. package/dist/runtime/cli-core.js +7 -4
  22. package/dist/runtime/cli-diagnostics.d.ts +83 -1
  23. package/dist/runtime/cli-diagnostics.js +85 -2
  24. package/dist/runtime/cli-doctor-workspace.js +552 -13
  25. package/dist/runtime/cli-doctor.d.ts +4 -2
  26. package/dist/runtime/cli-doctor.js +2 -1
  27. package/dist/runtime/cli-help.js +19 -9
  28. package/dist/runtime/cli-init.d.ts +67 -3
  29. package/dist/runtime/cli-init.js +603 -64
  30. package/dist/runtime/cli-validation.js +4 -3
  31. package/dist/runtime/index.d.ts +9 -4
  32. package/dist/runtime/index.js +7 -3
  33. package/dist/runtime/package-json-types.d.ts +12 -0
  34. package/dist/runtime/package-json-types.js +1 -0
  35. package/dist/runtime/package-versions.d.ts +17 -2
  36. package/dist/runtime/package-versions.js +46 -1
  37. package/dist/runtime/php-utils.d.ts +16 -0
  38. package/dist/runtime/php-utils.js +59 -0
  39. package/dist/runtime/scaffold-answer-resolution.js +7 -6
  40. package/dist/runtime/scaffold-apply-utils.d.ts +2 -3
  41. package/dist/runtime/scaffold-apply-utils.js +3 -43
  42. package/dist/runtime/template-source-cache.d.ts +112 -0
  43. package/dist/runtime/template-source-cache.js +434 -0
  44. package/dist/runtime/template-source-seeds.js +319 -53
  45. package/dist/runtime/workspace-inventory.d.ts +43 -2
  46. package/dist/runtime/workspace-inventory.js +138 -5
  47. package/package.json +2 -2
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { CLI_DIAGNOSTIC_CODES, createCliDiagnosticCodeError, } from "./cli-diagnostics.js";
3
4
  /**
4
5
  * Normalize one optional CLI string flag by trimming whitespace and collapsing
5
6
  * empty strings to `undefined`.
@@ -44,7 +45,7 @@ export function resolveLocalCliPathOption(options) {
44
45
  }
45
46
  const resolvedPath = path.resolve(options.cwd, normalizedValue);
46
47
  if (!fs.existsSync(resolvedPath)) {
47
- throw new Error(`\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
48
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
48
49
  }
49
50
  return resolvedPath;
50
51
  }
@@ -58,7 +59,7 @@ export function resolveLocalCliPathOption(options) {
58
59
  */
59
60
  export function assertExternalLayerCompositionOptions(options) {
60
61
  if (options.externalLayerId && !options.externalLayerSource) {
61
- throw new Error("externalLayerId requires externalLayerSource when composing built-in template layers.");
62
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "externalLayerId requires externalLayerSource when composing built-in template layers.");
62
63
  }
63
64
  }
64
65
  /**
@@ -85,7 +86,7 @@ export function assertBuiltInTemplateVariantAllowed(options) {
85
86
  if (!options.variant) {
86
87
  return;
87
88
  }
88
- throw new Error(createBuiltInVariantErrorMessage({
89
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, createBuiltInVariantErrorMessage({
89
90
  templateId: options.templateId,
90
91
  variant: options.variant,
91
92
  }));
@@ -5,8 +5,11 @@
5
5
  * CLI while keeping reusable project logic out of the CLI package itself.
6
6
  * Consumers should prefer these exports for scaffold, add, migrate, doctor,
7
7
  * and workspace-aware helpers such as `getWorkspaceBlockSelectOptions`,
8
- * `runAddBlockCommand`, `runAddVariationCommand`, `runAddPatternCommand`,
9
- * `runAddBindingSourceCommand`, `runAddEditorPluginCommand`,
8
+ * `runAddBlockCommand`, `runAddBlockStyleCommand`,
9
+ * `runAddBlockTransformCommand`, `runAddVariationCommand`,
10
+ * `runAddPatternCommand`, `runAddBindingSourceCommand`,
11
+ * `runAddEditorPluginCommand`,
12
+ * `runAddAdminViewCommand`,
10
13
  * `runAddHookedBlockCommand`,
11
14
  * `HOOKED_BLOCK_POSITION_IDS`, and `runDoctor`.
12
15
  */
@@ -26,7 +29,9 @@ export { manifestAttributeToJsonSchema, projectJsonSchemaDocument, manifestToJso
26
29
  export { buildCompoundChildStarterManifestDocument, getStarterManifestFiles, stringifyStarterManifest, } from "./starter-manifests.js";
27
30
  export type { EndpointAuthIntent, EndpointOpenApiAuthMode, EndpointOpenApiContractDocument, EndpointOpenApiDocumentOptions, EndpointOpenApiEndpointDefinition, EndpointOpenApiMethod, EndpointWordPressAuthDefinition, EndpointWordPressAuthMechanism, JsonSchemaDocument, JsonSchemaProjectionProfile, JsonSchemaObject, NormalizedEndpointAuthDefinition, OpenApiDocument, OpenApiInfo, OpenApiOperation, OpenApiParameter, OpenApiPathItem, OpenApiSecurityScheme, } from "./schema-core.js";
28
31
  export { PACKAGE_MANAGER_IDS, PACKAGE_MANAGERS, formatPackageExecCommand, formatInstallCommand, formatRunScript, getPackageManager, getPackageManagerSelectOptions, transformPackageManagerText, } from "./package-managers.js";
32
+ export { clearPackageVersionsCache, getPackageVersions, invalidatePackageVersionsCache, } from "./package-versions.js";
33
+ export type { PackageVersions } from "./package-versions.js";
29
34
  export { TEMPLATE_IDS, TEMPLATE_REGISTRY, getTemplateById, getTemplateSelectOptions, listTemplates, } from "./template-registry.js";
30
35
  export { STALE_TEMP_ROOT_MAX_AGE_MS, WP_TYPIA_TEMP_ROOT_PREFIX, cleanupManagedTempRoot, cleanupStaleTempRoots, createManagedTempRoot, getTrackedTempRoots, } from "./temp-roots.js";
31
- export { createReadlinePrompt, createCliCommandError, CliDiagnosticError, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, HOOKED_BLOCK_POSITION_IDS, EDITOR_PLUGIN_SLOT_IDS, isCliDiagnosticError, runAddAbilityCommand, runAddAiFeatureCommand, runAddBindingSourceCommand, runAddBlockCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runDoctor, runAddVariationCommand, runScaffoldFlow, } from "./cli-core.js";
32
- export type { CliDiagnosticMessage, DoctorCheck, EditorPluginSlotId, HookedBlockPositionId, ReadlinePrompt, } from "./cli-core.js";
36
+ export { createReadlinePrompt, createCliCommandError, createCliDiagnosticCodeError, CliDiagnosticError, CLI_DIAGNOSTIC_CODES, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, 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";
37
+ export type { CliDiagnosticCode, CliDiagnosticCodeError, CliDiagnosticMessage, DoctorCheck, EditorPluginSlotId, HookedBlockPositionId, ReadlinePrompt, } from "./cli-core.js";
@@ -5,8 +5,11 @@
5
5
  * CLI while keeping reusable project logic out of the CLI package itself.
6
6
  * Consumers should prefer these exports for scaffold, add, migrate, doctor,
7
7
  * and workspace-aware helpers such as `getWorkspaceBlockSelectOptions`,
8
- * `runAddBlockCommand`, `runAddVariationCommand`, `runAddPatternCommand`,
9
- * `runAddBindingSourceCommand`, `runAddEditorPluginCommand`,
8
+ * `runAddBlockCommand`, `runAddBlockStyleCommand`,
9
+ * `runAddBlockTransformCommand`, `runAddVariationCommand`,
10
+ * `runAddPatternCommand`, `runAddBindingSourceCommand`,
11
+ * `runAddEditorPluginCommand`,
12
+ * `runAddAdminViewCommand`,
10
13
  * `runAddHookedBlockCommand`,
11
14
  * `HOOKED_BLOCK_POSITION_IDS`, and `runDoctor`.
12
15
  */
@@ -20,6 +23,7 @@ export { parseWorkspacePackageManagerId, resolveWorkspaceProject, tryResolveWork
20
23
  export { manifestAttributeToJsonSchema, projectJsonSchemaDocument, manifestToJsonSchema, manifestToOpenApi, normalizeEndpointAuthDefinition, } from "./schema-core.js";
21
24
  export { buildCompoundChildStarterManifestDocument, getStarterManifestFiles, stringifyStarterManifest, } from "./starter-manifests.js";
22
25
  export { PACKAGE_MANAGER_IDS, PACKAGE_MANAGERS, formatPackageExecCommand, formatInstallCommand, formatRunScript, getPackageManager, getPackageManagerSelectOptions, transformPackageManagerText, } from "./package-managers.js";
26
+ export { clearPackageVersionsCache, getPackageVersions, invalidatePackageVersionsCache, } from "./package-versions.js";
23
27
  export { TEMPLATE_IDS, TEMPLATE_REGISTRY, getTemplateById, getTemplateSelectOptions, listTemplates, } from "./template-registry.js";
24
28
  export { STALE_TEMP_ROOT_MAX_AGE_MS, WP_TYPIA_TEMP_ROOT_PREFIX, cleanupManagedTempRoot, cleanupStaleTempRoots, createManagedTempRoot, getTrackedTempRoots, } from "./temp-roots.js";
25
- export { createReadlinePrompt, createCliCommandError, CliDiagnosticError, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, HOOKED_BLOCK_POSITION_IDS, EDITOR_PLUGIN_SLOT_IDS, isCliDiagnosticError, runAddAbilityCommand, runAddAiFeatureCommand, runAddBindingSourceCommand, runAddBlockCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runDoctor, runAddVariationCommand, runScaffoldFlow, } from "./cli-core.js";
29
+ export { createReadlinePrompt, createCliCommandError, createCliDiagnosticCodeError, CliDiagnosticError, CLI_DIAGNOSTIC_CODES, formatCliDiagnosticError, formatAddHelpText, formatDoctorCheckLine, formatDoctorSummaryLine, formatHelpText, formatTemplateDetails, formatTemplateFeatures, formatTemplateSummary, getDoctorChecks, getDoctorFailureDetailLines, getFailingDoctorChecks, getNextSteps, getOptionalOnboarding, getWorkspaceBlockSelectOptions, 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";
@@ -0,0 +1,12 @@
1
+ export interface GeneratedPackageJson {
2
+ dependencies?: Record<string, string>;
3
+ devDependencies?: Record<string, string>;
4
+ packageManager?: string;
5
+ scripts?: Record<string, string>;
6
+ wpTypia?: {
7
+ projectType?: string;
8
+ templatePackage?: string;
9
+ [key: string]: unknown;
10
+ };
11
+ [key: string]: unknown;
12
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,9 +1,13 @@
1
- interface PackageVersions {
1
+ export interface PackageVersions {
2
2
  apiClientPackageVersion: string;
3
3
  blockRuntimePackageVersion: string;
4
4
  blockTypesPackageVersion: string;
5
5
  projectToolsPackageVersion: string;
6
6
  restPackageVersion: string;
7
+ tsxPackageVersion: string;
8
+ typiaPackageVersion: string;
9
+ typiaUnpluginPackageVersion: string;
10
+ typescriptPackageVersion: string;
7
11
  wpTypiaPackageExactVersion: string;
8
12
  wpTypiaPackageVersion: string;
9
13
  }
@@ -14,6 +18,17 @@ interface PackageVersions {
14
18
  * manifests when they want the next lookup to recompute version metadata
15
19
  * synchronously from disk.
16
20
  */
21
+ export declare function clearPackageVersionsCache(): void;
22
+ /**
23
+ * Backwards-compatible alias for integrations that adopted the original
24
+ * internal invalidation name before the public cache policy was documented.
25
+ */
17
26
  export declare function invalidatePackageVersionsCache(): void;
27
+ /**
28
+ * Resolve package versions used in generated manifests and onboarding text.
29
+ *
30
+ * The lookup keeps a process-local cached result while recomputing manifest
31
+ * fingerprints on each call. When the relevant package metadata changes on
32
+ * disk, the cache key changes and the returned version object is refreshed.
33
+ */
18
34
  export declare function getPackageVersions(): PackageVersions;
19
- export {};
@@ -5,6 +5,8 @@ import { PROJECT_TOOLS_PACKAGE_ROOT } from "./template-registry.js";
5
5
  const require = createRequire(import.meta.url);
6
6
  const DEFAULT_VERSION_RANGE = "^0.0.0";
7
7
  const DEFAULT_EXACT_VERSION = "0.0.0";
8
+ const DEFAULT_TSX_PACKAGE_VERSION = "^4.20.5";
9
+ const DEFAULT_TYPIA_UNPLUGIN_PACKAGE_VERSION = "^12.0.1";
8
10
  let cachedPackageVersions = null;
9
11
  function getErrorCode(error) {
10
12
  return typeof error === "object" && error !== null && "code" in error
@@ -31,6 +33,10 @@ function normalizeExactVersion(value) {
31
33
  }
32
34
  return trimmed.replace(/^[~^<>=]+/, "");
33
35
  }
36
+ function normalizeVersionRangeWithFallback(value, fallback) {
37
+ const normalized = normalizeVersionRange(value);
38
+ return normalized === DEFAULT_VERSION_RANGE ? fallback : normalized;
39
+ }
34
40
  function createContentFingerprint(source) {
35
41
  let hash = 2166136261;
36
42
  for (let index = 0; index < source.length; index += 1) {
@@ -91,11 +97,26 @@ function composePackageVersionsCacheKey(locations) {
91
97
  * manifests when they want the next lookup to recompute version metadata
92
98
  * synchronously from disk.
93
99
  */
94
- export function invalidatePackageVersionsCache() {
100
+ export function clearPackageVersionsCache() {
95
101
  cachedPackageVersions = null;
96
102
  }
103
+ /**
104
+ * Backwards-compatible alias for integrations that adopted the original
105
+ * internal invalidation name before the public cache policy was documented.
106
+ */
107
+ export function invalidatePackageVersionsCache() {
108
+ clearPackageVersionsCache();
109
+ }
110
+ /**
111
+ * Resolve package versions used in generated manifests and onboarding text.
112
+ *
113
+ * The lookup keeps a process-local cached result while recomputing manifest
114
+ * fingerprints on each call. When the relevant package metadata changes on
115
+ * disk, the cache key changes and the returned version object is refreshed.
116
+ */
97
117
  export function getPackageVersions() {
98
118
  const createManifestLocation = resolvePackageManifestLocation(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json"));
119
+ const monorepoManifestLocation = resolvePackageManifestLocation(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "..", "..", "package.json"));
99
120
  const blockRuntimeManifestLocation = resolvePackageManifestLocation(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia-block-runtime", "package.json"));
100
121
  const wpTypiaManifestLocation = resolvePackageManifestLocation(path.join(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json"));
101
122
  const installedProjectToolsManifestLocation = resolveInstalledPackageManifestLocation("@wp-typia/project-tools");
@@ -103,9 +124,14 @@ export function getPackageVersions() {
103
124
  const installedBlockRuntimeManifestLocation = resolveInstalledPackageManifestLocation("@wp-typia/block-runtime");
104
125
  const installedBlockTypesManifestLocation = resolveInstalledPackageManifestLocation("@wp-typia/block-types");
105
126
  const installedRestManifestLocation = resolveInstalledPackageManifestLocation("@wp-typia/rest");
127
+ const installedTsxManifestLocation = resolveInstalledPackageManifestLocation("tsx");
128
+ const installedTypiaManifestLocation = resolveInstalledPackageManifestLocation("typia");
129
+ const installedTypiaUnpluginManifestLocation = resolveInstalledPackageManifestLocation("@typia/unplugin");
130
+ const installedTypescriptManifestLocation = resolveInstalledPackageManifestLocation("typescript");
106
131
  const installedWpTypiaManifestLocation = resolveInstalledPackageManifestLocation("wp-typia");
107
132
  const cacheKey = composePackageVersionsCacheKey([
108
133
  createManifestLocation,
134
+ monorepoManifestLocation,
109
135
  blockRuntimeManifestLocation,
110
136
  wpTypiaManifestLocation,
111
137
  installedProjectToolsManifestLocation,
@@ -113,6 +139,10 @@ export function getPackageVersions() {
113
139
  installedBlockRuntimeManifestLocation,
114
140
  installedBlockTypesManifestLocation,
115
141
  installedRestManifestLocation,
142
+ installedTsxManifestLocation,
143
+ installedTypiaManifestLocation,
144
+ installedTypiaUnpluginManifestLocation,
145
+ installedTypescriptManifestLocation,
116
146
  installedWpTypiaManifestLocation,
117
147
  ]);
118
148
  if (cachedPackageVersions?.cacheKey === cacheKey) {
@@ -121,6 +151,7 @@ export function getPackageVersions() {
121
151
  const createManifest = readPackageManifest(createManifestLocation) ??
122
152
  readPackageManifest(installedProjectToolsManifestLocation) ??
123
153
  {};
154
+ const monorepoManifest = readPackageManifest(monorepoManifestLocation) ?? {};
124
155
  const blockRuntimeManifest = readPackageManifest(blockRuntimeManifestLocation) ??
125
156
  readPackageManifest(installedBlockRuntimeManifestLocation) ??
126
157
  {};
@@ -139,6 +170,20 @@ export function getPackageVersions() {
139
170
  projectToolsPackageVersion: normalizeVersionRange(createManifest.version),
140
171
  restPackageVersion: normalizeVersionRange(createManifest.dependencies?.["@wp-typia/rest"] ??
141
172
  readPackageManifest(installedRestManifestLocation)?.version),
173
+ tsxPackageVersion: normalizeVersionRangeWithFallback(monorepoManifest.dependencies?.tsx ??
174
+ monorepoManifest.devDependencies?.tsx ??
175
+ readPackageManifest(installedTsxManifestLocation)?.version, DEFAULT_TSX_PACKAGE_VERSION),
176
+ typiaPackageVersion: normalizeVersionRangeWithFallback(monorepoManifest.dependencies?.typia ??
177
+ monorepoManifest.devDependencies?.typia ??
178
+ createManifest.dependencies?.typia ??
179
+ readPackageManifest(installedTypiaManifestLocation)?.version, DEFAULT_VERSION_RANGE),
180
+ typiaUnpluginPackageVersion: normalizeVersionRangeWithFallback(monorepoManifest.dependencies?.["@typia/unplugin"] ??
181
+ monorepoManifest.devDependencies?.["@typia/unplugin"] ??
182
+ readPackageManifest(installedTypiaUnpluginManifestLocation)?.version, DEFAULT_TYPIA_UNPLUGIN_PACKAGE_VERSION),
183
+ typescriptPackageVersion: normalizeVersionRangeWithFallback(monorepoManifest.dependencies?.typescript ??
184
+ monorepoManifest.devDependencies?.typescript ??
185
+ createManifest.dependencies?.typescript ??
186
+ readPackageManifest(installedTypescriptManifestLocation)?.version, DEFAULT_VERSION_RANGE),
142
187
  wpTypiaPackageExactVersion: normalizeExactVersion(wpTypiaManifest.version),
143
188
  wpTypiaPackageVersion: normalizeVersionRange(wpTypiaManifest.version),
144
189
  };
@@ -0,0 +1,16 @@
1
+ export type PhpFunctionRange = {
2
+ end: number;
3
+ source: string;
4
+ start: number;
5
+ };
6
+ export type PhpFunctionRangeOptions = {
7
+ includeTrailingNewlines?: boolean;
8
+ };
9
+ export type ReplacePhpFunctionDefinitionOptions = PhpFunctionRangeOptions & {
10
+ trimReplacementStart?: boolean;
11
+ };
12
+ export declare function escapeRegex(value: string): string;
13
+ export declare function quotePhpString(value: string): string;
14
+ export declare function hasPhpFunctionDefinition(source: string, functionName: string): boolean;
15
+ export declare function findPhpFunctionRange(source: string, functionName: string, options?: PhpFunctionRangeOptions): PhpFunctionRange | null;
16
+ export declare function replacePhpFunctionDefinition(source: string, functionName: string, replacement: string, options?: ReplacePhpFunctionDefinitionOptions): string | null;
@@ -0,0 +1,59 @@
1
+ export function escapeRegex(value) {
2
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
3
+ }
4
+ export function quotePhpString(value) {
5
+ return `'${value.replace(/\\/gu, "\\\\").replace(/'/gu, "\\'")}'`;
6
+ }
7
+ export function hasPhpFunctionDefinition(source, functionName) {
8
+ return new RegExp(`function\\s+${escapeRegex(functionName)}\\s*\\(`, "u").test(source);
9
+ }
10
+ export function findPhpFunctionRange(source, functionName, options = {}) {
11
+ const signaturePattern = new RegExp(`function\\s+${escapeRegex(functionName)}\\s*\\([^)]*\\)\\s*(?::\\s*[^{};]+)?\\s*\\{`, "u");
12
+ const signatureMatch = signaturePattern.exec(source);
13
+ if (!signatureMatch) {
14
+ return null;
15
+ }
16
+ const functionStart = signatureMatch.index;
17
+ const openBraceOffset = signatureMatch[0].lastIndexOf("{");
18
+ if (openBraceOffset === -1) {
19
+ return null;
20
+ }
21
+ const openBraceIndex = functionStart + openBraceOffset;
22
+ let depth = 0;
23
+ for (let index = openBraceIndex; index < source.length; index += 1) {
24
+ const character = source[index];
25
+ if (character === "{") {
26
+ depth += 1;
27
+ continue;
28
+ }
29
+ if (character !== "}") {
30
+ continue;
31
+ }
32
+ depth -= 1;
33
+ if (depth === 0) {
34
+ let end = index + 1;
35
+ if (options.includeTrailingNewlines ?? true) {
36
+ while (end < source.length && /[\r\n]/u.test(source[end] ?? "")) {
37
+ end += 1;
38
+ }
39
+ }
40
+ return {
41
+ end,
42
+ source: source.slice(functionStart, end),
43
+ start: functionStart,
44
+ };
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ export function replacePhpFunctionDefinition(source, functionName, replacement, options = {}) {
50
+ const functionRange = findPhpFunctionRange(source, functionName, options);
51
+ if (!functionRange) {
52
+ return null;
53
+ }
54
+ return [
55
+ source.slice(0, functionRange.start),
56
+ options.trimReplacementStart ? replacement.trimStart() : replacement,
57
+ source.slice(functionRange.end),
58
+ ].join("");
59
+ }
@@ -2,6 +2,7 @@ import { execSync } from 'node:child_process';
2
2
  import path from 'node:path';
3
3
  import { PACKAGE_MANAGER_IDS, getPackageManager, } from './package-managers.js';
4
4
  import { normalizeBlockSlug, resolveScaffoldIdentifiers, validateBlockSlug, validateNamespace, } from './scaffold-identifiers.js';
5
+ import { CLI_DIAGNOSTIC_CODES, createCliDiagnosticCodeError, } from './cli-diagnostics.js';
5
6
  import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, TEMPLATE_IDS, getTemplateById, isBuiltInTemplateId, } from './template-registry.js';
6
7
  import { getRemovedBuiltInTemplateMessage, isRemovedBuiltInTemplateId, } from './template-defaults.js';
7
8
  import { parseNpmTemplateLocator } from './template-source-locators.js';
@@ -75,7 +76,7 @@ function normalizeQueryPostType(value) {
75
76
  }
76
77
  const validationResult = validateQueryPostType(value);
77
78
  if (validationResult !== true) {
78
- throw new Error(validationResult);
79
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, validationResult);
79
80
  }
80
81
  return value.trim().toLowerCase();
81
82
  }
@@ -163,7 +164,7 @@ export async function resolveTemplateId({ templateId, yes = false, isInteractive
163
164
  if (templateId) {
164
165
  const normalizedTemplateId = normalizeTemplateSelection(templateId);
165
166
  if (isRemovedBuiltInTemplateId(templateId)) {
166
- throw new Error(getRemovedBuiltInTemplateMessage(templateId));
167
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getRemovedBuiltInTemplateMessage(templateId));
167
168
  }
168
169
  if (normalizedTemplateId === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE) {
169
170
  return normalizedTemplateId;
@@ -173,10 +174,10 @@ export async function resolveTemplateId({ templateId, yes = false, isInteractive
173
174
  }
174
175
  const mistypedBuiltInTemplateMessage = getMistypedBuiltInTemplateMessage(templateId);
175
176
  if (mistypedBuiltInTemplateMessage) {
176
- throw new Error(mistypedBuiltInTemplateMessage);
177
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, mistypedBuiltInTemplateMessage);
177
178
  }
178
179
  if (!looksLikeExplicitExternalTemplateLocator(normalizedTemplateId)) {
179
- throw new Error(getUnknownTemplateMessage(templateId));
180
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getUnknownTemplateMessage(templateId));
180
181
  }
181
182
  return normalizedTemplateId;
182
183
  }
@@ -184,7 +185,7 @@ export async function resolveTemplateId({ templateId, yes = false, isInteractive
184
185
  return 'basic';
185
186
  }
186
187
  if (!isInteractive || !selectTemplate) {
187
- throw new Error(`Template is required in non-interactive mode. Use ${TEMPLATE_SELECTION_HINT}.`);
188
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `Template is required in non-interactive mode. Use ${TEMPLATE_SELECTION_HINT}.`);
188
189
  }
189
190
  return normalizeTemplateSelection(await selectTemplate());
190
191
  }
@@ -202,7 +203,7 @@ export async function resolvePackageManagerId({ packageManager, yes = false, isI
202
203
  return 'npm';
203
204
  }
204
205
  if (!isInteractive || !selectPackageManager) {
205
- throw new Error(`Package manager is required in non-interactive mode. Use --package-manager <${PACKAGE_MANAGER_IDS.join('|')}>.`);
206
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `Package manager is required in non-interactive mode. Use --package-manager <${PACKAGE_MANAGER_IDS.join('|')}>.`);
206
207
  }
207
208
  return selectPackageManager();
208
209
  }
@@ -2,8 +2,9 @@ import { type BuiltInBlockArtifact } from "./built-in-block-artifacts.js";
2
2
  import type { BuiltInCodeArtifact } from "./built-in-block-code-artifacts.js";
3
3
  import { type BuiltInTemplateId } from "./template-registry.js";
4
4
  import type { PackageManagerId } from "./package-managers.js";
5
+ export { applyWorkspaceMigrationCapability, isOfficialWorkspaceProject, } from "./scaffold-bootstrap.js";
5
6
  import type { ScaffoldProgressEvent, ScaffoldTemplateVariables } from "./scaffold.js";
6
- export { buildGitignore, buildReadme, mergeTextLines, } from "./scaffold-documents.js";
7
+ export { buildGitignore, buildReadme, mergeTextLines } from "./scaffold-documents.js";
7
8
  export interface InstallDependenciesOptions {
8
9
  packageManager: PackageManagerId;
9
10
  projectDir: string;
@@ -27,8 +28,6 @@ export declare function replaceTextRecursively(targetDir: string, packageManager
27
28
  repositoryReference?: string;
28
29
  }): Promise<void>;
29
30
  export declare function defaultInstallDependencies({ projectDir, packageManager, }: InstallDependenciesOptions): Promise<void>;
30
- export declare function isOfficialWorkspaceProject(projectDir: string): boolean;
31
- export declare function applyWorkspaceMigrationCapability(projectDir: string, packageManager: PackageManagerId): Promise<void>;
32
31
  /**
33
32
  * Applies a built-in scaffold into the target directory, including generated
34
33
  * code artifacts, starter manifests, preset files, and placeholder rewrites.
@@ -5,19 +5,17 @@ import { execSync } from "node:child_process";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { applyGeneratedProjectDxPackageJson, applyLocalDevPresetFiles, } from "./local-dev-presets.js";
7
7
  import { applyMigrationUiCapability } from "./migration-ui-capability.js";
8
- import { getPackageVersions } from "./package-versions.js";
9
- import { ensureMigrationDirectories, writeInitialMigrationScaffold, writeMigrationConfig, } from "./migration-project.js";
10
8
  import { syncPersistenceRestArtifacts, } from "./persistence-rest-artifacts.js";
11
9
  import { buildGitignore, buildReadme, mergeTextLines, } from "./scaffold-documents.js";
12
10
  import { getStarterManifestFiles, stringifyStarterManifest, } from "./starter-manifests.js";
13
11
  import { formatNonEmptyTargetDirectoryError, } from "./scaffold-bootstrap.js";
14
12
  import { stringifyBuiltInBlockJsonDocument, } from "./built-in-block-artifacts.js";
15
- import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, } from "./template-registry.js";
16
13
  import { copyInterpolatedDirectory } from "./template-render.js";
17
- import { formatInstallCommand, formatPackageExecCommand, transformPackageManagerText, } from "./package-managers.js";
14
+ import { formatInstallCommand, transformPackageManagerText, } from "./package-managers.js";
18
15
  import { normalizePackageJson } from "./scaffold-package-manager-files.js";
16
+ export { applyWorkspaceMigrationCapability, isOfficialWorkspaceProject, } from "./scaffold-bootstrap.js";
19
17
  import { replaceRepositoryReferencePlaceholders, resolveScaffoldRepositoryReference, } from "./scaffold-repository-reference.js";
20
- export { buildGitignore, buildReadme, mergeTextLines, } from "./scaffold-documents.js";
18
+ export { buildGitignore, buildReadme, mergeTextLines } from "./scaffold-documents.js";
21
19
  async function reportScaffoldProgress(onProgress, event) {
22
20
  await onProgress?.(event);
23
21
  }
@@ -208,44 +206,6 @@ export async function defaultInstallDependencies({ projectDir, packageManager, }
208
206
  stdio: "inherit",
209
207
  });
210
208
  }
211
- export function isOfficialWorkspaceProject(projectDir) {
212
- const packageJsonPath = path.join(projectDir, "package.json");
213
- if (!fs.existsSync(packageJsonPath)) {
214
- return false;
215
- }
216
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
217
- return (packageJson.wpTypia?.projectType === "workspace" &&
218
- packageJson.wpTypia?.templatePackage === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE);
219
- }
220
- export async function applyWorkspaceMigrationCapability(projectDir, packageManager) {
221
- const packageJsonPath = path.join(projectDir, "package.json");
222
- const packageJson = JSON.parse(await fsp.readFile(packageJsonPath, "utf8"));
223
- const wpTypiaPackageVersion = getPackageVersions().wpTypiaPackageVersion;
224
- const canonicalCliSpecifier = wpTypiaPackageVersion === "^0.0.0"
225
- ? "wp-typia"
226
- : `wp-typia@${wpTypiaPackageVersion.replace(/^[~^]/u, "")}`;
227
- const migrationCli = (args) => formatPackageExecCommand(packageManager, canonicalCliSpecifier, `migrate ${args}`);
228
- packageJson.scripts = {
229
- ...(packageJson.scripts ?? {}),
230
- "migration:init": migrationCli("init --current-migration-version v1"),
231
- "migration:snapshot": migrationCli("snapshot"),
232
- "migration:diff": migrationCli("diff"),
233
- "migration:scaffold": migrationCli("scaffold"),
234
- "migration:doctor": migrationCli("doctor --all"),
235
- "migration:fixtures": migrationCli("fixtures --all"),
236
- "migration:verify": migrationCli("verify --all"),
237
- "migration:fuzz": migrationCli("fuzz --all"),
238
- };
239
- await fsp.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}\n`, "utf8");
240
- writeMigrationConfig(projectDir, {
241
- blocks: [],
242
- currentMigrationVersion: "v1",
243
- snapshotDir: "src/migrations/versions",
244
- supportedMigrationVersions: ["v1"],
245
- });
246
- ensureMigrationDirectories(projectDir, []);
247
- writeInitialMigrationScaffold(projectDir, "v1", []);
248
- }
249
209
  /**
250
210
  * Applies a built-in scaffold into the target directory, including generated
251
211
  * code artifacts, starter manifests, preset files, and placeholder rewrites.
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Environment variable that disables external template cache reads and writes.
3
+ *
4
+ * Set to `0`, `false`, `no`, or `off` to bypass the cache.
5
+ */
6
+ export declare const EXTERNAL_TEMPLATE_CACHE_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE";
7
+ /**
8
+ * Environment variable that overrides the external template cache root.
9
+ */
10
+ export declare const EXTERNAL_TEMPLATE_CACHE_DIR_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR";
11
+ /**
12
+ * Serializable metadata recorded in the cache marker for diagnostics.
13
+ */
14
+ type ExternalTemplateCacheMetadata = Record<string, string | null>;
15
+ /**
16
+ * Describes a deterministic external template cache entry.
17
+ *
18
+ * `namespace` scopes independent cache families, `keyParts` identify the exact
19
+ * source/integrity tuple, and `metadata` is persisted to the marker file.
20
+ */
21
+ export interface ExternalTemplateCacheDescriptor {
22
+ /**
23
+ * Ordered values that deterministically identify one cached template source.
24
+ */
25
+ keyParts: readonly string[];
26
+ /**
27
+ * Diagnostic values persisted to the cache marker after sanitization.
28
+ */
29
+ metadata: ExternalTemplateCacheMetadata;
30
+ /**
31
+ * Cache family scope, stored as a single safe directory segment.
32
+ */
33
+ namespace: string;
34
+ }
35
+ /**
36
+ * Result returned when a cache entry is reused or populated.
37
+ */
38
+ export interface ExternalTemplateCacheResolution {
39
+ /**
40
+ * Whether the returned source directory came from an existing cache entry.
41
+ */
42
+ cacheHit: boolean;
43
+ /**
44
+ * Populated or reused template source directory.
45
+ */
46
+ sourceDir: string;
47
+ }
48
+ /**
49
+ * Metadata-only lookup descriptor for finding an existing reusable cache entry.
50
+ */
51
+ export interface ExternalTemplateCacheLookupDescriptor {
52
+ /**
53
+ * Metadata fields that must match the sanitized marker metadata.
54
+ */
55
+ metadata: ExternalTemplateCacheMetadata;
56
+ /**
57
+ * Cache family scope, stored as a single safe directory segment.
58
+ */
59
+ namespace: string;
60
+ }
61
+ /**
62
+ * Checks whether remote external template source caching is enabled.
63
+ *
64
+ * Caching is enabled by default. Set `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE` to
65
+ * `0`, `false`, `no`, or `off` to force uncached resolution.
66
+ *
67
+ * @param env Environment object to inspect, defaulting to `process.env`.
68
+ * @returns Whether external template source cache reads and writes are enabled.
69
+ */
70
+ export declare function isExternalTemplateCacheEnabled(env?: NodeJS.ProcessEnv): boolean;
71
+ /**
72
+ * Resolves the external template source cache root directory.
73
+ *
74
+ * `WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR` overrides the location. Without an
75
+ * override, wp-typia uses a per-user `wp-typia-template-source-cache-*`
76
+ * directory inside the operating system temp directory.
77
+ *
78
+ * @param env Environment object to inspect, defaulting to `process.env`.
79
+ * @returns Absolute cache root directory path.
80
+ */
81
+ export declare function getExternalTemplateCacheRoot(env?: NodeJS.ProcessEnv): string;
82
+ /**
83
+ * Creates a deterministic cache key from source identity and integrity parts.
84
+ *
85
+ * @param keyParts Ordered values that identify one cached template source.
86
+ * @returns SHA-256 hex digest of the JSON-serialized key parts.
87
+ */
88
+ export declare function createExternalTemplateCacheKey(keyParts: readonly string[]): string;
89
+ /**
90
+ * Finds a reusable cache entry whose marker metadata includes the expected fields.
91
+ *
92
+ * This lookup is intended for resilient fallbacks where a caller cannot compute
93
+ * the exact deterministic key but can safely reuse a previously validated local
94
+ * cache entry for the same source identity.
95
+ *
96
+ * @param descriptor Cache namespace and marker metadata fields to match.
97
+ * @returns Existing cache resolution details, or `null` when no safe entry exists.
98
+ */
99
+ export declare function findReusableExternalTemplateSourceCache(descriptor: ExternalTemplateCacheLookupDescriptor): Promise<ExternalTemplateCacheResolution | null>;
100
+ /**
101
+ * Resolves or populates a cached external template source directory.
102
+ *
103
+ * Returns `null` when caching is disabled. Cache misses populate a temporary
104
+ * directory first and then atomically move it into place; concurrent writers
105
+ * that lose the race reuse the completed marker/source pair.
106
+ *
107
+ * @param descriptor Namespace, key parts, and metadata for the cache entry.
108
+ * @param populateSourceDir Callback that writes the guarded source on a miss.
109
+ * @returns Cache resolution details, or `null` when caching is disabled.
110
+ */
111
+ export declare function resolveExternalTemplateSourceCache(descriptor: ExternalTemplateCacheDescriptor, populateSourceDir: (sourceDir: string) => Promise<void>): Promise<ExternalTemplateCacheResolution | null>;
112
+ export {};