@wp-typia/project-tools 0.16.10 → 0.16.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/runtime/built-in-block-artifact-documents.d.ts +3 -0
- package/dist/runtime/built-in-block-artifact-documents.js +2 -0
- package/dist/runtime/built-in-block-artifact-types.d.ts +51 -0
- package/dist/runtime/built-in-block-artifact-types.js +304 -0
- package/dist/runtime/built-in-block-artifacts.js +4 -803
- package/dist/runtime/built-in-block-attribute-emitters.d.ts +71 -0
- package/dist/runtime/built-in-block-attribute-emitters.js +176 -0
- package/dist/runtime/built-in-block-attribute-specs.d.ts +38 -0
- package/dist/runtime/built-in-block-attribute-specs.js +358 -0
- package/dist/runtime/built-in-block-code-templates/basic.d.ts +4 -0
- package/dist/runtime/built-in-block-code-templates/basic.js +249 -0
- package/dist/runtime/built-in-block-code-templates/compound-child.d.ts +4 -0
- package/dist/runtime/built-in-block-code-templates/compound-child.js +138 -0
- package/dist/runtime/built-in-block-code-templates/compound-parent.d.ts +6 -0
- package/dist/runtime/built-in-block-code-templates/compound-parent.js +227 -0
- package/dist/runtime/built-in-block-code-templates/compound-persistence.d.ts +4 -0
- package/dist/runtime/built-in-block-code-templates/compound-persistence.js +478 -0
- package/dist/runtime/built-in-block-code-templates/compound.d.ts +3 -0
- package/dist/runtime/built-in-block-code-templates/compound.js +3 -0
- package/dist/runtime/built-in-block-code-templates/interactivity.d.ts +5 -0
- package/dist/runtime/built-in-block-code-templates/interactivity.js +547 -0
- package/dist/runtime/built-in-block-code-templates/persistence.d.ts +5 -0
- package/dist/runtime/built-in-block-code-templates/persistence.js +550 -0
- package/dist/runtime/built-in-block-code-templates/shared.d.ts +16 -0
- package/dist/runtime/built-in-block-code-templates/shared.js +53 -0
- package/dist/runtime/built-in-block-code-templates.d.ts +5 -32
- package/dist/runtime/built-in-block-code-templates.js +5 -2230
- package/dist/runtime/cli-add-block-config.d.ts +6 -0
- package/dist/runtime/cli-add-block-config.js +143 -0
- package/dist/runtime/cli-add-block-legacy-validator.d.ts +4 -0
- package/dist/runtime/cli-add-block-legacy-validator.js +168 -0
- package/dist/runtime/cli-add-block.js +3 -301
- package/dist/runtime/cli-add-workspace-assets.d.ts +38 -0
- package/dist/runtime/cli-add-workspace-assets.js +399 -0
- package/dist/runtime/cli-add-workspace.d.ts +2 -38
- package/dist/runtime/cli-add-workspace.js +5 -396
- package/dist/runtime/cli-doctor-environment.d.ts +12 -0
- package/dist/runtime/cli-doctor-environment.js +123 -0
- package/dist/runtime/cli-doctor-workspace.d.ts +14 -0
- package/dist/runtime/cli-doctor-workspace.js +296 -0
- package/dist/runtime/cli-doctor.d.ts +4 -2
- package/dist/runtime/cli-doctor.js +10 -405
- package/dist/runtime/cli-help.js +1 -1
- package/dist/runtime/cli-scaffold.js +1 -1
- package/dist/runtime/migration-command-surface.d.ts +67 -0
- package/dist/runtime/migration-command-surface.js +189 -0
- package/dist/runtime/migration-diff-rename.d.ts +13 -0
- package/dist/runtime/migration-diff-rename.js +192 -0
- package/dist/runtime/migration-diff-transform.d.ts +14 -0
- package/dist/runtime/migration-diff-transform.js +105 -0
- package/dist/runtime/migration-diff.js +12 -297
- package/dist/runtime/migration-generated-artifacts.d.ts +3 -0
- package/dist/runtime/migration-generated-artifacts.js +41 -0
- package/dist/runtime/migration-maintenance.d.ts +51 -0
- package/dist/runtime/migration-maintenance.js +380 -0
- package/dist/runtime/migration-planning.d.ts +23 -0
- package/dist/runtime/migration-planning.js +131 -0
- package/dist/runtime/migration-project-config-source.d.ts +6 -0
- package/dist/runtime/migration-project-config-source.js +424 -0
- package/dist/runtime/migration-project-layout-discovery.d.ts +61 -0
- package/dist/runtime/migration-project-layout-discovery.js +337 -0
- package/dist/runtime/migration-project-layout-paths.d.ts +135 -0
- package/dist/runtime/migration-project-layout-paths.js +288 -0
- package/dist/runtime/migration-project-layout.d.ts +3 -0
- package/dist/runtime/migration-project-layout.js +2 -0
- package/dist/runtime/migration-project-workspace.d.ts +47 -0
- package/dist/runtime/migration-project-workspace.js +212 -0
- package/dist/runtime/migration-project.d.ts +4 -94
- package/dist/runtime/migration-project.js +3 -1101
- package/dist/runtime/migration-render-diff-rule.d.ts +5 -0
- package/dist/runtime/migration-render-diff-rule.js +120 -0
- package/dist/runtime/migration-render-execution.d.ts +3 -0
- package/dist/runtime/migration-render-execution.js +428 -0
- package/dist/runtime/migration-render-generated.d.ts +27 -0
- package/dist/runtime/migration-render-generated.js +230 -0
- package/dist/runtime/migration-render-support.d.ts +3 -0
- package/dist/runtime/migration-render-support.js +16 -0
- package/dist/runtime/migration-render.d.ts +3 -33
- package/dist/runtime/migration-render.js +3 -789
- package/dist/runtime/migration-ui-capability.js +1 -1
- package/dist/runtime/migrations.d.ts +24 -118
- package/dist/runtime/migrations.js +12 -700
- package/dist/runtime/scaffold-bootstrap.d.ts +45 -0
- package/dist/runtime/scaffold-bootstrap.js +185 -0
- package/dist/runtime/scaffold-package-manager-files.d.ts +35 -0
- package/dist/runtime/scaffold-package-manager-files.js +79 -0
- package/dist/runtime/scaffold.d.ts +1 -12
- package/dist/runtime/scaffold.js +10 -393
- package/dist/runtime/template-source-contracts.d.ts +81 -0
- package/dist/runtime/template-source-contracts.js +1 -0
- package/dist/runtime/template-source-external.d.ts +21 -0
- package/dist/runtime/template-source-external.js +184 -0
- package/dist/runtime/template-source-locators.d.ts +4 -0
- package/dist/runtime/template-source-locators.js +72 -0
- package/dist/runtime/template-source-normalization.d.ts +7 -0
- package/dist/runtime/template-source-normalization.js +53 -0
- package/dist/runtime/template-source-remote.d.ts +23 -0
- package/dist/runtime/template-source-remote.js +336 -0
- package/dist/runtime/template-source-seeds.d.ts +12 -0
- package/dist/runtime/template-source-seeds.js +243 -0
- package/dist/runtime/template-source.d.ts +4 -86
- package/dist/runtime/template-source.js +9 -828
- package/package.json +5 -5
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type RunAddBindingSourceCommandOptions, type RunAddPatternCommandOptions } from "./cli-add-shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* Add one PHP block pattern shell to an official workspace project.
|
|
4
|
+
*
|
|
5
|
+
* @param options Command options for the pattern scaffold workflow.
|
|
6
|
+
* @param options.cwd Working directory used to resolve the nearest official workspace.
|
|
7
|
+
* Defaults to `process.cwd()`.
|
|
8
|
+
* @param options.patternName Human-entered pattern name that will be normalized
|
|
9
|
+
* and validated before files are written.
|
|
10
|
+
* @returns A promise that resolves with the normalized `patternSlug` and
|
|
11
|
+
* owning `projectDir` after the pattern file and inventory entry have been
|
|
12
|
+
* written successfully.
|
|
13
|
+
* @throws {Error} When the command is run outside an official workspace, when
|
|
14
|
+
* the pattern slug is invalid, or when a conflicting file or inventory entry
|
|
15
|
+
* already exists.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runAddPatternCommand({ cwd, patternName, }: RunAddPatternCommandOptions): Promise<{
|
|
18
|
+
patternSlug: string;
|
|
19
|
+
projectDir: string;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Add one block binding source scaffold to an official workspace project.
|
|
23
|
+
*
|
|
24
|
+
* @param options Command options for the binding-source scaffold workflow.
|
|
25
|
+
* @param options.bindingSourceName Human-entered binding source name that will
|
|
26
|
+
* be normalized and validated before files are written.
|
|
27
|
+
* @param options.cwd Working directory used to resolve the nearest official
|
|
28
|
+
* workspace. Defaults to `process.cwd()`.
|
|
29
|
+
* @returns A promise that resolves with the normalized `bindingSourceSlug` and
|
|
30
|
+
* owning `projectDir` after the server/editor files and inventory entry have
|
|
31
|
+
* been written successfully.
|
|
32
|
+
* @throws {Error} When the command is run outside an official workspace, when
|
|
33
|
+
* the slug is invalid, or when a conflicting file or inventory entry exists.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runAddBindingSourceCommand({ bindingSourceName, cwd, }: RunAddBindingSourceCommandOptions): Promise<{
|
|
36
|
+
bindingSourceSlug: string;
|
|
37
|
+
projectDir: string;
|
|
38
|
+
}>;
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { promises as fsp } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { resolveWorkspaceProject, } from "./workspace-project.js";
|
|
5
|
+
import { readWorkspaceInventory, appendWorkspaceInventoryEntries } from "./workspace-inventory.js";
|
|
6
|
+
import { toTitleCase } from "./string-case.js";
|
|
7
|
+
import { assertBindingSourceDoesNotExist, assertPatternDoesNotExist, assertValidGeneratedSlug, getWorkspaceBootstrapPath, normalizeBlockSlug, patchFile, quoteTsString, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
8
|
+
const PATTERN_BOOTSTRAP_CATEGORY = "register_block_pattern_category";
|
|
9
|
+
const BINDING_SOURCE_SERVER_GLOB = "/src/bindings/*/server.php";
|
|
10
|
+
const BINDING_SOURCE_EDITOR_SCRIPT = "build/bindings/index.js";
|
|
11
|
+
const BINDING_SOURCE_EDITOR_ASSET = "build/bindings/index.asset.php";
|
|
12
|
+
function escapeRegex(value) {
|
|
13
|
+
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
14
|
+
}
|
|
15
|
+
function quotePhpString(value) {
|
|
16
|
+
return `'${value.replace(/\\/gu, "\\\\").replace(/'/gu, "\\'")}'`;
|
|
17
|
+
}
|
|
18
|
+
function buildPatternConfigEntry(patternSlug) {
|
|
19
|
+
return [
|
|
20
|
+
"\t{",
|
|
21
|
+
`\t\tfile: ${quoteTsString(`src/patterns/${patternSlug}.php`)},`,
|
|
22
|
+
`\t\tslug: ${quoteTsString(patternSlug)},`,
|
|
23
|
+
"\t},",
|
|
24
|
+
].join("\n");
|
|
25
|
+
}
|
|
26
|
+
function buildBindingSourceConfigEntry(bindingSourceSlug) {
|
|
27
|
+
return [
|
|
28
|
+
"\t{",
|
|
29
|
+
`\t\teditorFile: ${quoteTsString(`src/bindings/${bindingSourceSlug}/editor.ts`)},`,
|
|
30
|
+
`\t\tserverFile: ${quoteTsString(`src/bindings/${bindingSourceSlug}/server.php`)},`,
|
|
31
|
+
`\t\tslug: ${quoteTsString(bindingSourceSlug)},`,
|
|
32
|
+
"\t},",
|
|
33
|
+
].join("\n");
|
|
34
|
+
}
|
|
35
|
+
function buildPatternSource(patternSlug, namespace, textDomain) {
|
|
36
|
+
const patternTitle = toTitleCase(patternSlug);
|
|
37
|
+
return `<?php
|
|
38
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
39
|
+
\treturn;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
register_block_pattern(
|
|
43
|
+
\t'${namespace}/${patternSlug}',
|
|
44
|
+
\tarray(
|
|
45
|
+
\t\t'title' => __( ${JSON.stringify(patternTitle)}, '${textDomain}' ),
|
|
46
|
+
\t\t'description' => __( ${JSON.stringify(`A starter pattern for ${patternTitle}.`)}, '${textDomain}' ),
|
|
47
|
+
\t\t'categories' => array( '${namespace}' ),
|
|
48
|
+
\t\t'content' => '<!-- wp:paragraph --><p>' . esc_html__( 'Describe this pattern here.', '${textDomain}' ) . '</p><!-- /wp:paragraph -->',
|
|
49
|
+
\t)
|
|
50
|
+
);
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
function buildBindingSourceServerSource(bindingSourceSlug, phpPrefix, namespace, textDomain) {
|
|
54
|
+
const bindingSourceTitle = toTitleCase(bindingSourceSlug);
|
|
55
|
+
const bindingSourcePhpId = bindingSourceSlug.replace(/-/g, "_");
|
|
56
|
+
const bindingSourceValueFunctionName = `${phpPrefix}_${bindingSourcePhpId}_binding_source_values`;
|
|
57
|
+
const bindingSourceResolveFunctionName = `${phpPrefix}_${bindingSourcePhpId}_resolve_binding_source_value`;
|
|
58
|
+
const starterValue = `${bindingSourceTitle} starter value`;
|
|
59
|
+
return `<?php
|
|
60
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
61
|
+
\treturn;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if ( ! function_exists( 'register_block_bindings_source' ) ) {
|
|
65
|
+
\treturn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if ( ! function_exists( '${bindingSourceValueFunctionName}' ) ) {
|
|
69
|
+
\tfunction ${bindingSourceValueFunctionName}() : array {
|
|
70
|
+
\t\treturn array(
|
|
71
|
+
\t\t\t${quotePhpString(bindingSourceSlug)} => ${quotePhpString(starterValue)},
|
|
72
|
+
\t\t);
|
|
73
|
+
\t}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if ( ! function_exists( '${bindingSourceResolveFunctionName}' ) ) {
|
|
77
|
+
\tfunction ${bindingSourceResolveFunctionName}( array $source_args ) : string {
|
|
78
|
+
\t\t$field = isset( $source_args['field'] ) && is_string( $source_args['field'] )
|
|
79
|
+
\t\t\t? $source_args['field']
|
|
80
|
+
\t\t\t: '${bindingSourceSlug}';
|
|
81
|
+
\t\t$binding_source_values = ${bindingSourceValueFunctionName}();
|
|
82
|
+
\t\t$value = $binding_source_values[ $field ] ?? '';
|
|
83
|
+
|
|
84
|
+
\t\treturn is_string( $value ) ? $value : '';
|
|
85
|
+
\t}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
register_block_bindings_source(
|
|
89
|
+
\t${quotePhpString(`${namespace}/${bindingSourceSlug}`)},
|
|
90
|
+
\tarray(
|
|
91
|
+
\t\t'label' => __( ${quotePhpString(bindingSourceTitle)}, ${quotePhpString(textDomain)} ),
|
|
92
|
+
\t\t'get_value_callback' => ${quotePhpString(bindingSourceResolveFunctionName)},
|
|
93
|
+
\t)
|
|
94
|
+
);
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
function buildBindingSourceEditorSource(bindingSourceSlug, namespace, textDomain) {
|
|
98
|
+
const bindingSourceTitle = toTitleCase(bindingSourceSlug);
|
|
99
|
+
const starterValue = `${bindingSourceTitle} starter value`;
|
|
100
|
+
return `import { registerBlockBindingsSource } from '@wordpress/blocks';
|
|
101
|
+
import { __ } from '@wordpress/i18n';
|
|
102
|
+
|
|
103
|
+
interface BindingSourceRegistration {
|
|
104
|
+
\targs?: {
|
|
105
|
+
\t\tfield?: string;
|
|
106
|
+
\t};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const BINDING_SOURCE_VALUES: Record<string, string> = {
|
|
110
|
+
\t${quoteTsString(bindingSourceSlug)}: ${quoteTsString(starterValue)},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
function resolveBindingSourceValue( field: string ): string {
|
|
114
|
+
\treturn BINDING_SOURCE_VALUES[ field ] ?? '';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
registerBlockBindingsSource( {
|
|
118
|
+
\tname: ${quoteTsString(`${namespace}/${bindingSourceSlug}`)},
|
|
119
|
+
\tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(textDomain)} ),
|
|
120
|
+
\tgetFieldsList() {
|
|
121
|
+
\t\treturn [
|
|
122
|
+
\t\t\t{
|
|
123
|
+
\t\t\t\tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(textDomain)} ),
|
|
124
|
+
\t\t\t\ttype: 'string',
|
|
125
|
+
\t\t\t\targs: {
|
|
126
|
+
\t\t\t\t\tfield: ${quoteTsString(bindingSourceSlug)},
|
|
127
|
+
\t\t\t\t},
|
|
128
|
+
\t\t\t},
|
|
129
|
+
\t\t];
|
|
130
|
+
\t},
|
|
131
|
+
\tgetValues( { bindings } ) {
|
|
132
|
+
\t\tconst values: Record<string, string> = {};
|
|
133
|
+
\t\tfor ( const [ attributeName, binding ] of Object.entries(
|
|
134
|
+
\t\t\tbindings as Record<string, BindingSourceRegistration>
|
|
135
|
+
\t\t) ) {
|
|
136
|
+
\t\t\tconst field =
|
|
137
|
+
\t\t\t\ttypeof binding?.args?.field === 'string'
|
|
138
|
+
\t\t\t\t\t? binding.args.field
|
|
139
|
+
\t\t\t\t\t: ${quoteTsString(bindingSourceSlug)};
|
|
140
|
+
\t\t\tvalues[ attributeName ] = resolveBindingSourceValue( field );
|
|
141
|
+
\t\t}
|
|
142
|
+
\t\treturn values;
|
|
143
|
+
\t},
|
|
144
|
+
} );
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
function buildBindingSourceIndexSource(bindingSourceSlugs) {
|
|
148
|
+
const importLines = bindingSourceSlugs
|
|
149
|
+
.map((bindingSourceSlug) => `import './${bindingSourceSlug}/editor';`)
|
|
150
|
+
.join("\n");
|
|
151
|
+
return `${importLines}${importLines ? "\n\n" : ""}// wp-typia add binding-source entries\n`;
|
|
152
|
+
}
|
|
153
|
+
async function ensurePatternBootstrapAnchors(workspace) {
|
|
154
|
+
const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
|
|
155
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
156
|
+
await patchFile(bootstrapPath, (source) => {
|
|
157
|
+
let nextSource = source;
|
|
158
|
+
const patternCategoryFunctionName = `${workspace.workspace.phpPrefix}_register_pattern_category`;
|
|
159
|
+
const patternRegistrationFunctionName = `${workspace.workspace.phpPrefix}_register_patterns`;
|
|
160
|
+
const patternCategoryHook = `add_action( 'init', '${patternCategoryFunctionName}' );`;
|
|
161
|
+
const patternRegistrationHook = `add_action( 'init', '${patternRegistrationFunctionName}', 20 );`;
|
|
162
|
+
const patternFunctions = `
|
|
163
|
+
|
|
164
|
+
function ${patternCategoryFunctionName}() {
|
|
165
|
+
\tif ( function_exists( 'register_block_pattern_category' ) ) {
|
|
166
|
+
\t\tregister_block_pattern_category(
|
|
167
|
+
\t\t\t'${workspace.workspace.namespace}',
|
|
168
|
+
\t\t\tarray(
|
|
169
|
+
\t\t\t\t'label' => __( ${JSON.stringify(`${toTitleCase(workspaceBaseName)} Patterns`)}, '${workspace.workspace.textDomain}' ),
|
|
170
|
+
\t\t\t)
|
|
171
|
+
\t\t);
|
|
172
|
+
\t}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function ${patternRegistrationFunctionName}() {
|
|
176
|
+
\tforeach ( glob( __DIR__ . '/src/patterns/*.php' ) ?: array() as $pattern_module ) {
|
|
177
|
+
\t\trequire $pattern_module;
|
|
178
|
+
\t}
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
181
|
+
if (!nextSource.includes(PATTERN_BOOTSTRAP_CATEGORY)) {
|
|
182
|
+
const insertionAnchors = [
|
|
183
|
+
/add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
|
|
184
|
+
/\?>\s*$/u,
|
|
185
|
+
];
|
|
186
|
+
let inserted = false;
|
|
187
|
+
for (const anchor of insertionAnchors) {
|
|
188
|
+
const candidate = nextSource.replace(anchor, (match) => `${patternFunctions}\n${match}`);
|
|
189
|
+
if (candidate !== nextSource) {
|
|
190
|
+
nextSource = candidate;
|
|
191
|
+
inserted = true;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (!inserted) {
|
|
196
|
+
nextSource = `${nextSource.trimEnd()}\n${patternFunctions}\n`;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (!nextSource.includes(patternCategoryFunctionName) ||
|
|
200
|
+
!nextSource.includes(patternRegistrationFunctionName)) {
|
|
201
|
+
throw new Error(`Unable to inject pattern bootstrap functions into ${path.basename(bootstrapPath)}.`);
|
|
202
|
+
}
|
|
203
|
+
if (!nextSource.includes(patternCategoryHook)) {
|
|
204
|
+
nextSource = `${nextSource.trimEnd()}\n${patternCategoryHook}\n`;
|
|
205
|
+
}
|
|
206
|
+
if (!nextSource.includes(patternRegistrationHook)) {
|
|
207
|
+
nextSource = `${nextSource.trimEnd()}\n${patternRegistrationHook}\n`;
|
|
208
|
+
}
|
|
209
|
+
return nextSource;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
async function ensureBindingSourceBootstrapAnchors(workspace) {
|
|
213
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
214
|
+
await patchFile(bootstrapPath, (source) => {
|
|
215
|
+
let nextSource = source;
|
|
216
|
+
const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
|
|
217
|
+
const bindingRegistrationFunctionName = `${workspace.workspace.phpPrefix}_register_binding_sources`;
|
|
218
|
+
const bindingEditorEnqueueFunctionName = `${workspace.workspace.phpPrefix}_enqueue_binding_sources_editor`;
|
|
219
|
+
const bindingRegistrationHook = `add_action( 'init', '${bindingRegistrationFunctionName}', 20 );`;
|
|
220
|
+
const bindingEditorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${bindingEditorEnqueueFunctionName}' );`;
|
|
221
|
+
const bindingRegistrationFunction = `
|
|
222
|
+
|
|
223
|
+
function ${bindingRegistrationFunctionName}() {
|
|
224
|
+
\tforeach ( glob( __DIR__ . '${BINDING_SOURCE_SERVER_GLOB}' ) ?: array() as $binding_source_module ) {
|
|
225
|
+
\t\trequire_once $binding_source_module;
|
|
226
|
+
\t}
|
|
227
|
+
}
|
|
228
|
+
`;
|
|
229
|
+
const bindingEditorEnqueueFunction = `
|
|
230
|
+
|
|
231
|
+
function ${bindingEditorEnqueueFunctionName}() {
|
|
232
|
+
\t$script_path = __DIR__ . '/${BINDING_SOURCE_EDITOR_SCRIPT}';
|
|
233
|
+
\t$asset_path = __DIR__ . '/${BINDING_SOURCE_EDITOR_ASSET}';
|
|
234
|
+
|
|
235
|
+
\tif ( ! file_exists( $script_path ) || ! file_exists( $asset_path ) ) {
|
|
236
|
+
\t\treturn;
|
|
237
|
+
\t}
|
|
238
|
+
|
|
239
|
+
\t$asset = require $asset_path;
|
|
240
|
+
\tif ( ! is_array( $asset ) ) {
|
|
241
|
+
\t\t$asset = array();
|
|
242
|
+
\t}
|
|
243
|
+
|
|
244
|
+
\twp_enqueue_script(
|
|
245
|
+
\t\t'${workspaceBaseName}-binding-sources',
|
|
246
|
+
\t\tplugins_url( '${BINDING_SOURCE_EDITOR_SCRIPT}', __FILE__ ),
|
|
247
|
+
\t\tisset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array(),
|
|
248
|
+
\t\tisset( $asset['version'] ) ? $asset['version'] : filemtime( $script_path ),
|
|
249
|
+
\t\ttrue
|
|
250
|
+
\t);
|
|
251
|
+
}
|
|
252
|
+
`;
|
|
253
|
+
const insertionAnchors = [
|
|
254
|
+
/add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
|
|
255
|
+
/\?>\s*$/u,
|
|
256
|
+
];
|
|
257
|
+
const hasPhpFunctionDefinition = (functionName) => new RegExp(`function\\s+${escapeRegex(functionName)}\\s*\\(`, "u").test(nextSource);
|
|
258
|
+
const insertPhpSnippet = (snippet) => {
|
|
259
|
+
for (const anchor of insertionAnchors) {
|
|
260
|
+
const candidate = nextSource.replace(anchor, (match) => `${snippet}\n${match}`);
|
|
261
|
+
if (candidate !== nextSource) {
|
|
262
|
+
nextSource = candidate;
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
267
|
+
};
|
|
268
|
+
const appendPhpSnippet = (snippet) => {
|
|
269
|
+
const closingTagPattern = /\?>\s*$/u;
|
|
270
|
+
if (closingTagPattern.test(nextSource)) {
|
|
271
|
+
nextSource = nextSource.replace(closingTagPattern, `${snippet}\n?>`);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
275
|
+
};
|
|
276
|
+
if (!hasPhpFunctionDefinition(bindingRegistrationFunctionName)) {
|
|
277
|
+
insertPhpSnippet(bindingRegistrationFunction);
|
|
278
|
+
}
|
|
279
|
+
if (!hasPhpFunctionDefinition(bindingEditorEnqueueFunctionName)) {
|
|
280
|
+
insertPhpSnippet(bindingEditorEnqueueFunction);
|
|
281
|
+
}
|
|
282
|
+
if (!nextSource.includes(bindingRegistrationHook)) {
|
|
283
|
+
appendPhpSnippet(bindingRegistrationHook);
|
|
284
|
+
}
|
|
285
|
+
if (!nextSource.includes(bindingEditorEnqueueHook)) {
|
|
286
|
+
appendPhpSnippet(bindingEditorEnqueueHook);
|
|
287
|
+
}
|
|
288
|
+
return nextSource;
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function resolveBindingSourceRegistryPath(projectDir) {
|
|
292
|
+
const bindingsDir = path.join(projectDir, "src", "bindings");
|
|
293
|
+
return [path.join(bindingsDir, "index.ts"), path.join(bindingsDir, "index.js")].find((candidatePath) => fs.existsSync(candidatePath)) ?? path.join(bindingsDir, "index.ts");
|
|
294
|
+
}
|
|
295
|
+
async function writeBindingSourceRegistry(projectDir, bindingSourceSlug) {
|
|
296
|
+
const bindingsDir = path.join(projectDir, "src", "bindings");
|
|
297
|
+
const bindingsIndexPath = resolveBindingSourceRegistryPath(projectDir);
|
|
298
|
+
await fsp.mkdir(bindingsDir, { recursive: true });
|
|
299
|
+
const existingBindingSourceSlugs = fs
|
|
300
|
+
.readdirSync(bindingsDir, { withFileTypes: true })
|
|
301
|
+
.filter((entry) => entry.isDirectory())
|
|
302
|
+
.map((entry) => entry.name);
|
|
303
|
+
const nextBindingSourceSlugs = Array.from(new Set([...existingBindingSourceSlugs, bindingSourceSlug])).sort();
|
|
304
|
+
await fsp.writeFile(bindingsIndexPath, buildBindingSourceIndexSource(nextBindingSourceSlugs), "utf8");
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Add one PHP block pattern shell to an official workspace project.
|
|
308
|
+
*
|
|
309
|
+
* @param options Command options for the pattern scaffold workflow.
|
|
310
|
+
* @param options.cwd Working directory used to resolve the nearest official workspace.
|
|
311
|
+
* Defaults to `process.cwd()`.
|
|
312
|
+
* @param options.patternName Human-entered pattern name that will be normalized
|
|
313
|
+
* and validated before files are written.
|
|
314
|
+
* @returns A promise that resolves with the normalized `patternSlug` and
|
|
315
|
+
* owning `projectDir` after the pattern file and inventory entry have been
|
|
316
|
+
* written successfully.
|
|
317
|
+
* @throws {Error} When the command is run outside an official workspace, when
|
|
318
|
+
* the pattern slug is invalid, or when a conflicting file or inventory entry
|
|
319
|
+
* already exists.
|
|
320
|
+
*/
|
|
321
|
+
export async function runAddPatternCommand({ cwd = process.cwd(), patternName, }) {
|
|
322
|
+
const workspace = resolveWorkspaceProject(cwd);
|
|
323
|
+
const patternSlug = assertValidGeneratedSlug("Pattern name", normalizeBlockSlug(patternName), "wp-typia add pattern <name>");
|
|
324
|
+
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
325
|
+
assertPatternDoesNotExist(workspace.projectDir, patternSlug, inventory);
|
|
326
|
+
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
327
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
328
|
+
const patternFilePath = path.join(workspace.projectDir, "src", "patterns", `${patternSlug}.php`);
|
|
329
|
+
const mutationSnapshot = {
|
|
330
|
+
fileSources: await snapshotWorkspaceFiles([blockConfigPath, bootstrapPath]),
|
|
331
|
+
snapshotDirs: [],
|
|
332
|
+
targetPaths: [patternFilePath],
|
|
333
|
+
};
|
|
334
|
+
try {
|
|
335
|
+
await fsp.mkdir(path.dirname(patternFilePath), { recursive: true });
|
|
336
|
+
await ensurePatternBootstrapAnchors(workspace);
|
|
337
|
+
await fsp.writeFile(patternFilePath, buildPatternSource(patternSlug, workspace.workspace.namespace, workspace.workspace.textDomain), "utf8");
|
|
338
|
+
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
339
|
+
patternEntries: [buildPatternConfigEntry(patternSlug)],
|
|
340
|
+
});
|
|
341
|
+
return {
|
|
342
|
+
patternSlug,
|
|
343
|
+
projectDir: workspace.projectDir,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
await rollbackWorkspaceMutation(mutationSnapshot);
|
|
348
|
+
throw error;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Add one block binding source scaffold to an official workspace project.
|
|
353
|
+
*
|
|
354
|
+
* @param options Command options for the binding-source scaffold workflow.
|
|
355
|
+
* @param options.bindingSourceName Human-entered binding source name that will
|
|
356
|
+
* be normalized and validated before files are written.
|
|
357
|
+
* @param options.cwd Working directory used to resolve the nearest official
|
|
358
|
+
* workspace. Defaults to `process.cwd()`.
|
|
359
|
+
* @returns A promise that resolves with the normalized `bindingSourceSlug` and
|
|
360
|
+
* owning `projectDir` after the server/editor files and inventory entry have
|
|
361
|
+
* been written successfully.
|
|
362
|
+
* @throws {Error} When the command is run outside an official workspace, when
|
|
363
|
+
* the slug is invalid, or when a conflicting file or inventory entry exists.
|
|
364
|
+
*/
|
|
365
|
+
export async function runAddBindingSourceCommand({ bindingSourceName, cwd = process.cwd(), }) {
|
|
366
|
+
const workspace = resolveWorkspaceProject(cwd);
|
|
367
|
+
const bindingSourceSlug = assertValidGeneratedSlug("Binding source name", normalizeBlockSlug(bindingSourceName), "wp-typia add binding-source <name>");
|
|
368
|
+
const inventory = readWorkspaceInventory(workspace.projectDir);
|
|
369
|
+
assertBindingSourceDoesNotExist(workspace.projectDir, bindingSourceSlug, inventory);
|
|
370
|
+
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
371
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
372
|
+
const bindingsIndexPath = resolveBindingSourceRegistryPath(workspace.projectDir);
|
|
373
|
+
const bindingSourceDir = path.join(workspace.projectDir, "src", "bindings", bindingSourceSlug);
|
|
374
|
+
const serverFilePath = path.join(bindingSourceDir, "server.php");
|
|
375
|
+
const editorFilePath = path.join(bindingSourceDir, "editor.ts");
|
|
376
|
+
const mutationSnapshot = {
|
|
377
|
+
fileSources: await snapshotWorkspaceFiles([blockConfigPath, bootstrapPath, bindingsIndexPath]),
|
|
378
|
+
snapshotDirs: [],
|
|
379
|
+
targetPaths: [bindingSourceDir],
|
|
380
|
+
};
|
|
381
|
+
try {
|
|
382
|
+
await fsp.mkdir(bindingSourceDir, { recursive: true });
|
|
383
|
+
await ensureBindingSourceBootstrapAnchors(workspace);
|
|
384
|
+
await fsp.writeFile(serverFilePath, buildBindingSourceServerSource(bindingSourceSlug, workspace.workspace.phpPrefix, workspace.workspace.namespace, workspace.workspace.textDomain), "utf8");
|
|
385
|
+
await fsp.writeFile(editorFilePath, buildBindingSourceEditorSource(bindingSourceSlug, workspace.workspace.namespace, workspace.workspace.textDomain), "utf8");
|
|
386
|
+
await writeBindingSourceRegistry(workspace.projectDir, bindingSourceSlug);
|
|
387
|
+
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
388
|
+
bindingSourceEntries: [buildBindingSourceConfigEntry(bindingSourceSlug)],
|
|
389
|
+
});
|
|
390
|
+
return {
|
|
391
|
+
bindingSourceSlug,
|
|
392
|
+
projectDir: workspace.projectDir,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
await rollbackWorkspaceMutation(mutationSnapshot);
|
|
397
|
+
throw error;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { HookedBlockPositionId } from "./hooked-blocks.js";
|
|
2
|
-
import { type
|
|
2
|
+
import { type RunAddHookedBlockCommandOptions, type RunAddVariationCommandOptions } from "./cli-add-shared.js";
|
|
3
|
+
export { runAddBindingSourceCommand, runAddPatternCommand, } from "./cli-add-workspace-assets.js";
|
|
3
4
|
/**
|
|
4
5
|
* Add one variation entry to an existing workspace block.
|
|
5
6
|
*
|
|
@@ -21,43 +22,6 @@ export declare function runAddVariationCommand({ blockName, cwd, variationName,
|
|
|
21
22
|
projectDir: string;
|
|
22
23
|
variationSlug: string;
|
|
23
24
|
}>;
|
|
24
|
-
/**
|
|
25
|
-
* Add one PHP block pattern shell to an official workspace project.
|
|
26
|
-
*
|
|
27
|
-
* @param options Command options for the pattern scaffold workflow.
|
|
28
|
-
* @param options.cwd Working directory used to resolve the nearest official workspace.
|
|
29
|
-
* Defaults to `process.cwd()`.
|
|
30
|
-
* @param options.patternName Human-entered pattern name that will be normalized
|
|
31
|
-
* and validated before files are written.
|
|
32
|
-
* @returns A promise that resolves with the normalized `patternSlug` and
|
|
33
|
-
* owning `projectDir` after the pattern file and inventory entry have been
|
|
34
|
-
* written successfully.
|
|
35
|
-
* @throws {Error} When the command is run outside an official workspace, when
|
|
36
|
-
* the pattern slug is invalid, or when a conflicting file or inventory entry
|
|
37
|
-
* already exists.
|
|
38
|
-
*/
|
|
39
|
-
export declare function runAddPatternCommand({ cwd, patternName, }: RunAddPatternCommandOptions): Promise<{
|
|
40
|
-
patternSlug: string;
|
|
41
|
-
projectDir: string;
|
|
42
|
-
}>;
|
|
43
|
-
/**
|
|
44
|
-
* Add one block binding source scaffold to an official workspace project.
|
|
45
|
-
*
|
|
46
|
-
* @param options Command options for the binding-source scaffold workflow.
|
|
47
|
-
* @param options.bindingSourceName Human-entered binding source name that will
|
|
48
|
-
* be normalized and validated before files are written.
|
|
49
|
-
* @param options.cwd Working directory used to resolve the nearest official
|
|
50
|
-
* workspace. Defaults to `process.cwd()`.
|
|
51
|
-
* @returns A promise that resolves with the normalized `bindingSourceSlug` and
|
|
52
|
-
* owning `projectDir` after the server/editor files and inventory entry have
|
|
53
|
-
* been written successfully.
|
|
54
|
-
* @throws {Error} When the command is run outside an official workspace, when
|
|
55
|
-
* the slug is invalid, or when a conflicting file or inventory entry exists.
|
|
56
|
-
*/
|
|
57
|
-
export declare function runAddBindingSourceCommand({ bindingSourceName, cwd, }: RunAddBindingSourceCommandOptions): Promise<{
|
|
58
|
-
bindingSourceSlug: string;
|
|
59
|
-
projectDir: string;
|
|
60
|
-
}>;
|
|
61
25
|
/**
|
|
62
26
|
* Add one `blockHooks` entry to an existing official workspace block.
|
|
63
27
|
*
|