@wp-typia/project-tools 0.22.6 → 0.22.8
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.
- package/dist/runtime/block-targets.d.ts +40 -0
- package/dist/runtime/block-targets.js +71 -0
- package/dist/runtime/built-in-block-artifact-types.js +2 -1
- package/dist/runtime/built-in-block-attribute-specs.js +2 -1
- package/dist/runtime/built-in-block-code-artifacts.js +2 -0
- package/dist/runtime/built-in-block-non-ts-family-artifacts.js +12 -9
- package/dist/runtime/built-in-block-non-ts-render-utils.js +2 -0
- package/dist/runtime/cli-add-block-config.js +2 -1
- package/dist/runtime/cli-add-block-json.d.ts +2 -2
- package/dist/runtime/cli-add-block-json.js +5 -4
- package/dist/runtime/cli-add-block.js +4 -3
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +21 -15
- package/dist/runtime/cli-add-workspace-ability.js +2 -2
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +17 -13
- package/dist/runtime/cli-add-workspace-admin-view.js +2 -2
- package/dist/runtime/cli-add-workspace-ai.js +2 -2
- package/dist/runtime/cli-add-workspace-assets.js +42 -48
- package/dist/runtime/cli-add-workspace-rest.js +2 -2
- package/dist/runtime/cli-add-workspace.js +14 -49
- package/dist/runtime/cli-diagnostics.js +6 -0
- package/dist/runtime/cli-init-plan-presentation.d.ts +16 -0
- package/dist/runtime/cli-init-plan-presentation.js +74 -0
- package/dist/runtime/cli-init-plan.js +5 -77
- package/dist/runtime/cli-scaffold.js +2 -1
- package/dist/runtime/create-template-validation.d.ts +10 -0
- package/dist/runtime/create-template-validation.js +121 -0
- package/dist/runtime/package-versions.d.ts +1 -1
- package/dist/runtime/package-versions.js +16 -3
- package/dist/runtime/php-utils.js +151 -148
- package/dist/runtime/scaffold-answer-resolution.js +5 -108
- package/dist/runtime/scaffold-apply-utils.js +3 -2
- package/dist/runtime/scaffold-identifiers.js +4 -3
- package/dist/runtime/scaffold-template-assertions.d.ts +6 -0
- package/dist/runtime/scaffold-template-assertions.js +33 -0
- package/dist/runtime/scaffold-template-variable-groups.d.ts +2 -0
- package/dist/runtime/scaffold-template-variable-groups.js +7 -0
- package/dist/runtime/string-case.d.ts +2 -4
- package/dist/runtime/string-case.js +15 -4
- package/dist/runtime/template-source-cache-policy.d.ts +53 -0
- package/dist/runtime/template-source-cache-policy.js +135 -0
- package/dist/runtime/template-source-cache.d.ts +1 -45
- package/dist/runtime/template-source-cache.js +9 -152
- package/dist/runtime/ts-property-names.d.ts +11 -0
- package/dist/runtime/ts-property-names.js +16 -0
- package/dist/runtime/workspace-inventory.d.ts +13 -1
- package/dist/runtime/workspace-inventory.js +35 -9
- package/package.json +6 -1
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
1
|
import { promises as fsp } from "node:fs";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { syncBlockMetadata, } from "@wp-typia/block-runtime/metadata-core";
|
|
5
4
|
import ts from "typescript";
|
|
6
5
|
import { resolveWorkspaceProject, } from "./workspace-project.js";
|
|
7
|
-
import {
|
|
6
|
+
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
8
7
|
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
9
8
|
import { findPhpFunctionRange, hasPhpFunctionDefinition, quotePhpString, replacePhpFunctionDefinition, } from "./php-utils.js";
|
|
10
9
|
import { assertBindingSourceDoesNotExist, assertEditorPluginDoesNotExist, assertPatternDoesNotExist, assertValidEditorPluginSlot, assertValidGeneratedSlug, getWorkspaceBootstrapPath, normalizeBlockSlug, patchFile, quoteTsString, resolveWorkspaceBlock, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
11
10
|
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
11
|
+
import { resolveWorkspaceBlockTargetName } from "./block-targets.js";
|
|
12
|
+
import { pathExists, readOptionalUtf8File } from "./fs-async.js";
|
|
12
13
|
import { normalizeOptionalCliString } from "./cli-validation.js";
|
|
14
|
+
import { getPropertyNameText } from "./ts-property-names.js";
|
|
13
15
|
const PATTERN_BOOTSTRAP_CATEGORY = "register_block_pattern_category";
|
|
14
16
|
const BINDING_SOURCE_SERVER_GLOB = "/src/bindings/*/server.php";
|
|
15
17
|
const BINDING_SOURCE_EDITOR_SCRIPT = "build/bindings/index.js";
|
|
@@ -48,26 +50,6 @@ function assertValidBindingAttributeName(attributeName) {
|
|
|
48
50
|
}
|
|
49
51
|
return trimmed;
|
|
50
52
|
}
|
|
51
|
-
function resolveBindingTargetBlockSlug(blockName, namespace) {
|
|
52
|
-
const trimmed = blockName.trim();
|
|
53
|
-
if (!trimmed) {
|
|
54
|
-
throw new Error("`wp-typia add binding-source` requires --block <block-slug|namespace/block-slug> to include a value when --attribute is provided.");
|
|
55
|
-
}
|
|
56
|
-
const blockNameSegments = trimmed.split("/");
|
|
57
|
-
if (blockNameSegments.length > 2) {
|
|
58
|
-
throw new Error(`Binding target block "${trimmed}" must use <block-slug> or <namespace/block-slug> format.`);
|
|
59
|
-
}
|
|
60
|
-
if (blockNameSegments.some((segment) => segment.trim() === "")) {
|
|
61
|
-
throw new Error(`Binding target block "${trimmed}" must use <block-slug> or <namespace/block-slug> format without empty path segments.`);
|
|
62
|
-
}
|
|
63
|
-
const [maybeNamespace, maybeSlug] = blockNameSegments.length === 2
|
|
64
|
-
? blockNameSegments
|
|
65
|
-
: [undefined, blockNameSegments[0]];
|
|
66
|
-
if (maybeNamespace && maybeNamespace !== namespace) {
|
|
67
|
-
throw new Error(`Binding target block "${trimmed}" uses namespace "${maybeNamespace}". Expected "${namespace}".`);
|
|
68
|
-
}
|
|
69
|
-
return normalizeBlockSlug(maybeSlug ?? "");
|
|
70
|
-
}
|
|
71
53
|
function buildEditorPluginConfigEntry(editorPluginSlug, slot) {
|
|
72
54
|
return [
|
|
73
55
|
"\t{",
|
|
@@ -237,9 +219,15 @@ function resolveBindingTarget(options, namespace) {
|
|
|
237
219
|
if (!hasBlock || !hasAttribute) {
|
|
238
220
|
throw new Error("`wp-typia add binding-source` requires --block and --attribute to be provided together.");
|
|
239
221
|
}
|
|
222
|
+
const targetBlock = resolveWorkspaceBlockTargetName(blockName ?? "", namespace, {
|
|
223
|
+
empty: () => "`wp-typia add binding-source` requires --block <block-slug|namespace/block-slug> to include a value when --attribute is provided.",
|
|
224
|
+
emptySegment: (input) => `Binding target block "${input}" must use <block-slug> or <namespace/block-slug> format without empty path segments.`,
|
|
225
|
+
invalidFormat: (input) => `Binding target block "${input}" must use <block-slug> or <namespace/block-slug> format.`,
|
|
226
|
+
namespaceMismatch: (input, actualNamespace, expectedNamespace) => `Binding target block "${input}" uses namespace "${actualNamespace}". Expected "${expectedNamespace}".`,
|
|
227
|
+
});
|
|
240
228
|
return {
|
|
241
229
|
attributeName: assertValidBindingAttributeName(attributeName ?? ""),
|
|
242
|
-
blockSlug:
|
|
230
|
+
blockSlug: targetBlock.blockSlug,
|
|
243
231
|
};
|
|
244
232
|
}
|
|
245
233
|
function formatBindingAttributeTypeMember(attributeName) {
|
|
@@ -266,12 +254,6 @@ function getInterfaceDeclaration(source, interfaceName) {
|
|
|
266
254
|
visit(sourceFile);
|
|
267
255
|
return declaration ? { declaration, sourceFile } : undefined;
|
|
268
256
|
}
|
|
269
|
-
function getPropertyNameText(name) {
|
|
270
|
-
if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) {
|
|
271
|
-
return name.text;
|
|
272
|
-
}
|
|
273
|
-
return undefined;
|
|
274
|
-
}
|
|
275
257
|
function interfaceHasAttributeMember(declaration, attributeName) {
|
|
276
258
|
return declaration.members.some((member) => ts.isPropertySignature(member) &&
|
|
277
259
|
member.name !== undefined &&
|
|
@@ -722,41 +704,53 @@ async function ensureEditorPluginWebpackAnchors(workspace) {
|
|
|
722
704
|
return nextSource;
|
|
723
705
|
});
|
|
724
706
|
}
|
|
725
|
-
function resolveBindingSourceRegistryPath(projectDir) {
|
|
707
|
+
async function resolveBindingSourceRegistryPath(projectDir) {
|
|
726
708
|
const bindingsDir = path.join(projectDir, "src", "bindings");
|
|
727
|
-
|
|
709
|
+
for (const candidatePath of [
|
|
710
|
+
path.join(bindingsDir, "index.ts"),
|
|
711
|
+
path.join(bindingsDir, "index.js"),
|
|
712
|
+
]) {
|
|
713
|
+
if (await pathExists(candidatePath)) {
|
|
714
|
+
return candidatePath;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return path.join(bindingsDir, "index.ts");
|
|
728
718
|
}
|
|
729
719
|
async function writeBindingSourceRegistry(projectDir, bindingSourceSlug) {
|
|
730
720
|
const bindingsDir = path.join(projectDir, "src", "bindings");
|
|
731
|
-
const bindingsIndexPath = resolveBindingSourceRegistryPath(projectDir);
|
|
721
|
+
const bindingsIndexPath = await resolveBindingSourceRegistryPath(projectDir);
|
|
732
722
|
await fsp.mkdir(bindingsDir, { recursive: true });
|
|
733
|
-
const existingBindingSourceSlugs =
|
|
734
|
-
.readdirSync(bindingsDir, { withFileTypes: true })
|
|
723
|
+
const existingBindingSourceSlugs = (await fsp.readdir(bindingsDir, { withFileTypes: true }))
|
|
735
724
|
.filter((entry) => entry.isDirectory())
|
|
736
725
|
.map((entry) => entry.name);
|
|
737
726
|
const nextBindingSourceSlugs = Array.from(new Set([...existingBindingSourceSlugs, bindingSourceSlug])).sort();
|
|
738
727
|
await fsp.writeFile(bindingsIndexPath, buildBindingSourceIndexSource(nextBindingSourceSlugs), "utf8");
|
|
739
728
|
}
|
|
740
|
-
function resolveEditorPluginRegistryPath(projectDir) {
|
|
729
|
+
async function resolveEditorPluginRegistryPath(projectDir) {
|
|
741
730
|
const editorPluginsDir = path.join(projectDir, "src", "editor-plugins");
|
|
742
|
-
|
|
731
|
+
for (const candidatePath of [
|
|
743
732
|
path.join(editorPluginsDir, "index.ts"),
|
|
744
733
|
path.join(editorPluginsDir, "index.js"),
|
|
745
|
-
]
|
|
734
|
+
]) {
|
|
735
|
+
if (await pathExists(candidatePath)) {
|
|
736
|
+
return candidatePath;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return path.join(editorPluginsDir, "index.ts");
|
|
746
740
|
}
|
|
747
|
-
function readEditorPluginRegistrySlugs(registryPath) {
|
|
748
|
-
|
|
741
|
+
async function readEditorPluginRegistrySlugs(registryPath) {
|
|
742
|
+
const source = await readOptionalUtf8File(registryPath);
|
|
743
|
+
if (source === null) {
|
|
749
744
|
return [];
|
|
750
745
|
}
|
|
751
|
-
const source = fs.readFileSync(registryPath, "utf8");
|
|
752
746
|
return Array.from(source.matchAll(/^\s*import\s+['"]\.\/([^/'"]+)(?:\/index(?:\.[cm]?[jt]sx?)?)?['"];?\s*$/gmu)).map((match) => match[1]);
|
|
753
747
|
}
|
|
754
748
|
async function writeEditorPluginRegistry(projectDir, editorPluginSlug) {
|
|
755
749
|
const editorPluginsDir = path.join(projectDir, "src", "editor-plugins");
|
|
756
|
-
const registryPath = resolveEditorPluginRegistryPath(projectDir);
|
|
750
|
+
const registryPath = await resolveEditorPluginRegistryPath(projectDir);
|
|
757
751
|
await fsp.mkdir(editorPluginsDir, { recursive: true });
|
|
758
|
-
const existingEditorPluginSlugs =
|
|
759
|
-
const existingRegistrySlugs = readEditorPluginRegistrySlugs(registryPath);
|
|
752
|
+
const existingEditorPluginSlugs = (await readWorkspaceInventoryAsync(projectDir)).editorPlugins.map((entry) => entry.slug);
|
|
753
|
+
const existingRegistrySlugs = await readEditorPluginRegistrySlugs(registryPath);
|
|
760
754
|
const nextEditorPluginSlugs = Array.from(new Set([...existingEditorPluginSlugs, ...existingRegistrySlugs, editorPluginSlug])).sort();
|
|
761
755
|
await fsp.writeFile(registryPath, buildEditorPluginRegistrySource(nextEditorPluginSlugs), "utf8");
|
|
762
756
|
}
|
|
@@ -779,12 +773,12 @@ export async function runAddEditorPluginCommand({ cwd = process.cwd(), editorPlu
|
|
|
779
773
|
const workspace = resolveWorkspaceProject(cwd);
|
|
780
774
|
const editorPluginSlug = assertValidGeneratedSlug("Editor plugin name", normalizeBlockSlug(editorPluginName), "wp-typia add editor-plugin <name> [--slot <sidebar|document-setting-panel>]");
|
|
781
775
|
const resolvedSlot = assertValidEditorPluginSlot(slot);
|
|
782
|
-
const inventory =
|
|
776
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
783
777
|
assertEditorPluginDoesNotExist(workspace.projectDir, editorPluginSlug, inventory);
|
|
784
778
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
785
779
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
786
780
|
const buildScriptPath = path.join(workspace.projectDir, "scripts", "build-workspace.mjs");
|
|
787
|
-
const editorPluginsIndexPath = resolveEditorPluginRegistryPath(workspace.projectDir);
|
|
781
|
+
const editorPluginsIndexPath = await resolveEditorPluginRegistryPath(workspace.projectDir);
|
|
788
782
|
const webpackConfigPath = path.join(workspace.projectDir, "webpack.config.js");
|
|
789
783
|
const editorPluginDir = path.join(workspace.projectDir, "src", "editor-plugins", editorPluginSlug);
|
|
790
784
|
const entryFilePath = path.join(editorPluginDir, "index.tsx");
|
|
@@ -848,7 +842,7 @@ export async function runAddEditorPluginCommand({ cwd = process.cwd(), editorPlu
|
|
|
848
842
|
export async function runAddPatternCommand({ cwd = process.cwd(), patternName, }) {
|
|
849
843
|
const workspace = resolveWorkspaceProject(cwd);
|
|
850
844
|
const patternSlug = assertValidGeneratedSlug("Pattern name", normalizeBlockSlug(patternName), "wp-typia add pattern <name>");
|
|
851
|
-
const inventory =
|
|
845
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
852
846
|
assertPatternDoesNotExist(workspace.projectDir, patternSlug, inventory);
|
|
853
847
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
854
848
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
@@ -898,7 +892,7 @@ export async function runAddPatternCommand({ cwd = process.cwd(), patternName, }
|
|
|
898
892
|
export async function runAddBindingSourceCommand({ attributeName, bindingSourceName, blockName, cwd = process.cwd(), }) {
|
|
899
893
|
const workspace = resolveWorkspaceProject(cwd);
|
|
900
894
|
const bindingSourceSlug = assertValidGeneratedSlug("Binding source name", normalizeBlockSlug(bindingSourceName), "wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>]");
|
|
901
|
-
const inventory =
|
|
895
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
902
896
|
assertBindingSourceDoesNotExist(workspace.projectDir, bindingSourceSlug, inventory);
|
|
903
897
|
const target = resolveBindingTarget({
|
|
904
898
|
attributeName,
|
|
@@ -907,7 +901,7 @@ export async function runAddBindingSourceCommand({ attributeName, bindingSourceN
|
|
|
907
901
|
const targetBlock = target ? resolveWorkspaceBlock(inventory, target.blockSlug) : undefined;
|
|
908
902
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
909
903
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
910
|
-
const bindingsIndexPath = resolveBindingSourceRegistryPath(workspace.projectDir);
|
|
904
|
+
const bindingsIndexPath = await resolveBindingSourceRegistryPath(workspace.projectDir);
|
|
911
905
|
const bindingSourceDir = path.join(workspace.projectDir, "src", "bindings", bindingSourceSlug);
|
|
912
906
|
const serverFilePath = path.join(bindingSourceDir, "server.php");
|
|
913
907
|
const editorFilePath = path.join(bindingSourceDir, "editor.ts");
|
|
@@ -7,7 +7,7 @@ import { buildRestResourceApiSource, buildRestResourceConfigEntry, buildRestReso
|
|
|
7
7
|
import { quotePhpString } from "./php-utils.js";
|
|
8
8
|
import { syncRestResourceArtifacts } from "./rest-resource-artifacts.js";
|
|
9
9
|
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
10
|
-
import { appendWorkspaceInventoryEntries,
|
|
10
|
+
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
11
11
|
import { resolveWorkspaceProject } from "./workspace-project.js";
|
|
12
12
|
function buildRestResourceRouteRegistrations(restResourceSlug, methods, functions) {
|
|
13
13
|
const collectionRoutes = [];
|
|
@@ -434,7 +434,7 @@ export async function runAddRestResourceCommand({ cwd = process.cwd(), methods,
|
|
|
434
434
|
const restResourceSlug = assertValidGeneratedSlug("REST resource name", normalizeBlockSlug(restResourceName), "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create>]");
|
|
435
435
|
const resolvedMethods = assertValidRestResourceMethods(methods);
|
|
436
436
|
const resolvedNamespace = resolveRestResourceNamespace(workspace.workspace.namespace, namespace);
|
|
437
|
-
const inventory =
|
|
437
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
438
438
|
assertRestResourceDoesNotExist(workspace.projectDir, restResourceSlug, inventory);
|
|
439
439
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
440
440
|
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
1
|
import { promises as fsp } from "node:fs";
|
|
3
2
|
import path from "node:path";
|
|
3
|
+
import { pathExists } from "./fs-async.js";
|
|
4
|
+
import { assertFullBlockName, resolveWorkspaceTargetBlockName, } from "./block-targets.js";
|
|
4
5
|
import { resolveWorkspaceProject } from "./workspace-project.js";
|
|
5
|
-
import { appendWorkspaceInventoryEntries,
|
|
6
|
+
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
6
7
|
import { toKebabCase, toSnakeCase, toTitleCase } from "./string-case.js";
|
|
7
8
|
import { assertBlockStyleDoesNotExist, assertBlockTransformDoesNotExist, assertValidGeneratedSlug, assertValidHookAnchor, assertValidHookedBlockPosition, assertVariationDoesNotExist, getMutableBlockHooks, normalizeBlockSlug, patchFile, quoteTsString, readWorkspaceBlockJson, resolveWorkspaceBlock, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
8
9
|
import { findExecutablePatternMatch, hasExecutablePattern, hasUncommentedPattern, maskTypeScriptCommentsAndLiterals, } from "./ts-source-masking.js";
|
|
@@ -19,7 +20,6 @@ const BLOCK_TRANSFORMS_IMPORT_PATTERN = /^\s*import\s*\{\s*applyWorkspaceBlockTr
|
|
|
19
20
|
const BLOCK_TRANSFORMS_CALL_LINE = "applyWorkspaceBlockTransforms(registration.settings);";
|
|
20
21
|
const BLOCK_TRANSFORMS_CALL_PATTERN = /applyWorkspaceBlockTransforms\s*\(\s*registration\s*\.\s*settings\s*\)\s*;?/u;
|
|
21
22
|
const SCAFFOLD_REGISTRATION_SETTINGS_CALL_PATTERN = /registerScaffoldBlockType\s*\(\s*registration\s*\.\s*name\s*,\s*registration\s*\.\s*settings\s*\)\s*;?/u;
|
|
22
|
-
const FULL_BLOCK_NAME_PATTERN = /^[a-z0-9-]+\/[a-z0-9-]+$/u;
|
|
23
23
|
function isIdentifierBoundary(source, index) {
|
|
24
24
|
if (index < 0 || index >= source.length) {
|
|
25
25
|
return true;
|
|
@@ -381,8 +381,7 @@ async function writeVariationRegistry(projectDir, blockSlug, variationSlug) {
|
|
|
381
381
|
const variationsDir = path.join(projectDir, "src", "blocks", blockSlug, "variations");
|
|
382
382
|
const variationsIndexPath = path.join(variationsDir, "index.ts");
|
|
383
383
|
await fsp.mkdir(variationsDir, { recursive: true });
|
|
384
|
-
const existingVariationSlugs =
|
|
385
|
-
.readdirSync(variationsDir)
|
|
384
|
+
const existingVariationSlugs = (await fsp.readdir(variationsDir))
|
|
386
385
|
.filter((entry) => entry.endsWith(".ts") && entry !== "index.ts")
|
|
387
386
|
.map((entry) => entry.replace(/\.ts$/u, ""));
|
|
388
387
|
const nextVariationSlugs = Array.from(new Set([...existingVariationSlugs, variationSlug])).sort();
|
|
@@ -392,8 +391,7 @@ async function writeBlockStyleRegistry(projectDir, blockSlug, styleSlug) {
|
|
|
392
391
|
const stylesDir = path.join(projectDir, "src", "blocks", blockSlug, "styles");
|
|
393
392
|
const stylesIndexPath = path.join(stylesDir, "index.ts");
|
|
394
393
|
await fsp.mkdir(stylesDir, { recursive: true });
|
|
395
|
-
const existingStyleSlugs =
|
|
396
|
-
.readdirSync(stylesDir)
|
|
394
|
+
const existingStyleSlugs = (await fsp.readdir(stylesDir))
|
|
397
395
|
.filter((entry) => entry.endsWith(".ts") && entry !== "index.ts")
|
|
398
396
|
.map((entry) => entry.replace(/\.ts$/u, ""));
|
|
399
397
|
const nextStyleSlugs = Array.from(new Set([...existingStyleSlugs, styleSlug])).sort();
|
|
@@ -403,45 +401,12 @@ async function writeBlockTransformRegistry(projectDir, blockSlug, transformSlug)
|
|
|
403
401
|
const transformsDir = path.join(projectDir, "src", "blocks", blockSlug, "transforms");
|
|
404
402
|
const transformsIndexPath = path.join(transformsDir, "index.ts");
|
|
405
403
|
await fsp.mkdir(transformsDir, { recursive: true });
|
|
406
|
-
const existingTransformSlugs =
|
|
407
|
-
.readdirSync(transformsDir)
|
|
404
|
+
const existingTransformSlugs = (await fsp.readdir(transformsDir))
|
|
408
405
|
.filter((entry) => entry.endsWith(".ts") && entry !== "index.ts")
|
|
409
406
|
.map((entry) => entry.replace(/\.ts$/u, ""));
|
|
410
407
|
const nextTransformSlugs = Array.from(new Set([...existingTransformSlugs, transformSlug])).sort();
|
|
411
408
|
await fsp.writeFile(transformsIndexPath, buildBlockTransformIndexSource(nextTransformSlugs), "utf8");
|
|
412
409
|
}
|
|
413
|
-
function assertFullBlockName(blockName, flagName) {
|
|
414
|
-
const trimmed = blockName.trim();
|
|
415
|
-
if (!trimmed) {
|
|
416
|
-
throw new Error(`\`${flagName}\` requires a block name.`);
|
|
417
|
-
}
|
|
418
|
-
if (!FULL_BLOCK_NAME_PATTERN.test(trimmed)) {
|
|
419
|
-
throw new Error(`\`${flagName}\` must use <namespace/block-slug> format.`);
|
|
420
|
-
}
|
|
421
|
-
return trimmed;
|
|
422
|
-
}
|
|
423
|
-
function resolveWorkspaceTargetBlockName(blockName, namespace, flagName) {
|
|
424
|
-
const trimmed = blockName.trim();
|
|
425
|
-
if (!trimmed) {
|
|
426
|
-
throw new Error(`\`${flagName}\` requires <block-slug|namespace/block-slug>.`);
|
|
427
|
-
}
|
|
428
|
-
const blockNameSegments = trimmed.split("/");
|
|
429
|
-
if (blockNameSegments.length > 2 ||
|
|
430
|
-
blockNameSegments.some((segment) => segment.trim() === "")) {
|
|
431
|
-
throw new Error(`\`${flagName}\` must use <block-slug|namespace/block-slug> format.`);
|
|
432
|
-
}
|
|
433
|
-
const [maybeNamespace, maybeSlug] = blockNameSegments.length === 2
|
|
434
|
-
? blockNameSegments
|
|
435
|
-
: [undefined, blockNameSegments[0]];
|
|
436
|
-
if (maybeNamespace && maybeNamespace !== namespace) {
|
|
437
|
-
throw new Error(`\`${flagName}\` references namespace "${maybeNamespace}". Expected "${namespace}".`);
|
|
438
|
-
}
|
|
439
|
-
const blockSlug = normalizeBlockSlug(maybeSlug ?? "");
|
|
440
|
-
return {
|
|
441
|
-
blockName: `${namespace}/${blockSlug}`,
|
|
442
|
-
blockSlug,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
410
|
/**
|
|
446
411
|
* Re-export the DataViews admin screen scaffold workflow from the focused
|
|
447
412
|
* admin-view runtime helper module.
|
|
@@ -487,7 +452,7 @@ export async function runAddVariationCommand({ blockName, cwd = process.cwd(), v
|
|
|
487
452
|
const workspace = resolveWorkspaceProject(cwd);
|
|
488
453
|
const blockSlug = normalizeBlockSlug(blockName);
|
|
489
454
|
const variationSlug = assertValidGeneratedSlug("Variation name", normalizeBlockSlug(variationName), "wp-typia add variation <name> --block <block-slug>");
|
|
490
|
-
const inventory =
|
|
455
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
491
456
|
resolveWorkspaceBlock(inventory, blockSlug);
|
|
492
457
|
assertVariationDoesNotExist(workspace.projectDir, blockSlug, variationSlug, inventory);
|
|
493
458
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
@@ -495,7 +460,7 @@ export async function runAddVariationCommand({ blockName, cwd = process.cwd(), v
|
|
|
495
460
|
const variationsDir = path.join(workspace.projectDir, "src", "blocks", blockSlug, "variations");
|
|
496
461
|
const variationFilePath = path.join(variationsDir, `${variationSlug}.ts`);
|
|
497
462
|
const variationsIndexPath = path.join(variationsDir, "index.ts");
|
|
498
|
-
const shouldRemoveVariationsDirOnRollback = !
|
|
463
|
+
const shouldRemoveVariationsDirOnRollback = !(await pathExists(variationsDir));
|
|
499
464
|
const mutationSnapshot = {
|
|
500
465
|
fileSources: await snapshotWorkspaceFiles([
|
|
501
466
|
blockConfigPath,
|
|
@@ -547,7 +512,7 @@ export async function runAddBlockStyleCommand({ blockName, cwd = process.cwd(),
|
|
|
547
512
|
const workspace = resolveWorkspaceProject(cwd);
|
|
548
513
|
const blockSlug = normalizeBlockSlug(blockName);
|
|
549
514
|
const styleSlug = assertValidGeneratedSlug("Style name", normalizeBlockSlug(styleName), "wp-typia add style <name> --block <block-slug>");
|
|
550
|
-
const inventory =
|
|
515
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
551
516
|
resolveWorkspaceBlock(inventory, blockSlug);
|
|
552
517
|
assertBlockStyleDoesNotExist(workspace.projectDir, blockSlug, styleSlug, inventory);
|
|
553
518
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
@@ -555,7 +520,7 @@ export async function runAddBlockStyleCommand({ blockName, cwd = process.cwd(),
|
|
|
555
520
|
const stylesDir = path.join(workspace.projectDir, "src", "blocks", blockSlug, "styles");
|
|
556
521
|
const styleFilePath = path.join(stylesDir, `${styleSlug}.ts`);
|
|
557
522
|
const stylesIndexPath = path.join(stylesDir, "index.ts");
|
|
558
|
-
const shouldRemoveStylesDirOnRollback = !
|
|
523
|
+
const shouldRemoveStylesDirOnRollback = !(await pathExists(stylesDir));
|
|
559
524
|
const mutationSnapshot = {
|
|
560
525
|
fileSources: await snapshotWorkspaceFiles([
|
|
561
526
|
blockConfigPath,
|
|
@@ -616,7 +581,7 @@ export async function runAddBlockTransformCommand({ cwd = process.cwd(), fromBlo
|
|
|
616
581
|
const transformSlug = assertValidGeneratedSlug("Transform name", normalizeBlockSlug(transformName), "wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug>");
|
|
617
582
|
const resolvedFromBlockName = assertFullBlockName(fromBlockName, "--from");
|
|
618
583
|
const target = resolveWorkspaceTargetBlockName(toBlockName, workspace.workspace.namespace, "--to");
|
|
619
|
-
const inventory =
|
|
584
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
620
585
|
resolveWorkspaceBlock(inventory, target.blockSlug);
|
|
621
586
|
assertBlockTransformDoesNotExist(workspace.projectDir, target.blockSlug, transformSlug, inventory);
|
|
622
587
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
@@ -624,7 +589,7 @@ export async function runAddBlockTransformCommand({ cwd = process.cwd(), fromBlo
|
|
|
624
589
|
const transformsDir = path.join(workspace.projectDir, "src", "blocks", target.blockSlug, "transforms");
|
|
625
590
|
const transformFilePath = path.join(transformsDir, `${transformSlug}.ts`);
|
|
626
591
|
const transformsIndexPath = path.join(transformsDir, "index.ts");
|
|
627
|
-
const shouldRemoveTransformsDirOnRollback = !
|
|
592
|
+
const shouldRemoveTransformsDirOnRollback = !(await pathExists(transformsDir));
|
|
628
593
|
const mutationSnapshot = {
|
|
629
594
|
fileSources: await snapshotWorkspaceFiles([
|
|
630
595
|
blockConfigPath,
|
|
@@ -687,7 +652,7 @@ export async function runAddBlockTransformCommand({ cwd = process.cwd(), fromBlo
|
|
|
687
652
|
export async function runAddHookedBlockCommand({ anchorBlockName, blockName, cwd = process.cwd(), position, }) {
|
|
688
653
|
const workspace = resolveWorkspaceProject(cwd);
|
|
689
654
|
const blockSlug = normalizeBlockSlug(blockName);
|
|
690
|
-
const inventory =
|
|
655
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
691
656
|
resolveWorkspaceBlock(inventory, blockSlug);
|
|
692
657
|
const resolvedAnchorBlockName = assertValidHookAnchor(anchorBlockName);
|
|
693
658
|
const resolvedPosition = assertValidHookedBlockPosition(position);
|
|
@@ -695,7 +660,7 @@ export async function runAddHookedBlockCommand({ anchorBlockName, blockName, cwd
|
|
|
695
660
|
if (resolvedAnchorBlockName === selfHookAnchor) {
|
|
696
661
|
throw new Error("`wp-typia add hooked-block` cannot hook a block relative to its own block name.");
|
|
697
662
|
}
|
|
698
|
-
const { blockJson, blockJsonPath } = readWorkspaceBlockJson(workspace.projectDir, blockSlug);
|
|
663
|
+
const { blockJson, blockJsonPath } = await readWorkspaceBlockJson(workspace.projectDir, blockSlug);
|
|
699
664
|
const blockJsonRelativePath = path.relative(workspace.projectDir, blockJsonPath);
|
|
700
665
|
const blockHooks = getMutableBlockHooks(blockJson, blockJsonRelativePath);
|
|
701
666
|
if (Object.prototype.hasOwnProperty.call(blockHooks, resolvedAnchorBlockName)) {
|
|
@@ -226,6 +226,12 @@ export function createCliDiagnosticCodeError(code, message, options) {
|
|
|
226
226
|
error.code = code;
|
|
227
227
|
return error;
|
|
228
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Compatibility-only fallback for legacy or third-party errors that have not
|
|
231
|
+
* yet been tagged by their throw site. New user-facing failures should pass an
|
|
232
|
+
* explicit code through `createCliDiagnosticCodeError()` or
|
|
233
|
+
* `createCliCommandError({ code })` instead of relying on message matching.
|
|
234
|
+
*/
|
|
229
235
|
function inferCliDiagnosticCode(options) {
|
|
230
236
|
const inheritedCode = readCliDiagnosticCode(options.error);
|
|
231
237
|
if (inheritedCode) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type PackageManagerId } from "./package-managers.js";
|
|
2
|
+
import type { InitCommandMode, InitPlanLayoutKind, InitPlanStatus, RetrofitInitPlan } from "./cli-init-types.js";
|
|
3
|
+
export declare function buildInitPlanChangeSummary(changes: Pick<RetrofitInitPlan, "generatedArtifacts" | "packageChanges" | "plannedFiles">, options: {
|
|
4
|
+
includeGeneratedArtifacts: boolean;
|
|
5
|
+
}): string[];
|
|
6
|
+
export declare function buildInitPlanNextSteps(options: {
|
|
7
|
+
commandMode: InitCommandMode;
|
|
8
|
+
dependencyChangeCount: number;
|
|
9
|
+
hasPlannedChanges: boolean;
|
|
10
|
+
layoutKind: InitPlanLayoutKind;
|
|
11
|
+
packageManager: PackageManagerId;
|
|
12
|
+
}): string[];
|
|
13
|
+
export declare function buildRetrofitPlanSummary(options: {
|
|
14
|
+
commandMode: InitCommandMode;
|
|
15
|
+
status: InitPlanStatus;
|
|
16
|
+
}): string;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { formatAddDevDependenciesCommand, formatPackageExecCommand, formatRunScript, } from "./package-managers.js";
|
|
2
|
+
import { buildRequiredDevDependencyMapEntries, getWpTypiaCliSpecifier, } from "./cli-init-package-json.js";
|
|
3
|
+
export function buildInitPlanChangeSummary(changes, options) {
|
|
4
|
+
const lines = [];
|
|
5
|
+
for (const dependencyChange of changes.packageChanges.addDevDependencies) {
|
|
6
|
+
lines.push(`devDependency ${dependencyChange.action} ${dependencyChange.name} -> ${dependencyChange.requiredValue}`);
|
|
7
|
+
}
|
|
8
|
+
if (changes.packageChanges.packageManagerField) {
|
|
9
|
+
lines.push(`packageManager ${changes.packageChanges.packageManagerField.action} -> ${changes.packageChanges.packageManagerField.requiredValue}`);
|
|
10
|
+
}
|
|
11
|
+
for (const scriptChange of changes.packageChanges.scripts) {
|
|
12
|
+
lines.push(`script ${scriptChange.action} ${scriptChange.name} -> ${scriptChange.requiredValue}`);
|
|
13
|
+
}
|
|
14
|
+
for (const filePlan of changes.plannedFiles) {
|
|
15
|
+
lines.push(`file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`);
|
|
16
|
+
}
|
|
17
|
+
if (options.includeGeneratedArtifacts) {
|
|
18
|
+
for (const artifactPath of changes.generatedArtifacts) {
|
|
19
|
+
lines.push(`generated artifact ${artifactPath}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return lines;
|
|
23
|
+
}
|
|
24
|
+
export function buildInitPlanNextSteps(options) {
|
|
25
|
+
const cliSpecifier = getWpTypiaCliSpecifier();
|
|
26
|
+
const syncTypesRun = formatRunScript(options.packageManager, "sync-types");
|
|
27
|
+
const syncRun = formatRunScript(options.packageManager, "sync");
|
|
28
|
+
const doctorRun = formatPackageExecCommand(options.packageManager, cliSpecifier, "doctor");
|
|
29
|
+
const migrationInitRun = formatPackageExecCommand(options.packageManager, cliSpecifier, "migrate init --current-migration-version v1");
|
|
30
|
+
const dependencyInstallCommand = formatAddDevDependenciesCommand(options.packageManager, buildRequiredDevDependencyMapEntries());
|
|
31
|
+
if (options.layoutKind === "unsupported") {
|
|
32
|
+
return [
|
|
33
|
+
"Align the project to one of the supported retrofit layouts listed below, then rerun `wp-typia init`.",
|
|
34
|
+
dependencyInstallCommand,
|
|
35
|
+
syncTypesRun,
|
|
36
|
+
doctorRun,
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
if (options.commandMode === "apply") {
|
|
40
|
+
return [
|
|
41
|
+
...(options.dependencyChangeCount > 0
|
|
42
|
+
? [
|
|
43
|
+
"Install or reinstall project dependencies so the retrofit sync scripts and metadata generators are available locally.",
|
|
44
|
+
dependencyInstallCommand,
|
|
45
|
+
]
|
|
46
|
+
: []),
|
|
47
|
+
syncRun,
|
|
48
|
+
doctorRun,
|
|
49
|
+
`Optional migration bootstrap: ${migrationInitRun}`,
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
return [
|
|
53
|
+
...(options.hasPlannedChanges
|
|
54
|
+
? [
|
|
55
|
+
"Re-run `wp-typia init --apply` to write the planned package.json changes and helper files automatically.",
|
|
56
|
+
...(options.dependencyChangeCount > 0 ? [dependencyInstallCommand] : []),
|
|
57
|
+
]
|
|
58
|
+
: []),
|
|
59
|
+
syncRun,
|
|
60
|
+
doctorRun,
|
|
61
|
+
`Optional migration bootstrap: ${migrationInitRun}`,
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
export function buildRetrofitPlanSummary(options) {
|
|
65
|
+
if (options.status === "already-initialized") {
|
|
66
|
+
return options.commandMode === "apply"
|
|
67
|
+
? "This project already exposes the minimum wp-typia retrofit surface. No files were changed."
|
|
68
|
+
: "This project already exposes the minimum wp-typia retrofit surface.";
|
|
69
|
+
}
|
|
70
|
+
if (options.commandMode === "apply") {
|
|
71
|
+
return "Applied the minimum wp-typia retrofit surface so package.json and helper scripts are ready for the next install and sync run.";
|
|
72
|
+
}
|
|
73
|
+
return "This command previews the minimum wp-typia adoption layer for the current project without rewriting it into a full scaffold.";
|
|
74
|
+
}
|
|
@@ -3,9 +3,10 @@ import path from "node:path";
|
|
|
3
3
|
import { analyzeSourceTypes } from "@wp-typia/block-runtime/metadata-parser";
|
|
4
4
|
import ts from "typescript";
|
|
5
5
|
import { discoverMigrationInitLayout } from "./migration-project.js";
|
|
6
|
-
import {
|
|
6
|
+
import { formatPackageExecCommand, formatRunScript } from "./package-managers.js";
|
|
7
7
|
import { toPascalCase } from "./string-case.js";
|
|
8
|
-
import { buildDependencyChanges, buildPackageManagerFieldChange,
|
|
8
|
+
import { buildDependencyChanges, buildPackageManagerFieldChange, buildScriptChanges, getWpTypiaCliSpecifier, hasExistingWpTypiaProjectSurface, readProjectPackageJson, resolveInitPackageManager, } from "./cli-init-package-json.js";
|
|
9
|
+
import { buildInitPlanChangeSummary, buildInitPlanNextSteps, buildRetrofitPlanSummary, } from "./cli-init-plan-presentation.js";
|
|
9
10
|
import { RETROFIT_APPLY_PREVIEW_NOTE, SUPPORTED_RETROFIT_LAYOUT_NOTE, } from "./cli-init-types.js";
|
|
10
11
|
import { tryResolveWorkspaceProject } from "./workspace-project.js";
|
|
11
12
|
function normalizeRelativePath(value) {
|
|
@@ -161,82 +162,9 @@ function buildPlannedFiles(projectDir, layoutKind) {
|
|
|
161
162
|
},
|
|
162
163
|
];
|
|
163
164
|
}
|
|
164
|
-
function buildChangeSummary(changes, options) {
|
|
165
|
-
const lines = [];
|
|
166
|
-
for (const dependencyChange of changes.packageChanges.addDevDependencies) {
|
|
167
|
-
lines.push(`devDependency ${dependencyChange.action} ${dependencyChange.name} -> ${dependencyChange.requiredValue}`);
|
|
168
|
-
}
|
|
169
|
-
if (changes.packageChanges.packageManagerField) {
|
|
170
|
-
lines.push(`packageManager ${changes.packageChanges.packageManagerField.action} -> ${changes.packageChanges.packageManagerField.requiredValue}`);
|
|
171
|
-
}
|
|
172
|
-
for (const scriptChange of changes.packageChanges.scripts) {
|
|
173
|
-
lines.push(`script ${scriptChange.action} ${scriptChange.name} -> ${scriptChange.requiredValue}`);
|
|
174
|
-
}
|
|
175
|
-
for (const filePlan of changes.plannedFiles) {
|
|
176
|
-
lines.push(`file ${filePlan.action} ${filePlan.path} (${filePlan.purpose})`);
|
|
177
|
-
}
|
|
178
|
-
if (options.includeGeneratedArtifacts) {
|
|
179
|
-
for (const artifactPath of changes.generatedArtifacts) {
|
|
180
|
-
lines.push(`generated artifact ${artifactPath}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return lines;
|
|
184
|
-
}
|
|
185
|
-
function buildNextSteps(options) {
|
|
186
|
-
const cliSpecifier = getWpTypiaCliSpecifier();
|
|
187
|
-
const syncTypesRun = formatRunScript(options.packageManager, "sync-types");
|
|
188
|
-
const syncRun = formatRunScript(options.packageManager, "sync");
|
|
189
|
-
const doctorRun = formatPackageExecCommand(options.packageManager, cliSpecifier, "doctor");
|
|
190
|
-
const migrationInitRun = formatPackageExecCommand(options.packageManager, cliSpecifier, "migrate init --current-migration-version v1");
|
|
191
|
-
const dependencyInstallCommand = formatAddDevDependenciesCommand(options.packageManager, buildRequiredDevDependencyMapEntries());
|
|
192
|
-
if (options.layoutKind === "unsupported") {
|
|
193
|
-
return [
|
|
194
|
-
"Align the project to one of the supported retrofit layouts listed below, then rerun `wp-typia init`.",
|
|
195
|
-
dependencyInstallCommand,
|
|
196
|
-
syncTypesRun,
|
|
197
|
-
doctorRun,
|
|
198
|
-
];
|
|
199
|
-
}
|
|
200
|
-
if (options.commandMode === "apply") {
|
|
201
|
-
return [
|
|
202
|
-
...(options.dependencyChangeCount > 0
|
|
203
|
-
? [
|
|
204
|
-
"Install or reinstall project dependencies so the retrofit sync scripts and metadata generators are available locally.",
|
|
205
|
-
dependencyInstallCommand,
|
|
206
|
-
]
|
|
207
|
-
: []),
|
|
208
|
-
syncRun,
|
|
209
|
-
doctorRun,
|
|
210
|
-
`Optional migration bootstrap: ${migrationInitRun}`,
|
|
211
|
-
];
|
|
212
|
-
}
|
|
213
|
-
const steps = [
|
|
214
|
-
...(options.hasPlannedChanges
|
|
215
|
-
? [
|
|
216
|
-
"Re-run `wp-typia init --apply` to write the planned package.json changes and helper files automatically.",
|
|
217
|
-
...(options.dependencyChangeCount > 0 ? [dependencyInstallCommand] : []),
|
|
218
|
-
]
|
|
219
|
-
: []),
|
|
220
|
-
syncRun,
|
|
221
|
-
doctorRun,
|
|
222
|
-
`Optional migration bootstrap: ${migrationInitRun}`,
|
|
223
|
-
];
|
|
224
|
-
return steps;
|
|
225
|
-
}
|
|
226
|
-
function buildRetrofitPlanSummary(options) {
|
|
227
|
-
if (options.status === "already-initialized") {
|
|
228
|
-
return options.commandMode === "apply"
|
|
229
|
-
? "This project already exposes the minimum wp-typia retrofit surface. No files were changed."
|
|
230
|
-
: "This project already exposes the minimum wp-typia retrofit surface.";
|
|
231
|
-
}
|
|
232
|
-
if (options.commandMode === "apply") {
|
|
233
|
-
return "Applied the minimum wp-typia retrofit surface so package.json and helper scripts are ready for the next install and sync run.";
|
|
234
|
-
}
|
|
235
|
-
return "This command previews the minimum wp-typia adoption layer for the current project without rewriting it into a full scaffold.";
|
|
236
|
-
}
|
|
237
165
|
export function createRetrofitPlan(options) {
|
|
238
166
|
const includeGeneratedArtifacts = options.commandMode === "preview-only";
|
|
239
|
-
const plannedChanges =
|
|
167
|
+
const plannedChanges = buildInitPlanChangeSummary({
|
|
240
168
|
generatedArtifacts: options.generatedArtifacts,
|
|
241
169
|
packageChanges: options.packageChanges,
|
|
242
170
|
plannedFiles: options.plannedFiles,
|
|
@@ -249,7 +177,7 @@ export function createRetrofitPlan(options) {
|
|
|
249
177
|
detectedLayout: options.detectedLayout,
|
|
250
178
|
generatedArtifacts: options.generatedArtifacts,
|
|
251
179
|
nextSteps: options.nextSteps ??
|
|
252
|
-
|
|
180
|
+
buildInitPlanNextSteps({
|
|
253
181
|
commandMode: options.commandMode,
|
|
254
182
|
dependencyChangeCount: options.packageChanges.addDevDependencies.length,
|
|
255
183
|
hasPlannedChanges: plannedChanges.length > 0,
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, resolvePackageManagerId, resolveTemplateId, scaffoldProject, } from "./scaffold.js";
|
|
5
5
|
import { parseAlternateRenderTargets } from "./alternate-render-targets.js";
|
|
6
6
|
import { parseCompoundInnerBlocksPreset } from "./compound-inner-blocks.js";
|
|
7
|
+
import { isCompoundPersistenceEnabled } from "./scaffold-template-variable-groups.js";
|
|
7
8
|
import { formatInstallCommand, formatRunScript, } from "./package-managers.js";
|
|
8
9
|
import { getPrimaryDevelopmentScript } from "./local-dev-presets.js";
|
|
9
10
|
import { createManagedTempRoot } from "./temp-roots.js";
|
|
@@ -444,7 +445,7 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
444
445
|
availableScripts,
|
|
445
446
|
packageManager: resolvedPackageManager,
|
|
446
447
|
templateId: resolvedTemplateId,
|
|
447
|
-
compoundPersistenceEnabled: resolvedResult.result.variables
|
|
448
|
+
compoundPersistenceEnabled: isCompoundPersistenceEnabled(resolvedResult.result.variables),
|
|
448
449
|
}),
|
|
449
450
|
plan: resolvedResult.plan,
|
|
450
451
|
projectDir,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const CREATE_TEMPLATE_SELECTION_HINT: string;
|
|
2
|
+
/**
|
|
3
|
+
* Validate an explicitly supplied create template id before entering the full
|
|
4
|
+
* scaffold flow.
|
|
5
|
+
*
|
|
6
|
+
* Built-in template ids and the workspace alias resolve immediately, common
|
|
7
|
+
* built-in typos keep suggestion diagnostics, and explicit external template
|
|
8
|
+
* locators remain deferred to the external template resolver.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateExplicitCreateTemplateId(templateId: string): string;
|