@wp-typia/project-tools 0.18.0 → 0.19.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/alternate-render-targets.d.ts +5 -0
- package/dist/runtime/alternate-render-targets.js +29 -0
- package/dist/runtime/block-generator-service-core.d.ts +1 -1
- package/dist/runtime/block-generator-service-core.js +11 -7
- package/dist/runtime/block-generator-service-spec.d.ts +8 -1
- package/dist/runtime/block-generator-service-spec.js +43 -1
- package/dist/runtime/built-in-block-code-templates/compound-child.d.ts +1 -1
- package/dist/runtime/built-in-block-code-templates/compound-child.js +14 -9
- package/dist/runtime/built-in-block-code-templates/compound-parent.d.ts +2 -2
- package/dist/runtime/built-in-block-code-templates/compound-parent.js +100 -43
- package/dist/runtime/built-in-block-code-templates/compound-persistence.d.ts +1 -1
- package/dist/runtime/built-in-block-code-templates/compound-persistence.js +11 -8
- package/dist/runtime/built-in-block-non-ts-artifacts.js +505 -2
- package/dist/runtime/cli-add-block.d.ts +4 -1
- package/dist/runtime/cli-add-block.js +55 -26
- package/dist/runtime/cli-add-shared.d.ts +3 -1
- package/dist/runtime/cli-add-shared.js +12 -12
- package/dist/runtime/cli-core.d.ts +2 -0
- package/dist/runtime/cli-core.js +1 -0
- package/dist/runtime/cli-help.js +4 -3
- package/dist/runtime/cli-scaffold.d.ts +3 -1
- package/dist/runtime/cli-scaffold.js +88 -12
- package/dist/runtime/cli-templates.js +26 -1
- package/dist/runtime/cli-validation.d.ts +66 -0
- package/dist/runtime/cli-validation.js +92 -0
- package/dist/runtime/compound-inner-blocks.d.ts +78 -0
- package/dist/runtime/compound-inner-blocks.js +88 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/migration-command-surface.js +2 -0
- package/dist/runtime/package-versions.d.ts +1 -0
- package/dist/runtime/package-versions.js +12 -0
- package/dist/runtime/scaffold-answer-resolution.js +10 -6
- package/dist/runtime/scaffold-documents.js +22 -2
- package/dist/runtime/scaffold-identifiers.d.ts +17 -0
- package/dist/runtime/scaffold-identifiers.js +22 -0
- package/dist/runtime/scaffold-onboarding.js +21 -13
- package/dist/runtime/scaffold-template-variables.js +22 -0
- package/dist/runtime/scaffold.d.ts +16 -1
- package/dist/runtime/scaffold.js +7 -4
- package/dist/runtime/template-source.js +5 -3
- package/dist/runtime/workspace-project.js +1 -1
- package/package.json +7 -2
- package/templates/_shared/compound/core/scripts/add-compound-child.ts.mustache +318 -18
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Normalize one optional CLI string flag by trimming whitespace and collapsing
|
|
5
|
+
* empty strings to `undefined`.
|
|
6
|
+
*
|
|
7
|
+
* @param value Raw CLI value before normalization.
|
|
8
|
+
* @returns The trimmed string when present, otherwise `undefined`.
|
|
9
|
+
*/
|
|
10
|
+
export function normalizeOptionalCliString(value) {
|
|
11
|
+
if (typeof value !== "string") {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const trimmed = value.trim();
|
|
15
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
16
|
+
}
|
|
17
|
+
function looksLikeLocalCliPath(value) {
|
|
18
|
+
return (path.isAbsolute(value) ||
|
|
19
|
+
value.startsWith("./") ||
|
|
20
|
+
value.startsWith("../") ||
|
|
21
|
+
value.startsWith(".\\") ||
|
|
22
|
+
value.startsWith("..\\"));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve one CLI path flag relative to the caller when it is expressed as a
|
|
26
|
+
* local filesystem path.
|
|
27
|
+
*
|
|
28
|
+
* Non-local values such as npm package specs or `github:` locators pass
|
|
29
|
+
* through unchanged. Local relative and absolute paths are resolved against the
|
|
30
|
+
* provided `cwd` and must exist on disk.
|
|
31
|
+
*
|
|
32
|
+
* @param options Path resolution inputs for one CLI flag.
|
|
33
|
+
* @param options.cwd Caller working directory used for relative path
|
|
34
|
+
* resolution.
|
|
35
|
+
* @param options.label Human-readable option label used in thrown errors.
|
|
36
|
+
* @param options.value Raw CLI value before trimming and path resolution.
|
|
37
|
+
* @returns The normalized string, or `undefined` when the option was omitted.
|
|
38
|
+
* @throws When a local-looking path resolves to a missing filesystem entry.
|
|
39
|
+
*/
|
|
40
|
+
export function resolveLocalCliPathOption(options) {
|
|
41
|
+
const normalizedValue = normalizeOptionalCliString(options.value);
|
|
42
|
+
if (!normalizedValue || !looksLikeLocalCliPath(normalizedValue)) {
|
|
43
|
+
return normalizedValue;
|
|
44
|
+
}
|
|
45
|
+
const resolvedPath = path.resolve(options.cwd, normalizedValue);
|
|
46
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
47
|
+
throw new Error(`\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
|
|
48
|
+
}
|
|
49
|
+
return resolvedPath;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validate the built-in template composition rule for external layers.
|
|
53
|
+
*
|
|
54
|
+
* @param options External layer CLI options after normalization.
|
|
55
|
+
* @param options.externalLayerId Optional selected layer id.
|
|
56
|
+
* @param options.externalLayerSource Optional layer source locator or path.
|
|
57
|
+
* @throws When `externalLayerId` is provided without `externalLayerSource`.
|
|
58
|
+
*/
|
|
59
|
+
export function assertExternalLayerCompositionOptions(options) {
|
|
60
|
+
if (options.externalLayerId && !options.externalLayerSource) {
|
|
61
|
+
throw new Error("externalLayerId requires externalLayerSource when composing built-in template layers.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build the shared error message used when a built-in template receives a
|
|
66
|
+
* `--variant` override.
|
|
67
|
+
*
|
|
68
|
+
* @param options Built-in template context.
|
|
69
|
+
* @param options.templateId Built-in template id that rejected the variant.
|
|
70
|
+
* @param options.variant User-supplied variant override.
|
|
71
|
+
* @returns The canonical user-facing error message.
|
|
72
|
+
*/
|
|
73
|
+
export function createBuiltInVariantErrorMessage(options) {
|
|
74
|
+
return `--variant is only supported for official external template configs. Received variant "${options.variant}" for built-in template "${options.templateId}".`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Reject unsupported `--variant` usage for built-in templates.
|
|
78
|
+
*
|
|
79
|
+
* @param options Built-in template validation context.
|
|
80
|
+
* @param options.templateId Built-in template id being scaffolded.
|
|
81
|
+
* @param options.variant Optional variant override from CLI flags.
|
|
82
|
+
* @throws When a built-in template receives any explicit `--variant` value.
|
|
83
|
+
*/
|
|
84
|
+
export function assertBuiltInTemplateVariantAllowed(options) {
|
|
85
|
+
if (!options.variant) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
throw new Error(createBuiltInVariantErrorMessage({
|
|
89
|
+
templateId: options.templateId,
|
|
90
|
+
variant: options.variant,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable preset ids exposed to scaffold and UI consumers for compound
|
|
3
|
+
* InnerBlocks authoring behavior.
|
|
4
|
+
*/
|
|
5
|
+
export declare const COMPOUND_INNER_BLOCKS_PRESET_IDS: readonly ["freeform", "ordered", "horizontal", "locked-structure"];
|
|
6
|
+
export type CompoundInnerBlocksPresetId = (typeof COMPOUND_INNER_BLOCKS_PRESET_IDS)[number];
|
|
7
|
+
/**
|
|
8
|
+
* Default preset applied when callers do not provide an explicit compound
|
|
9
|
+
* InnerBlocks mode.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID: CompoundInnerBlocksPresetId;
|
|
12
|
+
export type CompoundInnerBlocksOrientation = "horizontal" | "vertical";
|
|
13
|
+
export type CompoundInnerBlocksTemplateLock = false | "insert" | "all";
|
|
14
|
+
/**
|
|
15
|
+
* Runtime-facing description of one compound InnerBlocks preset.
|
|
16
|
+
*/
|
|
17
|
+
export interface CompoundInnerBlocksPresetDefinition {
|
|
18
|
+
description: string;
|
|
19
|
+
directInsert: boolean;
|
|
20
|
+
label: string;
|
|
21
|
+
orientation?: CompoundInnerBlocksOrientation;
|
|
22
|
+
templateLock: CompoundInnerBlocksTemplateLock;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Canonical preset registry used by the CLI, generated scaffolds, and TUI
|
|
26
|
+
* forms.
|
|
27
|
+
*/
|
|
28
|
+
export declare const COMPOUND_INNER_BLOCKS_PRESET_REGISTRY: {
|
|
29
|
+
readonly freeform: {
|
|
30
|
+
readonly description: "Unlocked nested authoring with the default inserter and starter child template.";
|
|
31
|
+
readonly directInsert: false;
|
|
32
|
+
readonly label: "freeform";
|
|
33
|
+
readonly orientation: "vertical";
|
|
34
|
+
readonly templateLock: false;
|
|
35
|
+
};
|
|
36
|
+
readonly ordered: {
|
|
37
|
+
readonly description: "Vertical ordered flow that keeps starter structure fixed while allowing new sibling inserts.";
|
|
38
|
+
readonly directInsert: true;
|
|
39
|
+
readonly label: "ordered";
|
|
40
|
+
readonly orientation: "vertical";
|
|
41
|
+
readonly templateLock: "insert";
|
|
42
|
+
};
|
|
43
|
+
readonly horizontal: {
|
|
44
|
+
readonly description: "Horizontal nested layout with one-click direct inserts for row or tab style containers.";
|
|
45
|
+
readonly directInsert: true;
|
|
46
|
+
readonly label: "horizontal";
|
|
47
|
+
readonly orientation: "horizontal";
|
|
48
|
+
readonly templateLock: false;
|
|
49
|
+
};
|
|
50
|
+
readonly "locked-structure": {
|
|
51
|
+
readonly description: "Locked starter structure for guided document shells where authors should only edit seeded children.";
|
|
52
|
+
readonly directInsert: false;
|
|
53
|
+
readonly label: "locked-structure";
|
|
54
|
+
readonly orientation: "vertical";
|
|
55
|
+
readonly templateLock: "all";
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Returns whether a string matches one of the supported compound preset ids.
|
|
60
|
+
*/
|
|
61
|
+
export declare function isCompoundInnerBlocksPresetId(value: string): value is CompoundInnerBlocksPresetId;
|
|
62
|
+
/**
|
|
63
|
+
* Parses a raw CLI or config value into a supported preset id.
|
|
64
|
+
*
|
|
65
|
+
* Returns `undefined` for non-string or empty input, and throws when the input
|
|
66
|
+
* is a non-empty unsupported preset id.
|
|
67
|
+
*/
|
|
68
|
+
export declare function parseCompoundInnerBlocksPreset(value?: string): CompoundInnerBlocksPresetId | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Resolves an optional preset id to a concrete preset, defaulting to
|
|
71
|
+
* `DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveCompoundInnerBlocksPreset(value?: CompoundInnerBlocksPresetId): CompoundInnerBlocksPresetId;
|
|
74
|
+
/**
|
|
75
|
+
* Looks up the preset definition for the provided preset id, applying the
|
|
76
|
+
* default preset when the input is omitted.
|
|
77
|
+
*/
|
|
78
|
+
export declare function getCompoundInnerBlocksPresetDefinition(value?: CompoundInnerBlocksPresetId): CompoundInnerBlocksPresetDefinition;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable preset ids exposed to scaffold and UI consumers for compound
|
|
3
|
+
* InnerBlocks authoring behavior.
|
|
4
|
+
*/
|
|
5
|
+
export const COMPOUND_INNER_BLOCKS_PRESET_IDS = [
|
|
6
|
+
"freeform",
|
|
7
|
+
"ordered",
|
|
8
|
+
"horizontal",
|
|
9
|
+
"locked-structure",
|
|
10
|
+
];
|
|
11
|
+
/**
|
|
12
|
+
* Default preset applied when callers do not provide an explicit compound
|
|
13
|
+
* InnerBlocks mode.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID = "freeform";
|
|
16
|
+
/**
|
|
17
|
+
* Canonical preset registry used by the CLI, generated scaffolds, and TUI
|
|
18
|
+
* forms.
|
|
19
|
+
*/
|
|
20
|
+
export const COMPOUND_INNER_BLOCKS_PRESET_REGISTRY = {
|
|
21
|
+
freeform: {
|
|
22
|
+
description: "Unlocked nested authoring with the default inserter and starter child template.",
|
|
23
|
+
directInsert: false,
|
|
24
|
+
label: "freeform",
|
|
25
|
+
orientation: "vertical",
|
|
26
|
+
templateLock: false,
|
|
27
|
+
},
|
|
28
|
+
ordered: {
|
|
29
|
+
description: "Vertical ordered flow that keeps starter structure fixed while allowing new sibling inserts.",
|
|
30
|
+
directInsert: true,
|
|
31
|
+
label: "ordered",
|
|
32
|
+
orientation: "vertical",
|
|
33
|
+
templateLock: "insert",
|
|
34
|
+
},
|
|
35
|
+
horizontal: {
|
|
36
|
+
description: "Horizontal nested layout with one-click direct inserts for row or tab style containers.",
|
|
37
|
+
directInsert: true,
|
|
38
|
+
label: "horizontal",
|
|
39
|
+
orientation: "horizontal",
|
|
40
|
+
templateLock: false,
|
|
41
|
+
},
|
|
42
|
+
"locked-structure": {
|
|
43
|
+
description: "Locked starter structure for guided document shells where authors should only edit seeded children.",
|
|
44
|
+
directInsert: false,
|
|
45
|
+
label: "locked-structure",
|
|
46
|
+
orientation: "vertical",
|
|
47
|
+
templateLock: "all",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Returns whether a string matches one of the supported compound preset ids.
|
|
52
|
+
*/
|
|
53
|
+
export function isCompoundInnerBlocksPresetId(value) {
|
|
54
|
+
return COMPOUND_INNER_BLOCKS_PRESET_IDS.includes(value);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parses a raw CLI or config value into a supported preset id.
|
|
58
|
+
*
|
|
59
|
+
* Returns `undefined` for non-string or empty input, and throws when the input
|
|
60
|
+
* is a non-empty unsupported preset id.
|
|
61
|
+
*/
|
|
62
|
+
export function parseCompoundInnerBlocksPreset(value) {
|
|
63
|
+
if (typeof value !== "string") {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const normalizedValue = value.trim();
|
|
67
|
+
if (normalizedValue.length === 0) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
if (!isCompoundInnerBlocksPresetId(normalizedValue)) {
|
|
71
|
+
throw new Error(`Unsupported InnerBlocks preset "${value}". Expected one of: ${COMPOUND_INNER_BLOCKS_PRESET_IDS.join(", ")}.`);
|
|
72
|
+
}
|
|
73
|
+
return normalizedValue;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolves an optional preset id to a concrete preset, defaulting to
|
|
77
|
+
* `DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID`.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveCompoundInnerBlocksPreset(value) {
|
|
80
|
+
return value ?? DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Looks up the preset definition for the provided preset id, applying the
|
|
84
|
+
* default preset when the input is omitted.
|
|
85
|
+
*/
|
|
86
|
+
export function getCompoundInnerBlocksPresetDefinition(value) {
|
|
87
|
+
return COMPOUND_INNER_BLOCKS_PRESET_REGISTRY[resolveCompoundInnerBlocksPreset(value)];
|
|
88
|
+
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* `runAddHookedBlockCommand`,
|
|
11
11
|
* `HOOKED_BLOCK_POSITION_IDS`, and `runDoctor`.
|
|
12
12
|
*/
|
|
13
|
+
export { COMPOUND_INNER_BLOCKS_PRESET_IDS, DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID, getCompoundInnerBlocksPresetDefinition, isCompoundInnerBlocksPresetId, parseCompoundInnerBlocksPreset, resolveCompoundInnerBlocksPreset, } from "./compound-inner-blocks.js";
|
|
14
|
+
export type { CompoundInnerBlocksPresetDefinition, CompoundInnerBlocksPresetId, CompoundInnerBlocksTemplateLock, } from "./compound-inner-blocks.js";
|
|
13
15
|
export { scaffoldProject, collectScaffoldAnswers, getDefaultAnswers, getTemplateVariables, resolvePackageManagerId, resolveTemplateId, } from "./scaffold.js";
|
|
14
16
|
export { BlockGeneratorService } from "./block-generator-service.js";
|
|
15
17
|
export type { ApplyBlockInput, BlockGenerationTarget, BlockSpec, PlanBlockInput, PlanBlockResult, RenderBlockInput, RenderBlockResult, ValidateBlockInput, ValidateBlockResult, } from "./block-generator-service.js";
|
package/dist/runtime/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* `runAddHookedBlockCommand`,
|
|
11
11
|
* `HOOKED_BLOCK_POSITION_IDS`, and `runDoctor`.
|
|
12
12
|
*/
|
|
13
|
+
export { COMPOUND_INNER_BLOCKS_PRESET_IDS, DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID, getCompoundInnerBlocksPresetDefinition, isCompoundInnerBlocksPresetId, parseCompoundInnerBlocksPreset, resolveCompoundInnerBlocksPreset, } from "./compound-inner-blocks.js";
|
|
13
14
|
export { scaffoldProject, collectScaffoldAnswers, getDefaultAnswers, getTemplateVariables, resolvePackageManagerId, resolveTemplateId, } from "./scaffold.js";
|
|
14
15
|
export { BlockGeneratorService } from "./block-generator-service.js";
|
|
15
16
|
export { BLOCK_GENERATION_TOOL_CONTRACT_VERSION, inspectBlockGeneration, } from "./block-generator-tool-contract.js";
|
|
@@ -19,6 +19,8 @@ export function formatMigrationHelpText() {
|
|
|
19
19
|
|
|
20
20
|
Notes:
|
|
21
21
|
\`migrate init\` auto-detects supported single-block and \`src/blocks/*\` multi-block layouts.
|
|
22
|
+
\`migrate init\` only retrofits migration support into projects that already match those layouts.
|
|
23
|
+
A broader project-level \`wp-typia init\` path remains future work.
|
|
22
24
|
Migration versions use strict schema labels like \`v1\`, \`v2\`, and \`v3\`.
|
|
23
25
|
\`migrate wizard\` is TTY-only and helps you choose one legacy migration version to preview.
|
|
24
26
|
\`migrate plan\` and \`migrate wizard\` are read-only previews; they do not scaffold rules or fixtures.
|
|
@@ -4,6 +4,7 @@ interface PackageVersions {
|
|
|
4
4
|
blockTypesPackageVersion: string;
|
|
5
5
|
projectToolsPackageVersion: string;
|
|
6
6
|
restPackageVersion: string;
|
|
7
|
+
wpTypiaPackageExactVersion: string;
|
|
7
8
|
wpTypiaPackageVersion: string;
|
|
8
9
|
}
|
|
9
10
|
export declare function getPackageVersions(): PackageVersions;
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { PROJECT_TOOLS_PACKAGE_ROOT } from "./template-registry.js";
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
6
|
const DEFAULT_VERSION_RANGE = "^0.0.0";
|
|
7
|
+
const DEFAULT_EXACT_VERSION = "0.0.0";
|
|
7
8
|
let cachedPackageVersions = null;
|
|
8
9
|
function getErrorCode(error) {
|
|
9
10
|
return typeof error === "object" && error !== null && "code" in error
|
|
@@ -20,6 +21,16 @@ function normalizeVersionRange(value) {
|
|
|
20
21
|
}
|
|
21
22
|
return /^[~^<>=]/.test(trimmed) ? trimmed : `^${trimmed}`;
|
|
22
23
|
}
|
|
24
|
+
function normalizeExactVersion(value) {
|
|
25
|
+
const trimmed = value?.trim();
|
|
26
|
+
if (!trimmed) {
|
|
27
|
+
return DEFAULT_EXACT_VERSION;
|
|
28
|
+
}
|
|
29
|
+
if (trimmed.startsWith("workspace:")) {
|
|
30
|
+
return DEFAULT_EXACT_VERSION;
|
|
31
|
+
}
|
|
32
|
+
return trimmed.replace(/^[~^<>=]+/, "");
|
|
33
|
+
}
|
|
23
34
|
function readPackageManifest(packageJsonPath) {
|
|
24
35
|
try {
|
|
25
36
|
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -67,6 +78,7 @@ export function getPackageVersions() {
|
|
|
67
78
|
projectToolsPackageVersion: normalizeVersionRange(createManifest.version),
|
|
68
79
|
restPackageVersion: normalizeVersionRange(createManifest.dependencies?.["@wp-typia/rest"] ??
|
|
69
80
|
resolveInstalledPackageManifest("@wp-typia/rest")?.version),
|
|
81
|
+
wpTypiaPackageExactVersion: normalizeExactVersion(wpTypiaManifest.version),
|
|
70
82
|
wpTypiaPackageVersion: normalizeVersionRange(wpTypiaManifest.version),
|
|
71
83
|
};
|
|
72
84
|
return cachedPackageVersions;
|
|
@@ -10,6 +10,7 @@ const TEMPLATE_SELECTION_HINT = `--template <${[
|
|
|
10
10
|
WORKSPACE_TEMPLATE_ALIAS,
|
|
11
11
|
].join('|')}|./path|github:owner/repo/path[#ref]|npm-package>`;
|
|
12
12
|
const TEMPLATE_SUGGESTION_IDS = [...TEMPLATE_IDS, WORKSPACE_TEMPLATE_ALIAS];
|
|
13
|
+
const QUERY_POST_TYPE_RULE = 'Use lowercase, 1-20 chars, and only a-z, 0-9, "_" or "-".';
|
|
13
14
|
/**
|
|
14
15
|
* Detect the current author name from local Git config.
|
|
15
16
|
*
|
|
@@ -50,12 +51,15 @@ export function getDefaultAnswers(projectName, templateId) {
|
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
function validateQueryPostType(value) {
|
|
53
|
-
const
|
|
54
|
+
const rawValue = value.trim();
|
|
55
|
+
const normalizedValue = rawValue.toLowerCase();
|
|
54
56
|
if (normalizedValue.length === 0) {
|
|
55
57
|
return 'Query post type is required.';
|
|
56
58
|
}
|
|
57
59
|
if (!/^[a-z0-9_-]{1,20}$/u.test(normalizedValue)) {
|
|
58
|
-
return
|
|
60
|
+
return rawValue === normalizedValue
|
|
61
|
+
? `Query post type "${rawValue}" is invalid. ${QUERY_POST_TYPE_RULE}`
|
|
62
|
+
: `Query post type "${rawValue}" normalizes to "${normalizedValue}", which is invalid. ${QUERY_POST_TYPE_RULE}`;
|
|
59
63
|
}
|
|
60
64
|
return true;
|
|
61
65
|
}
|
|
@@ -63,11 +67,11 @@ function normalizeQueryPostType(value) {
|
|
|
63
67
|
if (typeof value !== 'string') {
|
|
64
68
|
return undefined;
|
|
65
69
|
}
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
throw new Error(
|
|
70
|
+
const validationResult = validateQueryPostType(value);
|
|
71
|
+
if (validationResult !== true) {
|
|
72
|
+
throw new Error(validationResult);
|
|
69
73
|
}
|
|
70
|
-
return
|
|
74
|
+
return value.trim().toLowerCase();
|
|
71
75
|
}
|
|
72
76
|
function normalizeTemplateSelection(templateId) {
|
|
73
77
|
return templateId === WORKSPACE_TEMPLATE_ALIAS
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getPrimaryDevelopmentScript } from './local-dev-presets.js';
|
|
2
2
|
import { getCompoundExtensionWorkflowSection, getInitialCommitCommands, getInitialCommitNote, getOptionalOnboardingNote, getOptionalOnboardingSteps, getQuickStartWorkflowNote, getPhpRestExtensionPointsSection, getTemplateSourceOfTruthNote, } from './scaffold-onboarding.js';
|
|
3
|
-
import { formatInstallCommand, formatRunScript, } from './package-managers.js';
|
|
3
|
+
import { formatPackageExecCommand, formatInstallCommand, formatRunScript, } from './package-managers.js';
|
|
4
|
+
import { getPackageVersions } from './package-versions.js';
|
|
4
5
|
/**
|
|
5
6
|
* Builds the generated README markdown for one scaffolded project.
|
|
6
7
|
*
|
|
@@ -22,7 +23,25 @@ export function buildReadme(templateId, variables, packageManager, { withMigrati
|
|
|
22
23
|
const publicPersistencePolicyNote = variables.isPublicPersistencePolicy === 'true'
|
|
23
24
|
? 'Public persistence writes use signed short-lived tokens, per-request ids, and coarse rate limiting by default. Add application-specific abuse controls before using the same pattern for high-value metrics or experiments.'
|
|
24
25
|
: null;
|
|
26
|
+
const alternateRenderTargetSection = variables.hasAlternateRenderTargets === 'true'
|
|
27
|
+
? `## Alternate Render Targets\n\nThis scaffold keeps \`${templateId === 'compound' ? `src/blocks/${variables.slugKebabCase}/render.php` : 'src/render.php'}\` as the default web render boundary and also generates ${[
|
|
28
|
+
variables.hasAlternateEmailRenderTarget === 'true'
|
|
29
|
+
? `\`${templateId === 'compound' ? `src/blocks/${variables.slugKebabCase}/render-email.php` : 'src/render-email.php'}\``
|
|
30
|
+
: null,
|
|
31
|
+
variables.hasAlternateMjmlRenderTarget === 'true'
|
|
32
|
+
? `\`${templateId === 'compound' ? `src/blocks/${variables.slugKebabCase}/render-mjml.php` : 'src/render-mjml.php'}\``
|
|
33
|
+
: null,
|
|
34
|
+
variables.hasAlternatePlainTextRenderTarget === 'true'
|
|
35
|
+
? `\`${templateId === 'compound' ? `src/blocks/${variables.slugKebabCase}/render-text.php` : 'src/render-text.php'}\``
|
|
36
|
+
: null,
|
|
37
|
+
]
|
|
38
|
+
.filter((value) => Boolean(value))
|
|
39
|
+
.join(', ')}. All of those entries delegate through \`${templateId === 'compound' ? `src/blocks/${variables.slugKebabCase}/render-targets.php` : 'src/render-targets.php'}\`, so attribute normalization, validation, and render-target adapter hooks stay aligned across web, email, MJML, and plain-text integrations.`
|
|
40
|
+
: '';
|
|
25
41
|
const compoundExtensionWorkflowSection = getCompoundExtensionWorkflowSection(packageManager, templateId);
|
|
42
|
+
const compoundInnerBlocksSection = templateId === 'compound'
|
|
43
|
+
? `## Compound InnerBlocks Presets\n\nThis scaffold starts with the \`${variables.compoundInnerBlocksPreset}\` preset for compound container authoring. Static nested relationships still belong in each generated \`block.json\` via \`allowedBlocks\`, \`parent\`, and \`ancestor\`, while \`src/blocks/${variables.slugKebabCase}/children.ts\` owns editor-only \`InnerBlocks\` behavior such as \`orientation\`, \`templateLock\`, \`defaultBlock\`, and \`directInsert\`.\n\n- \`freeform\`: unlocked inserter flow with the starter child template.\n- \`ordered\`: vertical ordered flow with \`templateLock="insert"\` and direct inserts.\n- \`horizontal\`: row-like nested authoring with direct inserts.\n- \`locked-structure\`: fully locked starter structure.\n\nWhen you need to change that authoring behavior later, update the preset helpers in \`src/blocks/${variables.slugKebabCase}/children.ts\` and keep fixed child constraints metadata-owned instead of duplicating them in editor props. If you need tighter wrapper ownership or sibling markup control, switch the generated edit components to \`useInnerBlocksProps\` and reuse \`getRootInnerBlocksPropsOptions()\` / \`getChildInnerBlocksPropsOptions( metadata.name )\` so the same preset behavior carries forward without rebuilding the option set by hand.`
|
|
44
|
+
: '';
|
|
26
45
|
const phpRestExtensionPointsSection = getPhpRestExtensionPointsSection(templateId, {
|
|
27
46
|
compoundPersistenceEnabled,
|
|
28
47
|
slug: variables.slug,
|
|
@@ -69,6 +88,7 @@ ${getQuickStartWorkflowNote(packageManager, templateId, {
|
|
|
69
88
|
\`\`\`bash
|
|
70
89
|
${formatRunScript(packageManager, 'build')}
|
|
71
90
|
${formatRunScript(packageManager, 'typecheck')}
|
|
91
|
+
${formatPackageExecCommand(packageManager, `wp-typia@${getPackageVersions().wpTypiaPackageExactVersion}`, 'doctor')}
|
|
72
92
|
\`\`\`
|
|
73
93
|
|
|
74
94
|
${advancedSyncSection}
|
|
@@ -81,7 +101,7 @@ ${initialCommitCommands.join('\n')}
|
|
|
81
101
|
|
|
82
102
|
${getInitialCommitNote()}
|
|
83
103
|
|
|
84
|
-
${sourceOfTruthNote}${publicPersistencePolicyNote ? `\n\n${publicPersistencePolicyNote}` : ''}${migrationSection ? `\n\n${migrationSection}` : ''}${compoundExtensionWorkflowSection ? `\n\n${compoundExtensionWorkflowSection}` : ''}${wpEnvSection ? `\n\n${wpEnvSection}` : ''}${testPresetSection ? `\n\n${testPresetSection}` : ''}${phpRestExtensionPointsSection ? `\n\n${phpRestExtensionPointsSection}` : ''}
|
|
104
|
+
${sourceOfTruthNote}${publicPersistencePolicyNote ? `\n\n${publicPersistencePolicyNote}` : ''}${alternateRenderTargetSection ? `\n\n${alternateRenderTargetSection}` : ''}${compoundInnerBlocksSection ? `\n\n${compoundInnerBlocksSection}` : ''}${migrationSection ? `\n\n${migrationSection}` : ''}${compoundExtensionWorkflowSection ? `\n\n${compoundExtensionWorkflowSection}` : ''}${wpEnvSection ? `\n\n${wpEnvSection}` : ''}${testPresetSection ? `\n\n${testPresetSection}` : ''}${phpRestExtensionPointsSection ? `\n\n${phpRestExtensionPointsSection}` : ''}
|
|
85
105
|
`;
|
|
86
106
|
}
|
|
87
107
|
/**
|
|
@@ -10,6 +10,23 @@ export declare function validateTextDomain(input: string): true | string;
|
|
|
10
10
|
export declare function validatePhpPrefix(input: string): true | string;
|
|
11
11
|
export declare function assertValidIdentifier(label: string, value: string, validate: (value: string) => true | string): string;
|
|
12
12
|
export declare function normalizeBlockSlug(input: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Normalize one human-entered block slug and reject values that collapse to an
|
|
15
|
+
* empty generated slug.
|
|
16
|
+
*
|
|
17
|
+
* @param options Normalization context for one block-like name.
|
|
18
|
+
* @param options.input Raw user input before kebab-case normalization.
|
|
19
|
+
* @param options.label Human-readable field label used in thrown errors.
|
|
20
|
+
* @param options.usage Example CLI usage shown when the input is blank.
|
|
21
|
+
* @returns A non-empty normalized slug.
|
|
22
|
+
* @throws When the input is blank after trimming.
|
|
23
|
+
* @throws When normalization removes every character from the original input.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveNonEmptyNormalizedBlockSlug(options: {
|
|
26
|
+
input: string;
|
|
27
|
+
label: string;
|
|
28
|
+
usage: string;
|
|
29
|
+
}): string;
|
|
13
30
|
export declare function resolveValidatedBlockSlug(value: string): string;
|
|
14
31
|
export declare function resolveValidatedNamespace(value: string): string;
|
|
15
32
|
export declare function resolveValidatedTextDomain(value: string): string;
|
|
@@ -34,6 +34,28 @@ export function assertValidIdentifier(label, value, validate) {
|
|
|
34
34
|
export function normalizeBlockSlug(input) {
|
|
35
35
|
return toKebabCase(input);
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Normalize one human-entered block slug and reject values that collapse to an
|
|
39
|
+
* empty generated slug.
|
|
40
|
+
*
|
|
41
|
+
* @param options Normalization context for one block-like name.
|
|
42
|
+
* @param options.input Raw user input before kebab-case normalization.
|
|
43
|
+
* @param options.label Human-readable field label used in thrown errors.
|
|
44
|
+
* @param options.usage Example CLI usage shown when the input is blank.
|
|
45
|
+
* @returns A non-empty normalized slug.
|
|
46
|
+
* @throws When the input is blank after trimming.
|
|
47
|
+
* @throws When normalization removes every character from the original input.
|
|
48
|
+
*/
|
|
49
|
+
export function resolveNonEmptyNormalizedBlockSlug(options) {
|
|
50
|
+
const normalizedSlug = normalizeBlockSlug(options.input);
|
|
51
|
+
if (normalizedSlug.length > 0) {
|
|
52
|
+
return normalizedSlug;
|
|
53
|
+
}
|
|
54
|
+
if (options.input.trim().length === 0) {
|
|
55
|
+
throw new Error(`${options.label} is required. Use \`${options.usage}\`.`);
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`${options.label} "${options.input.trim()}" normalizes to an empty slug. Use letters or numbers so wp-typia can generate a block slug.`);
|
|
58
|
+
}
|
|
37
59
|
export function resolveValidatedBlockSlug(value) {
|
|
38
60
|
return assertValidIdentifier("Block slug", normalizeBlockSlug(value), validateBlockSlug);
|
|
39
61
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { formatRunScript } from "./package-managers.js";
|
|
1
|
+
import { formatPackageExecCommand, formatRunScript, } from "./package-managers.js";
|
|
2
|
+
import { getPackageVersions } from "./package-versions.js";
|
|
2
3
|
import { getPrimaryDevelopmentScript } from "./local-dev-presets.js";
|
|
3
4
|
import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, isBuiltInTemplateId, } from "./template-registry.js";
|
|
4
5
|
const INITIAL_COMMIT_COMMANDS = [
|
|
@@ -6,6 +7,9 @@ const INITIAL_COMMIT_COMMANDS = [
|
|
|
6
7
|
"git add .",
|
|
7
8
|
'git commit -m "Initial scaffold"',
|
|
8
9
|
];
|
|
10
|
+
function getDoctorVerificationCommand(packageManager) {
|
|
11
|
+
return formatPackageExecCommand(packageManager, `wp-typia@${getPackageVersions().wpTypiaPackageExactVersion}`, "doctor");
|
|
12
|
+
}
|
|
9
13
|
function templateHasPersistenceSync(templateId, { compoundPersistenceEnabled = false } = {}) {
|
|
10
14
|
return templateId === "persistence" || (templateId === "compound" && compoundPersistenceEnabled);
|
|
11
15
|
}
|
|
@@ -40,29 +44,31 @@ export function getOptionalOnboardingSteps(packageManager, templateId, options =
|
|
|
40
44
|
* Returns the quick-start note explaining the scaffold's primary local loop.
|
|
41
45
|
*/
|
|
42
46
|
export function getQuickStartWorkflowNote(packageManager, templateId = "basic", options = {}) {
|
|
47
|
+
const doctorCommand = getDoctorVerificationCommand(packageManager);
|
|
43
48
|
if (templateId === "query-loop") {
|
|
44
|
-
return `${formatRunScript(packageManager, "dev")} runs the editor build/watch loop that registers your Query Loop variation in the block editor. This scaffold
|
|
49
|
+
return `${formatRunScript(packageManager, "dev")} runs the editor build/watch loop that registers your Query Loop variation in the block editor. This scaffold intentionally skips \`src/types.ts\`, \`block.json\`, and Typia manifests because the source of truth lives in the variation registration flow. Update \`src/index.ts\` for variation defaults, \`src/patterns/*.php\` for richer connected layouts, \`src/query-extension.ts\` for custom query params, and \`inc/query-runtime.php\` for frontend/editor preview parity. Use ${doctorCommand} when you want a quick environment and workspace sanity check.`;
|
|
45
50
|
}
|
|
46
51
|
const developmentScript = getPrimaryDevelopmentScript(templateId);
|
|
47
52
|
const devCommand = formatRunScript(packageManager, developmentScript);
|
|
48
53
|
const startCommand = formatRunScript(packageManager, "start");
|
|
49
54
|
if (developmentScript === "start") {
|
|
50
|
-
return `${startCommand} is the primary local entry point for this template.
|
|
55
|
+
return `${startCommand} is the primary local entry point for this template. Use ${doctorCommand} when you want a quick environment and workspace sanity check before build or commit.`;
|
|
51
56
|
}
|
|
52
57
|
if (developmentScript !== "dev") {
|
|
53
|
-
return `${devCommand} is the primary local entry point for this template. Use ${startCommand}
|
|
58
|
+
return `${devCommand} is the primary local entry point for this template. Use ${startCommand} for the one-shot startup flow, and ${doctorCommand} when you want a quick verification pass before build or commit.`;
|
|
54
59
|
}
|
|
55
60
|
if (templateHasPersistenceSync(templateId, options)) {
|
|
56
|
-
return `${devCommand} keeps the editor, type-derived artifacts, and REST-derived artifacts moving together during local development. Use ${startCommand}
|
|
61
|
+
return `${devCommand} keeps the editor, type-derived artifacts, and REST-derived artifacts moving together during local development. Use ${startCommand} for a one-shot sync plus editor startup, and ${doctorCommand} when you want an explicit verification pass before build or commit.`;
|
|
57
62
|
}
|
|
58
|
-
return `${devCommand} keeps the editor and type-derived artifacts moving together during local development. Use ${startCommand}
|
|
63
|
+
return `${devCommand} keeps the editor and type-derived artifacts moving together during local development. Use ${startCommand} for a one-shot sync plus editor startup, and ${doctorCommand} when you want an explicit verification pass before build or commit.`;
|
|
59
64
|
}
|
|
60
65
|
/**
|
|
61
66
|
* Returns the onboarding note explaining when manual sync is optional.
|
|
62
67
|
*/
|
|
63
68
|
export function getOptionalOnboardingNote(packageManager, templateId = "basic", options = {}) {
|
|
69
|
+
const doctorCommand = getDoctorVerificationCommand(packageManager);
|
|
64
70
|
if (templateId === "query-loop") {
|
|
65
|
-
return `This scaffold does not generate a \`sync\` script, \`block.json\`, or Typia manifests. Edit \`src/index.ts
|
|
71
|
+
return `This scaffold owns a \`core/query\` variation, so it does not generate a \`sync\` script, \`src/types.ts\`, \`block.json\`, or Typia manifests. Edit \`src/index.ts\`, \`src/patterns/*.php\`, \`src/query-extension.ts\`, and \`inc/query-runtime.php\` as needed, then rerun ${formatRunScript(packageManager, "build")}, ${formatRunScript(packageManager, "typecheck")}, or ${doctorCommand}.`;
|
|
66
72
|
}
|
|
67
73
|
const optionalSyncScripts = getOptionalSyncScriptNames(templateId, options);
|
|
68
74
|
const hasUnifiedSync = optionalSyncScripts.includes("sync");
|
|
@@ -76,7 +82,7 @@ export function getOptionalOnboardingNote(packageManager, templateId = "basic",
|
|
|
76
82
|
const typecheckCommand = formatRunScript(packageManager, "typecheck");
|
|
77
83
|
const strictSyncCommand = formatRunScript(packageManager, "sync-types", "--strict --report json");
|
|
78
84
|
const advancedPersistenceNote = templateHasPersistenceSync(templateId, options)
|
|
79
|
-
? ` ${syncRestCommand} remains available for
|
|
85
|
+
? ` ${syncRestCommand} remains available for REST-only refreshes after ${syncTypesCommand}.`
|
|
80
86
|
: "";
|
|
81
87
|
const isCustomTemplate = !isBuiltInTemplateId(templateId) &&
|
|
82
88
|
templateId !== OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE;
|
|
@@ -86,12 +92,12 @@ export function getOptionalOnboardingNote(packageManager, templateId = "basic",
|
|
|
86
92
|
? `Run ${syncSteps.join(" then ")} manually before build, typecheck, or commit. ${syncCheckCommand} verifies the current type-derived artifacts without rewriting them.${optionalSyncScripts.includes("sync-rest") ? ` ${syncRestCommand} remains available for REST-only refreshes after ${syncTypesCommand}.` : ""}`
|
|
87
93
|
: null;
|
|
88
94
|
if (fallbackCustomTemplateNote) {
|
|
89
|
-
return fallbackCustomTemplateNote
|
|
95
|
+
return `${fallbackCustomTemplateNote} Use ${doctorCommand} when you want a quick environment and workspace sanity check.`;
|
|
90
96
|
}
|
|
91
97
|
if (isCustomTemplate && syncSteps.length === 0) {
|
|
92
|
-
return
|
|
98
|
+
return `No optional sync command was detected for this custom template. Use ${doctorCommand} for a quick environment and workspace sanity check, then follow the template's own artifact-refresh guidance before build, typecheck, or your first commit.`;
|
|
93
99
|
}
|
|
94
|
-
return `You usually do not need to run ${syncCommand} during a normal ${formatRunScript(packageManager, developmentScript)} session. Run ${syncCommand}
|
|
100
|
+
return `You usually do not need to run ${syncCommand} during a normal ${formatRunScript(packageManager, developmentScript)} session. Run ${syncCommand} before ${formatRunScript(packageManager, "build")}, ${typecheckCommand}, or ${doctorCommand} when you want a reviewable refresh. ${syncTypesCommand} stays warn-only by default; use \`${failOnLossySyncCommand}\` or \`${strictSyncCommand}\` for stricter CI checks.${advancedPersistenceNote} Generated syncs do not create migration history, so refresh before your first commit if this directory is new.`;
|
|
95
101
|
}
|
|
96
102
|
/**
|
|
97
103
|
* Returns the recommended version-control commands for a fresh scaffold.
|
|
@@ -110,7 +116,7 @@ export function getInitialCommitNote() {
|
|
|
110
116
|
*/
|
|
111
117
|
export function getTemplateSourceOfTruthNote(templateId, { compoundPersistenceEnabled = false } = {}) {
|
|
112
118
|
if (templateId === "query-loop") {
|
|
113
|
-
return "`src/index.ts` remains the source of truth for the Query Loop variation name, default query attributes, `allowedControls`, and the minimal inline starter `innerBlocks`. Use `src/patterns/*.php` for richer connected layout presets that stay tied to the same variation namespace, use `src/query-extension.ts` for custom query seed values or optional editor-only hook registration, and use `inc/query-runtime.php` to keep frontend and editor preview query mapping aligned for those custom keys. The generated plugin bootstrap should stay focused on script registration, pattern loading, and explicit runtime glue for the variation.";
|
|
119
|
+
return "`src/index.ts` remains the source of truth for the Query Loop variation name, default query attributes, `allowedControls`, and the minimal inline starter `innerBlocks`. This scaffold intentionally does not generate `src/types.ts`, `block.json`, or Typia manifests because those artifacts belong to standalone block families, not `core/query` variation ownership. Use `src/patterns/*.php` for richer connected layout presets that stay tied to the same variation namespace, use `src/query-extension.ts` for custom query seed values or optional editor-only hook registration, and use `inc/query-runtime.php` to keep frontend and editor preview query mapping aligned for those custom keys. The generated plugin bootstrap should stay focused on script registration, pattern loading, and explicit runtime glue for the variation.";
|
|
114
120
|
}
|
|
115
121
|
if (templateId === "compound") {
|
|
116
122
|
const compoundBase = "`src/blocks/*/types.ts` files remain the source of truth for each block's `block.json`, `typia.manifest.json`, and `typia-validator.php`. Fresh scaffolds include starter `typia.manifest.json` files so editor imports resolve before the first sync.";
|
|
@@ -138,10 +144,12 @@ ${formatRunScript(packageManager, "add-child", '--slug faq-item --title "FAQ Ite
|
|
|
138
144
|
|
|
139
145
|
${formatRunScript(packageManager, "add-child", '--slug section --title "Section" --container --inserter visible')}
|
|
140
146
|
|
|
147
|
+
${formatRunScript(packageManager, "add-child", '--slug clause --title "Clause" --ancestor section --dry-run')}
|
|
148
|
+
|
|
141
149
|
${formatRunScript(packageManager, "add-child", '--slug clause --title "Clause" --ancestor section')}
|
|
142
150
|
\`\`\`
|
|
143
151
|
|
|
144
|
-
This scaffolds additional compound child block types, updates \`scripts/block-config.ts\` and \`src/blocks/*/children.ts\`, and now supports root-level hidden children, visible container children, and nested ancestor chains for richer document-style block hierarchies.`;
|
|
152
|
+
This scaffolds additional compound child block types, updates \`scripts/block-config.ts\` and \`src/blocks/*/children.ts\`, and now supports root-level hidden children, visible container children, and nested ancestor chains for richer document-style block hierarchies. Pass \`--dry-run\` when you want a validated child-graph preview and planned write list before the script mutates files.`;
|
|
145
153
|
}
|
|
146
154
|
function formatPhpRestExtensionPointsSection({ apiTypesPath, extraNote, mainPhpPath, mainPhpScope, transportPath, }) {
|
|
147
155
|
const schemaJsonGlob = apiTypesPath.replace(/api-types\.ts$/u, "api-schemas/*.schema.json");
|
|
@@ -2,6 +2,7 @@ import { buildTemplateVariablesFromBlockSpec, createBuiltInBlockSpec, } from './
|
|
|
2
2
|
import { getPackageVersions } from './package-versions.js';
|
|
3
3
|
import { buildBlockCssClassName, buildFrontendCssClassName, resolveScaffoldIdentifiers, } from './scaffold-identifiers.js';
|
|
4
4
|
import { BUILTIN_BLOCK_METADATA_VERSION, COMPOUND_CHILD_BLOCK_METADATA_DEFAULTS, getBuiltInTemplateMetadataDefaults, } from './template-defaults.js';
|
|
5
|
+
import { DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID, getCompoundInnerBlocksPresetDefinition, } from './compound-inner-blocks.js';
|
|
5
6
|
import { getTemplateById, isBuiltInTemplateId, } from './template-registry.js';
|
|
6
7
|
import { toPascalCase, toSnakeCase, } from './string-case.js';
|
|
7
8
|
/**
|
|
@@ -43,6 +44,8 @@ export function getTemplateVariables(templateId, answers) {
|
|
|
43
44
|
const compoundChildTitle = `${title} Item`;
|
|
44
45
|
const cssClassName = buildBlockCssClassName(namespace, slug);
|
|
45
46
|
const compoundChildCssClassName = buildBlockCssClassName(namespace, `${slug}-item`);
|
|
47
|
+
const compoundInnerBlocksPreset = answers.compoundInnerBlocksPreset ?? DEFAULT_COMPOUND_INNER_BLOCKS_PRESET_ID;
|
|
48
|
+
const compoundInnerBlocksPresetDefinition = getCompoundInnerBlocksPresetDefinition(compoundInnerBlocksPreset);
|
|
46
49
|
const compoundPersistenceEnabled = templateId === 'persistence'
|
|
47
50
|
? true
|
|
48
51
|
: templateId === 'compound'
|
|
@@ -55,6 +58,8 @@ export function getTemplateVariables(templateId, answers) {
|
|
|
55
58
|
? answers.persistencePolicy ?? 'authenticated'
|
|
56
59
|
: 'authenticated';
|
|
57
60
|
return {
|
|
61
|
+
alternateRenderTargetsCsv: '',
|
|
62
|
+
alternateRenderTargetsJson: '[]',
|
|
58
63
|
apiClientPackageVersion,
|
|
59
64
|
author: answers.author.trim(),
|
|
60
65
|
blockRuntimePackageVersion,
|
|
@@ -68,6 +73,23 @@ export function getTemplateVariables(templateId, answers) {
|
|
|
68
73
|
compoundChildIcon: COMPOUND_CHILD_BLOCK_METADATA_DEFAULTS.icon,
|
|
69
74
|
compoundChildTitleJson: JSON.stringify(compoundChildTitle),
|
|
70
75
|
compoundPersistenceEnabled: compoundPersistenceEnabled ? 'true' : 'false',
|
|
76
|
+
compoundInnerBlocksDirectInsert: compoundInnerBlocksPresetDefinition.directInsert
|
|
77
|
+
? 'true'
|
|
78
|
+
: 'false',
|
|
79
|
+
compoundInnerBlocksOrientation: compoundInnerBlocksPresetDefinition.orientation ?? '',
|
|
80
|
+
compoundInnerBlocksOrientationExpression: compoundInnerBlocksPresetDefinition.orientation
|
|
81
|
+
? `'${compoundInnerBlocksPresetDefinition.orientation}'`
|
|
82
|
+
: 'undefined',
|
|
83
|
+
compoundInnerBlocksPreset,
|
|
84
|
+
compoundInnerBlocksPresetDescription: compoundInnerBlocksPresetDefinition.description,
|
|
85
|
+
compoundInnerBlocksPresetLabel: compoundInnerBlocksPresetDefinition.label,
|
|
86
|
+
compoundInnerBlocksTemplateLockExpression: compoundInnerBlocksPresetDefinition.templateLock === false
|
|
87
|
+
? 'false'
|
|
88
|
+
: `'${compoundInnerBlocksPresetDefinition.templateLock}'`,
|
|
89
|
+
hasAlternateEmailRenderTarget: 'false',
|
|
90
|
+
hasAlternateMjmlRenderTarget: 'false',
|
|
91
|
+
hasAlternatePlainTextRenderTarget: 'false',
|
|
92
|
+
hasAlternateRenderTargets: 'false',
|
|
71
93
|
projectToolsPackageVersion,
|
|
72
94
|
cssClassName,
|
|
73
95
|
dataStorageMode,
|