@wp-typia/project-tools 0.16.13 → 0.17.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/README.md +0 -1
- package/dist/runtime/block-generator-service-spec.d.ts +6 -0
- package/dist/runtime/block-generator-service-spec.js +27 -0
- package/dist/runtime/built-in-block-code-artifacts.js +14 -1
- package/dist/runtime/built-in-block-code-templates/query-loop.d.ts +1 -0
- package/dist/runtime/built-in-block-code-templates/query-loop.js +70 -0
- package/dist/runtime/built-in-block-code-templates.d.ts +1 -0
- package/dist/runtime/built-in-block-code-templates.js +1 -0
- package/dist/runtime/built-in-block-non-ts-artifacts.js +2 -0
- package/dist/runtime/cli-help.js +1 -0
- package/dist/runtime/cli-prompt.js +78 -19
- package/dist/runtime/cli-scaffold.d.ts +2 -1
- package/dist/runtime/cli-scaffold.js +2 -1
- package/dist/runtime/local-dev-presets.js +21 -11
- package/dist/runtime/scaffold-answer-resolution.d.ts +37 -0
- package/dist/runtime/scaffold-answer-resolution.js +163 -0
- package/dist/runtime/scaffold-apply-utils.d.ts +1 -16
- package/dist/runtime/scaffold-apply-utils.js +4 -128
- package/dist/runtime/scaffold-documents.d.ts +34 -0
- package/dist/runtime/scaffold-documents.js +143 -0
- package/dist/runtime/scaffold-onboarding.js +12 -0
- package/dist/runtime/scaffold-template-variables.d.ts +9 -0
- package/dist/runtime/scaffold-template-variables.js +117 -0
- package/dist/runtime/scaffold.d.ts +19 -9
- package/dist/runtime/scaffold.js +6 -202
- package/dist/runtime/template-defaults.d.ts +7 -0
- package/dist/runtime/template-defaults.js +4 -0
- package/dist/runtime/template-registry.d.ts +1 -1
- package/dist/runtime/template-registry.js +14 -1
- package/package.json +3 -3
- package/templates/query-loop/inc/query-runtime.php.mustache +85 -0
- package/templates/query-loop/package.json.mustache +32 -0
- package/templates/query-loop/src/patterns/grid.php.mustache +49 -0
- package/templates/query-loop/src/patterns/list.php.mustache +48 -0
- package/templates/query-loop/src/query-extension.ts.mustache +41 -0
- package/templates/query-loop/src/validator-toolkit.ts.mustache +1 -0
- package/templates/query-loop/webpack.config.js.mustache +16 -0
- package/templates/query-loop/{{slugKebabCase}}.php.mustache +84 -0
package/README.md
CHANGED
|
@@ -12,7 +12,6 @@ Package roles:
|
|
|
12
12
|
templates no longer ship structural, TS/TSX, style, or block-local `render.php`
|
|
13
13
|
Mustache files.
|
|
14
14
|
- `@wp-typia/block-runtime/*` owns generated-project runtime helpers.
|
|
15
|
-
- `@wp-typia/create` is the deprecated legacy package shell.
|
|
16
15
|
|
|
17
16
|
Supported public imports:
|
|
18
17
|
|
|
@@ -27,6 +27,11 @@ export interface BlockSpec {
|
|
|
27
27
|
project: {
|
|
28
28
|
author: string;
|
|
29
29
|
};
|
|
30
|
+
queryLoop: {
|
|
31
|
+
allowedControls: readonly string[];
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
postType: string;
|
|
34
|
+
};
|
|
30
35
|
runtime: {
|
|
31
36
|
withMigrationUi: boolean;
|
|
32
37
|
withTestPreset: boolean;
|
|
@@ -66,6 +71,7 @@ export interface PlanBlockInput {
|
|
|
66
71
|
templateId: BuiltInTemplateId;
|
|
67
72
|
variant?: string;
|
|
68
73
|
withMigrationUi?: boolean;
|
|
74
|
+
queryPostType?: string;
|
|
69
75
|
withTestPreset?: boolean;
|
|
70
76
|
withWpEnv?: boolean;
|
|
71
77
|
}
|
|
@@ -24,6 +24,15 @@ function getBuiltInPersistenceSpec({ templateId, dataStorageMode, persistencePol
|
|
|
24
24
|
enabled: false,
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
const DEFAULT_QUERY_LOOP_ALLOWED_CONTROLS = [
|
|
28
|
+
"inherit",
|
|
29
|
+
"postType",
|
|
30
|
+
"order",
|
|
31
|
+
"sticky",
|
|
32
|
+
"taxQuery",
|
|
33
|
+
"author",
|
|
34
|
+
"search",
|
|
35
|
+
];
|
|
27
36
|
export function createBuiltInBlockSpec({ answers, dataStorageMode, persistencePolicy, templateId, withMigrationUi = false, withTestPreset = false, withWpEnv = false, }) {
|
|
28
37
|
const template = getTemplateById(templateId);
|
|
29
38
|
const metadataDefaults = getBuiltInTemplateMetadataDefaults(templateId);
|
|
@@ -52,6 +61,17 @@ export function createBuiltInBlockSpec({ answers, dataStorageMode, persistencePo
|
|
|
52
61
|
project: {
|
|
53
62
|
author: answers.author.trim(),
|
|
54
63
|
},
|
|
64
|
+
queryLoop: templateId === "query-loop"
|
|
65
|
+
? {
|
|
66
|
+
allowedControls: DEFAULT_QUERY_LOOP_ALLOWED_CONTROLS,
|
|
67
|
+
enabled: true,
|
|
68
|
+
postType: (answers.queryPostType ?? "post").trim() || "post",
|
|
69
|
+
}
|
|
70
|
+
: {
|
|
71
|
+
allowedControls: [],
|
|
72
|
+
enabled: false,
|
|
73
|
+
postType: "post",
|
|
74
|
+
},
|
|
55
75
|
runtime: {
|
|
56
76
|
withMigrationUi,
|
|
57
77
|
withTestPreset,
|
|
@@ -82,6 +102,7 @@ export function buildTemplateVariablesFromBlockSpec(spec) {
|
|
|
82
102
|
const persistencePolicy = persistenceEnabled
|
|
83
103
|
? spec.persistence.persistencePolicy
|
|
84
104
|
: "authenticated";
|
|
105
|
+
const queryVariationNamespace = `${namespace}/${slug}`;
|
|
85
106
|
return {
|
|
86
107
|
apiClientPackageVersion,
|
|
87
108
|
author: spec.project.author,
|
|
@@ -101,7 +122,13 @@ export function buildTemplateVariablesFromBlockSpec(spec) {
|
|
|
101
122
|
dashCase: slug,
|
|
102
123
|
dataStorageMode,
|
|
103
124
|
description: spec.metadata.description,
|
|
125
|
+
descriptionJson: JSON.stringify(spec.metadata.description),
|
|
104
126
|
frontendCssClassName: buildFrontendCssClassName(cssClassName),
|
|
127
|
+
queryAllowedControlsJson: JSON.stringify(spec.queryLoop.enabled ? spec.queryLoop.allowedControls : [], null, 2),
|
|
128
|
+
queryPostType: spec.queryLoop.enabled ? spec.queryLoop.postType : "post",
|
|
129
|
+
queryPostTypeJson: JSON.stringify(spec.queryLoop.enabled ? spec.queryLoop.postType : "post"),
|
|
130
|
+
queryVariationNamespace,
|
|
131
|
+
queryVariationNamespaceJson: JSON.stringify(queryVariationNamespace),
|
|
105
132
|
isAuthenticatedPersistencePolicy: persistencePolicy === "authenticated" ? "true" : "false",
|
|
106
133
|
isPublicPersistencePolicy: persistencePolicy === "public" ? "true" : "false",
|
|
107
134
|
bootstrapCredentialDeclarations: persistencePolicy === "public"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildBuiltInNonTsArtifacts } from "./built-in-block-non-ts-artifacts.js";
|
|
2
|
-
import { BASIC_EDIT_TEMPLATE, BASIC_INDEX_TEMPLATE, BASIC_SAVE_TEMPLATE, BASIC_VALIDATORS_TEMPLATE, BLOCK_METADATA_WRAPPER_TEMPLATE, COMPOUND_CHILD_EDIT_TEMPLATE, COMPOUND_CHILD_INDEX_TEMPLATE, COMPOUND_CHILD_SAVE_TEMPLATE, COMPOUND_CHILD_VALIDATORS_TEMPLATE, COMPOUND_CHILDREN_TEMPLATE, COMPOUND_LOCAL_HOOKS_TEMPLATE, COMPOUND_PARENT_EDIT_TEMPLATE, COMPOUND_PARENT_INDEX_TEMPLATE, COMPOUND_PARENT_SAVE_TEMPLATE, COMPOUND_PARENT_VALIDATORS_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_INTERACTIVITY_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_SAVE_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_VALIDATORS_TEMPLATE, INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, MANIFEST_DEFAULTS_DOCUMENT_WRAPPER_TEMPLATE, MANIFEST_DOCUMENT_WRAPPER_TEMPLATE, PERSISTENCE_EDIT_TEMPLATE, PERSISTENCE_INDEX_TEMPLATE, PERSISTENCE_INTERACTIVITY_TEMPLATE, PERSISTENCE_SAVE_TEMPLATE, PERSISTENCE_VALIDATORS_TEMPLATE, SHARED_HOOKS_TEMPLATE, } from "./built-in-block-code-templates.js";
|
|
2
|
+
import { BASIC_EDIT_TEMPLATE, BASIC_INDEX_TEMPLATE, BASIC_SAVE_TEMPLATE, BASIC_VALIDATORS_TEMPLATE, BLOCK_METADATA_WRAPPER_TEMPLATE, COMPOUND_CHILD_EDIT_TEMPLATE, COMPOUND_CHILD_INDEX_TEMPLATE, COMPOUND_CHILD_SAVE_TEMPLATE, COMPOUND_CHILD_VALIDATORS_TEMPLATE, COMPOUND_CHILDREN_TEMPLATE, COMPOUND_LOCAL_HOOKS_TEMPLATE, COMPOUND_PARENT_EDIT_TEMPLATE, COMPOUND_PARENT_INDEX_TEMPLATE, COMPOUND_PARENT_SAVE_TEMPLATE, COMPOUND_PARENT_VALIDATORS_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_INTERACTIVITY_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_SAVE_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_VALIDATORS_TEMPLATE, INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, MANIFEST_DEFAULTS_DOCUMENT_WRAPPER_TEMPLATE, MANIFEST_DOCUMENT_WRAPPER_TEMPLATE, PERSISTENCE_EDIT_TEMPLATE, PERSISTENCE_INDEX_TEMPLATE, PERSISTENCE_INTERACTIVITY_TEMPLATE, PERSISTENCE_SAVE_TEMPLATE, PERSISTENCE_VALIDATORS_TEMPLATE, QUERY_LOOP_INDEX_TEMPLATE, SHARED_HOOKS_TEMPLATE, } from "./built-in-block-code-templates.js";
|
|
3
3
|
import { renderMustacheTemplateString } from "./template-render.js";
|
|
4
4
|
function renderCodeTemplate(template, variables) {
|
|
5
5
|
const rendered = renderMustacheTemplateString(template, variables);
|
|
@@ -162,6 +162,17 @@ function buildPersistenceCodeArtifacts(variables) {
|
|
|
162
162
|
...buildBuiltInNonTsArtifacts({ templateId: "persistence", variables }),
|
|
163
163
|
]);
|
|
164
164
|
}
|
|
165
|
+
function buildQueryLoopCodeArtifacts(variables) {
|
|
166
|
+
return ensureUniqueArtifactPaths([
|
|
167
|
+
...createCodeArtifacts([
|
|
168
|
+
{
|
|
169
|
+
relativePath: "src/index.ts",
|
|
170
|
+
template: QUERY_LOOP_INDEX_TEMPLATE,
|
|
171
|
+
},
|
|
172
|
+
], variables),
|
|
173
|
+
...buildBuiltInNonTsArtifacts({ templateId: "query-loop", variables }),
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
165
176
|
/**
|
|
166
177
|
* Build the emitter-owned scaffold files for a built-in template family.
|
|
167
178
|
*
|
|
@@ -179,6 +190,8 @@ export function buildBuiltInCodeArtifacts({ templateId, variables, }) {
|
|
|
179
190
|
return buildPersistenceCodeArtifacts(variables);
|
|
180
191
|
case "compound":
|
|
181
192
|
return buildCompoundCodeArtifacts(variables);
|
|
193
|
+
case "query-loop":
|
|
194
|
+
return buildQueryLoopCodeArtifacts(variables);
|
|
182
195
|
default: {
|
|
183
196
|
const unhandledTemplateId = templateId;
|
|
184
197
|
throw new Error(`Unhandled built-in template id: ${unhandledTemplateId}`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const QUERY_LOOP_INDEX_TEMPLATE = "import { registerBlockVariation } from '@wordpress/blocks';\nimport type { BlockVariation } from '@wp-typia/block-types/blocks/registration';\nimport { __ } from '@wordpress/i18n';\nimport {\n getQueryLoopCustomAllowedControls,\n getQueryLoopCustomQuerySeed,\n registerQueryLoopEditorExtensions,\n} from './query-extension';\n\ntype QueryLoopVariationAttributes = {\n namespace?: string;\n query?: {\n inherit?: boolean;\n order?: 'asc' | 'desc';\n orderBy?: string;\n perPage?: number;\n postType?: string;\n wpTypiaVariation?: string;\n [key: string]: unknown;\n };\n};\n\ntype QueryLoopVariation = BlockVariation<QueryLoopVariationAttributes> & {\n allowedControls: string[];\n};\n\nconst VARIATION_NAME = {{queryVariationNamespaceJson}};\nconst DEFAULT_ALLOWED_CONTROLS = {{queryAllowedControlsJson}};\nconst customQuerySeed = getQueryLoopCustomQuerySeed();\nconst allowedControls = Array.from(\n new Set([...DEFAULT_ALLOWED_CONTROLS, ...getQueryLoopCustomAllowedControls()]),\n);\n\nconst queryLoopVariation = {\n name: VARIATION_NAME,\n title: __({{titleJson}}, '{{textDomain}}'),\n description: __({{descriptionJson}}, '{{textDomain}}'),\n scope: ['inserter'],\n isActive: ['namespace'],\n attributes: {\n namespace: VARIATION_NAME,\n query: {\n inherit: false,\n order: 'desc',\n orderBy: 'date',\n perPage: 6,\n postType: {{queryPostTypeJson}},\n ...customQuerySeed,\n wpTypiaVariation: VARIATION_NAME,\n },\n },\n allowedControls,\n innerBlocks: [\n [\n 'core/post-template',\n {},\n [\n ['core/post-featured-image'],\n ['core/post-title', { isLink: true }],\n ['core/post-excerpt'],\n ],\n ],\n ['core/query-pagination'],\n ['core/query-no-results'],\n ],\n} satisfies QueryLoopVariation;\n\nregisterBlockVariation('core/query', queryLoopVariation);\nregisterQueryLoopEditorExtensions({ variationName: VARIATION_NAME });\n";
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export const QUERY_LOOP_INDEX_TEMPLATE = `import { registerBlockVariation } from '@wordpress/blocks';
|
|
2
|
+
import type { BlockVariation } from '@wp-typia/block-types/blocks/registration';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
import {
|
|
5
|
+
getQueryLoopCustomAllowedControls,
|
|
6
|
+
getQueryLoopCustomQuerySeed,
|
|
7
|
+
registerQueryLoopEditorExtensions,
|
|
8
|
+
} from './query-extension';
|
|
9
|
+
|
|
10
|
+
type QueryLoopVariationAttributes = {
|
|
11
|
+
namespace?: string;
|
|
12
|
+
query?: {
|
|
13
|
+
inherit?: boolean;
|
|
14
|
+
order?: 'asc' | 'desc';
|
|
15
|
+
orderBy?: string;
|
|
16
|
+
perPage?: number;
|
|
17
|
+
postType?: string;
|
|
18
|
+
wpTypiaVariation?: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type QueryLoopVariation = BlockVariation<QueryLoopVariationAttributes> & {
|
|
24
|
+
allowedControls: string[];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const VARIATION_NAME = {{queryVariationNamespaceJson}};
|
|
28
|
+
const DEFAULT_ALLOWED_CONTROLS = {{queryAllowedControlsJson}};
|
|
29
|
+
const customQuerySeed = getQueryLoopCustomQuerySeed();
|
|
30
|
+
const allowedControls = Array.from(
|
|
31
|
+
new Set([...DEFAULT_ALLOWED_CONTROLS, ...getQueryLoopCustomAllowedControls()]),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const queryLoopVariation = {
|
|
35
|
+
name: VARIATION_NAME,
|
|
36
|
+
title: __({{titleJson}}, '{{textDomain}}'),
|
|
37
|
+
description: __({{descriptionJson}}, '{{textDomain}}'),
|
|
38
|
+
scope: ['inserter'],
|
|
39
|
+
isActive: ['namespace'],
|
|
40
|
+
attributes: {
|
|
41
|
+
namespace: VARIATION_NAME,
|
|
42
|
+
query: {
|
|
43
|
+
inherit: false,
|
|
44
|
+
order: 'desc',
|
|
45
|
+
orderBy: 'date',
|
|
46
|
+
perPage: 6,
|
|
47
|
+
postType: {{queryPostTypeJson}},
|
|
48
|
+
...customQuerySeed,
|
|
49
|
+
wpTypiaVariation: VARIATION_NAME,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
allowedControls,
|
|
53
|
+
innerBlocks: [
|
|
54
|
+
[
|
|
55
|
+
'core/post-template',
|
|
56
|
+
{},
|
|
57
|
+
[
|
|
58
|
+
['core/post-featured-image'],
|
|
59
|
+
['core/post-title', { isLink: true }],
|
|
60
|
+
['core/post-excerpt'],
|
|
61
|
+
],
|
|
62
|
+
],
|
|
63
|
+
['core/query-pagination'],
|
|
64
|
+
['core/query-no-results'],
|
|
65
|
+
],
|
|
66
|
+
} satisfies QueryLoopVariation;
|
|
67
|
+
|
|
68
|
+
registerBlockVariation('core/query', queryLoopVariation);
|
|
69
|
+
registerQueryLoopEditorExtensions({ variationName: VARIATION_NAME });
|
|
70
|
+
`;
|
|
@@ -6,4 +6,5 @@ export { BLOCK_METADATA_WRAPPER_TEMPLATE, MANIFEST_DEFAULTS_DOCUMENT_WRAPPER_TEM
|
|
|
6
6
|
export { BASIC_EDIT_TEMPLATE, BASIC_INDEX_TEMPLATE, BASIC_SAVE_TEMPLATE, BASIC_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/basic.js";
|
|
7
7
|
export { INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/interactivity.js";
|
|
8
8
|
export { PERSISTENCE_EDIT_TEMPLATE, PERSISTENCE_INDEX_TEMPLATE, PERSISTENCE_INTERACTIVITY_TEMPLATE, PERSISTENCE_SAVE_TEMPLATE, PERSISTENCE_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/persistence.js";
|
|
9
|
+
export { QUERY_LOOP_INDEX_TEMPLATE, } from "./built-in-block-code-templates/query-loop.js";
|
|
9
10
|
export { COMPOUND_CHILD_EDIT_TEMPLATE, COMPOUND_CHILD_INDEX_TEMPLATE, COMPOUND_CHILDREN_TEMPLATE, COMPOUND_CHILD_SAVE_TEMPLATE, COMPOUND_CHILD_VALIDATORS_TEMPLATE, COMPOUND_LOCAL_HOOKS_TEMPLATE, COMPOUND_PARENT_EDIT_TEMPLATE, COMPOUND_PARENT_INDEX_TEMPLATE, COMPOUND_PARENT_SAVE_TEMPLATE, COMPOUND_PARENT_VALIDATORS_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_INTERACTIVITY_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_SAVE_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/compound.js";
|
|
@@ -6,4 +6,5 @@ export { BLOCK_METADATA_WRAPPER_TEMPLATE, MANIFEST_DEFAULTS_DOCUMENT_WRAPPER_TEM
|
|
|
6
6
|
export { BASIC_EDIT_TEMPLATE, BASIC_INDEX_TEMPLATE, BASIC_SAVE_TEMPLATE, BASIC_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/basic.js";
|
|
7
7
|
export { INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/interactivity.js";
|
|
8
8
|
export { PERSISTENCE_EDIT_TEMPLATE, PERSISTENCE_INDEX_TEMPLATE, PERSISTENCE_INTERACTIVITY_TEMPLATE, PERSISTENCE_SAVE_TEMPLATE, PERSISTENCE_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/persistence.js";
|
|
9
|
+
export { QUERY_LOOP_INDEX_TEMPLATE, } from "./built-in-block-code-templates/query-loop.js";
|
|
9
10
|
export { COMPOUND_CHILD_EDIT_TEMPLATE, COMPOUND_CHILD_INDEX_TEMPLATE, COMPOUND_CHILDREN_TEMPLATE, COMPOUND_CHILD_SAVE_TEMPLATE, COMPOUND_CHILD_VALIDATORS_TEMPLATE, COMPOUND_LOCAL_HOOKS_TEMPLATE, COMPOUND_PARENT_EDIT_TEMPLATE, COMPOUND_PARENT_INDEX_TEMPLATE, COMPOUND_PARENT_SAVE_TEMPLATE, COMPOUND_PARENT_VALIDATORS_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_INTERACTIVITY_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_SAVE_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/compound.js";
|
|
@@ -555,6 +555,8 @@ export function buildBuiltInNonTsArtifacts({ templateId, variables, }) {
|
|
|
555
555
|
return buildPersistenceArtifacts(variables);
|
|
556
556
|
case "compound":
|
|
557
557
|
return buildCompoundArtifacts(variables);
|
|
558
|
+
case "query-loop":
|
|
559
|
+
return [];
|
|
558
560
|
default: {
|
|
559
561
|
const unhandledTemplateId = templateId;
|
|
560
562
|
throw new Error(`Unhandled built-in template id: ${unhandledTemplateId}`);
|
package/dist/runtime/cli-help.js
CHANGED
|
@@ -11,6 +11,7 @@ import { TEMPLATE_IDS } from "./template-registry.js";
|
|
|
11
11
|
export function formatHelpText() {
|
|
12
12
|
return `Usage:
|
|
13
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>]
|
|
14
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>]
|
|
15
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>]
|
|
16
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,18 +18,17 @@ export function createReadlinePrompt() {
|
|
|
18
18
|
* retry behavior without stubbing global stdin/stdout.
|
|
19
19
|
*/
|
|
20
20
|
export function createReadlinePromptWithInterface(rl) {
|
|
21
|
+
const askQuestion = (query) => new Promise((resolve) => {
|
|
22
|
+
rl.question(query, resolve);
|
|
23
|
+
});
|
|
21
24
|
return {
|
|
22
25
|
async text(message, defaultValue, validate) {
|
|
23
|
-
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
24
26
|
while (true) {
|
|
25
|
-
const
|
|
26
|
-
rl.question(`${message}${suffix}: `, resolve);
|
|
27
|
-
});
|
|
28
|
-
const value = String(answer).trim() || defaultValue;
|
|
27
|
+
const value = normalizePromptAnswer(await askQuestion(formatTextPrompt(message, defaultValue))) || defaultValue;
|
|
29
28
|
if (validate) {
|
|
30
29
|
const result = validate(value);
|
|
31
30
|
if (result !== true) {
|
|
32
|
-
console.error(
|
|
31
|
+
console.error(formatValidationError(message, result, defaultValue));
|
|
33
32
|
continue;
|
|
34
33
|
}
|
|
35
34
|
}
|
|
@@ -40,22 +39,22 @@ export function createReadlinePromptWithInterface(rl) {
|
|
|
40
39
|
if (options.length === 0) {
|
|
41
40
|
throw new Error(`select() requires at least one option for prompt: ${message}`);
|
|
42
41
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const hint = option.hint ? ` - ${option.hint}` : "";
|
|
46
|
-
console.log(` ${index + 1}. ${option.label}${hint}`);
|
|
47
|
-
});
|
|
42
|
+
const resolvedDefaultIndex = getResolvedDefaultIndex(options, defaultValue);
|
|
43
|
+
renderSelectPrompt(message, options, resolvedDefaultIndex);
|
|
48
44
|
while (true) {
|
|
49
|
-
const answer = await
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
const answer = normalizePromptAnswer(await askQuestion(formatChoicePrompt(resolvedDefaultIndex)));
|
|
46
|
+
if (answer.length === 0) {
|
|
47
|
+
return options[resolvedDefaultIndex].value;
|
|
48
|
+
}
|
|
49
|
+
const selection = resolvePromptSelection(options, answer);
|
|
50
|
+
if (selection) {
|
|
51
|
+
return selection.value;
|
|
53
52
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
if (isPromptHelpToken(answer)) {
|
|
54
|
+
renderSelectPrompt(message, options, resolvedDefaultIndex);
|
|
55
|
+
continue;
|
|
57
56
|
}
|
|
58
|
-
console.error(
|
|
57
|
+
console.error(formatInvalidSelectionError(answer, options, resolvedDefaultIndex));
|
|
59
58
|
}
|
|
60
59
|
},
|
|
61
60
|
close() {
|
|
@@ -63,3 +62,63 @@ export function createReadlinePromptWithInterface(rl) {
|
|
|
63
62
|
},
|
|
64
63
|
};
|
|
65
64
|
}
|
|
65
|
+
function normalizePromptAnswer(value) {
|
|
66
|
+
return String(value).trim();
|
|
67
|
+
}
|
|
68
|
+
function normalizePromptToken(value) {
|
|
69
|
+
return value.trim().toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
function getResolvedDefaultIndex(options, defaultValue) {
|
|
72
|
+
const candidateIndex = Number.isInteger(defaultValue) ? defaultValue - 1 : -1;
|
|
73
|
+
return options[candidateIndex] ? candidateIndex : 0;
|
|
74
|
+
}
|
|
75
|
+
function formatTextPrompt(message, defaultValue) {
|
|
76
|
+
const suffix = defaultValue.length > 0 ? ` [default: ${defaultValue}]` : "";
|
|
77
|
+
return `${message}${suffix}: `;
|
|
78
|
+
}
|
|
79
|
+
function formatValidationError(message, result, defaultValue) {
|
|
80
|
+
const detail = typeof result === "string" ? result : "Invalid input";
|
|
81
|
+
const retryHint = defaultValue.length > 0 ? ` Press Enter to keep "${defaultValue}".` : "";
|
|
82
|
+
return `❌ ${message}: ${detail}.${retryHint}`;
|
|
83
|
+
}
|
|
84
|
+
function formatChoicePrompt(defaultIndex) {
|
|
85
|
+
return `Choice [default: ${defaultIndex + 1}, ? for options]: `;
|
|
86
|
+
}
|
|
87
|
+
function renderSelectPrompt(message, options, defaultIndex) {
|
|
88
|
+
console.log(message);
|
|
89
|
+
console.log(" Enter a number, option label, or option value. Press Enter to keep the default, or type ? to list choices again.");
|
|
90
|
+
options.forEach((option, index) => {
|
|
91
|
+
const defaultMarker = index === defaultIndex ? " (default)" : "";
|
|
92
|
+
const valueHint = normalizePromptToken(option.label) === normalizePromptToken(option.value)
|
|
93
|
+
? ""
|
|
94
|
+
: ` [${option.value}]`;
|
|
95
|
+
console.log(` ${index + 1}. ${option.label}${valueHint}${defaultMarker}`);
|
|
96
|
+
if (option.hint) {
|
|
97
|
+
console.log(` ${option.hint}`);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function isPromptHelpToken(answer) {
|
|
102
|
+
const normalized = normalizePromptToken(answer);
|
|
103
|
+
return normalized === "?" || normalized === "help" || normalized === "list";
|
|
104
|
+
}
|
|
105
|
+
function resolvePromptSelection(options, answer) {
|
|
106
|
+
const numericChoice = Number(answer);
|
|
107
|
+
if (!Number.isNaN(numericChoice) && options[numericChoice - 1]) {
|
|
108
|
+
return options[numericChoice - 1];
|
|
109
|
+
}
|
|
110
|
+
const normalizedAnswer = normalizePromptToken(answer);
|
|
111
|
+
return options.find((option) => {
|
|
112
|
+
const normalizedLabel = normalizePromptToken(option.label);
|
|
113
|
+
const normalizedValue = normalizePromptToken(option.value);
|
|
114
|
+
return normalizedAnswer === normalizedLabel || normalizedAnswer === normalizedValue;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function formatInvalidSelectionError(answer, options, defaultIndex) {
|
|
118
|
+
const optionValues = options.map((option) => option.value).join(", ");
|
|
119
|
+
return [
|
|
120
|
+
`❌ Invalid selection: ${answer}.`,
|
|
121
|
+
`Enter 1-${options.length}, one of: ${optionValues},`,
|
|
122
|
+
`or press Enter for "${options[defaultIndex].label}".`,
|
|
123
|
+
].join(" ");
|
|
124
|
+
}
|
|
@@ -34,6 +34,7 @@ interface RunScaffoldFlowOptions {
|
|
|
34
34
|
phpPrefix?: string;
|
|
35
35
|
projectInput: string;
|
|
36
36
|
promptText?: Parameters<typeof collectScaffoldAnswers>[0]["promptText"];
|
|
37
|
+
queryPostType?: string;
|
|
37
38
|
selectDataStorage?: () => Promise<DataStorageMode>;
|
|
38
39
|
selectExternalLayerId?: (options: ExternalLayerSelectionOption[]) => Promise<string>;
|
|
39
40
|
selectPackageManager?: () => Promise<PackageManagerId>;
|
|
@@ -73,7 +74,7 @@ export declare function getOptionalOnboarding({ availableScripts, packageManager
|
|
|
73
74
|
* project.
|
|
74
75
|
* @returns The scaffold result together with next-step guidance.
|
|
75
76
|
*/
|
|
76
|
-
export declare function runScaffoldFlow({ projectInput, cwd, templateId, dataStorageMode, externalLayerId, externalLayerSource, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, yes, noInstall, isInteractive, allowExistingDir, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }: RunScaffoldFlowOptions): Promise<{
|
|
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<{
|
|
77
78
|
optionalOnboarding: OptionalOnboardingGuidance;
|
|
78
79
|
projectDir: string;
|
|
79
80
|
projectInput: string;
|
|
@@ -135,7 +135,7 @@ export function getOptionalOnboarding({ availableScripts, packageManager, templa
|
|
|
135
135
|
* project.
|
|
136
136
|
* @returns The scaffold result together with next-step guidance.
|
|
137
137
|
*/
|
|
138
|
-
export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templateId, dataStorageMode, externalLayerId, externalLayerSource, persistencePolicy, packageManager, namespace, textDomain, phpPrefix, yes = false, noInstall = false, isInteractive = false, allowExistingDir = false, selectTemplate, selectDataStorage, selectExternalLayerId, selectPersistencePolicy, selectPackageManager, promptText, installDependencies = undefined, variant, selectWithTestPreset, selectWithWpEnv, selectWithMigrationUi, withMigrationUi, withTestPreset, withWpEnv, }) {
|
|
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, }) {
|
|
139
139
|
const normalizedExternalLayerId = typeof externalLayerId === "string" && externalLayerId.trim().length > 0
|
|
140
140
|
? externalLayerId.trim()
|
|
141
141
|
: undefined;
|
|
@@ -228,6 +228,7 @@ export async function runScaffoldFlow({ projectInput, cwd = process.cwd(), templ
|
|
|
228
228
|
persistencePolicy: resolvedPersistencePolicy,
|
|
229
229
|
phpPrefix,
|
|
230
230
|
projectName,
|
|
231
|
+
queryPostType,
|
|
231
232
|
templateId: resolvedTemplateId,
|
|
232
233
|
textDomain,
|
|
233
234
|
yes,
|
|
@@ -13,6 +13,12 @@ import { copyInterpolatedDirectory } from "./template-render.js";
|
|
|
13
13
|
function templateHasPersistenceSync(templateId, compoundPersistenceEnabled) {
|
|
14
14
|
return templateId === "persistence" || (templateId === "compound" && compoundPersistenceEnabled);
|
|
15
15
|
}
|
|
16
|
+
function templateSupportsGeneratedSyncWatchers(templateId) {
|
|
17
|
+
return (templateId === "basic" ||
|
|
18
|
+
templateId === "interactivity" ||
|
|
19
|
+
templateId === "persistence" ||
|
|
20
|
+
templateId === "compound");
|
|
21
|
+
}
|
|
16
22
|
function getWatchSyncTypesScript(packageManager, templateId) {
|
|
17
23
|
if (templateId === "compound") {
|
|
18
24
|
return `chokidar "src/blocks/**/types.ts" "scripts/block-config.ts" --debounce 200 -c "${formatRunScript(packageManager, "sync-types")}"`;
|
|
@@ -80,11 +86,16 @@ export async function applyLocalDevPresetFiles({ projectDir, variables, withTest
|
|
|
80
86
|
*/
|
|
81
87
|
export async function applyGeneratedProjectDxPackageJson({ compoundPersistenceEnabled = false, packageManager, projectDir, templateId, withTestPreset = false, withWpEnv = false, }) {
|
|
82
88
|
const hasPersistenceSync = templateHasPersistenceSync(templateId, compoundPersistenceEnabled);
|
|
89
|
+
const supportsGeneratedSyncWatchers = templateSupportsGeneratedSyncWatchers(templateId);
|
|
83
90
|
await mutatePackageJson(projectDir, (packageJson) => {
|
|
84
91
|
packageJson.devDependencies = {
|
|
85
92
|
...(packageJson.devDependencies ?? {}),
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
...(supportsGeneratedSyncWatchers
|
|
94
|
+
? {
|
|
95
|
+
"chokidar-cli": "^3.0.0",
|
|
96
|
+
concurrently: "^9.0.1",
|
|
97
|
+
}
|
|
98
|
+
: {}),
|
|
88
99
|
};
|
|
89
100
|
if (withWpEnv || withTestPreset) {
|
|
90
101
|
packageJson.devDependencies["@wordpress/env"] = "^11.2.0";
|
|
@@ -95,12 +106,16 @@ export async function applyGeneratedProjectDxPackageJson({ compoundPersistenceEn
|
|
|
95
106
|
const scripts = {
|
|
96
107
|
...(packageJson.scripts ?? {}),
|
|
97
108
|
};
|
|
98
|
-
|
|
99
|
-
|
|
109
|
+
if (supportsGeneratedSyncWatchers) {
|
|
110
|
+
scripts["start:editor"] = "wp-scripts start --experimental-modules";
|
|
111
|
+
scripts["watch:sync-types"] = getWatchSyncTypesScript(packageManager, templateId);
|
|
112
|
+
}
|
|
100
113
|
if (hasPersistenceSync) {
|
|
101
114
|
scripts["watch:sync-rest"] = getWatchSyncRestScript(packageManager, templateId);
|
|
102
115
|
}
|
|
103
|
-
|
|
116
|
+
if (supportsGeneratedSyncWatchers) {
|
|
117
|
+
scripts.dev = getDevScript(packageManager, compoundPersistenceEnabled, templateId);
|
|
118
|
+
}
|
|
104
119
|
if (withWpEnv) {
|
|
105
120
|
scripts["wp-env:start"] = "wp-env start";
|
|
106
121
|
scripts["wp-env:stop"] = "wp-env stop";
|
|
@@ -123,10 +138,5 @@ export async function applyGeneratedProjectDxPackageJson({ compoundPersistenceEn
|
|
|
123
138
|
* scaffolded template.
|
|
124
139
|
*/
|
|
125
140
|
export function getPrimaryDevelopmentScript(templateId) {
|
|
126
|
-
return templateId
|
|
127
|
-
templateId === "interactivity" ||
|
|
128
|
-
templateId === "persistence" ||
|
|
129
|
-
templateId === "compound"
|
|
130
|
-
? "dev"
|
|
131
|
-
: "start";
|
|
141
|
+
return templateSupportsGeneratedSyncWatchers(templateId) ? "dev" : "start";
|
|
132
142
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PackageManagerId } from './package-managers.js';
|
|
2
|
+
import type { CollectScaffoldAnswersOptions, ResolvePackageManagerOptions, ResolveTemplateOptions, ScaffoldAnswers } from './scaffold.js';
|
|
3
|
+
/**
|
|
4
|
+
* Detect the current author name from local Git config.
|
|
5
|
+
*
|
|
6
|
+
* @returns The configured Git author name, or `"Your Name"` when unavailable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function detectAuthor(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Compute the default scaffold answers for one project and template pair.
|
|
11
|
+
*
|
|
12
|
+
* @param projectName User-supplied project directory or block name seed.
|
|
13
|
+
* @param templateId Selected scaffold template identifier.
|
|
14
|
+
* @returns Normalized default answers for scaffold prompts and non-interactive flows.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getDefaultAnswers(projectName: string, templateId: string): ScaffoldAnswers;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the scaffold template id from flags, defaults, and interactive selection.
|
|
19
|
+
*
|
|
20
|
+
* @param options Template resolution options for interactive and non-interactive flows.
|
|
21
|
+
* @returns The normalized template identifier to scaffold.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveTemplateId({ templateId, yes, isInteractive, selectTemplate, }: ResolveTemplateOptions): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the package manager id from flags, defaults, and interactive selection.
|
|
26
|
+
*
|
|
27
|
+
* @param options Package manager resolution options for interactive and non-interactive flows.
|
|
28
|
+
* @returns The normalized package manager id.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolvePackageManagerId({ packageManager, yes, isInteractive, selectPackageManager, }: ResolvePackageManagerOptions): Promise<PackageManagerId>;
|
|
31
|
+
/**
|
|
32
|
+
* Collect scaffold answers from defaults, CLI overrides, and optional prompts.
|
|
33
|
+
*
|
|
34
|
+
* @param options Answer collection inputs including prompt callbacks and explicit overrides.
|
|
35
|
+
* @returns The normalized scaffold answers used for rendering and file generation.
|
|
36
|
+
*/
|
|
37
|
+
export declare function collectScaffoldAnswers({ projectName, templateId, yes, dataStorageMode, namespace, persistencePolicy, phpPrefix, promptText, queryPostType, textDomain, }: CollectScaffoldAnswersOptions): Promise<ScaffoldAnswers>;
|