@wp-typia/project-tools 0.16.11 → 0.16.13
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/README.md +9 -3
- package/dist/runtime/block-generator-service-core.d.ts +8 -0
- package/dist/runtime/block-generator-service-core.js +274 -0
- package/dist/runtime/block-generator-service-spec.d.ts +104 -0
- package/dist/runtime/block-generator-service-spec.js +139 -0
- package/dist/runtime/block-generator-service.d.ts +2 -110
- package/dist/runtime/block-generator-service.js +2 -389
- package/dist/runtime/built-in-block-artifact-documents.d.ts +3 -0
- package/dist/runtime/built-in-block-artifact-documents.js +2 -0
- package/dist/runtime/built-in-block-artifact-types.d.ts +51 -0
- package/dist/runtime/built-in-block-artifact-types.js +304 -0
- package/dist/runtime/built-in-block-artifacts.js +4 -803
- package/dist/runtime/built-in-block-attribute-emitters.d.ts +71 -0
- package/dist/runtime/built-in-block-attribute-emitters.js +176 -0
- package/dist/runtime/built-in-block-attribute-specs.d.ts +38 -0
- package/dist/runtime/built-in-block-attribute-specs.js +358 -0
- package/dist/runtime/built-in-block-code-templates/basic.d.ts +4 -0
- package/dist/runtime/built-in-block-code-templates/basic.js +249 -0
- package/dist/runtime/built-in-block-code-templates/compound-child.d.ts +4 -0
- package/dist/runtime/built-in-block-code-templates/compound-child.js +138 -0
- package/dist/runtime/built-in-block-code-templates/compound-parent.d.ts +6 -0
- package/dist/runtime/built-in-block-code-templates/compound-parent.js +227 -0
- package/dist/runtime/built-in-block-code-templates/compound-persistence.d.ts +4 -0
- package/dist/runtime/built-in-block-code-templates/compound-persistence.js +478 -0
- package/dist/runtime/built-in-block-code-templates/compound.d.ts +3 -0
- package/dist/runtime/built-in-block-code-templates/compound.js +3 -0
- package/dist/runtime/built-in-block-code-templates/interactivity.d.ts +5 -0
- package/dist/runtime/built-in-block-code-templates/interactivity.js +547 -0
- package/dist/runtime/built-in-block-code-templates/persistence.d.ts +5 -0
- package/dist/runtime/built-in-block-code-templates/persistence.js +550 -0
- package/dist/runtime/built-in-block-code-templates/shared.d.ts +16 -0
- package/dist/runtime/built-in-block-code-templates/shared.js +53 -0
- package/dist/runtime/built-in-block-code-templates.d.ts +5 -32
- package/dist/runtime/built-in-block-code-templates.js +5 -2230
- package/dist/runtime/cli-add-block-config.d.ts +6 -0
- package/dist/runtime/cli-add-block-config.js +143 -0
- package/dist/runtime/cli-add-block-legacy-validator.d.ts +4 -0
- package/dist/runtime/cli-add-block-legacy-validator.js +168 -0
- package/dist/runtime/cli-add-block.js +3 -301
- package/dist/runtime/cli-add-workspace-assets.d.ts +38 -0
- package/dist/runtime/cli-add-workspace-assets.js +399 -0
- package/dist/runtime/cli-add-workspace.d.ts +2 -38
- package/dist/runtime/cli-add-workspace.js +5 -396
- package/dist/runtime/cli-diagnostics.js +76 -4
- package/dist/runtime/cli-doctor-environment.d.ts +12 -0
- package/dist/runtime/cli-doctor-environment.js +123 -0
- package/dist/runtime/cli-doctor-workspace.d.ts +18 -0
- package/dist/runtime/cli-doctor-workspace.js +308 -0
- package/dist/runtime/cli-doctor.d.ts +4 -2
- package/dist/runtime/cli-doctor.js +10 -405
- package/dist/runtime/cli-help.js +1 -1
- package/dist/runtime/cli-scaffold.d.ts +8 -1
- package/dist/runtime/cli-scaffold.js +47 -4
- package/dist/runtime/migration-command-surface.d.ts +67 -0
- package/dist/runtime/migration-command-surface.js +189 -0
- package/dist/runtime/migration-diff-rename.d.ts +13 -0
- package/dist/runtime/migration-diff-rename.js +192 -0
- package/dist/runtime/migration-diff-transform.d.ts +14 -0
- package/dist/runtime/migration-diff-transform.js +105 -0
- package/dist/runtime/migration-diff.js +12 -297
- package/dist/runtime/migration-generated-artifacts.d.ts +3 -0
- package/dist/runtime/migration-generated-artifacts.js +41 -0
- package/dist/runtime/migration-maintenance-fixtures.d.ts +23 -0
- package/dist/runtime/migration-maintenance-fixtures.js +126 -0
- package/dist/runtime/migration-maintenance-verify.d.ts +26 -0
- package/dist/runtime/migration-maintenance-verify.js +262 -0
- package/dist/runtime/migration-maintenance.d.ts +2 -0
- package/dist/runtime/migration-maintenance.js +2 -0
- package/dist/runtime/migration-planning.d.ts +23 -0
- package/dist/runtime/migration-planning.js +131 -0
- package/dist/runtime/migration-project-config-source.d.ts +6 -0
- package/dist/runtime/migration-project-config-source.js +424 -0
- package/dist/runtime/migration-project-layout-discovery.d.ts +61 -0
- package/dist/runtime/migration-project-layout-discovery.js +337 -0
- package/dist/runtime/migration-project-layout-paths.d.ts +135 -0
- package/dist/runtime/migration-project-layout-paths.js +288 -0
- package/dist/runtime/migration-project-layout.d.ts +3 -0
- package/dist/runtime/migration-project-layout.js +2 -0
- package/dist/runtime/migration-project-workspace.d.ts +47 -0
- package/dist/runtime/migration-project-workspace.js +212 -0
- package/dist/runtime/migration-project.d.ts +4 -94
- package/dist/runtime/migration-project.js +3 -1101
- package/dist/runtime/migration-render-diff-rule.d.ts +5 -0
- package/dist/runtime/migration-render-diff-rule.js +120 -0
- package/dist/runtime/migration-render-execution.d.ts +3 -0
- package/dist/runtime/migration-render-execution.js +428 -0
- package/dist/runtime/migration-render-generated.d.ts +27 -0
- package/dist/runtime/migration-render-generated.js +230 -0
- package/dist/runtime/migration-render-support.d.ts +3 -0
- package/dist/runtime/migration-render-support.js +16 -0
- package/dist/runtime/migration-render.d.ts +3 -33
- package/dist/runtime/migration-render.js +3 -789
- package/dist/runtime/migrations.d.ts +24 -121
- package/dist/runtime/migrations.js +12 -700
- package/dist/runtime/scaffold-apply-utils.d.ts +9 -0
- package/dist/runtime/scaffold-apply-utils.js +27 -4
- package/dist/runtime/scaffold-bootstrap.d.ts +45 -0
- package/dist/runtime/scaffold-bootstrap.js +185 -0
- package/dist/runtime/scaffold-onboarding.d.ts +12 -0
- package/dist/runtime/scaffold-onboarding.js +42 -5
- package/dist/runtime/scaffold-package-manager-files.d.ts +35 -0
- package/dist/runtime/scaffold-package-manager-files.js +79 -0
- package/dist/runtime/scaffold.d.ts +1 -12
- package/dist/runtime/scaffold.js +11 -394
- package/dist/runtime/template-source-contracts.d.ts +81 -0
- package/dist/runtime/template-source-contracts.js +1 -0
- package/dist/runtime/template-source-external.d.ts +21 -0
- package/dist/runtime/template-source-external.js +184 -0
- package/dist/runtime/template-source-locators.d.ts +4 -0
- package/dist/runtime/template-source-locators.js +72 -0
- package/dist/runtime/template-source-normalization.d.ts +7 -0
- package/dist/runtime/template-source-normalization.js +53 -0
- package/dist/runtime/template-source-remote.d.ts +23 -0
- package/dist/runtime/template-source-remote.js +336 -0
- package/dist/runtime/template-source-seeds.d.ts +12 -0
- package/dist/runtime/template-source-seeds.js +243 -0
- package/dist/runtime/template-source.d.ts +4 -86
- package/dist/runtime/template-source.js +9 -828
- package/package.json +4 -4
|
@@ -1,417 +1,22 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { execFileSync } from "node:child_process";
|
|
5
|
-
import { access, constants as fsConstants, rm, writeFile } from "node:fs/promises";
|
|
6
|
-
import { parseScaffoldBlockMetadata } from "@wp-typia/block-runtime/blocks";
|
|
7
|
-
import { getBuiltInTemplateLayerDirs, isOmittableBuiltInTemplateLayerDir, } from "./template-builtins.js";
|
|
8
|
-
import { HOOKED_BLOCK_ANCHOR_PATTERN, HOOKED_BLOCK_POSITION_SET, } from "./hooked-blocks.js";
|
|
9
|
-
import { isBuiltInTemplateId, listTemplates } from "./template-registry.js";
|
|
10
|
-
import { readWorkspaceInventory } from "./workspace-inventory.js";
|
|
11
|
-
import { getInvalidWorkspaceProjectReason, parseWorkspacePackageJson, WORKSPACE_TEMPLATE_PACKAGE, tryResolveWorkspaceProject, } from "./workspace-project.js";
|
|
12
1
|
import { createCliCommandError, formatDoctorCheckLine, formatDoctorSummaryLine, getDoctorFailureDetailLines, } from "./cli-diagnostics.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const WORKSPACE_BINDING_SERVER_GLOB = "/src/bindings/*/server.php";
|
|
16
|
-
const WORKSPACE_BINDING_EDITOR_SCRIPT = "build/bindings/index.js";
|
|
17
|
-
const WORKSPACE_BINDING_EDITOR_ASSET = "build/bindings/index.asset.php";
|
|
18
|
-
const WORKSPACE_GENERATED_BLOCK_ARTIFACTS = [
|
|
19
|
-
"block.json",
|
|
20
|
-
"typia.manifest.json",
|
|
21
|
-
"typia.schema.json",
|
|
22
|
-
"typia-validator.php",
|
|
23
|
-
"typia.openapi.json",
|
|
24
|
-
];
|
|
25
|
-
function readCommandVersion(command, args = ["--version"]) {
|
|
26
|
-
try {
|
|
27
|
-
return execFileSync(command, args, {
|
|
28
|
-
encoding: "utf8",
|
|
29
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
30
|
-
}).trim();
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function compareMajorVersion(actualVersion, minimumMajor) {
|
|
37
|
-
const parsed = Number.parseInt(actualVersion.replace(/^v/, "").split(".")[0] ?? "", 10);
|
|
38
|
-
return Number.isFinite(parsed) && parsed >= minimumMajor;
|
|
39
|
-
}
|
|
40
|
-
async function checkWritableDirectory(directory) {
|
|
41
|
-
try {
|
|
42
|
-
await access(directory, fsConstants.W_OK);
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async function checkTempDirectory() {
|
|
50
|
-
const tempFile = path.join(os.tmpdir(), `wp-typia-${Date.now()}.tmp`);
|
|
51
|
-
try {
|
|
52
|
-
await writeFile(tempFile, "ok", "utf8");
|
|
53
|
-
await rm(tempFile, { force: true });
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function createDoctorCheck(label, status, detail) {
|
|
61
|
-
return { detail, label, status };
|
|
62
|
-
}
|
|
63
|
-
function getWorkspaceBootstrapRelativePath(packageName) {
|
|
64
|
-
const packageBaseName = packageName.split("/").pop() ?? packageName;
|
|
65
|
-
return `${packageBaseName}.php`;
|
|
66
|
-
}
|
|
67
|
-
function checkExistingFiles(projectDir, label, filePaths) {
|
|
68
|
-
const missing = filePaths
|
|
69
|
-
.filter((filePath) => typeof filePath === "string")
|
|
70
|
-
.filter((filePath) => !fs.existsSync(path.join(projectDir, filePath)));
|
|
71
|
-
return createDoctorCheck(label, missing.length === 0 ? "pass" : "fail", missing.length === 0 ? "All referenced files exist" : `Missing: ${missing.join(", ")}`);
|
|
72
|
-
}
|
|
73
|
-
function checkWorkspacePackageMetadata(workspace, packageJson) {
|
|
74
|
-
const issues = [];
|
|
75
|
-
const packageName = packageJson.name;
|
|
76
|
-
const bootstrapRelativePath = getWorkspaceBootstrapRelativePath(typeof packageName === "string" && packageName.length > 0 ? packageName : workspace.packageName);
|
|
77
|
-
const wpTypia = packageJson.wpTypia;
|
|
78
|
-
if (typeof packageName !== "string" || packageName.length === 0) {
|
|
79
|
-
issues.push("package.json must define a string name for workspace bootstrap resolution");
|
|
80
|
-
}
|
|
81
|
-
if (wpTypia?.projectType !== "workspace") {
|
|
82
|
-
issues.push('wpTypia.projectType must be "workspace"');
|
|
83
|
-
}
|
|
84
|
-
if (wpTypia?.templatePackage !== WORKSPACE_TEMPLATE_PACKAGE) {
|
|
85
|
-
issues.push(`wpTypia.templatePackage must be "${WORKSPACE_TEMPLATE_PACKAGE}"`);
|
|
86
|
-
}
|
|
87
|
-
if (wpTypia?.namespace !== workspace.workspace.namespace) {
|
|
88
|
-
issues.push(`wpTypia.namespace must equal "${workspace.workspace.namespace}"`);
|
|
89
|
-
}
|
|
90
|
-
if (wpTypia?.textDomain !== workspace.workspace.textDomain) {
|
|
91
|
-
issues.push(`wpTypia.textDomain must equal "${workspace.workspace.textDomain}"`);
|
|
92
|
-
}
|
|
93
|
-
if (wpTypia?.phpPrefix !== workspace.workspace.phpPrefix) {
|
|
94
|
-
issues.push(`wpTypia.phpPrefix must equal "${workspace.workspace.phpPrefix}"`);
|
|
95
|
-
}
|
|
96
|
-
if (!fs.existsSync(path.join(workspace.projectDir, bootstrapRelativePath))) {
|
|
97
|
-
issues.push(`Missing bootstrap file ${bootstrapRelativePath}`);
|
|
98
|
-
}
|
|
99
|
-
return createDoctorCheck("Workspace package metadata", issues.length === 0 ? "pass" : "fail", issues.length === 0
|
|
100
|
-
? `package.json metadata aligns with ${workspace.packageName} and ${bootstrapRelativePath}`
|
|
101
|
-
: issues.join("; "));
|
|
102
|
-
}
|
|
103
|
-
function getWorkspaceBlockRequiredFiles(block) {
|
|
104
|
-
const blockDir = path.join("src", "blocks", block.slug);
|
|
105
|
-
return Array.from(new Set([
|
|
106
|
-
block.typesFile,
|
|
107
|
-
block.apiTypesFile,
|
|
108
|
-
block.openApiFile,
|
|
109
|
-
path.join(blockDir, "index.tsx"),
|
|
110
|
-
...WORKSPACE_GENERATED_BLOCK_ARTIFACTS.map((fileName) => path.join(blockDir, fileName)),
|
|
111
|
-
].filter((filePath) => typeof filePath === "string")));
|
|
112
|
-
}
|
|
113
|
-
function checkWorkspaceBlockMetadata(projectDir, workspace, block) {
|
|
114
|
-
const blockJsonRelativePath = path.join("src", "blocks", block.slug, "block.json");
|
|
115
|
-
const blockJsonPath = path.join(projectDir, blockJsonRelativePath);
|
|
116
|
-
if (!fs.existsSync(blockJsonPath)) {
|
|
117
|
-
return createDoctorCheck(`Block metadata ${block.slug}`, "fail", `Missing ${blockJsonRelativePath}`);
|
|
118
|
-
}
|
|
119
|
-
let blockJson;
|
|
120
|
-
try {
|
|
121
|
-
blockJson = parseScaffoldBlockMetadata(JSON.parse(fs.readFileSync(blockJsonPath, "utf8")));
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
return createDoctorCheck(`Block metadata ${block.slug}`, "fail", error instanceof Error ? error.message : String(error));
|
|
125
|
-
}
|
|
126
|
-
const expectedName = `${workspace.workspace.namespace}/${block.slug}`;
|
|
127
|
-
const issues = [];
|
|
128
|
-
if (blockJson.name !== expectedName) {
|
|
129
|
-
issues.push(`block.json name must equal "${expectedName}"`);
|
|
130
|
-
}
|
|
131
|
-
if (blockJson.textdomain !== workspace.workspace.textDomain) {
|
|
132
|
-
issues.push(`block.json textdomain must equal "${workspace.workspace.textDomain}"`);
|
|
133
|
-
}
|
|
134
|
-
return createDoctorCheck(`Block metadata ${block.slug}`, issues.length === 0 ? "pass" : "fail", issues.length === 0
|
|
135
|
-
? `block.json matches ${expectedName} and ${workspace.workspace.textDomain}`
|
|
136
|
-
: issues.join("; "));
|
|
137
|
-
}
|
|
138
|
-
function checkWorkspaceBlockHooks(projectDir, blockSlug) {
|
|
139
|
-
const blockJsonRelativePath = path.join("src", "blocks", blockSlug, "block.json");
|
|
140
|
-
const blockJsonPath = path.join(projectDir, blockJsonRelativePath);
|
|
141
|
-
if (!fs.existsSync(blockJsonPath)) {
|
|
142
|
-
return createDoctorCheck(`Block hooks ${blockSlug}`, "fail", `Missing ${blockJsonRelativePath}`);
|
|
143
|
-
}
|
|
144
|
-
let blockJson;
|
|
145
|
-
try {
|
|
146
|
-
blockJson = parseScaffoldBlockMetadata(JSON.parse(fs.readFileSync(blockJsonPath, "utf8")));
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
return createDoctorCheck(`Block hooks ${blockSlug}`, "fail", error instanceof Error ? error.message : String(error));
|
|
150
|
-
}
|
|
151
|
-
const blockHooks = blockJson.blockHooks;
|
|
152
|
-
if (blockHooks === undefined) {
|
|
153
|
-
return createDoctorCheck(`Block hooks ${blockSlug}`, "pass", "No blockHooks metadata configured");
|
|
154
|
-
}
|
|
155
|
-
if (!blockHooks || typeof blockHooks !== "object" || Array.isArray(blockHooks)) {
|
|
156
|
-
return createDoctorCheck(`Block hooks ${blockSlug}`, "fail", `${blockJsonRelativePath} must define blockHooks as an object when present.`);
|
|
157
|
-
}
|
|
158
|
-
const blockName = typeof blockJson.name === "string" && blockJson.name.trim().length > 0
|
|
159
|
-
? blockJson.name.trim()
|
|
160
|
-
: null;
|
|
161
|
-
const invalidEntries = Object.entries(blockHooks).filter(([anchor, position]) => (blockName !== null && anchor.trim() === blockName) ||
|
|
162
|
-
anchor.trim().length === 0 ||
|
|
163
|
-
anchor !== anchor.trim() ||
|
|
164
|
-
!HOOKED_BLOCK_ANCHOR_PATTERN.test(anchor) ||
|
|
165
|
-
typeof position !== "string" ||
|
|
166
|
-
!HOOKED_BLOCK_POSITION_SET.has(position));
|
|
167
|
-
return createDoctorCheck(`Block hooks ${blockSlug}`, invalidEntries.length === 0 ? "pass" : "fail", invalidEntries.length === 0
|
|
168
|
-
? `blockHooks metadata is valid${Object.keys(blockHooks).length > 0 ? ` (${Object.keys(blockHooks).join(", ")})` : ""}`
|
|
169
|
-
: `Invalid blockHooks entries: ${invalidEntries
|
|
170
|
-
.map(([anchor, position]) => `${anchor || "<empty>"} => ${String(position)}`)
|
|
171
|
-
.join(", ")}`);
|
|
172
|
-
}
|
|
173
|
-
function checkWorkspaceBlockCollectionImport(projectDir, blockSlug) {
|
|
174
|
-
const entryRelativePath = path.join("src", "blocks", blockSlug, "index.tsx");
|
|
175
|
-
const entryPath = path.join(projectDir, entryRelativePath);
|
|
176
|
-
if (!fs.existsSync(entryPath)) {
|
|
177
|
-
return createDoctorCheck(`Block collection ${blockSlug}`, "fail", `Missing ${entryRelativePath}`);
|
|
178
|
-
}
|
|
179
|
-
const source = fs.readFileSync(entryPath, "utf8");
|
|
180
|
-
const hasCollectionImport = WORKSPACE_COLLECTION_IMPORT_PATTERN.test(source);
|
|
181
|
-
return createDoctorCheck(`Block collection ${blockSlug}`, hasCollectionImport ? "pass" : "fail", hasCollectionImport
|
|
182
|
-
? "Shared block collection import is present"
|
|
183
|
-
: `Missing a shared collection import like ${WORKSPACE_COLLECTION_IMPORT_LINE}`);
|
|
184
|
-
}
|
|
185
|
-
function checkWorkspacePatternBootstrap(projectDir, packageName) {
|
|
186
|
-
const packageBaseName = packageName.split("/").pop() ?? packageName;
|
|
187
|
-
const bootstrapPath = path.join(projectDir, `${packageBaseName}.php`);
|
|
188
|
-
if (!fs.existsSync(bootstrapPath)) {
|
|
189
|
-
return createDoctorCheck("Pattern bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
|
|
190
|
-
}
|
|
191
|
-
const source = fs.readFileSync(bootstrapPath, "utf8");
|
|
192
|
-
const hasCategoryAnchor = source.includes("register_block_pattern_category");
|
|
193
|
-
const hasPatternGlob = source.includes("/src/patterns/*.php");
|
|
194
|
-
return createDoctorCheck("Pattern bootstrap", hasCategoryAnchor && hasPatternGlob ? "pass" : "fail", hasCategoryAnchor && hasPatternGlob
|
|
195
|
-
? "Pattern category and loader hooks are present"
|
|
196
|
-
: "Missing pattern category registration or src/patterns loader hook");
|
|
197
|
-
}
|
|
198
|
-
function checkWorkspaceBindingBootstrap(projectDir, packageName) {
|
|
199
|
-
const packageBaseName = packageName.split("/").pop() ?? packageName;
|
|
200
|
-
const bootstrapPath = path.join(projectDir, `${packageBaseName}.php`);
|
|
201
|
-
if (!fs.existsSync(bootstrapPath)) {
|
|
202
|
-
return createDoctorCheck("Binding bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
|
|
203
|
-
}
|
|
204
|
-
const source = fs.readFileSync(bootstrapPath, "utf8");
|
|
205
|
-
const hasServerGlob = source.includes(WORKSPACE_BINDING_SERVER_GLOB);
|
|
206
|
-
const hasEditorEnqueueHook = source.includes("enqueue_block_editor_assets");
|
|
207
|
-
const hasEditorScript = source.includes(WORKSPACE_BINDING_EDITOR_SCRIPT);
|
|
208
|
-
const hasEditorAsset = source.includes(WORKSPACE_BINDING_EDITOR_ASSET);
|
|
209
|
-
return createDoctorCheck("Binding bootstrap", hasServerGlob && hasEditorEnqueueHook && hasEditorScript && hasEditorAsset ? "pass" : "fail", hasServerGlob && hasEditorEnqueueHook && hasEditorScript && hasEditorAsset
|
|
210
|
-
? "Binding source PHP and editor bootstrap hooks are present"
|
|
211
|
-
: "Missing binding source PHP require glob or editor enqueue hook");
|
|
212
|
-
}
|
|
213
|
-
function checkWorkspaceBindingSourcesIndex(projectDir, bindingSources) {
|
|
214
|
-
const indexRelativePath = [path.join("src", "bindings", "index.ts"), path.join("src", "bindings", "index.js")].find((relativePath) => fs.existsSync(path.join(projectDir, relativePath)));
|
|
215
|
-
if (!indexRelativePath) {
|
|
216
|
-
return createDoctorCheck("Binding sources index", "fail", "Missing src/bindings/index.ts or src/bindings/index.js");
|
|
217
|
-
}
|
|
218
|
-
const indexPath = path.join(projectDir, indexRelativePath);
|
|
219
|
-
const source = fs.readFileSync(indexPath, "utf8");
|
|
220
|
-
const missingImports = bindingSources.filter((bindingSource) => !source.includes(`./${bindingSource.slug}/editor`));
|
|
221
|
-
return createDoctorCheck("Binding sources index", missingImports.length === 0 ? "pass" : "fail", missingImports.length === 0
|
|
222
|
-
? "Binding source editor registrations are aggregated"
|
|
223
|
-
: `Missing editor imports for: ${missingImports.map((entry) => entry.slug).join(", ")}`);
|
|
224
|
-
}
|
|
225
|
-
function checkVariationEntrypoint(projectDir, blockSlug) {
|
|
226
|
-
const entryPath = path.join(projectDir, "src", "blocks", blockSlug, "index.tsx");
|
|
227
|
-
if (!fs.existsSync(entryPath)) {
|
|
228
|
-
return createDoctorCheck(`Variation entrypoint ${blockSlug}`, "fail", `Missing ${path.relative(projectDir, entryPath)}`);
|
|
229
|
-
}
|
|
230
|
-
const source = fs.readFileSync(entryPath, "utf8");
|
|
231
|
-
const hasImport = source.includes("./variations");
|
|
232
|
-
const hasCall = source.includes("registerWorkspaceVariations()");
|
|
233
|
-
return createDoctorCheck(`Variation entrypoint ${blockSlug}`, hasImport && hasCall ? "pass" : "fail", hasImport && hasCall
|
|
234
|
-
? "Variations registration hook is present"
|
|
235
|
-
: "Missing ./variations import or registerWorkspaceVariations() call");
|
|
236
|
-
}
|
|
237
|
-
function checkMigrationWorkspaceHint(workspace, packageJson) {
|
|
238
|
-
const hasMigrationScript = typeof packageJson.scripts?.["migration:doctor"] === "string";
|
|
239
|
-
const migrationConfigRelativePath = path.join("src", "migrations", "config.ts");
|
|
240
|
-
const hasMigrationConfig = fs.existsSync(path.join(workspace.projectDir, migrationConfigRelativePath));
|
|
241
|
-
if (!hasMigrationScript && !hasMigrationConfig) {
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
return createDoctorCheck("Migration workspace", hasMigrationConfig ? "pass" : "fail", hasMigrationConfig
|
|
245
|
-
? "Run `wp-typia migrate doctor --all` for migration target, snapshot, fixture, and generated artifact checks"
|
|
246
|
-
: `Missing ${migrationConfigRelativePath} for the configured migration workspace`);
|
|
247
|
-
}
|
|
2
|
+
import { getEnvironmentDoctorChecks } from "./cli-doctor-environment.js";
|
|
3
|
+
import { getWorkspaceDoctorChecks } from "./cli-doctor-workspace.js";
|
|
248
4
|
/**
|
|
249
5
|
* Collect all runtime doctor checks for the current environment.
|
|
250
6
|
*
|
|
251
|
-
* The returned array
|
|
252
|
-
* writability
|
|
7
|
+
* The returned array concatenates environment checks (command availability,
|
|
8
|
+
* directory writability, and built-in template assets) followed by
|
|
9
|
+
* workspace checks (package metadata, inventory, blocks, variations,
|
|
10
|
+
* patterns, bindings, and optional migration hints) in display order.
|
|
253
11
|
*
|
|
254
12
|
* @param cwd Working directory to validate for writability.
|
|
255
13
|
* @returns Ordered doctor check rows ready for CLI rendering.
|
|
256
14
|
*/
|
|
257
15
|
export async function getDoctorChecks(cwd) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const cwdWritable = await checkWritableDirectory(cwd);
|
|
263
|
-
const tempWritable = await checkTempDirectory();
|
|
264
|
-
checks.push({
|
|
265
|
-
status: bunVersion && compareMajorVersion(bunVersion, 1) ? "pass" : "fail",
|
|
266
|
-
label: "Bun",
|
|
267
|
-
detail: bunVersion ? `Detected ${bunVersion}` : "Not available",
|
|
268
|
-
});
|
|
269
|
-
checks.push({
|
|
270
|
-
status: nodeVersion && compareMajorVersion(nodeVersion, 20) ? "pass" : "fail",
|
|
271
|
-
label: "Node",
|
|
272
|
-
detail: nodeVersion ? `Detected ${nodeVersion}` : "Not available",
|
|
273
|
-
});
|
|
274
|
-
checks.push({
|
|
275
|
-
status: gitVersion ? "pass" : "fail",
|
|
276
|
-
label: "git",
|
|
277
|
-
detail: gitVersion ?? "Not available",
|
|
278
|
-
});
|
|
279
|
-
checks.push({
|
|
280
|
-
status: cwdWritable ? "pass" : "fail",
|
|
281
|
-
label: "Current directory",
|
|
282
|
-
detail: cwdWritable ? "Writable" : "Not writable",
|
|
283
|
-
});
|
|
284
|
-
checks.push({
|
|
285
|
-
status: tempWritable ? "pass" : "fail",
|
|
286
|
-
label: "Temp directory",
|
|
287
|
-
detail: tempWritable ? "Writable" : "Not writable",
|
|
288
|
-
});
|
|
289
|
-
for (const template of listTemplates()) {
|
|
290
|
-
if (!isBuiltInTemplateId(template.id)) {
|
|
291
|
-
const templateDirExists = fs.existsSync(template.templateDir);
|
|
292
|
-
const hasAssets = templateDirExists &&
|
|
293
|
-
fs.existsSync(path.join(template.templateDir, "package.json.mustache"));
|
|
294
|
-
checks.push({
|
|
295
|
-
status: !templateDirExists || hasAssets ? "pass" : "fail",
|
|
296
|
-
label: `Template ${template.id}`,
|
|
297
|
-
detail: !templateDirExists
|
|
298
|
-
? "External template metadata only; local overlay package is not installed."
|
|
299
|
-
: hasAssets
|
|
300
|
-
? template.templateDir
|
|
301
|
-
: "Missing core template assets",
|
|
302
|
-
});
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
const builtInTemplateId = template.id;
|
|
306
|
-
const layerDirs = builtInTemplateId === "persistence"
|
|
307
|
-
? Array.from(new Set([
|
|
308
|
-
...getBuiltInTemplateLayerDirs(builtInTemplateId, { persistencePolicy: "authenticated" }),
|
|
309
|
-
...getBuiltInTemplateLayerDirs(builtInTemplateId, { persistencePolicy: "public" }),
|
|
310
|
-
]))
|
|
311
|
-
: builtInTemplateId === "compound"
|
|
312
|
-
? Array.from(new Set([
|
|
313
|
-
...getBuiltInTemplateLayerDirs(builtInTemplateId),
|
|
314
|
-
...getBuiltInTemplateLayerDirs(builtInTemplateId, {
|
|
315
|
-
persistenceEnabled: true,
|
|
316
|
-
persistencePolicy: "authenticated",
|
|
317
|
-
}),
|
|
318
|
-
...getBuiltInTemplateLayerDirs(builtInTemplateId, {
|
|
319
|
-
persistenceEnabled: true,
|
|
320
|
-
persistencePolicy: "public",
|
|
321
|
-
}),
|
|
322
|
-
]))
|
|
323
|
-
: getBuiltInTemplateLayerDirs(builtInTemplateId);
|
|
324
|
-
const missingRequiredLayer = layerDirs.some((layerDir) => !fs.existsSync(layerDir) &&
|
|
325
|
-
!isOmittableBuiltInTemplateLayerDir(builtInTemplateId, layerDir));
|
|
326
|
-
const existingLayerDirs = layerDirs.filter((layerDir) => fs.existsSync(layerDir));
|
|
327
|
-
const hasAssets = !missingRequiredLayer &&
|
|
328
|
-
existingLayerDirs.some((layerDir) => fs.existsSync(path.join(layerDir, "package.json.mustache"))) &&
|
|
329
|
-
existingLayerDirs.some((layerDir) => fs.existsSync(path.join(layerDir, "src")));
|
|
330
|
-
checks.push({
|
|
331
|
-
status: hasAssets ? "pass" : "fail",
|
|
332
|
-
label: `Template ${template.id}`,
|
|
333
|
-
detail: hasAssets
|
|
334
|
-
? existingLayerDirs.join(" + ")
|
|
335
|
-
: "Missing core template assets",
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
let workspace = null;
|
|
339
|
-
let invalidWorkspaceReason = null;
|
|
340
|
-
try {
|
|
341
|
-
invalidWorkspaceReason = getInvalidWorkspaceProjectReason(cwd);
|
|
342
|
-
workspace = tryResolveWorkspaceProject(cwd);
|
|
343
|
-
}
|
|
344
|
-
catch (error) {
|
|
345
|
-
checks.push(createDoctorCheck("Workspace package metadata", "fail", error instanceof Error ? error.message : String(error)));
|
|
346
|
-
return checks;
|
|
347
|
-
}
|
|
348
|
-
if (!workspace) {
|
|
349
|
-
if (invalidWorkspaceReason) {
|
|
350
|
-
checks.push(createDoctorCheck("Workspace package metadata", "fail", invalidWorkspaceReason));
|
|
351
|
-
}
|
|
352
|
-
return checks;
|
|
353
|
-
}
|
|
354
|
-
checks.push(createDoctorCheck("Workspace marker", "pass", `Official workspace detected for ${workspace.workspace.namespace}`));
|
|
355
|
-
let workspacePackageJson;
|
|
356
|
-
try {
|
|
357
|
-
workspacePackageJson = parseWorkspacePackageJson(workspace.projectDir);
|
|
358
|
-
}
|
|
359
|
-
catch (error) {
|
|
360
|
-
checks.push(createDoctorCheck("Workspace package metadata", "fail", error instanceof Error ? error.message : String(error)));
|
|
361
|
-
return checks;
|
|
362
|
-
}
|
|
363
|
-
checks.push(checkWorkspacePackageMetadata(workspace, workspacePackageJson));
|
|
364
|
-
try {
|
|
365
|
-
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
366
|
-
checks.push(createDoctorCheck("Workspace inventory", "pass", `${inventory.blocks.length} block(s), ${inventory.variations.length} variation(s), ${inventory.patterns.length} pattern(s), ${inventory.bindingSources.length} binding source(s)`));
|
|
367
|
-
for (const block of inventory.blocks) {
|
|
368
|
-
checks.push(checkExistingFiles(workspace.projectDir, `Block ${block.slug}`, [
|
|
369
|
-
...getWorkspaceBlockRequiredFiles(block),
|
|
370
|
-
]));
|
|
371
|
-
checks.push(checkWorkspaceBlockMetadata(workspace.projectDir, workspace, block));
|
|
372
|
-
checks.push(checkWorkspaceBlockHooks(workspace.projectDir, block.slug));
|
|
373
|
-
checks.push(checkWorkspaceBlockCollectionImport(workspace.projectDir, block.slug));
|
|
374
|
-
}
|
|
375
|
-
const registeredBlockSlugs = new Set(inventory.blocks.map((block) => block.slug));
|
|
376
|
-
const variationTargetBlocks = new Set();
|
|
377
|
-
for (const variation of inventory.variations) {
|
|
378
|
-
if (!registeredBlockSlugs.has(variation.block)) {
|
|
379
|
-
checks.push(createDoctorCheck(`Variation ${variation.block}/${variation.slug}`, "fail", `Variation references unknown block "${variation.block}"`));
|
|
380
|
-
continue;
|
|
381
|
-
}
|
|
382
|
-
variationTargetBlocks.add(variation.block);
|
|
383
|
-
checks.push(checkExistingFiles(workspace.projectDir, `Variation ${variation.block}/${variation.slug}`, [variation.file]));
|
|
384
|
-
}
|
|
385
|
-
for (const blockSlug of variationTargetBlocks) {
|
|
386
|
-
checks.push(checkVariationEntrypoint(workspace.projectDir, blockSlug));
|
|
387
|
-
}
|
|
388
|
-
const shouldCheckPatternBootstrap = inventory.patterns.length > 0 ||
|
|
389
|
-
fs.existsSync(path.join(workspace.projectDir, "src", "patterns"));
|
|
390
|
-
if (shouldCheckPatternBootstrap) {
|
|
391
|
-
checks.push(checkWorkspacePatternBootstrap(workspace.projectDir, workspace.packageName));
|
|
392
|
-
}
|
|
393
|
-
for (const pattern of inventory.patterns) {
|
|
394
|
-
checks.push(checkExistingFiles(workspace.projectDir, `Pattern ${pattern.slug}`, [pattern.file]));
|
|
395
|
-
}
|
|
396
|
-
if (inventory.bindingSources.length > 0) {
|
|
397
|
-
checks.push(checkWorkspaceBindingBootstrap(workspace.projectDir, workspace.packageName));
|
|
398
|
-
checks.push(checkWorkspaceBindingSourcesIndex(workspace.projectDir, inventory.bindingSources));
|
|
399
|
-
}
|
|
400
|
-
for (const bindingSource of inventory.bindingSources) {
|
|
401
|
-
checks.push(checkExistingFiles(workspace.projectDir, `Binding source ${bindingSource.slug}`, [
|
|
402
|
-
bindingSource.serverFile,
|
|
403
|
-
bindingSource.editorFile,
|
|
404
|
-
]));
|
|
405
|
-
}
|
|
406
|
-
const migrationWorkspaceCheck = checkMigrationWorkspaceHint(workspace, workspacePackageJson);
|
|
407
|
-
if (migrationWorkspaceCheck) {
|
|
408
|
-
checks.push(migrationWorkspaceCheck);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
catch (error) {
|
|
412
|
-
checks.push(createDoctorCheck("Workspace inventory", "fail", error instanceof Error ? error.message : String(error)));
|
|
413
|
-
}
|
|
414
|
-
return checks;
|
|
16
|
+
return [
|
|
17
|
+
...(await getEnvironmentDoctorChecks(cwd)),
|
|
18
|
+
...getWorkspaceDoctorChecks(cwd),
|
|
19
|
+
];
|
|
415
20
|
}
|
|
416
21
|
/**
|
|
417
22
|
* Run doctor checks, render each line, and fail when any check does not pass.
|
package/dist/runtime/cli-help.js
CHANGED
|
@@ -39,7 +39,7 @@ Notes:
|
|
|
39
39
|
\`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/\`.
|
|
40
40
|
\`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`.
|
|
41
41
|
\`add hooked-block\` patches an existing workspace block's \`block.json\` \`blockHooks\` metadata.
|
|
42
|
-
\`wp-typia doctor\` checks environment readiness
|
|
42
|
+
\`wp-typia doctor\` always checks environment readiness and reports when it only ran environment-level diagnostics; official workspace roots also get inventory and source-tree drift checks.
|
|
43
43
|
\`wp-typia migrate doctor --all\` checks migration target alignment, snapshots, fixtures, and generated migration artifacts.
|
|
44
44
|
\`migrate\` is the canonical migration command; \`migrations\` is no longer supported.`;
|
|
45
45
|
}
|
|
@@ -78,7 +78,14 @@ export declare function runScaffoldFlow({ projectInput, cwd, templateId, dataSto
|
|
|
78
78
|
projectDir: string;
|
|
79
79
|
projectInput: string;
|
|
80
80
|
packageManager: PackageManagerId;
|
|
81
|
-
result: import("./scaffold.js").ScaffoldProjectResult;
|
|
82
81
|
nextSteps: string[];
|
|
82
|
+
result: {
|
|
83
|
+
warnings: string[];
|
|
84
|
+
packageManager: PackageManagerId;
|
|
85
|
+
projectDir: string;
|
|
86
|
+
selectedVariant: string | null;
|
|
87
|
+
templateId: string;
|
|
88
|
+
variables: import("./scaffold.js").ScaffoldTemplateVariables;
|
|
89
|
+
};
|
|
83
90
|
}>;
|
|
84
91
|
export {};
|
|
@@ -6,6 +6,29 @@ import { getPrimaryDevelopmentScript } from "./local-dev-presets.js";
|
|
|
6
6
|
import { getOptionalOnboardingNote, getOptionalOnboardingSteps, } from "./scaffold-onboarding.js";
|
|
7
7
|
import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, isBuiltInTemplateId, } from "./template-registry.js";
|
|
8
8
|
import { resolveOptionalInteractiveExternalLayerId, } from "./external-layer-selection.js";
|
|
9
|
+
function validateCreateProjectInput(projectInput) {
|
|
10
|
+
const normalizedProjectInput = projectInput.trim();
|
|
11
|
+
if (normalizedProjectInput.length === 0) {
|
|
12
|
+
throw new Error("Project directory is required. Usage: wp-typia create <project-dir> (or wp-typia <project-dir> when <project-dir> is the only positional argument).");
|
|
13
|
+
}
|
|
14
|
+
const normalizedProjectPath = path.normalize(normalizedProjectInput).replace(/[\\/]+$/u, "") ||
|
|
15
|
+
path.normalize(normalizedProjectInput);
|
|
16
|
+
if (normalizedProjectPath === "." || normalizedProjectPath === "..") {
|
|
17
|
+
throw new Error("`wp-typia create` requires a new project directory. Use an explicit child directory instead of `.` or `..`.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function collectProjectDirectoryWarnings(projectDir) {
|
|
21
|
+
const warnings = [];
|
|
22
|
+
const projectName = path.basename(projectDir);
|
|
23
|
+
if (/\s/u.test(projectName)) {
|
|
24
|
+
warnings.push(`Project directory "${projectName}" contains spaces. The generated next-step commands will be quoted, but a simple kebab-case directory name is usually easier to use with shells and downstream tooling.`);
|
|
25
|
+
}
|
|
26
|
+
const shellSensitiveCharacters = Array.from(new Set(projectName.match(/[^A-Za-z0-9._ -]/gu) ?? []));
|
|
27
|
+
if (shellSensitiveCharacters.length > 0) {
|
|
28
|
+
warnings.push(`Project directory "${projectName}" contains shell-sensitive characters (${shellSensitiveCharacters.join(", ")}). Prefer letters, numbers, ".", "_" and "-" when possible.`);
|
|
29
|
+
}
|
|
30
|
+
return warnings;
|
|
31
|
+
}
|
|
9
32
|
function templateUsesPersistenceSettings(templateId, options) {
|
|
10
33
|
if (templateId === "persistence") {
|
|
11
34
|
return true;
|
|
@@ -15,6 +38,19 @@ function templateUsesPersistenceSettings(templateId, options) {
|
|
|
15
38
|
}
|
|
16
39
|
return Boolean(options.dataStorageMode || options.persistencePolicy);
|
|
17
40
|
}
|
|
41
|
+
function templateSupportsPersistenceFlags(templateId) {
|
|
42
|
+
return templateId === "persistence" || templateId === "compound";
|
|
43
|
+
}
|
|
44
|
+
function validateCreateFlagContract(options) {
|
|
45
|
+
const { dataStorageMode, persistencePolicy, templateId, variant } = options;
|
|
46
|
+
if ((dataStorageMode || persistencePolicy) &&
|
|
47
|
+
!templateSupportsPersistenceFlags(templateId)) {
|
|
48
|
+
throw new Error("`--data-storage` and `--persistence-policy` are supported only for `wp-typia create --template persistence` or `--template compound`.");
|
|
49
|
+
}
|
|
50
|
+
if (variant && isBuiltInTemplateId(templateId)) {
|
|
51
|
+
throw new Error(`--variant is only supported for official external template configs. Received variant "${variant}" for built-in template "${templateId}".`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
18
54
|
function parseSelectableValue(label, value, isValue, allowedValues) {
|
|
19
55
|
if (isValue(value)) {
|
|
20
56
|
return value;
|
|
@@ -107,15 +143,19 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
107
143
|
externalLayerSource.trim().length > 0
|
|
108
144
|
? externalLayerSource.trim()
|
|
109
145
|
: undefined;
|
|
110
|
-
|
|
111
|
-
throw new Error("Project directory is required. Usage: wp-typia create <project-dir> (or wp-typia <project-dir> when <project-dir> is the only positional argument).");
|
|
112
|
-
}
|
|
146
|
+
validateCreateProjectInput(projectInput);
|
|
113
147
|
const resolvedTemplateId = await resolveTemplateId({
|
|
114
148
|
templateId,
|
|
115
149
|
yes,
|
|
116
150
|
isInteractive,
|
|
117
151
|
selectTemplate,
|
|
118
152
|
});
|
|
153
|
+
validateCreateFlagContract({
|
|
154
|
+
dataStorageMode,
|
|
155
|
+
persistencePolicy,
|
|
156
|
+
templateId: resolvedTemplateId,
|
|
157
|
+
variant,
|
|
158
|
+
});
|
|
119
159
|
const resolvedExternalLayerSelection = isBuiltInTemplateId(resolvedTemplateId) && isInteractive
|
|
120
160
|
? await resolveOptionalInteractiveExternalLayerId({
|
|
121
161
|
callerCwd: cwd,
|
|
@@ -237,7 +277,6 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
237
277
|
projectDir,
|
|
238
278
|
projectInput,
|
|
239
279
|
packageManager: resolvedPackageManager,
|
|
240
|
-
result,
|
|
241
280
|
nextSteps: getNextSteps({
|
|
242
281
|
projectInput,
|
|
243
282
|
projectDir,
|
|
@@ -245,6 +284,10 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
245
284
|
noInstall,
|
|
246
285
|
templateId: resolvedTemplateId,
|
|
247
286
|
}),
|
|
287
|
+
result: {
|
|
288
|
+
...result,
|
|
289
|
+
warnings: [...result.warnings, ...collectProjectDirectoryWarnings(projectDir)],
|
|
290
|
+
},
|
|
248
291
|
};
|
|
249
292
|
}
|
|
250
293
|
finally {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ReadlinePrompt } from './cli-prompt.js';
|
|
2
|
+
import type { ParsedMigrationArgs, RenderLine } from './migration-types.js';
|
|
3
|
+
export type CommandRenderOptions = {
|
|
4
|
+
prompt?: ReadlinePrompt;
|
|
5
|
+
renderLine?: RenderLine;
|
|
6
|
+
};
|
|
7
|
+
export type DiffLikeOptions = {
|
|
8
|
+
fromMigrationVersion?: string;
|
|
9
|
+
renderLine?: RenderLine;
|
|
10
|
+
toMigrationVersion?: string;
|
|
11
|
+
};
|
|
12
|
+
export type VerifyOptions = {
|
|
13
|
+
all?: boolean;
|
|
14
|
+
fromMigrationVersion?: string;
|
|
15
|
+
renderLine?: RenderLine;
|
|
16
|
+
};
|
|
17
|
+
export type FixturesOptions = {
|
|
18
|
+
all?: boolean;
|
|
19
|
+
confirmOverwrite?: ((message: string) => boolean) | undefined;
|
|
20
|
+
force?: boolean;
|
|
21
|
+
fromMigrationVersion?: string;
|
|
22
|
+
isInteractive?: boolean;
|
|
23
|
+
renderLine?: RenderLine;
|
|
24
|
+
toMigrationVersion?: string;
|
|
25
|
+
};
|
|
26
|
+
export type FuzzOptions = {
|
|
27
|
+
all?: boolean;
|
|
28
|
+
fromMigrationVersion?: string;
|
|
29
|
+
iterations?: number;
|
|
30
|
+
renderLine?: RenderLine;
|
|
31
|
+
seed?: number;
|
|
32
|
+
};
|
|
33
|
+
export type WizardOptions = CommandRenderOptions & {
|
|
34
|
+
isInteractive?: boolean;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Returns the formatted help text for migration CLI commands and flags.
|
|
38
|
+
*
|
|
39
|
+
* @returns Multi-line usage text for the `wp-typia migrate` command surface.
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatMigrationHelpText(): string;
|
|
42
|
+
/**
|
|
43
|
+
* Parses migration CLI arguments into a structured command payload.
|
|
44
|
+
*
|
|
45
|
+
* @param argv Command-line arguments that follow the `migrate` subcommand.
|
|
46
|
+
* @returns Parsed migration command and normalized flags for runtime dispatch.
|
|
47
|
+
* @throws Error When no arguments are provided, an unknown flag is encountered, or legacy semver flags are used.
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseMigrationArgs(argv: string[]): ParsedMigrationArgs;
|
|
50
|
+
/**
|
|
51
|
+
* Parse an optional positive integer flag value.
|
|
52
|
+
*
|
|
53
|
+
* @param value Raw CLI flag value, or `undefined` when the flag was omitted.
|
|
54
|
+
* @param label Human-readable flag label used in validation error messages.
|
|
55
|
+
* @returns The parsed integer when provided, otherwise `undefined`.
|
|
56
|
+
* @throws Error When the value is not a base-10 integer greater than zero.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parsePositiveInteger(value: string | undefined, label: string): number | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Parse an optional non-negative integer flag value.
|
|
61
|
+
*
|
|
62
|
+
* @param value Raw CLI flag value, or `undefined` when the flag was omitted.
|
|
63
|
+
* @param label Human-readable flag label used in validation error messages.
|
|
64
|
+
* @returns The parsed integer when provided, otherwise `undefined`.
|
|
65
|
+
* @throws Error When the value is not a base-10 integer greater than or equal to zero.
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseNonNegativeInteger(value: string | undefined, label: string): number | undefined;
|