@wp-typia/project-tools 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime/block-generator-service-core.d.ts +1 -1
- package/dist/runtime/block-generator-service-core.js +2 -1
- package/dist/runtime/block-generator-service-spec.d.ts +2 -1
- package/dist/runtime/built-in-block-artifacts.js +1 -0
- package/dist/runtime/built-in-block-code-templates/compound-child.d.ts +2 -2
- package/dist/runtime/built-in-block-code-templates/compound-child.js +30 -2
- package/dist/runtime/built-in-block-code-templates/compound-parent.d.ts +1 -1
- package/dist/runtime/built-in-block-code-templates/compound-parent.js +139 -19
- package/dist/runtime/cli-add-block.d.ts +2 -1
- package/dist/runtime/cli-add-block.js +19 -1
- package/dist/runtime/cli-add-shared.d.ts +55 -1
- package/dist/runtime/cli-add-shared.js +101 -2
- package/dist/runtime/cli-add-workspace-assets.d.ts +21 -1
- package/dist/runtime/cli-add-workspace-assets.js +417 -1
- package/dist/runtime/cli-add-workspace-rest.d.ts +14 -0
- package/dist/runtime/cli-add-workspace-rest.js +1060 -0
- package/dist/runtime/cli-add-workspace.d.ts +10 -1
- package/dist/runtime/cli-add-workspace.js +10 -1
- package/dist/runtime/cli-add.d.ts +3 -3
- package/dist/runtime/cli-add.js +2 -2
- package/dist/runtime/cli-core.d.ts +3 -1
- package/dist/runtime/cli-core.js +2 -1
- package/dist/runtime/cli-doctor-workspace.js +135 -1
- package/dist/runtime/cli-help.js +10 -6
- package/dist/runtime/cli-scaffold.d.ts +10 -2
- package/dist/runtime/cli-scaffold.js +136 -36
- package/dist/runtime/cli-templates.d.ts +4 -4
- package/dist/runtime/cli-templates.js +79 -39
- package/dist/runtime/index.d.ts +4 -3
- package/dist/runtime/index.js +3 -2
- package/dist/runtime/local-dev-presets.js +7 -2
- package/dist/runtime/rest-resource-artifacts.d.ts +35 -0
- package/dist/runtime/rest-resource-artifacts.js +158 -0
- package/dist/runtime/scaffold-answer-resolution.js +68 -2
- package/dist/runtime/scaffold-apply-utils.d.ts +4 -3
- package/dist/runtime/scaffold-apply-utils.js +34 -17
- package/dist/runtime/scaffold-bootstrap.d.ts +15 -0
- package/dist/runtime/scaffold-bootstrap.js +29 -7
- package/dist/runtime/scaffold-documents.js +2 -1
- package/dist/runtime/scaffold-onboarding.js +7 -3
- package/dist/runtime/scaffold-package-manager-files.js +6 -1
- package/dist/runtime/scaffold.d.ts +7 -1
- package/dist/runtime/scaffold.js +50 -8
- package/dist/runtime/template-render.d.ts +5 -2
- package/dist/runtime/template-render.js +9 -3
- package/dist/runtime/template-source-contracts.d.ts +11 -0
- package/dist/runtime/template-source-external.d.ts +1 -1
- package/dist/runtime/template-source-external.js +45 -13
- package/dist/runtime/template-source-normalization.d.ts +1 -1
- package/dist/runtime/template-source-normalization.js +5 -1
- package/dist/runtime/template-source-remote.d.ts +5 -0
- package/dist/runtime/template-source-remote.js +33 -0
- package/dist/runtime/template-source.js +30 -1
- package/dist/runtime/workspace-inventory.d.ts +43 -1
- package/dist/runtime/workspace-inventory.js +132 -1
- package/dist/runtime/workspace-project.d.ts +1 -1
- package/dist/runtime/workspace-project.js +2 -2
- package/package.json +3 -3
- package/templates/_shared/compound/core/scripts/add-compound-child.ts.mustache +428 -49
- package/templates/query-loop/src/validator-toolkit.ts.mustache +0 -1
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { HookedBlockPositionId } from "./hooked-blocks.js";
|
|
2
2
|
import { type RunAddHookedBlockCommandOptions, type RunAddVariationCommandOptions } from "./cli-add-shared.js";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Re-export focused workspace asset scaffold commands from the companion
|
|
5
|
+
* `cli-add-workspace-assets` module.
|
|
6
|
+
*/
|
|
7
|
+
export { runAddEditorPluginCommand, runAddBindingSourceCommand, runAddPatternCommand, } from "./cli-add-workspace-assets.js";
|
|
8
|
+
/**
|
|
9
|
+
* Re-export the plugin-level REST resource scaffold workflow from the focused
|
|
10
|
+
* rest-resource runtime helper module.
|
|
11
|
+
*/
|
|
12
|
+
export { runAddRestResourceCommand } from "./cli-add-workspace-rest.js";
|
|
4
13
|
/**
|
|
5
14
|
* Add one variation entry to an existing workspace block.
|
|
6
15
|
*
|
|
@@ -119,7 +119,16 @@ async function writeVariationRegistry(projectDir, blockSlug, variationSlug) {
|
|
|
119
119
|
const nextVariationSlugs = Array.from(new Set([...existingVariationSlugs, variationSlug])).sort();
|
|
120
120
|
await fsp.writeFile(variationsIndexPath, buildVariationIndexSource(nextVariationSlugs), "utf8");
|
|
121
121
|
}
|
|
122
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Re-export focused workspace asset scaffold commands from the companion
|
|
124
|
+
* `cli-add-workspace-assets` module.
|
|
125
|
+
*/
|
|
126
|
+
export { runAddEditorPluginCommand, runAddBindingSourceCommand, runAddPatternCommand, } from "./cli-add-workspace-assets.js";
|
|
127
|
+
/**
|
|
128
|
+
* Re-export the plugin-level REST resource scaffold workflow from the focused
|
|
129
|
+
* rest-resource runtime helper module.
|
|
130
|
+
*/
|
|
131
|
+
export { runAddRestResourceCommand } from "./cli-add-workspace-rest.js";
|
|
123
132
|
/**
|
|
124
133
|
* Add one variation entry to an existing workspace block.
|
|
125
134
|
*
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* - `cli-add-block` for built-in block scaffolding
|
|
8
8
|
* - `cli-add-workspace` for workspace mutation commands
|
|
9
9
|
*/
|
|
10
|
-
export { ADD_BLOCK_TEMPLATE_IDS, ADD_KIND_IDS, formatAddHelpText, } from "./cli-add-shared.js";
|
|
11
|
-
export type { AddBlockTemplateId, AddKindId, } from "./cli-add-shared.js";
|
|
10
|
+
export { ADD_BLOCK_TEMPLATE_IDS, ADD_KIND_IDS, EDITOR_PLUGIN_SLOT_IDS, formatAddHelpText, } from "./cli-add-shared.js";
|
|
11
|
+
export type { AddBlockTemplateId, AddKindId, EditorPluginSlotId, } from "./cli-add-shared.js";
|
|
12
12
|
export { runAddBlockCommand, seedWorkspaceMigrationProject, } from "./cli-add-block.js";
|
|
13
|
-
export { runAddBindingSourceCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddVariationCommand, } from "./cli-add-workspace.js";
|
|
13
|
+
export { runAddBindingSourceCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddRestResourceCommand, runAddVariationCommand, } from "./cli-add-workspace.js";
|
|
14
14
|
export { getWorkspaceBlockSelectOptions } from "./workspace-inventory.js";
|
package/dist/runtime/cli-add.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - `cli-add-block` for built-in block scaffolding
|
|
8
8
|
* - `cli-add-workspace` for workspace mutation commands
|
|
9
9
|
*/
|
|
10
|
-
export { ADD_BLOCK_TEMPLATE_IDS, ADD_KIND_IDS, formatAddHelpText, } from "./cli-add-shared.js";
|
|
10
|
+
export { ADD_BLOCK_TEMPLATE_IDS, ADD_KIND_IDS, EDITOR_PLUGIN_SLOT_IDS, formatAddHelpText, } from "./cli-add-shared.js";
|
|
11
11
|
export { runAddBlockCommand, seedWorkspaceMigrationProject, } from "./cli-add-block.js";
|
|
12
|
-
export { runAddBindingSourceCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddVariationCommand, } from "./cli-add-workspace.js";
|
|
12
|
+
export { runAddBindingSourceCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddRestResourceCommand, runAddVariationCommand, } from "./cli-add-workspace.js";
|
|
13
13
|
export { getWorkspaceBlockSelectOptions } from "./workspace-inventory.js";
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* and `HOOKED_BLOCK_POSITION_IDS`,
|
|
12
12
|
* `getWorkspaceBlockSelectOptions`, and `seedWorkspaceMigrationProject` for
|
|
13
13
|
* explicit `wp-typia add` flows,
|
|
14
|
+
* `runAddRestResourceCommand` for plugin-level REST resource scaffolds,
|
|
14
15
|
* `getDoctorChecks`, `runDoctor`, and `DoctorCheck` for diagnostics,
|
|
15
16
|
* `createCliCommandError` and `formatCliDiagnosticError` for shared
|
|
16
17
|
* non-interactive failure rendering,
|
|
@@ -25,8 +26,9 @@
|
|
|
25
26
|
export { getDoctorChecks, runDoctor, type DoctorCheck } from "./cli-doctor.js";
|
|
26
27
|
export { createCliCommandError, CliDiagnosticError, formatCliDiagnosticError, formatDoctorCheckLine, formatDoctorSummaryLine, getDoctorFailureDetailLines, getFailingDoctorChecks, isCliDiagnosticError, } from "./cli-diagnostics.js";
|
|
27
28
|
export type { CliDiagnosticMessage } from "./cli-diagnostics.js";
|
|
28
|
-
export { formatAddHelpText, getWorkspaceBlockSelectOptions, runAddBindingSourceCommand, runAddBlockCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddVariationCommand, seedWorkspaceMigrationProject, } from "./cli-add.js";
|
|
29
|
+
export { EDITOR_PLUGIN_SLOT_IDS, formatAddHelpText, getWorkspaceBlockSelectOptions, runAddBindingSourceCommand, runAddBlockCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddRestResourceCommand, runAddVariationCommand, seedWorkspaceMigrationProject, } from "./cli-add.js";
|
|
29
30
|
export { HOOKED_BLOCK_POSITION_IDS } from "./hooked-blocks.js";
|
|
31
|
+
export type { EditorPluginSlotId } from "./cli-add.js";
|
|
30
32
|
export type { HookedBlockPositionId } from "./hooked-blocks.js";
|
|
31
33
|
export { formatHelpText } from "./cli-help.js";
|
|
32
34
|
export { getNextSteps, getOptionalOnboarding, runScaffoldFlow, } from "./cli-scaffold.js";
|
package/dist/runtime/cli-core.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* and `HOOKED_BLOCK_POSITION_IDS`,
|
|
12
12
|
* `getWorkspaceBlockSelectOptions`, and `seedWorkspaceMigrationProject` for
|
|
13
13
|
* explicit `wp-typia add` flows,
|
|
14
|
+
* `runAddRestResourceCommand` for plugin-level REST resource scaffolds,
|
|
14
15
|
* `getDoctorChecks`, `runDoctor`, and `DoctorCheck` for diagnostics,
|
|
15
16
|
* `createCliCommandError` and `formatCliDiagnosticError` for shared
|
|
16
17
|
* non-interactive failure rendering,
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
*/
|
|
25
26
|
export { getDoctorChecks, runDoctor } from "./cli-doctor.js";
|
|
26
27
|
export { createCliCommandError, CliDiagnosticError, formatCliDiagnosticError, formatDoctorCheckLine, formatDoctorSummaryLine, getDoctorFailureDetailLines, getFailingDoctorChecks, isCliDiagnosticError, } from "./cli-diagnostics.js";
|
|
27
|
-
export { formatAddHelpText, getWorkspaceBlockSelectOptions, runAddBindingSourceCommand, runAddBlockCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddVariationCommand, seedWorkspaceMigrationProject, } from "./cli-add.js";
|
|
28
|
+
export { EDITOR_PLUGIN_SLOT_IDS, formatAddHelpText, getWorkspaceBlockSelectOptions, runAddBindingSourceCommand, runAddBlockCommand, runAddEditorPluginCommand, runAddHookedBlockCommand, runAddPatternCommand, runAddRestResourceCommand, runAddVariationCommand, seedWorkspaceMigrationProject, } from "./cli-add.js";
|
|
28
29
|
export { HOOKED_BLOCK_POSITION_IDS } from "./hooked-blocks.js";
|
|
29
30
|
export { formatHelpText } from "./cli-help.js";
|
|
30
31
|
export { getNextSteps, getOptionalOnboarding, runScaffoldFlow, } from "./cli-scaffold.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parseScaffoldBlockMetadata } from "@wp-typia/block-runtime/blocks";
|
|
4
|
+
import { EDITOR_PLUGIN_SLOT_IDS, REST_RESOURCE_METHOD_IDS, REST_RESOURCE_NAMESPACE_PATTERN, } from "./cli-add-shared.js";
|
|
4
5
|
import { HOOKED_BLOCK_ANCHOR_PATTERN, HOOKED_BLOCK_POSITION_SET, } from "./hooked-blocks.js";
|
|
5
6
|
import { readWorkspaceInventory } from "./workspace-inventory.js";
|
|
6
7
|
import { getInvalidWorkspaceProjectReason, parseWorkspacePackageJson, WORKSPACE_TEMPLATE_PACKAGE, tryResolveWorkspaceProject, } from "./workspace-project.js";
|
|
@@ -9,6 +10,10 @@ const WORKSPACE_COLLECTION_IMPORT_PATTERN = /^\s*import\s+["']\.\.\/\.\.\/collec
|
|
|
9
10
|
const WORKSPACE_BINDING_SERVER_GLOB = "/src/bindings/*/server.php";
|
|
10
11
|
const WORKSPACE_BINDING_EDITOR_SCRIPT = "build/bindings/index.js";
|
|
11
12
|
const WORKSPACE_BINDING_EDITOR_ASSET = "build/bindings/index.asset.php";
|
|
13
|
+
const WORKSPACE_REST_RESOURCE_GLOB = "/inc/rest/*.php";
|
|
14
|
+
const WORKSPACE_EDITOR_PLUGIN_EDITOR_SCRIPT = "build/editor-plugins/index.js";
|
|
15
|
+
const WORKSPACE_EDITOR_PLUGIN_EDITOR_ASSET = "build/editor-plugins/index.asset.php";
|
|
16
|
+
const WORKSPACE_EDITOR_PLUGIN_EDITOR_STYLE = "build/editor-plugins/style-index.css";
|
|
12
17
|
const WORKSPACE_GENERATED_BLOCK_ARTIFACTS = [
|
|
13
18
|
"block.json",
|
|
14
19
|
"typia.manifest.json",
|
|
@@ -22,6 +27,9 @@ function createDoctorCheck(label, status, detail) {
|
|
|
22
27
|
function createDoctorScopeCheck(status, detail) {
|
|
23
28
|
return createDoctorCheck("Doctor scope", status, detail);
|
|
24
29
|
}
|
|
30
|
+
function escapeRegex(value) {
|
|
31
|
+
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
32
|
+
}
|
|
25
33
|
function getWorkspaceBootstrapRelativePath(packageName) {
|
|
26
34
|
const packageBaseName = packageName.split("/").pop() ?? packageName;
|
|
27
35
|
return `${packageBaseName}.php`;
|
|
@@ -184,6 +192,117 @@ function checkWorkspaceBindingSourcesIndex(projectDir, bindingSources) {
|
|
|
184
192
|
? "Binding source editor registrations are aggregated"
|
|
185
193
|
: `Missing editor imports for: ${missingImports.map((entry) => entry.slug).join(", ")}`);
|
|
186
194
|
}
|
|
195
|
+
function getWorkspaceRestResourceRequiredFiles(restResource) {
|
|
196
|
+
const schemaNames = new Set();
|
|
197
|
+
if (restResource.methods.includes("list")) {
|
|
198
|
+
schemaNames.add("list-query");
|
|
199
|
+
schemaNames.add("list-response");
|
|
200
|
+
}
|
|
201
|
+
if (restResource.methods.includes("read")) {
|
|
202
|
+
schemaNames.add("read-query");
|
|
203
|
+
schemaNames.add("read-response");
|
|
204
|
+
}
|
|
205
|
+
if (restResource.methods.includes("create")) {
|
|
206
|
+
schemaNames.add("create-request");
|
|
207
|
+
schemaNames.add("create-response");
|
|
208
|
+
}
|
|
209
|
+
if (restResource.methods.includes("update")) {
|
|
210
|
+
schemaNames.add("update-query");
|
|
211
|
+
schemaNames.add("update-request");
|
|
212
|
+
schemaNames.add("update-response");
|
|
213
|
+
}
|
|
214
|
+
if (restResource.methods.includes("delete")) {
|
|
215
|
+
schemaNames.add("delete-query");
|
|
216
|
+
schemaNames.add("delete-response");
|
|
217
|
+
}
|
|
218
|
+
return Array.from(new Set([
|
|
219
|
+
restResource.apiFile,
|
|
220
|
+
...Array.from(schemaNames, (schemaName) => path.join(path.dirname(restResource.typesFile), "api-schemas", `${schemaName}.schema.json`)),
|
|
221
|
+
restResource.clientFile,
|
|
222
|
+
restResource.dataFile,
|
|
223
|
+
restResource.openApiFile,
|
|
224
|
+
restResource.phpFile,
|
|
225
|
+
restResource.typesFile,
|
|
226
|
+
restResource.validatorsFile,
|
|
227
|
+
]));
|
|
228
|
+
}
|
|
229
|
+
function checkWorkspaceRestResourceConfig(restResource) {
|
|
230
|
+
const hasNamespace = REST_RESOURCE_NAMESPACE_PATTERN.test(restResource.namespace);
|
|
231
|
+
const hasMethods = restResource.methods.length > 0 &&
|
|
232
|
+
restResource.methods.every((method) => REST_RESOURCE_METHOD_IDS.includes(method));
|
|
233
|
+
return createDoctorCheck(`REST resource config ${restResource.slug}`, hasNamespace && hasMethods ? "pass" : "fail", hasNamespace && hasMethods
|
|
234
|
+
? `REST resource namespace ${restResource.namespace} with methods ${restResource.methods.join(", ")}`
|
|
235
|
+
: "REST resource namespace or methods are invalid");
|
|
236
|
+
}
|
|
237
|
+
function checkWorkspaceRestResourceBootstrap(projectDir, packageName, phpPrefix) {
|
|
238
|
+
const packageBaseName = packageName.split("/").pop() ?? packageName;
|
|
239
|
+
const bootstrapPath = path.join(projectDir, `${packageBaseName}.php`);
|
|
240
|
+
if (!fs.existsSync(bootstrapPath)) {
|
|
241
|
+
return createDoctorCheck("REST resource bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
|
|
242
|
+
}
|
|
243
|
+
const source = fs.readFileSync(bootstrapPath, "utf8");
|
|
244
|
+
const registerFunctionName = `${phpPrefix}_register_rest_resources`;
|
|
245
|
+
const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
|
|
246
|
+
const hasServerGlob = source.includes(WORKSPACE_REST_RESOURCE_GLOB);
|
|
247
|
+
const hasRegisterHook = source.includes(registerHook);
|
|
248
|
+
return createDoctorCheck("REST resource bootstrap", hasServerGlob && hasRegisterHook ? "pass" : "fail", hasServerGlob && hasRegisterHook
|
|
249
|
+
? "REST resource PHP loader hook is present"
|
|
250
|
+
: "Missing REST resource PHP require glob or init hook");
|
|
251
|
+
}
|
|
252
|
+
function getWorkspaceEditorPluginRequiredFiles(editorPlugin) {
|
|
253
|
+
const editorPluginDir = path.join("src", "editor-plugins", editorPlugin.slug);
|
|
254
|
+
return Array.from(new Set([
|
|
255
|
+
editorPlugin.file,
|
|
256
|
+
path.join(editorPluginDir, "Sidebar.tsx"),
|
|
257
|
+
path.join(editorPluginDir, "data.ts"),
|
|
258
|
+
path.join(editorPluginDir, "types.ts"),
|
|
259
|
+
path.join(editorPluginDir, "style.scss"),
|
|
260
|
+
]));
|
|
261
|
+
}
|
|
262
|
+
function checkWorkspaceEditorPluginConfig(editorPlugin) {
|
|
263
|
+
const validSlots = new Set(EDITOR_PLUGIN_SLOT_IDS);
|
|
264
|
+
const isValidSlot = validSlots.has(editorPlugin.slot);
|
|
265
|
+
return createDoctorCheck(`Editor plugin config ${editorPlugin.slug}`, isValidSlot ? "pass" : "fail", isValidSlot
|
|
266
|
+
? `Editor plugin slot ${editorPlugin.slot} is supported`
|
|
267
|
+
: `Unsupported editor plugin slot "${editorPlugin.slot}". Expected one of: ${EDITOR_PLUGIN_SLOT_IDS.join(", ")}`);
|
|
268
|
+
}
|
|
269
|
+
function checkWorkspaceEditorPluginBootstrap(projectDir, packageName, phpPrefix) {
|
|
270
|
+
const packageBaseName = packageName.split("/").pop() ?? packageName;
|
|
271
|
+
const bootstrapPath = path.join(projectDir, `${packageBaseName}.php`);
|
|
272
|
+
if (!fs.existsSync(bootstrapPath)) {
|
|
273
|
+
return createDoctorCheck("Editor plugin bootstrap", "fail", `Missing ${path.basename(bootstrapPath)}`);
|
|
274
|
+
}
|
|
275
|
+
const source = fs.readFileSync(bootstrapPath, "utf8");
|
|
276
|
+
const enqueueFunctionName = `${phpPrefix}_enqueue_editor_plugins_editor`;
|
|
277
|
+
const enqueueHook = `add_action( 'enqueue_block_editor_assets', '${enqueueFunctionName}' );`;
|
|
278
|
+
const hasEditorEnqueueHook = source.includes(enqueueHook);
|
|
279
|
+
const hasEditorScript = source.includes(WORKSPACE_EDITOR_PLUGIN_EDITOR_SCRIPT);
|
|
280
|
+
const hasEditorAsset = source.includes(WORKSPACE_EDITOR_PLUGIN_EDITOR_ASSET);
|
|
281
|
+
const hasEditorStyle = source.includes(WORKSPACE_EDITOR_PLUGIN_EDITOR_STYLE);
|
|
282
|
+
return createDoctorCheck("Editor plugin bootstrap", hasEditorEnqueueHook && hasEditorScript && hasEditorAsset && hasEditorStyle ? "pass" : "fail", hasEditorEnqueueHook && hasEditorScript && hasEditorAsset && hasEditorStyle
|
|
283
|
+
? "Editor plugin enqueue hook is present"
|
|
284
|
+
: "Missing editor plugin enqueue hook or build/editor-plugins script/style asset references");
|
|
285
|
+
}
|
|
286
|
+
function checkWorkspaceEditorPluginIndex(projectDir, editorPlugins) {
|
|
287
|
+
const indexRelativePath = [
|
|
288
|
+
path.join("src", "editor-plugins", "index.ts"),
|
|
289
|
+
path.join("src", "editor-plugins", "index.js"),
|
|
290
|
+
].find((relativePath) => fs.existsSync(path.join(projectDir, relativePath)));
|
|
291
|
+
if (!indexRelativePath) {
|
|
292
|
+
return createDoctorCheck("Editor plugins index", "fail", "Missing src/editor-plugins/index.ts or src/editor-plugins/index.js");
|
|
293
|
+
}
|
|
294
|
+
const indexPath = path.join(projectDir, indexRelativePath);
|
|
295
|
+
const source = fs.readFileSync(indexPath, "utf8");
|
|
296
|
+
const missingImports = editorPlugins.filter((editorPlugin) => {
|
|
297
|
+
const importPattern = new RegExp(`['"\`]\\./${escapeRegex(editorPlugin.slug)}(?:/[^'"\`]*)?['"\`]`, "u");
|
|
298
|
+
return !importPattern.test(source);
|
|
299
|
+
});
|
|
300
|
+
return createDoctorCheck("Editor plugins index", missingImports.length === 0 ? "pass" : "fail", missingImports.length === 0
|
|
301
|
+
? "Editor plugin registrations are aggregated"
|
|
302
|
+
: `Missing editor plugin imports for: ${missingImports
|
|
303
|
+
.map((entry) => entry.slug)
|
|
304
|
+
.join(", ")}`);
|
|
305
|
+
}
|
|
187
306
|
function checkVariationEntrypoint(projectDir, blockSlug) {
|
|
188
307
|
const entryPath = path.join(projectDir, "src", "blocks", blockSlug, "index.tsx");
|
|
189
308
|
if (!fs.existsSync(entryPath)) {
|
|
@@ -258,7 +377,7 @@ export function getWorkspaceDoctorChecks(cwd) {
|
|
|
258
377
|
checks.push(checkWorkspacePackageMetadata(workspace, workspacePackageJson));
|
|
259
378
|
try {
|
|
260
379
|
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
261
|
-
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)`));
|
|
380
|
+
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), ${inventory.restResources.length} REST resource(s), ${inventory.editorPlugins.length} editor plugin(s)`));
|
|
262
381
|
for (const block of inventory.blocks) {
|
|
263
382
|
checks.push(checkExistingFiles(workspace.projectDir, `Block ${block.slug}`, getWorkspaceBlockRequiredFiles(block)));
|
|
264
383
|
checks.push(checkWorkspaceBlockMetadata(workspace.projectDir, workspace, block));
|
|
@@ -296,6 +415,21 @@ export function getWorkspaceDoctorChecks(cwd) {
|
|
|
296
415
|
bindingSource.editorFile,
|
|
297
416
|
]));
|
|
298
417
|
}
|
|
418
|
+
if (inventory.restResources.length > 0) {
|
|
419
|
+
checks.push(checkWorkspaceRestResourceBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
|
|
420
|
+
}
|
|
421
|
+
for (const restResource of inventory.restResources) {
|
|
422
|
+
checks.push(checkWorkspaceRestResourceConfig(restResource));
|
|
423
|
+
checks.push(checkExistingFiles(workspace.projectDir, `REST resource ${restResource.slug}`, getWorkspaceRestResourceRequiredFiles(restResource)));
|
|
424
|
+
}
|
|
425
|
+
if (inventory.editorPlugins.length > 0) {
|
|
426
|
+
checks.push(checkWorkspaceEditorPluginBootstrap(workspace.projectDir, workspace.packageName, workspace.workspace.phpPrefix));
|
|
427
|
+
checks.push(checkWorkspaceEditorPluginIndex(workspace.projectDir, inventory.editorPlugins));
|
|
428
|
+
}
|
|
429
|
+
for (const editorPlugin of inventory.editorPlugins) {
|
|
430
|
+
checks.push(checkExistingFiles(workspace.projectDir, `Editor plugin ${editorPlugin.slug}`, getWorkspaceEditorPluginRequiredFiles(editorPlugin)));
|
|
431
|
+
checks.push(checkWorkspaceEditorPluginConfig(editorPlugin));
|
|
432
|
+
}
|
|
299
433
|
const migrationWorkspaceCheck = checkMigrationWorkspaceHint(workspace, workspacePackageJson);
|
|
300
434
|
if (migrationWorkspaceCheck) {
|
|
301
435
|
checks.push(migrationWorkspaceCheck);
|
package/dist/runtime/cli-help.js
CHANGED
|
@@ -10,17 +10,19 @@ import { TEMPLATE_IDS } from "./template-registry.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export function formatHelpText() {
|
|
12
12
|
return `Usage:
|
|
13
|
-
wp-typia create <project-dir> [--template <basic|interactivity>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
|
|
14
|
-
wp-typia create <project-dir> [--template query-loop] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--query-post-type <post-type>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
|
|
15
|
-
wp-typia create <project-dir> [--template <./path|github:owner/repo/path[#ref]>] [--variant <name>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
|
|
16
|
-
wp-typia create <project-dir> [--template <npm-package>] [--variant <name>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
|
|
17
|
-
wp-typia create <project-dir> [--template persistence] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
|
|
18
|
-
wp-typia create <project-dir> [--template compound] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--no-install] [--package-manager <id>]
|
|
13
|
+
wp-typia create <project-dir> [--template <basic|interactivity>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
|
|
14
|
+
wp-typia create <project-dir> [--template query-loop] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--query-post-type <post-type>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
|
|
15
|
+
wp-typia create <project-dir> [--template <./path|github:owner/repo/path[#ref]>] [--variant <name>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
|
|
16
|
+
wp-typia create <project-dir> [--template <npm-package>] [--variant <name>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
|
|
17
|
+
wp-typia create <project-dir> [--template persistence] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
|
|
18
|
+
wp-typia create <project-dir> [--template compound] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--namespace <value>] [--text-domain <value>] [--php-prefix <value>] [--with-migration-ui] [--with-wp-env] [--with-test-preset] [--yes] [--dry-run] [--no-install] [--package-manager <id>]
|
|
19
19
|
wp-typia <project-dir> [create flags...]
|
|
20
20
|
wp-typia add block <name> --template <basic|interactivity|persistence|compound> [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>]
|
|
21
21
|
wp-typia add variation <name> --block <block-slug>
|
|
22
22
|
wp-typia add pattern <name>
|
|
23
23
|
wp-typia add binding-source <name>
|
|
24
|
+
wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <method[,method...]>]
|
|
25
|
+
wp-typia add editor-plugin <name> [--slot <PluginSidebar>]
|
|
24
26
|
wp-typia add hooked-block <block-slug> --anchor <anchor-block-name> --position <before|after|firstChild|lastChild>
|
|
25
27
|
wp-typia migrate <init|snapshot|diff|scaffold|verify|doctor|fixtures|fuzz> [...]
|
|
26
28
|
wp-typia templates list
|
|
@@ -39,6 +41,8 @@ Notes:
|
|
|
39
41
|
\`add variation\` uses an existing workspace block from \`scripts/block-config.ts\`.
|
|
40
42
|
\`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/\`.
|
|
41
43
|
\`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`.
|
|
44
|
+
\`add rest-resource\` scaffolds plugin-level TypeScript REST contracts under \`src/rest/\` and PHP route glue under \`inc/rest/\`.
|
|
45
|
+
\`add editor-plugin\` scaffolds a document-level editor extension under \`src/editor-plugins/\`.
|
|
42
46
|
\`add hooked-block\` patches an existing workspace block's \`block.json\` \`blockHooks\` metadata.
|
|
43
47
|
\`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.
|
|
44
48
|
\`wp-typia migrate doctor --all\` checks migration target alignment, snapshots, fixtures, and generated migration artifacts.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { collectScaffoldAnswers, scaffoldProject } from "./scaffold.js";
|
|
2
|
-
import type { DataStorageMode, PersistencePolicy } from "./scaffold.js";
|
|
2
|
+
import type { DataStorageMode, PersistencePolicy, ScaffoldProgressEvent } from "./scaffold.js";
|
|
3
3
|
import type { PackageManagerId } from "./package-managers.js";
|
|
4
4
|
import { type ExternalLayerSelectionOption } from "./external-layer-selection.js";
|
|
5
5
|
import type { TemplateDefinition } from "./template-registry.js";
|
|
@@ -20,16 +20,22 @@ interface OptionalOnboardingGuidance {
|
|
|
20
20
|
note: string;
|
|
21
21
|
steps: string[];
|
|
22
22
|
}
|
|
23
|
+
export interface ScaffoldDryRunPlan {
|
|
24
|
+
dependencyInstall: "skipped-by-flag" | "would-install";
|
|
25
|
+
files: string[];
|
|
26
|
+
}
|
|
23
27
|
interface RunScaffoldFlowOptions {
|
|
24
28
|
allowExistingDir?: boolean;
|
|
25
29
|
cwd?: string;
|
|
26
30
|
dataStorageMode?: string;
|
|
31
|
+
dryRun?: boolean;
|
|
27
32
|
externalLayerId?: string;
|
|
28
33
|
externalLayerSource?: string;
|
|
29
34
|
installDependencies?: Parameters<typeof scaffoldProject>[0]["installDependencies"];
|
|
30
35
|
isInteractive?: boolean;
|
|
31
36
|
namespace?: string;
|
|
32
37
|
noInstall?: boolean;
|
|
38
|
+
onProgress?: ((event: ScaffoldProgressEvent) => void | Promise<void>) | undefined;
|
|
33
39
|
packageManager?: string;
|
|
34
40
|
phpPrefix?: string;
|
|
35
41
|
projectInput: string;
|
|
@@ -74,8 +80,10 @@ export declare function getOptionalOnboarding({ availableScripts, packageManager
|
|
|
74
80
|
* project.
|
|
75
81
|
* @returns The scaffold result together with next-step guidance.
|
|
76
82
|
*/
|
|
77
|
-
export declare function runScaffoldFlow({ projectInput, cwd, templateId, dataStorageMode, externalLayerId, externalLayerSource, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, queryPostType, yes, noInstall, isInteractive, allowExistingDir, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }: RunScaffoldFlowOptions): Promise<{
|
|
83
|
+
export declare function runScaffoldFlow({ projectInput, cwd, templateId, dataStorageMode, dryRun, externalLayerId, externalLayerSource, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, queryPostType, yes, noInstall, onProgress, isInteractive, allowExistingDir, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }: RunScaffoldFlowOptions): Promise<{
|
|
84
|
+
dryRun: boolean;
|
|
78
85
|
optionalOnboarding: OptionalOnboardingGuidance;
|
|
86
|
+
plan: ScaffoldDryRunPlan | undefined;
|
|
79
87
|
projectDir: string;
|
|
80
88
|
projectInput: string;
|
|
81
89
|
packageManager: PackageManagerId;
|
|
@@ -1,11 +1,79 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import { promises as fsp } from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, resolvePackageManagerId, resolveTemplateId, scaffoldProject, } from "./scaffold.js";
|
|
4
6
|
import { formatInstallCommand, formatRunScript, } from "./package-managers.js";
|
|
5
7
|
import { getPrimaryDevelopmentScript } from "./local-dev-presets.js";
|
|
6
8
|
import { getOptionalOnboardingNote, getOptionalOnboardingSteps, } from "./scaffold-onboarding.js";
|
|
9
|
+
import { formatNonEmptyTargetDirectoryError } from "./scaffold-bootstrap.js";
|
|
7
10
|
import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, isBuiltInTemplateId, } from "./template-registry.js";
|
|
8
11
|
import { resolveOptionalInteractiveExternalLayerId, } from "./external-layer-selection.js";
|
|
12
|
+
async function listRelativeProjectFiles(rootDir) {
|
|
13
|
+
const relativeFiles = [];
|
|
14
|
+
async function visit(currentDir) {
|
|
15
|
+
const entries = await fsp.readdir(currentDir, { withFileTypes: true });
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
const absolutePath = path.join(currentDir, entry.name);
|
|
18
|
+
if (entry.isDirectory()) {
|
|
19
|
+
await visit(absolutePath);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
relativeFiles.push(path
|
|
23
|
+
.relative(rootDir, absolutePath)
|
|
24
|
+
.replace(path.sep === "\\" ? /\\/gu : /\//gu, "/"));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
await visit(rootDir);
|
|
28
|
+
return relativeFiles.sort((left, right) => left.localeCompare(right));
|
|
29
|
+
}
|
|
30
|
+
async function assertDryRunTargetDirectoryReady(projectDir, allowExistingDir) {
|
|
31
|
+
if (!fs.existsSync(projectDir) || allowExistingDir) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const entries = await fsp.readdir(projectDir);
|
|
35
|
+
if (entries.length > 0) {
|
|
36
|
+
throw new Error(formatNonEmptyTargetDirectoryError(projectDir));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function buildScaffoldDryRunPlan({ allowExistingDir, answers, cwd, dataStorageMode, externalLayerId, externalLayerSource, externalLayerSourceLabel, installDependencies, noInstall, onProgress, packageManager, persistencePolicy, projectDir, templateId, variant, withMigrationUi, withTestPreset, withWpEnv, }) {
|
|
40
|
+
await assertDryRunTargetDirectoryReady(projectDir, allowExistingDir);
|
|
41
|
+
const tempRoot = await fsp.mkdtemp(path.join(os.tmpdir(), "wp-typia-scaffold-plan-"));
|
|
42
|
+
const previewProjectDir = path.join(tempRoot, "preview-project");
|
|
43
|
+
try {
|
|
44
|
+
const result = await scaffoldProject({
|
|
45
|
+
allowExistingDir: false,
|
|
46
|
+
answers,
|
|
47
|
+
cwd,
|
|
48
|
+
dataStorageMode,
|
|
49
|
+
externalLayerId,
|
|
50
|
+
externalLayerSource,
|
|
51
|
+
externalLayerSourceLabel,
|
|
52
|
+
installDependencies,
|
|
53
|
+
noInstall: true,
|
|
54
|
+
onProgress,
|
|
55
|
+
packageManager,
|
|
56
|
+
persistencePolicy,
|
|
57
|
+
projectDir: previewProjectDir,
|
|
58
|
+
templateId,
|
|
59
|
+
variant,
|
|
60
|
+
withMigrationUi,
|
|
61
|
+
withTestPreset,
|
|
62
|
+
withWpEnv,
|
|
63
|
+
});
|
|
64
|
+
const files = await listRelativeProjectFiles(previewProjectDir);
|
|
65
|
+
return {
|
|
66
|
+
plan: {
|
|
67
|
+
dependencyInstall: noInstall ? "skipped-by-flag" : "would-install",
|
|
68
|
+
files,
|
|
69
|
+
},
|
|
70
|
+
result,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
await fsp.rm(tempRoot, { force: true, recursive: true });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
9
77
|
function validateCreateProjectInput(projectInput) {
|
|
10
78
|
const normalizedProjectInput = projectInput.trim();
|
|
11
79
|
if (normalizedProjectInput.length === 0) {
|
|
@@ -135,7 +203,7 @@ export function getOptionalOnboarding({ availableScripts, packageManager, templa
|
|
|
135
203
|
* project.
|
|
136
204
|
* @returns The scaffold result together with next-step guidance.
|
|
137
205
|
*/
|
|
138
|
-
export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templateId, dataStorageMode, externalLayerId, externalLayerSource, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, queryPostType, yes = false, noInstall = false, isInteractive = false, allowExistingDir = false, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies = undefined, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }) {
|
|
206
|
+
export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templateId, dataStorageMode, dryRun = false, externalLayerId, externalLayerSource, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, queryPostType, yes = false, noInstall = false, onProgress, isInteractive = false, allowExistingDir = false, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies = undefined, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }) {
|
|
139
207
|
const normalizedExternalLayerId = typeof externalLayerId === "string" && externalLayerId.trim().length > 0
|
|
140
208
|
? externalLayerId.trim()
|
|
141
209
|
: undefined;
|
|
@@ -234,47 +302,76 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
234
302
|
yes,
|
|
235
303
|
promptText,
|
|
236
304
|
});
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
305
|
+
const resolvedResult = dryRun
|
|
306
|
+
? await buildScaffoldDryRunPlan({
|
|
307
|
+
allowExistingDir,
|
|
308
|
+
answers,
|
|
309
|
+
cwd,
|
|
310
|
+
dataStorageMode: resolvedDataStorage,
|
|
311
|
+
externalLayerId: resolvedExternalLayerSelection.externalLayerId,
|
|
312
|
+
externalLayerSource: resolvedExternalLayerSelection.externalLayerSource,
|
|
313
|
+
externalLayerSourceLabel: normalizedExternalLayerSource,
|
|
314
|
+
installDependencies,
|
|
315
|
+
noInstall,
|
|
316
|
+
onProgress,
|
|
317
|
+
packageManager: resolvedPackageManager,
|
|
318
|
+
persistencePolicy: resolvedPersistencePolicy,
|
|
319
|
+
projectDir,
|
|
320
|
+
templateId: resolvedTemplateId,
|
|
321
|
+
variant,
|
|
322
|
+
withMigrationUi: resolvedWithMigrationUi,
|
|
323
|
+
withTestPreset: resolvedWithTestPreset,
|
|
324
|
+
withWpEnv: resolvedWithWpEnv,
|
|
325
|
+
})
|
|
326
|
+
: {
|
|
327
|
+
plan: undefined,
|
|
328
|
+
result: await scaffoldProject({
|
|
329
|
+
answers,
|
|
330
|
+
allowExistingDir,
|
|
331
|
+
cwd,
|
|
332
|
+
dataStorageMode: resolvedDataStorage,
|
|
333
|
+
externalLayerId: resolvedExternalLayerSelection.externalLayerId,
|
|
334
|
+
externalLayerSource: resolvedExternalLayerSelection.externalLayerSource,
|
|
335
|
+
externalLayerSourceLabel: normalizedExternalLayerSource,
|
|
336
|
+
installDependencies,
|
|
337
|
+
noInstall,
|
|
338
|
+
onProgress,
|
|
339
|
+
packageManager: resolvedPackageManager,
|
|
340
|
+
persistencePolicy: resolvedPersistencePolicy,
|
|
341
|
+
projectDir,
|
|
342
|
+
templateId: resolvedTemplateId,
|
|
343
|
+
variant,
|
|
344
|
+
withMigrationUi: resolvedWithMigrationUi,
|
|
345
|
+
withTestPreset: resolvedWithTestPreset,
|
|
346
|
+
withWpEnv: resolvedWithWpEnv,
|
|
347
|
+
}),
|
|
348
|
+
};
|
|
256
349
|
let availableScripts;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
350
|
+
if (!dryRun) {
|
|
351
|
+
try {
|
|
352
|
+
const parsedPackageJson = JSON.parse(fs.readFileSync(path.join(projectDir, "package.json"), "utf8"));
|
|
353
|
+
const scripts = parsedPackageJson.scripts &&
|
|
354
|
+
typeof parsedPackageJson.scripts === "object" &&
|
|
355
|
+
!Array.isArray(parsedPackageJson.scripts)
|
|
356
|
+
? parsedPackageJson.scripts
|
|
357
|
+
: {};
|
|
358
|
+
availableScripts = Object.entries(scripts)
|
|
359
|
+
.filter(([, value]) => typeof value === "string")
|
|
360
|
+
.map(([scriptName]) => scriptName);
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
availableScripts = undefined;
|
|
364
|
+
}
|
|
270
365
|
}
|
|
271
366
|
return {
|
|
367
|
+
dryRun,
|
|
272
368
|
optionalOnboarding: getOptionalOnboarding({
|
|
273
369
|
availableScripts,
|
|
274
370
|
packageManager: resolvedPackageManager,
|
|
275
371
|
templateId: resolvedTemplateId,
|
|
276
|
-
compoundPersistenceEnabled: result.variables.compoundPersistenceEnabled === "true",
|
|
372
|
+
compoundPersistenceEnabled: resolvedResult.result.variables.compoundPersistenceEnabled === "true",
|
|
277
373
|
}),
|
|
374
|
+
plan: resolvedResult.plan,
|
|
278
375
|
projectDir,
|
|
279
376
|
projectInput,
|
|
280
377
|
packageManager: resolvedPackageManager,
|
|
@@ -286,8 +383,11 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
286
383
|
templateId: resolvedTemplateId,
|
|
287
384
|
}),
|
|
288
385
|
result: {
|
|
289
|
-
...result,
|
|
290
|
-
warnings: [
|
|
386
|
+
...resolvedResult.result,
|
|
387
|
+
warnings: [
|
|
388
|
+
...resolvedResult.result.warnings,
|
|
389
|
+
...collectProjectDirectoryWarnings(projectDir),
|
|
390
|
+
],
|
|
291
391
|
},
|
|
292
392
|
};
|
|
293
393
|
}
|
|
@@ -8,18 +8,18 @@ import type { TemplateDefinition } from "./template-registry.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function formatTemplateSummary(template: TemplateDefinition): string;
|
|
10
10
|
/**
|
|
11
|
-
* Format the feature hint
|
|
11
|
+
* Format the feature and capability hint lines shown under a template summary.
|
|
12
12
|
*
|
|
13
13
|
* @param template Template metadata including the `features` list.
|
|
14
|
-
* @returns Indented feature text for CLI list output.
|
|
14
|
+
* @returns Indented feature and capability text for CLI list output.
|
|
15
15
|
*/
|
|
16
16
|
export declare function formatTemplateFeatures(template: TemplateDefinition): string;
|
|
17
17
|
/**
|
|
18
18
|
* Format the detailed template description for `templates inspect`.
|
|
19
19
|
*
|
|
20
20
|
* This expands special layer combinations for the `persistence` and `compound`
|
|
21
|
-
* templates and returns a multi-line block
|
|
22
|
-
*
|
|
21
|
+
* templates and returns a multi-line block centered on human-facing identity,
|
|
22
|
+
* capabilities, and logical layer composition.
|
|
23
23
|
*
|
|
24
24
|
* @param template Template metadata including `id`, `defaultCategory`,
|
|
25
25
|
* `templateDir`, and `features`.
|