@wp-typia/project-tools 0.16.10 → 0.16.12

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 (104) hide show
  1. package/README.md +9 -3
  2. package/dist/runtime/built-in-block-artifact-documents.d.ts +3 -0
  3. package/dist/runtime/built-in-block-artifact-documents.js +2 -0
  4. package/dist/runtime/built-in-block-artifact-types.d.ts +51 -0
  5. package/dist/runtime/built-in-block-artifact-types.js +304 -0
  6. package/dist/runtime/built-in-block-artifacts.js +4 -803
  7. package/dist/runtime/built-in-block-attribute-emitters.d.ts +71 -0
  8. package/dist/runtime/built-in-block-attribute-emitters.js +176 -0
  9. package/dist/runtime/built-in-block-attribute-specs.d.ts +38 -0
  10. package/dist/runtime/built-in-block-attribute-specs.js +358 -0
  11. package/dist/runtime/built-in-block-code-templates/basic.d.ts +4 -0
  12. package/dist/runtime/built-in-block-code-templates/basic.js +249 -0
  13. package/dist/runtime/built-in-block-code-templates/compound-child.d.ts +4 -0
  14. package/dist/runtime/built-in-block-code-templates/compound-child.js +138 -0
  15. package/dist/runtime/built-in-block-code-templates/compound-parent.d.ts +6 -0
  16. package/dist/runtime/built-in-block-code-templates/compound-parent.js +227 -0
  17. package/dist/runtime/built-in-block-code-templates/compound-persistence.d.ts +4 -0
  18. package/dist/runtime/built-in-block-code-templates/compound-persistence.js +478 -0
  19. package/dist/runtime/built-in-block-code-templates/compound.d.ts +3 -0
  20. package/dist/runtime/built-in-block-code-templates/compound.js +3 -0
  21. package/dist/runtime/built-in-block-code-templates/interactivity.d.ts +5 -0
  22. package/dist/runtime/built-in-block-code-templates/interactivity.js +547 -0
  23. package/dist/runtime/built-in-block-code-templates/persistence.d.ts +5 -0
  24. package/dist/runtime/built-in-block-code-templates/persistence.js +550 -0
  25. package/dist/runtime/built-in-block-code-templates/shared.d.ts +16 -0
  26. package/dist/runtime/built-in-block-code-templates/shared.js +53 -0
  27. package/dist/runtime/built-in-block-code-templates.d.ts +5 -32
  28. package/dist/runtime/built-in-block-code-templates.js +5 -2230
  29. package/dist/runtime/cli-add-block-config.d.ts +6 -0
  30. package/dist/runtime/cli-add-block-config.js +143 -0
  31. package/dist/runtime/cli-add-block-legacy-validator.d.ts +4 -0
  32. package/dist/runtime/cli-add-block-legacy-validator.js +168 -0
  33. package/dist/runtime/cli-add-block.js +3 -301
  34. package/dist/runtime/cli-add-workspace-assets.d.ts +38 -0
  35. package/dist/runtime/cli-add-workspace-assets.js +399 -0
  36. package/dist/runtime/cli-add-workspace.d.ts +2 -38
  37. package/dist/runtime/cli-add-workspace.js +5 -396
  38. package/dist/runtime/cli-doctor-environment.d.ts +12 -0
  39. package/dist/runtime/cli-doctor-environment.js +123 -0
  40. package/dist/runtime/cli-doctor-workspace.d.ts +14 -0
  41. package/dist/runtime/cli-doctor-workspace.js +296 -0
  42. package/dist/runtime/cli-doctor.d.ts +4 -2
  43. package/dist/runtime/cli-doctor.js +10 -405
  44. package/dist/runtime/cli-help.js +1 -1
  45. package/dist/runtime/cli-scaffold.js +1 -1
  46. package/dist/runtime/migration-command-surface.d.ts +67 -0
  47. package/dist/runtime/migration-command-surface.js +189 -0
  48. package/dist/runtime/migration-diff-rename.d.ts +13 -0
  49. package/dist/runtime/migration-diff-rename.js +192 -0
  50. package/dist/runtime/migration-diff-transform.d.ts +14 -0
  51. package/dist/runtime/migration-diff-transform.js +105 -0
  52. package/dist/runtime/migration-diff.js +12 -297
  53. package/dist/runtime/migration-generated-artifacts.d.ts +3 -0
  54. package/dist/runtime/migration-generated-artifacts.js +41 -0
  55. package/dist/runtime/migration-maintenance.d.ts +51 -0
  56. package/dist/runtime/migration-maintenance.js +380 -0
  57. package/dist/runtime/migration-planning.d.ts +23 -0
  58. package/dist/runtime/migration-planning.js +131 -0
  59. package/dist/runtime/migration-project-config-source.d.ts +6 -0
  60. package/dist/runtime/migration-project-config-source.js +424 -0
  61. package/dist/runtime/migration-project-layout-discovery.d.ts +61 -0
  62. package/dist/runtime/migration-project-layout-discovery.js +337 -0
  63. package/dist/runtime/migration-project-layout-paths.d.ts +135 -0
  64. package/dist/runtime/migration-project-layout-paths.js +288 -0
  65. package/dist/runtime/migration-project-layout.d.ts +3 -0
  66. package/dist/runtime/migration-project-layout.js +2 -0
  67. package/dist/runtime/migration-project-workspace.d.ts +47 -0
  68. package/dist/runtime/migration-project-workspace.js +212 -0
  69. package/dist/runtime/migration-project.d.ts +4 -94
  70. package/dist/runtime/migration-project.js +3 -1101
  71. package/dist/runtime/migration-render-diff-rule.d.ts +5 -0
  72. package/dist/runtime/migration-render-diff-rule.js +120 -0
  73. package/dist/runtime/migration-render-execution.d.ts +3 -0
  74. package/dist/runtime/migration-render-execution.js +428 -0
  75. package/dist/runtime/migration-render-generated.d.ts +27 -0
  76. package/dist/runtime/migration-render-generated.js +230 -0
  77. package/dist/runtime/migration-render-support.d.ts +3 -0
  78. package/dist/runtime/migration-render-support.js +16 -0
  79. package/dist/runtime/migration-render.d.ts +3 -33
  80. package/dist/runtime/migration-render.js +3 -789
  81. package/dist/runtime/migration-ui-capability.js +1 -1
  82. package/dist/runtime/migrations.d.ts +24 -118
  83. package/dist/runtime/migrations.js +12 -700
  84. package/dist/runtime/scaffold-bootstrap.d.ts +45 -0
  85. package/dist/runtime/scaffold-bootstrap.js +185 -0
  86. package/dist/runtime/scaffold-package-manager-files.d.ts +35 -0
  87. package/dist/runtime/scaffold-package-manager-files.js +79 -0
  88. package/dist/runtime/scaffold.d.ts +1 -12
  89. package/dist/runtime/scaffold.js +10 -393
  90. package/dist/runtime/template-source-contracts.d.ts +81 -0
  91. package/dist/runtime/template-source-contracts.js +1 -0
  92. package/dist/runtime/template-source-external.d.ts +21 -0
  93. package/dist/runtime/template-source-external.js +184 -0
  94. package/dist/runtime/template-source-locators.d.ts +4 -0
  95. package/dist/runtime/template-source-locators.js +72 -0
  96. package/dist/runtime/template-source-normalization.d.ts +7 -0
  97. package/dist/runtime/template-source-normalization.js +53 -0
  98. package/dist/runtime/template-source-remote.d.ts +23 -0
  99. package/dist/runtime/template-source-remote.js +336 -0
  100. package/dist/runtime/template-source-seeds.d.ts +12 -0
  101. package/dist/runtime/template-source-seeds.js +243 -0
  102. package/dist/runtime/template-source.d.ts +4 -86
  103. package/dist/runtime/template-source.js +9 -828
  104. package/package.json +5 -5
@@ -0,0 +1,6 @@
1
+ import type { MigrationBlockConfig } from "./migration-types.js";
2
+ import type { ScaffoldTemplateVariables } from "./scaffold.js";
3
+ import { type AddBlockTemplateId } from "./cli-add-shared.js";
4
+ export declare function buildServerTemplateRoot(persistencePolicy: string | undefined): string;
5
+ export declare function buildConfigEntries(templateId: AddBlockTemplateId, variables: ScaffoldTemplateVariables): string[];
6
+ export declare function buildMigrationBlocks(templateId: AddBlockTemplateId, variables: ScaffoldTemplateVariables): MigrationBlockConfig[];
@@ -0,0 +1,143 @@
1
+ import path from "node:path";
2
+ import { SHARED_WORKSPACE_TEMPLATE_ROOT, } from "./template-registry.js";
3
+ import { quoteTsString, } from "./cli-add-shared.js";
4
+ export function buildServerTemplateRoot(persistencePolicy) {
5
+ return path.join(SHARED_WORKSPACE_TEMPLATE_ROOT, persistencePolicy === "public" ? "persistence-public" : "persistence-auth");
6
+ }
7
+ function buildSingleBlockConfigEntry(variables) {
8
+ return [
9
+ "\t{",
10
+ `\t\tslug: ${quoteTsString(variables.slugKebabCase)},`,
11
+ `\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}Attributes`)},`,
12
+ `\t\ttypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/types.ts`)},`,
13
+ "\t},",
14
+ ].join("\n");
15
+ }
16
+ function buildPersistenceBlockConfigEntry(variables) {
17
+ return [
18
+ "\t{",
19
+ `\t\tapiTypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/api-types.ts`)},`,
20
+ `\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}Attributes`)},`,
21
+ "\t\trestManifest: defineEndpointManifest( {",
22
+ "\t\t\tcontracts: {",
23
+ "\t\t\t\t'bootstrap-query': {",
24
+ `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}BootstrapQuery`)},`,
25
+ "\t\t\t\t},",
26
+ "\t\t\t\t'bootstrap-response': {",
27
+ `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}BootstrapResponse`)},`,
28
+ "\t\t\t\t},",
29
+ "\t\t\t\t'state-query': {",
30
+ `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}StateQuery`)},`,
31
+ "\t\t\t\t},",
32
+ "\t\t\t\t'state-response': {",
33
+ `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}StateResponse`)},`,
34
+ "\t\t\t\t},",
35
+ "\t\t\t\t'write-state-request': {",
36
+ `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}WriteStateRequest`)},`,
37
+ "\t\t\t\t},",
38
+ "\t\t\t},",
39
+ "\t\t\tendpoints: [",
40
+ "\t\t\t\t{",
41
+ "\t\t\t\t\tauth: 'public',",
42
+ "\t\t\t\t\tmethod: 'GET',",
43
+ `\t\t\t\t\toperationId: ${quoteTsString(`get${variables.pascalCase}State`)},`,
44
+ `\t\t\t\t\tpath: ${quoteTsString(`/${variables.namespace}/v1/${variables.slugKebabCase}/state`)},`,
45
+ "\t\t\t\t\tqueryContract: 'state-query',",
46
+ "\t\t\t\t\tresponseContract: 'state-response',",
47
+ `\t\t\t\t\tsummary: 'Read the current persisted state.',`,
48
+ `\t\t\t\t\ttags: [ ${quoteTsString(variables.title)} ],`,
49
+ "\t\t\t\t},",
50
+ "\t\t\t\t{",
51
+ `\t\t\t\t\tauth: ${quoteTsString(variables.restWriteAuthIntent)},`,
52
+ "\t\t\t\t\tbodyContract: 'write-state-request',",
53
+ "\t\t\t\t\tmethod: 'POST',",
54
+ `\t\t\t\t\toperationId: ${quoteTsString(`write${variables.pascalCase}State`)},`,
55
+ `\t\t\t\t\tpath: ${quoteTsString(`/${variables.namespace}/v1/${variables.slugKebabCase}/state`)},`,
56
+ "\t\t\t\t\tresponseContract: 'state-response',",
57
+ `\t\t\t\t\tsummary: 'Write the current persisted state.',`,
58
+ `\t\t\t\t\ttags: [ ${quoteTsString(variables.title)} ],`,
59
+ "\t\t\t\t\twordpressAuth: {",
60
+ `\t\t\t\t\t\tmechanism: ${quoteTsString(variables.restWriteAuthMechanism)},`,
61
+ "\t\t\t\t\t},",
62
+ "\t\t\t\t},",
63
+ "\t\t\t\t{",
64
+ "\t\t\t\t\tauth: 'public',",
65
+ "\t\t\t\t\tmethod: 'GET',",
66
+ `\t\t\t\t\toperationId: ${quoteTsString(`get${variables.pascalCase}Bootstrap`)},`,
67
+ `\t\t\t\t\tpath: ${quoteTsString(`/${variables.namespace}/v1/${variables.slugKebabCase}/bootstrap`)},`,
68
+ "\t\t\t\t\tqueryContract: 'bootstrap-query',",
69
+ "\t\t\t\t\tresponseContract: 'bootstrap-response',",
70
+ `\t\t\t\t\tsummary: 'Read fresh session bootstrap state for the current viewer.',`,
71
+ `\t\t\t\t\ttags: [ ${quoteTsString(variables.title)} ],`,
72
+ "\t\t\t\t},",
73
+ "\t\t\t],",
74
+ "\t\t\tinfo: {",
75
+ `\t\t\t\ttitle: ${quoteTsString(`${variables.title} REST API`)},`,
76
+ "\t\t\t\tversion: '1.0.0',",
77
+ "\t\t\t},",
78
+ "\t\t} ),",
79
+ `\t\topenApiFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/api.openapi.json`)},`,
80
+ `\t\tslug: ${quoteTsString(variables.slugKebabCase)},`,
81
+ `\t\ttypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/types.ts`)},`,
82
+ "\t},",
83
+ ].join("\n");
84
+ }
85
+ function buildCompoundChildConfigEntry(variables) {
86
+ return [
87
+ "\t{",
88
+ `\t\tslug: ${quoteTsString(`${variables.slugKebabCase}-item`)},`,
89
+ `\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}ItemAttributes`)},`,
90
+ `\t\ttypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}-item/types.ts`)},`,
91
+ "\t},",
92
+ ].join("\n");
93
+ }
94
+ export function buildConfigEntries(templateId, variables) {
95
+ if (templateId === "basic" || templateId === "interactivity") {
96
+ return [buildSingleBlockConfigEntry(variables)];
97
+ }
98
+ if (templateId === "persistence") {
99
+ return [buildPersistenceBlockConfigEntry(variables)];
100
+ }
101
+ if (variables.compoundPersistenceEnabled === "true") {
102
+ return [
103
+ buildPersistenceBlockConfigEntry(variables),
104
+ buildCompoundChildConfigEntry(variables),
105
+ ];
106
+ }
107
+ return [
108
+ buildSingleBlockConfigEntry(variables),
109
+ buildCompoundChildConfigEntry(variables),
110
+ ];
111
+ }
112
+ export function buildMigrationBlocks(templateId, variables) {
113
+ if (templateId === "compound") {
114
+ return [
115
+ {
116
+ blockJsonFile: `src/blocks/${variables.slugKebabCase}/block.json`,
117
+ blockName: `${variables.namespace}/${variables.slugKebabCase}`,
118
+ key: variables.slugKebabCase,
119
+ manifestFile: `src/blocks/${variables.slugKebabCase}/typia.manifest.json`,
120
+ saveFile: `src/blocks/${variables.slugKebabCase}/save.tsx`,
121
+ typesFile: `src/blocks/${variables.slugKebabCase}/types.ts`,
122
+ },
123
+ {
124
+ blockJsonFile: `src/blocks/${variables.slugKebabCase}-item/block.json`,
125
+ blockName: `${variables.namespace}/${variables.slugKebabCase}-item`,
126
+ key: `${variables.slugKebabCase}-item`,
127
+ manifestFile: `src/blocks/${variables.slugKebabCase}-item/typia.manifest.json`,
128
+ saveFile: `src/blocks/${variables.slugKebabCase}-item/save.tsx`,
129
+ typesFile: `src/blocks/${variables.slugKebabCase}-item/types.ts`,
130
+ },
131
+ ];
132
+ }
133
+ return [
134
+ {
135
+ blockJsonFile: `src/blocks/${variables.slugKebabCase}/block.json`,
136
+ blockName: `${variables.namespace}/${variables.slugKebabCase}`,
137
+ key: variables.slugKebabCase,
138
+ manifestFile: `src/blocks/${variables.slugKebabCase}/typia.manifest.json`,
139
+ saveFile: `src/blocks/${variables.slugKebabCase}/save.tsx`,
140
+ typesFile: `src/blocks/${variables.slugKebabCase}/types.ts`,
141
+ },
142
+ ];
143
+ }
@@ -0,0 +1,4 @@
1
+ export declare const COMPOUND_SHARED_SUPPORT_FILES: readonly ["hooks.ts", "validator-toolkit.ts"];
2
+ export declare function ensureBlockConfigCanAddRestManifests(source: string): string;
3
+ export declare function collectLegacyCompoundValidatorPaths(projectDir: string): Promise<string[]>;
4
+ export declare function ensureCompoundWorkspaceSupportFiles(projectDir: string, tempProjectDir: string, legacyValidatorPaths: readonly string[]): Promise<void>;
@@ -0,0 +1,168 @@
1
+ import fs from "node:fs";
2
+ import { promises as fsp } from "node:fs";
3
+ import path from "node:path";
4
+ import { readOptionalFile } from "./cli-add-shared.js";
5
+ export const COMPOUND_SHARED_SUPPORT_FILES = [
6
+ "hooks.ts",
7
+ "validator-toolkit.ts",
8
+ ];
9
+ const LEGACY_ASSERT_PATTERN = /assert:\s*typia\.createAssert</u;
10
+ const LEGACY_MANIFEST_PATTERN = /\r?\n[ \t]*manifest:\s*currentManifest,/u;
11
+ const LEGACY_VALIDATOR_MANIFEST_IMPORT_PATTERN = /^[\uFEFF \t]*import\s+currentManifest\s+from\s*["']\.\/typia\.manifest\.json["'];?$/u;
12
+ const LEGACY_TOOLKIT_CALL_PATTERN = /createTemplateValidatorToolkit<\s*(?<typeName>[A-Za-z0-9_]+)\s*>\s*\(\s*\{/u;
13
+ const LEGACY_VALIDATOR_TOOLKIT_IMPORT_PATTERN = /from\s*["']\.\.\/\.\.\/validator-toolkit["']/u;
14
+ const TYPIA_IMPORT_PATTERN = /^[\uFEFF \t]*import\s+typia\s+from\s*["']typia["'];?/mu;
15
+ const COMPATIBLE_COMPOUND_TOOLKIT_PATTERNS = [
16
+ /interface\s+TemplateValidatorFunctions\s*<\s*T\s+extends\s+object\s*>\s*\{/u,
17
+ /\bassert\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']assert["']\s*\]/u,
18
+ /\bclone\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']clone["']\s*\]/u,
19
+ /\bis\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']is["']\s*\]/u,
20
+ /\bprune\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']prune["']\s*\]/u,
21
+ /\brandom\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']random["']\s*\]/u,
22
+ /\bvalidate\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']validate["']\s*\]/u,
23
+ /createTemplateValidatorToolkit\s*<\s*T\s+extends\s+object\s*>\s*\(\s*\{/u,
24
+ ];
25
+ const REST_MANIFEST_IMPORT_PATTERN = /import\s*\{[^}]*\bdefineEndpointManifest\b[^}]*\}\s*from\s*["']@wp-typia\/block-runtime\/metadata-core["'];?/m;
26
+ export function ensureBlockConfigCanAddRestManifests(source) {
27
+ const importLine = "import { defineEndpointManifest } from '@wp-typia/block-runtime/metadata-core';";
28
+ if (REST_MANIFEST_IMPORT_PATTERN.test(source)) {
29
+ return source;
30
+ }
31
+ return `${importLine}\n\n${source}`;
32
+ }
33
+ function shouldRefreshCompoundValidatorToolkit(source) {
34
+ return (source === null ||
35
+ !COMPATIBLE_COMPOUND_TOOLKIT_PATTERNS.every((pattern) => pattern.test(source)));
36
+ }
37
+ function isLegacyCompoundValidatorSource(source) {
38
+ return (typeof source === "string" &&
39
+ LEGACY_VALIDATOR_TOOLKIT_IMPORT_PATTERN.test(source) &&
40
+ !LEGACY_ASSERT_PATTERN.test(source));
41
+ }
42
+ function hasTypiaImport(source) {
43
+ return TYPIA_IMPORT_PATTERN.test(source.replace(/\/\*[\s\S]*?\*\//gu, ""));
44
+ }
45
+ function replaceFirstNonCommentLine(source, pattern, replacement) {
46
+ const lineEnding = source.includes("\r\n") ? "\r\n" : "\n";
47
+ const lines = source.split(/\r?\n/);
48
+ let inBlockComment = false;
49
+ for (let index = 0; index < lines.length; index += 1) {
50
+ const line = lines[index] ?? "";
51
+ const trimmed = line.trimStart();
52
+ if (inBlockComment) {
53
+ if (trimmed.includes("*/")) {
54
+ inBlockComment = false;
55
+ }
56
+ continue;
57
+ }
58
+ if (trimmed.startsWith("//")) {
59
+ continue;
60
+ }
61
+ if (trimmed.startsWith("/*")) {
62
+ if (!trimmed.includes("*/")) {
63
+ inBlockComment = true;
64
+ }
65
+ continue;
66
+ }
67
+ if (!pattern.test(line)) {
68
+ continue;
69
+ }
70
+ lines[index] = replacement;
71
+ return lines.join(lineEnding);
72
+ }
73
+ return source;
74
+ }
75
+ function upgradeLegacyCompoundValidatorSource(source) {
76
+ const typeNameMatch = source.match(LEGACY_TOOLKIT_CALL_PATTERN);
77
+ const typeName = typeNameMatch?.groups?.typeName;
78
+ if (!typeName) {
79
+ throw new Error("Unable to upgrade a legacy compound validator without a generated type import.");
80
+ }
81
+ let nextSource = source;
82
+ if (!hasTypiaImport(nextSource)) {
83
+ nextSource = `import typia from 'typia';\n${nextSource}`;
84
+ }
85
+ nextSource = replaceFirstNonCommentLine(nextSource, LEGACY_VALIDATOR_MANIFEST_IMPORT_PATTERN, "import currentManifest from './manifest-defaults-document';");
86
+ nextSource = nextSource.replace(LEGACY_TOOLKIT_CALL_PATTERN, [
87
+ `createTemplateValidatorToolkit< ${typeName} >( {`,
88
+ `\tassert: typia.createAssert< ${typeName} >(),`,
89
+ `\tclone: typia.misc.createClone< ${typeName} >() as (`,
90
+ `\t\tvalue: ${typeName},`,
91
+ `\t) => ${typeName},`,
92
+ `\tis: typia.createIs< ${typeName} >(),`,
93
+ ].join("\n") + "\n");
94
+ const replacedManifest = nextSource.replace(LEGACY_MANIFEST_PATTERN, [
95
+ "",
96
+ "\tmanifest: currentManifest,",
97
+ `\tprune: typia.misc.createPrune< ${typeName} >(),`,
98
+ `\trandom: typia.createRandom< ${typeName} >() as (`,
99
+ "\t\t...args: unknown[]",
100
+ `\t) => ${typeName},`,
101
+ `\tvalidate: typia.createValidate< ${typeName} >(),`,
102
+ ].join("\n"));
103
+ if (replacedManifest === nextSource) {
104
+ throw new Error("Unable to upgrade legacy compound validator: manifest anchor not found.");
105
+ }
106
+ return replacedManifest;
107
+ }
108
+ function renderLegacyManifestDefaultsWrapperSource() {
109
+ return [
110
+ "import rawCurrentManifest from './typia.manifest.json';",
111
+ "import { defineManifestDefaultsDocument } from '@wp-typia/block-runtime/defaults';",
112
+ "",
113
+ "const currentManifest = defineManifestDefaultsDocument( rawCurrentManifest );",
114
+ "",
115
+ "export default currentManifest;",
116
+ "",
117
+ ].join("\n");
118
+ }
119
+ async function ensureLegacyCompoundValidatorManifestDefaultsWrapper(validatorPath) {
120
+ const validatorDir = path.dirname(validatorPath);
121
+ const wrapperPath = path.join(validatorDir, "manifest-defaults-document.ts");
122
+ const manifestPath = path.join(validatorDir, "typia.manifest.json");
123
+ if (fs.existsSync(wrapperPath) || !fs.existsSync(manifestPath)) {
124
+ return;
125
+ }
126
+ await fsp.writeFile(wrapperPath, renderLegacyManifestDefaultsWrapperSource(), "utf8");
127
+ }
128
+ export async function collectLegacyCompoundValidatorPaths(projectDir) {
129
+ const blocksDir = path.join(projectDir, "src", "blocks");
130
+ if (!fs.existsSync(blocksDir)) {
131
+ return [];
132
+ }
133
+ const blockEntries = await fsp.readdir(blocksDir, { withFileTypes: true });
134
+ const validatorPaths = await Promise.all(blockEntries
135
+ .filter((entry) => entry.isDirectory())
136
+ .map(async (entry) => {
137
+ const validatorPath = path.join(blocksDir, entry.name, "validators.ts");
138
+ const validatorSource = await readOptionalFile(validatorPath);
139
+ return isLegacyCompoundValidatorSource(validatorSource)
140
+ ? validatorPath
141
+ : null;
142
+ }));
143
+ return validatorPaths.filter((validatorPath) => validatorPath !== null);
144
+ }
145
+ export async function ensureCompoundWorkspaceSupportFiles(projectDir, tempProjectDir, legacyValidatorPaths) {
146
+ for (const fileName of COMPOUND_SHARED_SUPPORT_FILES) {
147
+ const sourcePath = path.join(tempProjectDir, "src", fileName);
148
+ if (!fs.existsSync(sourcePath)) {
149
+ continue;
150
+ }
151
+ const targetPath = path.join(projectDir, "src", fileName);
152
+ const currentSource = await readOptionalFile(targetPath);
153
+ if (fileName === "validator-toolkit.ts"
154
+ ? shouldRefreshCompoundValidatorToolkit(currentSource)
155
+ : currentSource === null) {
156
+ await fsp.mkdir(path.dirname(targetPath), { recursive: true });
157
+ await fsp.copyFile(sourcePath, targetPath);
158
+ }
159
+ }
160
+ for (const validatorPath of legacyValidatorPaths) {
161
+ const currentSource = await readOptionalFile(validatorPath);
162
+ if (!isLegacyCompoundValidatorSource(currentSource)) {
163
+ continue;
164
+ }
165
+ await ensureLegacyCompoundValidatorManifestDefaultsWrapper(validatorPath);
166
+ await fsp.writeFile(validatorPath, upgradeLegacyCompoundValidatorSource(currentSource), "utf8");
167
+ }
168
+ }
@@ -8,155 +8,15 @@ import { syncPersistenceRestArtifacts, } from "./persistence-rest-artifacts.js";
8
8
  import { snapshotProjectVersion } from "./migrations.js";
9
9
  import { getDefaultAnswers, scaffoldProject } from "./scaffold.js";
10
10
  import { copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, } from "./template-render.js";
11
- import { SHARED_WORKSPACE_TEMPLATE_ROOT, } from "./template-registry.js";
12
11
  import { appendWorkspaceInventoryEntries, } from "./workspace-inventory.js";
13
12
  import { resolveWorkspaceProject, } from "./workspace-project.js";
14
- import { ADD_BLOCK_TEMPLATE_IDS, buildWorkspacePhpPrefix, isAddBlockTemplateId, normalizeBlockSlug, patchFile, quoteTsString, readOptionalFile, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
13
+ import { ADD_BLOCK_TEMPLATE_IDS, buildWorkspacePhpPrefix, isAddBlockTemplateId, normalizeBlockSlug, patchFile, readOptionalFile, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
14
+ import { buildConfigEntries, buildMigrationBlocks, buildServerTemplateRoot, } from "./cli-add-block-config.js";
15
+ import { COMPOUND_SHARED_SUPPORT_FILES, collectLegacyCompoundValidatorPaths, ensureBlockConfigCanAddRestManifests, ensureCompoundWorkspaceSupportFiles, } from "./cli-add-block-legacy-validator.js";
15
16
  import { parseTemplateLocator, resolveTemplateSeed, } from "./template-source.js";
16
17
  import { resolveExternalTemplateLayers, } from "./template-layers.js";
17
18
  import { resolveOptionalInteractiveExternalLayerId, } from "./external-layer-selection.js";
18
19
  const COLLECTION_IMPORT_LINE = "import '../../collection';";
19
- const REST_MANIFEST_IMPORT_PATTERN = /import\s*\{[^}]*\bdefineEndpointManifest\b[^}]*\}\s*from\s*["']@wp-typia\/block-runtime\/metadata-core["'];?/m;
20
- function buildServerTemplateRoot(persistencePolicy) {
21
- return path.join(SHARED_WORKSPACE_TEMPLATE_ROOT, persistencePolicy === "public" ? "persistence-public" : "persistence-auth");
22
- }
23
- function buildSingleBlockConfigEntry(variables) {
24
- return [
25
- "\t{",
26
- `\t\tslug: ${quoteTsString(variables.slugKebabCase)},`,
27
- `\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}Attributes`)},`,
28
- `\t\ttypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/types.ts`)},`,
29
- "\t},",
30
- ].join("\n");
31
- }
32
- function buildPersistenceBlockConfigEntry(variables) {
33
- return [
34
- "\t{",
35
- `\t\tapiTypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/api-types.ts`)},`,
36
- `\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}Attributes`)},`,
37
- "\t\trestManifest: defineEndpointManifest( {",
38
- "\t\t\tcontracts: {",
39
- "\t\t\t\t'bootstrap-query': {",
40
- `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}BootstrapQuery`)},`,
41
- "\t\t\t\t},",
42
- "\t\t\t\t'bootstrap-response': {",
43
- `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}BootstrapResponse`)},`,
44
- "\t\t\t\t},",
45
- "\t\t\t\t'state-query': {",
46
- `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}StateQuery`)},`,
47
- "\t\t\t\t},",
48
- "\t\t\t\t'state-response': {",
49
- `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}StateResponse`)},`,
50
- "\t\t\t\t},",
51
- "\t\t\t\t'write-state-request': {",
52
- `\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}WriteStateRequest`)},`,
53
- "\t\t\t\t},",
54
- "\t\t\t},",
55
- "\t\t\tendpoints: [",
56
- "\t\t\t\t{",
57
- "\t\t\t\t\tauth: 'public',",
58
- "\t\t\t\t\tmethod: 'GET',",
59
- `\t\t\t\t\toperationId: ${quoteTsString(`get${variables.pascalCase}State`)},`,
60
- `\t\t\t\t\tpath: ${quoteTsString(`/${variables.namespace}/v1/${variables.slugKebabCase}/state`)},`,
61
- "\t\t\t\t\tqueryContract: 'state-query',",
62
- "\t\t\t\t\tresponseContract: 'state-response',",
63
- `\t\t\t\t\tsummary: 'Read the current persisted state.',`,
64
- `\t\t\t\t\ttags: [ ${quoteTsString(variables.title)} ],`,
65
- "\t\t\t\t},",
66
- "\t\t\t\t{",
67
- `\t\t\t\t\tauth: ${quoteTsString(variables.restWriteAuthIntent)},`,
68
- "\t\t\t\t\tbodyContract: 'write-state-request',",
69
- "\t\t\t\t\tmethod: 'POST',",
70
- `\t\t\t\t\toperationId: ${quoteTsString(`write${variables.pascalCase}State`)},`,
71
- `\t\t\t\t\tpath: ${quoteTsString(`/${variables.namespace}/v1/${variables.slugKebabCase}/state`)},`,
72
- "\t\t\t\t\tresponseContract: 'state-response',",
73
- `\t\t\t\t\tsummary: 'Write the current persisted state.',`,
74
- `\t\t\t\t\ttags: [ ${quoteTsString(variables.title)} ],`,
75
- "\t\t\t\t\twordpressAuth: {",
76
- `\t\t\t\t\t\tmechanism: ${quoteTsString(variables.restWriteAuthMechanism)},`,
77
- "\t\t\t\t\t},",
78
- "\t\t\t\t},",
79
- "\t\t\t\t{",
80
- "\t\t\t\t\tauth: 'public',",
81
- "\t\t\t\t\tmethod: 'GET',",
82
- `\t\t\t\t\toperationId: ${quoteTsString(`get${variables.pascalCase}Bootstrap`)},`,
83
- `\t\t\t\t\tpath: ${quoteTsString(`/${variables.namespace}/v1/${variables.slugKebabCase}/bootstrap`)},`,
84
- "\t\t\t\t\tqueryContract: 'bootstrap-query',",
85
- "\t\t\t\t\tresponseContract: 'bootstrap-response',",
86
- `\t\t\t\t\tsummary: 'Read fresh session bootstrap state for the current viewer.',`,
87
- `\t\t\t\t\ttags: [ ${quoteTsString(variables.title)} ],`,
88
- "\t\t\t\t},",
89
- "\t\t\t],",
90
- "\t\t\tinfo: {",
91
- `\t\t\t\ttitle: ${quoteTsString(`${variables.title} REST API`)},`,
92
- "\t\t\t\tversion: '1.0.0',",
93
- "\t\t\t},",
94
- "\t\t} ),",
95
- `\t\topenApiFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/api.openapi.json`)},`,
96
- `\t\tslug: ${quoteTsString(variables.slugKebabCase)},`,
97
- `\t\ttypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/types.ts`)},`,
98
- "\t},",
99
- ].join("\n");
100
- }
101
- function buildCompoundChildConfigEntry(variables) {
102
- return [
103
- "\t{",
104
- `\t\tslug: ${quoteTsString(`${variables.slugKebabCase}-item`)},`,
105
- `\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}ItemAttributes`)},`,
106
- `\t\ttypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}-item/types.ts`)},`,
107
- "\t},",
108
- ].join("\n");
109
- }
110
- function buildConfigEntries(templateId, variables) {
111
- if (templateId === "basic" || templateId === "interactivity") {
112
- return [buildSingleBlockConfigEntry(variables)];
113
- }
114
- if (templateId === "persistence") {
115
- return [buildPersistenceBlockConfigEntry(variables)];
116
- }
117
- if (variables.compoundPersistenceEnabled === "true") {
118
- return [
119
- buildPersistenceBlockConfigEntry(variables),
120
- buildCompoundChildConfigEntry(variables),
121
- ];
122
- }
123
- return [
124
- buildSingleBlockConfigEntry(variables),
125
- buildCompoundChildConfigEntry(variables),
126
- ];
127
- }
128
- function buildMigrationBlocks(templateId, variables) {
129
- if (templateId === "compound") {
130
- return [
131
- {
132
- blockJsonFile: `src/blocks/${variables.slugKebabCase}/block.json`,
133
- blockName: `${variables.namespace}/${variables.slugKebabCase}`,
134
- key: variables.slugKebabCase,
135
- manifestFile: `src/blocks/${variables.slugKebabCase}/typia.manifest.json`,
136
- saveFile: `src/blocks/${variables.slugKebabCase}/save.tsx`,
137
- typesFile: `src/blocks/${variables.slugKebabCase}/types.ts`,
138
- },
139
- {
140
- blockJsonFile: `src/blocks/${variables.slugKebabCase}-item/block.json`,
141
- blockName: `${variables.namespace}/${variables.slugKebabCase}-item`,
142
- key: `${variables.slugKebabCase}-item`,
143
- manifestFile: `src/blocks/${variables.slugKebabCase}-item/typia.manifest.json`,
144
- saveFile: `src/blocks/${variables.slugKebabCase}-item/save.tsx`,
145
- typesFile: `src/blocks/${variables.slugKebabCase}-item/types.ts`,
146
- },
147
- ];
148
- }
149
- return [
150
- {
151
- blockJsonFile: `src/blocks/${variables.slugKebabCase}/block.json`,
152
- blockName: `${variables.namespace}/${variables.slugKebabCase}`,
153
- key: variables.slugKebabCase,
154
- manifestFile: `src/blocks/${variables.slugKebabCase}/typia.manifest.json`,
155
- saveFile: `src/blocks/${variables.slugKebabCase}/save.tsx`,
156
- typesFile: `src/blocks/${variables.slugKebabCase}/types.ts`,
157
- },
158
- ];
159
- }
160
20
  async function ensureCollectionImport(filePath) {
161
21
  await patchFile(filePath, (source) => {
162
22
  if (source.includes(COLLECTION_IMPORT_LINE)) {
@@ -183,13 +43,6 @@ async function addCollectionImportsForTemplate(projectDir, templateId, variables
183
43
  }
184
44
  await ensureCollectionImport(path.join(projectDir, "src", "blocks", variables.slugKebabCase, "index.tsx"));
185
45
  }
186
- function ensureBlockConfigCanAddRestManifests(source) {
187
- const importLine = "import { defineEndpointManifest } from '@wp-typia/block-runtime/metadata-core';";
188
- if (REST_MANIFEST_IMPORT_PATTERN.test(source)) {
189
- return source;
190
- }
191
- return `${importLine}\n\n${source}`;
192
- }
193
46
  async function appendBlockConfigEntries(projectDir, entries, needsRestManifestImport) {
194
47
  await appendWorkspaceInventoryEntries(projectDir, {
195
48
  blockEntries: entries,
@@ -201,23 +54,6 @@ async function renderWorkspacePersistenceServerModule(projectDir, variables) {
201
54
  const templateDir = buildServerTemplateRoot(variables.persistencePolicy);
202
55
  await copyInterpolatedDirectory(templateDir, targetDir, variables);
203
56
  }
204
- const COMPOUND_SHARED_SUPPORT_FILES = ["hooks.ts", "validator-toolkit.ts"];
205
- const LEGACY_ASSERT_PATTERN = /assert:\s*typia\.createAssert</u;
206
- const LEGACY_MANIFEST_PATTERN = /\r?\n[ \t]*manifest:\s*currentManifest,/u;
207
- const LEGACY_VALIDATOR_MANIFEST_IMPORT_PATTERN = /^[\uFEFF \t]*import\s+currentManifest\s+from\s*["']\.\/typia\.manifest\.json["'];?$/u;
208
- const LEGACY_TOOLKIT_CALL_PATTERN = /createTemplateValidatorToolkit<\s*(?<typeName>[A-Za-z0-9_]+)\s*>\s*\(\s*\{/u;
209
- const LEGACY_VALIDATOR_TOOLKIT_IMPORT_PATTERN = /from\s*["']\.\.\/\.\.\/validator-toolkit["']/u;
210
- const TYPIA_IMPORT_PATTERN = /^[\uFEFF \t]*import\s+typia\s+from\s*["']typia["'];?/mu;
211
- const COMPATIBLE_COMPOUND_TOOLKIT_PATTERNS = [
212
- /interface\s+TemplateValidatorFunctions\s*<\s*T\s+extends\s+object\s*>\s*\{/u,
213
- /\bassert\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']assert["']\s*\]/u,
214
- /\bclone\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']clone["']\s*\]/u,
215
- /\bis\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']is["']\s*\]/u,
216
- /\bprune\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']prune["']\s*\]/u,
217
- /\brandom\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']random["']\s*\]/u,
218
- /\bvalidate\s*:\s*ScaffoldValidatorToolkitOptions\s*<\s*T\s*>\s*\[\s*["']validate["']\s*\]/u,
219
- /createTemplateValidatorToolkit\s*<\s*T\s+extends\s+object\s*>\s*\(\s*\{/u,
220
- ];
221
57
  function normalizeExternalLayerOption(value) {
222
58
  if (typeof value !== "string") {
223
59
  return undefined;
@@ -233,140 +69,6 @@ function resolveExternalLayerSourceFromCaller(source, callerCwd) {
233
69
  }
234
70
  return path.resolve(callerCwd, source);
235
71
  }
236
- function shouldRefreshCompoundValidatorToolkit(source) {
237
- return (source === null ||
238
- !COMPATIBLE_COMPOUND_TOOLKIT_PATTERNS.every((pattern) => pattern.test(source)));
239
- }
240
- function isLegacyCompoundValidatorSource(source) {
241
- return (typeof source === "string" &&
242
- LEGACY_VALIDATOR_TOOLKIT_IMPORT_PATTERN.test(source) &&
243
- !LEGACY_ASSERT_PATTERN.test(source));
244
- }
245
- function hasTypiaImport(source) {
246
- return TYPIA_IMPORT_PATTERN.test(source.replace(/\/\*[\s\S]*?\*\//gu, ""));
247
- }
248
- function replaceFirstNonCommentLine(source, pattern, replacement) {
249
- const lineEnding = source.includes("\r\n") ? "\r\n" : "\n";
250
- const lines = source.split(/\r?\n/);
251
- let inBlockComment = false;
252
- for (let index = 0; index < lines.length; index += 1) {
253
- const line = lines[index] ?? "";
254
- const trimmed = line.trimStart();
255
- if (inBlockComment) {
256
- if (trimmed.includes("*/")) {
257
- inBlockComment = false;
258
- }
259
- continue;
260
- }
261
- if (trimmed.startsWith("//")) {
262
- continue;
263
- }
264
- if (trimmed.startsWith("/*")) {
265
- if (!trimmed.includes("*/")) {
266
- inBlockComment = true;
267
- }
268
- continue;
269
- }
270
- if (!pattern.test(line)) {
271
- continue;
272
- }
273
- lines[index] = replacement;
274
- return lines.join(lineEnding);
275
- }
276
- return source;
277
- }
278
- function upgradeLegacyCompoundValidatorSource(source) {
279
- const typeNameMatch = source.match(LEGACY_TOOLKIT_CALL_PATTERN);
280
- const typeName = typeNameMatch?.groups?.typeName;
281
- if (!typeName) {
282
- throw new Error("Unable to upgrade a legacy compound validator without a generated type import.");
283
- }
284
- let nextSource = source;
285
- if (!hasTypiaImport(nextSource)) {
286
- nextSource = `import typia from 'typia';\n${nextSource}`;
287
- }
288
- nextSource = replaceFirstNonCommentLine(nextSource, LEGACY_VALIDATOR_MANIFEST_IMPORT_PATTERN, "import currentManifest from './manifest-defaults-document';");
289
- nextSource = nextSource.replace(LEGACY_TOOLKIT_CALL_PATTERN, [
290
- `createTemplateValidatorToolkit< ${typeName} >( {`,
291
- `\tassert: typia.createAssert< ${typeName} >(),`,
292
- `\tclone: typia.misc.createClone< ${typeName} >() as (`,
293
- `\t\tvalue: ${typeName},`,
294
- `\t) => ${typeName},`,
295
- `\tis: typia.createIs< ${typeName} >(),`,
296
- ].join("\n") + "\n");
297
- const replacedManifest = nextSource.replace(LEGACY_MANIFEST_PATTERN, [
298
- "",
299
- "\tmanifest: currentManifest,",
300
- `\tprune: typia.misc.createPrune< ${typeName} >(),`,
301
- `\trandom: typia.createRandom< ${typeName} >() as (`,
302
- "\t\t...args: unknown[]",
303
- `\t) => ${typeName},`,
304
- `\tvalidate: typia.createValidate< ${typeName} >(),`,
305
- ].join("\n"));
306
- if (replacedManifest === nextSource) {
307
- throw new Error("Unable to upgrade legacy compound validator: manifest anchor not found.");
308
- }
309
- return replacedManifest;
310
- }
311
- function renderLegacyManifestDefaultsWrapperSource() {
312
- return [
313
- "import rawCurrentManifest from './typia.manifest.json';",
314
- "import { defineManifestDefaultsDocument } from '@wp-typia/block-runtime/defaults';",
315
- "",
316
- "const currentManifest = defineManifestDefaultsDocument( rawCurrentManifest );",
317
- "",
318
- "export default currentManifest;",
319
- "",
320
- ].join("\n");
321
- }
322
- async function ensureLegacyCompoundValidatorManifestDefaultsWrapper(validatorPath) {
323
- const validatorDir = path.dirname(validatorPath);
324
- const wrapperPath = path.join(validatorDir, "manifest-defaults-document.ts");
325
- const manifestPath = path.join(validatorDir, "typia.manifest.json");
326
- if (fs.existsSync(wrapperPath) || !fs.existsSync(manifestPath)) {
327
- return;
328
- }
329
- await fsp.writeFile(wrapperPath, renderLegacyManifestDefaultsWrapperSource(), "utf8");
330
- }
331
- async function collectLegacyCompoundValidatorPaths(projectDir) {
332
- const blocksDir = path.join(projectDir, "src", "blocks");
333
- if (!fs.existsSync(blocksDir)) {
334
- return [];
335
- }
336
- const blockEntries = await fsp.readdir(blocksDir, { withFileTypes: true });
337
- const validatorPaths = await Promise.all(blockEntries
338
- .filter((entry) => entry.isDirectory())
339
- .map(async (entry) => {
340
- const validatorPath = path.join(blocksDir, entry.name, "validators.ts");
341
- const validatorSource = await readOptionalFile(validatorPath);
342
- return isLegacyCompoundValidatorSource(validatorSource) ? validatorPath : null;
343
- }));
344
- return validatorPaths.filter((validatorPath) => validatorPath !== null);
345
- }
346
- async function ensureCompoundWorkspaceSupportFiles(projectDir, tempProjectDir, legacyValidatorPaths) {
347
- for (const fileName of COMPOUND_SHARED_SUPPORT_FILES) {
348
- const sourcePath = path.join(tempProjectDir, "src", fileName);
349
- if (!fs.existsSync(sourcePath)) {
350
- continue;
351
- }
352
- const targetPath = path.join(projectDir, "src", fileName);
353
- const currentSource = await readOptionalFile(targetPath);
354
- if (fileName === "validator-toolkit.ts"
355
- ? shouldRefreshCompoundValidatorToolkit(currentSource)
356
- : currentSource === null) {
357
- await fsp.mkdir(path.dirname(targetPath), { recursive: true });
358
- await fsp.copyFile(sourcePath, targetPath);
359
- }
360
- }
361
- for (const validatorPath of legacyValidatorPaths) {
362
- const currentSource = await readOptionalFile(validatorPath);
363
- if (!isLegacyCompoundValidatorSource(currentSource)) {
364
- continue;
365
- }
366
- await ensureLegacyCompoundValidatorManifestDefaultsWrapper(validatorPath);
367
- await fsp.writeFile(validatorPath, upgradeLegacyCompoundValidatorSource(currentSource), "utf8");
368
- }
369
- }
370
72
  async function copyScaffoldedBlockSlice(projectDir, templateId, tempProjectDir, variables, legacyValidatorPaths = []) {
371
73
  if (templateId === "compound") {
372
74
  await ensureCompoundWorkspaceSupportFiles(projectDir, tempProjectDir, legacyValidatorPaths);