@wp-typia/project-tools 0.22.4 → 0.22.5
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.
|
@@ -2,6 +2,7 @@ import { promises as fsp } from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { getPackageVersions } from "./package-versions.js";
|
|
4
4
|
import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
|
|
5
|
+
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
5
6
|
import { hasPhpFunctionDefinition } from "./php-utils.js";
|
|
6
7
|
const AI_FEATURE_SERVER_GLOB = "/inc/ai-features/*.php";
|
|
7
8
|
/**
|
|
@@ -21,30 +22,8 @@ function ${registerFunctionName}() {
|
|
|
21
22
|
\t}
|
|
22
23
|
}
|
|
23
24
|
`;
|
|
24
|
-
const insertionAnchors = [
|
|
25
|
-
/add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
|
|
26
|
-
/\?>\s*$/u,
|
|
27
|
-
];
|
|
28
|
-
const insertPhpSnippet = (snippet) => {
|
|
29
|
-
for (const anchor of insertionAnchors) {
|
|
30
|
-
const candidate = nextSource.replace(anchor, (match) => `${snippet}\n${match}`);
|
|
31
|
-
if (candidate !== nextSource) {
|
|
32
|
-
nextSource = candidate;
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
37
|
-
};
|
|
38
|
-
const appendPhpSnippet = (snippet) => {
|
|
39
|
-
const closingTagPattern = /\?>\s*$/u;
|
|
40
|
-
if (closingTagPattern.test(nextSource)) {
|
|
41
|
-
nextSource = nextSource.replace(closingTagPattern, `${snippet}\n?>`);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
45
|
-
};
|
|
46
25
|
if (!hasPhpFunctionDefinition(nextSource, registerFunctionName)) {
|
|
47
|
-
|
|
26
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, registerFunction);
|
|
48
27
|
}
|
|
49
28
|
else if (!nextSource.includes(AI_FEATURE_SERVER_GLOB)) {
|
|
50
29
|
throw new Error([
|
|
@@ -54,7 +33,7 @@ function ${registerFunctionName}() {
|
|
|
54
33
|
].join(" "));
|
|
55
34
|
}
|
|
56
35
|
if (!nextSource.includes(registerHook)) {
|
|
57
|
-
|
|
36
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, registerHook);
|
|
58
37
|
}
|
|
59
38
|
return nextSource;
|
|
60
39
|
});
|
|
@@ -8,6 +8,7 @@ import { readWorkspaceInventory, appendWorkspaceInventoryEntries, } from "./work
|
|
|
8
8
|
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
9
9
|
import { findPhpFunctionRange, hasPhpFunctionDefinition, quotePhpString, replacePhpFunctionDefinition, } from "./php-utils.js";
|
|
10
10
|
import { assertBindingSourceDoesNotExist, assertEditorPluginDoesNotExist, assertPatternDoesNotExist, assertValidEditorPluginSlot, assertValidGeneratedSlug, getWorkspaceBootstrapPath, normalizeBlockSlug, patchFile, quoteTsString, resolveWorkspaceBlock, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
11
|
+
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
11
12
|
import { normalizeOptionalCliString } from "./cli-validation.js";
|
|
12
13
|
const PATTERN_BOOTSTRAP_CATEGORY = "register_block_pattern_category";
|
|
13
14
|
const BINDING_SOURCE_SERVER_GLOB = "/src/bindings/*/server.php";
|
|
@@ -597,39 +598,17 @@ function ${bindingEditorEnqueueFunctionName}() {
|
|
|
597
598
|
\t);
|
|
598
599
|
}
|
|
599
600
|
`;
|
|
600
|
-
const insertionAnchors = [
|
|
601
|
-
/add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
|
|
602
|
-
/\?>\s*$/u,
|
|
603
|
-
];
|
|
604
|
-
const insertPhpSnippet = (snippet) => {
|
|
605
|
-
for (const anchor of insertionAnchors) {
|
|
606
|
-
const candidate = nextSource.replace(anchor, (match) => `${snippet}\n${match}`);
|
|
607
|
-
if (candidate !== nextSource) {
|
|
608
|
-
nextSource = candidate;
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
613
|
-
};
|
|
614
|
-
const appendPhpSnippet = (snippet) => {
|
|
615
|
-
const closingTagPattern = /\?>\s*$/u;
|
|
616
|
-
if (closingTagPattern.test(nextSource)) {
|
|
617
|
-
nextSource = nextSource.replace(closingTagPattern, `${snippet}\n?>`);
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
621
|
-
};
|
|
622
601
|
if (!hasPhpFunctionDefinition(nextSource, bindingRegistrationFunctionName)) {
|
|
623
|
-
|
|
602
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, bindingRegistrationFunction);
|
|
624
603
|
}
|
|
625
604
|
if (!hasPhpFunctionDefinition(nextSource, bindingEditorEnqueueFunctionName)) {
|
|
626
|
-
|
|
605
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, bindingEditorEnqueueFunction);
|
|
627
606
|
}
|
|
628
607
|
if (!nextSource.includes(bindingRegistrationHook)) {
|
|
629
|
-
|
|
608
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, bindingRegistrationHook);
|
|
630
609
|
}
|
|
631
610
|
if (!nextSource.includes(bindingEditorEnqueueHook)) {
|
|
632
|
-
|
|
611
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, bindingEditorEnqueueHook);
|
|
633
612
|
}
|
|
634
613
|
return nextSource;
|
|
635
614
|
});
|
|
@@ -679,30 +658,8 @@ function ${enqueueFunctionName}() {
|
|
|
679
658
|
\t}
|
|
680
659
|
}
|
|
681
660
|
`;
|
|
682
|
-
const insertionAnchors = [
|
|
683
|
-
/add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
|
|
684
|
-
/\?>\s*$/u,
|
|
685
|
-
];
|
|
686
|
-
const insertPhpSnippet = (snippet) => {
|
|
687
|
-
for (const anchor of insertionAnchors) {
|
|
688
|
-
const candidate = nextSource.replace(anchor, (match) => `${snippet}\n${match}`);
|
|
689
|
-
if (candidate !== nextSource) {
|
|
690
|
-
nextSource = candidate;
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
695
|
-
};
|
|
696
|
-
const appendPhpSnippet = (snippet) => {
|
|
697
|
-
const closingTagPattern = /\?>\s*$/u;
|
|
698
|
-
if (closingTagPattern.test(nextSource)) {
|
|
699
|
-
nextSource = nextSource.replace(closingTagPattern, `${snippet}\n?>`);
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
702
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
703
|
-
};
|
|
704
661
|
if (!hasPhpFunctionDefinition(nextSource, enqueueFunctionName)) {
|
|
705
|
-
|
|
662
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, enqueueFunction);
|
|
706
663
|
}
|
|
707
664
|
else {
|
|
708
665
|
const requiredReferences = [
|
|
@@ -726,7 +683,7 @@ function ${enqueueFunctionName}() {
|
|
|
726
683
|
}
|
|
727
684
|
}
|
|
728
685
|
if (!nextSource.includes(enqueueHook)) {
|
|
729
|
-
|
|
686
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, enqueueHook);
|
|
730
687
|
}
|
|
731
688
|
return nextSource;
|
|
732
689
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
|
|
3
|
+
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
3
4
|
import { hasPhpFunctionDefinition } from "./php-utils.js";
|
|
4
5
|
const REST_RESOURCE_SERVER_GLOB = "/inc/rest/*.php";
|
|
5
6
|
export async function ensureRestResourceBootstrapAnchors(workspace) {
|
|
@@ -16,30 +17,8 @@ function ${registerFunctionName}() {
|
|
|
16
17
|
\t}
|
|
17
18
|
}
|
|
18
19
|
`;
|
|
19
|
-
const insertionAnchors = [
|
|
20
|
-
/add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
|
|
21
|
-
/\?>\s*$/u,
|
|
22
|
-
];
|
|
23
|
-
const insertPhpSnippet = (snippet) => {
|
|
24
|
-
for (const anchor of insertionAnchors) {
|
|
25
|
-
const candidate = nextSource.replace(anchor, (match) => `${snippet}\n${match}`);
|
|
26
|
-
if (candidate !== nextSource) {
|
|
27
|
-
nextSource = candidate;
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
32
|
-
};
|
|
33
|
-
const appendPhpSnippet = (snippet) => {
|
|
34
|
-
const closingTagPattern = /\?>\s*$/u;
|
|
35
|
-
if (closingTagPattern.test(nextSource)) {
|
|
36
|
-
nextSource = nextSource.replace(closingTagPattern, `${snippet}\n?>`);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
nextSource = `${nextSource.trimEnd()}\n${snippet}\n`;
|
|
40
|
-
};
|
|
41
20
|
if (!hasPhpFunctionDefinition(nextSource, registerFunctionName)) {
|
|
42
|
-
|
|
21
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, registerFunction);
|
|
43
22
|
}
|
|
44
23
|
else if (!nextSource.includes(REST_RESOURCE_SERVER_GLOB)) {
|
|
45
24
|
throw new Error([
|
|
@@ -49,7 +28,7 @@ function ${registerFunctionName}() {
|
|
|
49
28
|
].join(" "));
|
|
50
29
|
}
|
|
51
30
|
if (!nextSource.includes(registerHook)) {
|
|
52
|
-
|
|
31
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, registerHook);
|
|
53
32
|
}
|
|
54
33
|
return nextSource;
|
|
55
34
|
});
|
|
@@ -4,6 +4,9 @@ import { readFile, writeFile } from "node:fs/promises";
|
|
|
4
4
|
import ts from "typescript";
|
|
5
5
|
import { REST_RESOURCE_METHOD_IDS } from "./cli-add-shared.js";
|
|
6
6
|
import { escapeRegex } from "./php-utils.js";
|
|
7
|
+
function defineInventoryEntryParser(descriptor) {
|
|
8
|
+
return descriptor;
|
|
9
|
+
}
|
|
7
10
|
export const BLOCK_CONFIG_ENTRY_MARKER = "\t// wp-typia add block entries";
|
|
8
11
|
export const VARIATION_CONFIG_ENTRY_MARKER = "\t// wp-typia add variation entries";
|
|
9
12
|
export const BLOCK_STYLE_CONFIG_ENTRY_MARKER = "\t// wp-typia add style entries";
|
|
@@ -202,12 +205,41 @@ export const EDITOR_PLUGINS: WorkspaceEditorPluginConfig[] = [
|
|
|
202
205
|
\t// wp-typia add editor-plugin entries
|
|
203
206
|
];
|
|
204
207
|
`;
|
|
208
|
+
const BLOCK_INVENTORY_SECTION = {
|
|
209
|
+
parse: {
|
|
210
|
+
entriesKey: "blocks",
|
|
211
|
+
entry: defineInventoryEntryParser({
|
|
212
|
+
entryName: "BLOCKS",
|
|
213
|
+
fields: [
|
|
214
|
+
{ key: "apiTypesFile" },
|
|
215
|
+
{ key: "attributeTypeName" },
|
|
216
|
+
{ key: "openApiFile" },
|
|
217
|
+
{ key: "slug", required: true },
|
|
218
|
+
{ key: "typesFile", required: true },
|
|
219
|
+
],
|
|
220
|
+
}),
|
|
221
|
+
exportName: "BLOCKS",
|
|
222
|
+
required: true,
|
|
223
|
+
},
|
|
224
|
+
};
|
|
205
225
|
const INVENTORY_SECTIONS = [
|
|
206
226
|
{
|
|
207
227
|
interface: {
|
|
208
228
|
name: "WorkspaceVariationConfig",
|
|
209
229
|
section: VARIATIONS_INTERFACE_SECTION,
|
|
210
230
|
},
|
|
231
|
+
parse: {
|
|
232
|
+
entriesKey: "variations",
|
|
233
|
+
entry: defineInventoryEntryParser({
|
|
234
|
+
entryName: "VARIATIONS",
|
|
235
|
+
fields: [
|
|
236
|
+
{ key: "block", required: true },
|
|
237
|
+
{ key: "file", required: true },
|
|
238
|
+
{ key: "slug", required: true },
|
|
239
|
+
],
|
|
240
|
+
}),
|
|
241
|
+
hasSectionKey: "hasVariationsSection",
|
|
242
|
+
},
|
|
211
243
|
value: {
|
|
212
244
|
name: "VARIATIONS",
|
|
213
245
|
section: VARIATIONS_CONST_SECTION,
|
|
@@ -218,6 +250,18 @@ const INVENTORY_SECTIONS = [
|
|
|
218
250
|
name: "WorkspaceBlockStyleConfig",
|
|
219
251
|
section: BLOCK_STYLES_INTERFACE_SECTION,
|
|
220
252
|
},
|
|
253
|
+
parse: {
|
|
254
|
+
entriesKey: "blockStyles",
|
|
255
|
+
entry: defineInventoryEntryParser({
|
|
256
|
+
entryName: "BLOCK_STYLES",
|
|
257
|
+
fields: [
|
|
258
|
+
{ key: "block", required: true },
|
|
259
|
+
{ key: "file", required: true },
|
|
260
|
+
{ key: "slug", required: true },
|
|
261
|
+
],
|
|
262
|
+
}),
|
|
263
|
+
hasSectionKey: "hasBlockStylesSection",
|
|
264
|
+
},
|
|
221
265
|
value: {
|
|
222
266
|
name: "BLOCK_STYLES",
|
|
223
267
|
section: BLOCK_STYLES_CONST_SECTION,
|
|
@@ -228,6 +272,20 @@ const INVENTORY_SECTIONS = [
|
|
|
228
272
|
name: "WorkspaceBlockTransformConfig",
|
|
229
273
|
section: BLOCK_TRANSFORMS_INTERFACE_SECTION,
|
|
230
274
|
},
|
|
275
|
+
parse: {
|
|
276
|
+
entriesKey: "blockTransforms",
|
|
277
|
+
entry: defineInventoryEntryParser({
|
|
278
|
+
entryName: "BLOCK_TRANSFORMS",
|
|
279
|
+
fields: [
|
|
280
|
+
{ key: "block", required: true },
|
|
281
|
+
{ key: "file", required: true },
|
|
282
|
+
{ key: "from", required: true },
|
|
283
|
+
{ key: "slug", required: true },
|
|
284
|
+
{ key: "to", required: true },
|
|
285
|
+
],
|
|
286
|
+
}),
|
|
287
|
+
hasSectionKey: "hasBlockTransformsSection",
|
|
288
|
+
},
|
|
231
289
|
value: {
|
|
232
290
|
name: "BLOCK_TRANSFORMS",
|
|
233
291
|
section: BLOCK_TRANSFORMS_CONST_SECTION,
|
|
@@ -238,6 +296,17 @@ const INVENTORY_SECTIONS = [
|
|
|
238
296
|
name: "WorkspacePatternConfig",
|
|
239
297
|
section: PATTERNS_INTERFACE_SECTION,
|
|
240
298
|
},
|
|
299
|
+
parse: {
|
|
300
|
+
entriesKey: "patterns",
|
|
301
|
+
entry: defineInventoryEntryParser({
|
|
302
|
+
entryName: "PATTERNS",
|
|
303
|
+
fields: [
|
|
304
|
+
{ key: "file", required: true },
|
|
305
|
+
{ key: "slug", required: true },
|
|
306
|
+
],
|
|
307
|
+
}),
|
|
308
|
+
hasSectionKey: "hasPatternsSection",
|
|
309
|
+
},
|
|
241
310
|
value: {
|
|
242
311
|
name: "PATTERNS",
|
|
243
312
|
section: PATTERNS_CONST_SECTION,
|
|
@@ -248,6 +317,20 @@ const INVENTORY_SECTIONS = [
|
|
|
248
317
|
name: "WorkspaceBindingSourceConfig",
|
|
249
318
|
section: BINDING_SOURCES_INTERFACE_SECTION,
|
|
250
319
|
},
|
|
320
|
+
parse: {
|
|
321
|
+
entriesKey: "bindingSources",
|
|
322
|
+
entry: defineInventoryEntryParser({
|
|
323
|
+
entryName: "BINDING_SOURCES",
|
|
324
|
+
fields: [
|
|
325
|
+
{ key: "attribute" },
|
|
326
|
+
{ key: "block" },
|
|
327
|
+
{ key: "editorFile", required: true },
|
|
328
|
+
{ key: "serverFile", required: true },
|
|
329
|
+
{ key: "slug", required: true },
|
|
330
|
+
],
|
|
331
|
+
}),
|
|
332
|
+
hasSectionKey: "hasBindingSourcesSection",
|
|
333
|
+
},
|
|
251
334
|
value: {
|
|
252
335
|
name: "BINDING_SOURCES",
|
|
253
336
|
section: BINDING_SOURCES_CONST_SECTION,
|
|
@@ -258,6 +341,36 @@ const INVENTORY_SECTIONS = [
|
|
|
258
341
|
name: "WorkspaceRestResourceConfig",
|
|
259
342
|
section: REST_RESOURCES_INTERFACE_SECTION,
|
|
260
343
|
},
|
|
344
|
+
parse: {
|
|
345
|
+
entriesKey: "restResources",
|
|
346
|
+
entry: defineInventoryEntryParser({
|
|
347
|
+
entryName: "REST_RESOURCES",
|
|
348
|
+
fields: [
|
|
349
|
+
{ key: "apiFile", required: true },
|
|
350
|
+
{ key: "clientFile", required: true },
|
|
351
|
+
{ key: "dataFile", required: true },
|
|
352
|
+
{
|
|
353
|
+
key: "methods",
|
|
354
|
+
kind: "stringArray",
|
|
355
|
+
required: true,
|
|
356
|
+
validate: (value, context) => {
|
|
357
|
+
const methods = Array.isArray(value) ? value : [];
|
|
358
|
+
const invalidMethods = methods.filter((method) => !REST_RESOURCE_METHOD_IDS.includes(method));
|
|
359
|
+
if (invalidMethods.length > 0) {
|
|
360
|
+
throw new Error(`${context.entryName}[${context.elementIndex}].${context.key} includes unsupported values: ${invalidMethods.join(", ")}.`);
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
{ key: "namespace", required: true },
|
|
365
|
+
{ key: "openApiFile", required: true },
|
|
366
|
+
{ key: "phpFile", required: true },
|
|
367
|
+
{ key: "slug", required: true },
|
|
368
|
+
{ key: "typesFile", required: true },
|
|
369
|
+
{ key: "validatorsFile", required: true },
|
|
370
|
+
],
|
|
371
|
+
}),
|
|
372
|
+
hasSectionKey: "hasRestResourcesSection",
|
|
373
|
+
},
|
|
261
374
|
value: {
|
|
262
375
|
name: "REST_RESOURCES",
|
|
263
376
|
section: REST_RESOURCES_CONST_SECTION,
|
|
@@ -268,6 +381,25 @@ const INVENTORY_SECTIONS = [
|
|
|
268
381
|
name: "WorkspaceAbilityConfig",
|
|
269
382
|
section: ABILITIES_INTERFACE_SECTION,
|
|
270
383
|
},
|
|
384
|
+
parse: {
|
|
385
|
+
entriesKey: "abilities",
|
|
386
|
+
entry: defineInventoryEntryParser({
|
|
387
|
+
entryName: "ABILITIES",
|
|
388
|
+
fields: [
|
|
389
|
+
{ key: "clientFile", required: true },
|
|
390
|
+
{ key: "configFile", required: true },
|
|
391
|
+
{ key: "dataFile", required: true },
|
|
392
|
+
{ key: "inputSchemaFile", required: true },
|
|
393
|
+
{ key: "inputTypeName", required: true },
|
|
394
|
+
{ key: "outputSchemaFile", required: true },
|
|
395
|
+
{ key: "outputTypeName", required: true },
|
|
396
|
+
{ key: "phpFile", required: true },
|
|
397
|
+
{ key: "slug", required: true },
|
|
398
|
+
{ key: "typesFile", required: true },
|
|
399
|
+
],
|
|
400
|
+
}),
|
|
401
|
+
hasSectionKey: "hasAbilitiesSection",
|
|
402
|
+
},
|
|
271
403
|
value: {
|
|
272
404
|
name: "ABILITIES",
|
|
273
405
|
section: ABILITIES_CONST_SECTION,
|
|
@@ -278,6 +410,25 @@ const INVENTORY_SECTIONS = [
|
|
|
278
410
|
name: "WorkspaceAiFeatureConfig",
|
|
279
411
|
section: AI_FEATURES_INTERFACE_SECTION,
|
|
280
412
|
},
|
|
413
|
+
parse: {
|
|
414
|
+
entriesKey: "aiFeatures",
|
|
415
|
+
entry: defineInventoryEntryParser({
|
|
416
|
+
entryName: "AI_FEATURES",
|
|
417
|
+
fields: [
|
|
418
|
+
{ key: "aiSchemaFile", required: true },
|
|
419
|
+
{ key: "apiFile", required: true },
|
|
420
|
+
{ key: "clientFile", required: true },
|
|
421
|
+
{ key: "dataFile", required: true },
|
|
422
|
+
{ key: "namespace", required: true },
|
|
423
|
+
{ key: "openApiFile", required: true },
|
|
424
|
+
{ key: "phpFile", required: true },
|
|
425
|
+
{ key: "slug", required: true },
|
|
426
|
+
{ key: "typesFile", required: true },
|
|
427
|
+
{ key: "validatorsFile", required: true },
|
|
428
|
+
],
|
|
429
|
+
}),
|
|
430
|
+
hasSectionKey: "hasAiFeaturesSection",
|
|
431
|
+
},
|
|
281
432
|
value: {
|
|
282
433
|
name: "AI_FEATURES",
|
|
283
434
|
section: AI_FEATURES_CONST_SECTION,
|
|
@@ -288,6 +439,19 @@ const INVENTORY_SECTIONS = [
|
|
|
288
439
|
name: "WorkspaceAdminViewConfig",
|
|
289
440
|
section: ADMIN_VIEWS_INTERFACE_SECTION,
|
|
290
441
|
},
|
|
442
|
+
parse: {
|
|
443
|
+
entriesKey: "adminViews",
|
|
444
|
+
entry: defineInventoryEntryParser({
|
|
445
|
+
entryName: "ADMIN_VIEWS",
|
|
446
|
+
fields: [
|
|
447
|
+
{ key: "file", required: true },
|
|
448
|
+
{ key: "phpFile", required: true },
|
|
449
|
+
{ key: "slug", required: true },
|
|
450
|
+
{ key: "source" },
|
|
451
|
+
],
|
|
452
|
+
}),
|
|
453
|
+
hasSectionKey: "hasAdminViewsSection",
|
|
454
|
+
},
|
|
291
455
|
value: {
|
|
292
456
|
name: "ADMIN_VIEWS",
|
|
293
457
|
section: ADMIN_VIEWS_CONST_SECTION,
|
|
@@ -298,6 +462,18 @@ const INVENTORY_SECTIONS = [
|
|
|
298
462
|
name: "WorkspaceEditorPluginConfig",
|
|
299
463
|
section: EDITOR_PLUGINS_INTERFACE_SECTION,
|
|
300
464
|
},
|
|
465
|
+
parse: {
|
|
466
|
+
entriesKey: "editorPlugins",
|
|
467
|
+
entry: defineInventoryEntryParser({
|
|
468
|
+
entryName: "EDITOR_PLUGINS",
|
|
469
|
+
fields: [
|
|
470
|
+
{ key: "file", required: true },
|
|
471
|
+
{ key: "slug", required: true },
|
|
472
|
+
{ key: "slot", required: true },
|
|
473
|
+
],
|
|
474
|
+
}),
|
|
475
|
+
hasSectionKey: "hasEditorPluginsSection",
|
|
476
|
+
},
|
|
301
477
|
value: {
|
|
302
478
|
name: "EDITOR_PLUGINS",
|
|
303
479
|
section: EDITOR_PLUGINS_CONST_SECTION,
|
|
@@ -383,169 +559,60 @@ function getRequiredStringArrayProperty(entryName, elementIndex, objectLiteral,
|
|
|
383
559
|
}
|
|
384
560
|
throw new Error(`${entryName}[${elementIndex}] is missing required "${key}" in scripts/block-config.ts.`);
|
|
385
561
|
}
|
|
386
|
-
function
|
|
387
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
388
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
389
|
-
throw new Error(`BLOCKS[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
390
|
-
}
|
|
391
|
-
return {
|
|
392
|
-
apiTypesFile: getOptionalStringProperty("BLOCKS", elementIndex, element, "apiTypesFile"),
|
|
393
|
-
attributeTypeName: getOptionalStringProperty("BLOCKS", elementIndex, element, "attributeTypeName"),
|
|
394
|
-
openApiFile: getOptionalStringProperty("BLOCKS", elementIndex, element, "openApiFile"),
|
|
395
|
-
slug: getRequiredStringProperty("BLOCKS", elementIndex, element, "slug"),
|
|
396
|
-
typesFile: getRequiredStringProperty("BLOCKS", elementIndex, element, "typesFile"),
|
|
397
|
-
};
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
function parseVariationEntries(arrayLiteral) {
|
|
401
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
402
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
403
|
-
throw new Error(`VARIATIONS[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
404
|
-
}
|
|
405
|
-
return {
|
|
406
|
-
block: getRequiredStringProperty("VARIATIONS", elementIndex, element, "block"),
|
|
407
|
-
file: getRequiredStringProperty("VARIATIONS", elementIndex, element, "file"),
|
|
408
|
-
slug: getRequiredStringProperty("VARIATIONS", elementIndex, element, "slug"),
|
|
409
|
-
};
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
function parseBlockStyleEntries(arrayLiteral) {
|
|
413
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
414
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
415
|
-
throw new Error(`BLOCK_STYLES[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
416
|
-
}
|
|
417
|
-
return {
|
|
418
|
-
block: getRequiredStringProperty("BLOCK_STYLES", elementIndex, element, "block"),
|
|
419
|
-
file: getRequiredStringProperty("BLOCK_STYLES", elementIndex, element, "file"),
|
|
420
|
-
slug: getRequiredStringProperty("BLOCK_STYLES", elementIndex, element, "slug"),
|
|
421
|
-
};
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
function parseBlockTransformEntries(arrayLiteral) {
|
|
425
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
426
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
427
|
-
throw new Error(`BLOCK_TRANSFORMS[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
428
|
-
}
|
|
429
|
-
return {
|
|
430
|
-
block: getRequiredStringProperty("BLOCK_TRANSFORMS", elementIndex, element, "block"),
|
|
431
|
-
file: getRequiredStringProperty("BLOCK_TRANSFORMS", elementIndex, element, "file"),
|
|
432
|
-
from: getRequiredStringProperty("BLOCK_TRANSFORMS", elementIndex, element, "from"),
|
|
433
|
-
slug: getRequiredStringProperty("BLOCK_TRANSFORMS", elementIndex, element, "slug"),
|
|
434
|
-
to: getRequiredStringProperty("BLOCK_TRANSFORMS", elementIndex, element, "to"),
|
|
435
|
-
};
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
function parsePatternEntries(arrayLiteral) {
|
|
439
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
440
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
441
|
-
throw new Error(`PATTERNS[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
442
|
-
}
|
|
443
|
-
return {
|
|
444
|
-
file: getRequiredStringProperty("PATTERNS", elementIndex, element, "file"),
|
|
445
|
-
slug: getRequiredStringProperty("PATTERNS", elementIndex, element, "slug"),
|
|
446
|
-
};
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
function parseBindingSourceEntries(arrayLiteral) {
|
|
450
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
451
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
452
|
-
throw new Error(`BINDING_SOURCES[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
453
|
-
}
|
|
454
|
-
return {
|
|
455
|
-
attribute: getOptionalStringProperty("BINDING_SOURCES", elementIndex, element, "attribute"),
|
|
456
|
-
block: getOptionalStringProperty("BINDING_SOURCES", elementIndex, element, "block"),
|
|
457
|
-
editorFile: getRequiredStringProperty("BINDING_SOURCES", elementIndex, element, "editorFile"),
|
|
458
|
-
serverFile: getRequiredStringProperty("BINDING_SOURCES", elementIndex, element, "serverFile"),
|
|
459
|
-
slug: getRequiredStringProperty("BINDING_SOURCES", elementIndex, element, "slug"),
|
|
460
|
-
};
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
function parseRestResourceEntries(arrayLiteral) {
|
|
562
|
+
function parseInventoryEntries(arrayLiteral, descriptor) {
|
|
464
563
|
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
465
564
|
if (!ts.isObjectLiteralExpression(element)) {
|
|
466
|
-
throw new Error(
|
|
565
|
+
throw new Error(`${descriptor.entryName}[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
467
566
|
}
|
|
468
|
-
const
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
567
|
+
const entry = {};
|
|
568
|
+
for (const field of descriptor.fields) {
|
|
569
|
+
const kind = field.kind ?? "string";
|
|
570
|
+
const value = kind === "stringArray"
|
|
571
|
+
? getRequiredStringArrayProperty(descriptor.entryName, elementIndex, element, field.key)
|
|
572
|
+
: field.required
|
|
573
|
+
? getRequiredStringProperty(descriptor.entryName, elementIndex, element, field.key)
|
|
574
|
+
: getOptionalStringProperty(descriptor.entryName, elementIndex, element, field.key);
|
|
575
|
+
field.validate?.(value, {
|
|
576
|
+
elementIndex,
|
|
577
|
+
entryName: descriptor.entryName,
|
|
578
|
+
key: field.key,
|
|
579
|
+
});
|
|
580
|
+
entry[field.key] = value;
|
|
472
581
|
}
|
|
473
|
-
return
|
|
474
|
-
apiFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "apiFile"),
|
|
475
|
-
clientFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "clientFile"),
|
|
476
|
-
dataFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "dataFile"),
|
|
477
|
-
methods,
|
|
478
|
-
namespace: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "namespace"),
|
|
479
|
-
openApiFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "openApiFile"),
|
|
480
|
-
phpFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "phpFile"),
|
|
481
|
-
slug: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "slug"),
|
|
482
|
-
typesFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "typesFile"),
|
|
483
|
-
validatorsFile: getRequiredStringProperty("REST_RESOURCES", elementIndex, element, "validatorsFile"),
|
|
484
|
-
};
|
|
582
|
+
return entry;
|
|
485
583
|
});
|
|
486
584
|
}
|
|
487
|
-
function
|
|
488
|
-
|
|
489
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
490
|
-
throw new Error(`AI_FEATURES[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
491
|
-
}
|
|
585
|
+
function parseInventorySection(sourceFile, descriptor) {
|
|
586
|
+
if (!descriptor.parse) {
|
|
492
587
|
return {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
clientFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "clientFile"),
|
|
496
|
-
dataFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "dataFile"),
|
|
497
|
-
namespace: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "namespace"),
|
|
498
|
-
openApiFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "openApiFile"),
|
|
499
|
-
phpFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "phpFile"),
|
|
500
|
-
slug: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "slug"),
|
|
501
|
-
typesFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "typesFile"),
|
|
502
|
-
validatorsFile: getRequiredStringProperty("AI_FEATURES", elementIndex, element, "validatorsFile"),
|
|
588
|
+
entries: [],
|
|
589
|
+
found: false,
|
|
503
590
|
};
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
configFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "configFile"),
|
|
514
|
-
dataFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "dataFile"),
|
|
515
|
-
inputSchemaFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "inputSchemaFile"),
|
|
516
|
-
inputTypeName: getRequiredStringProperty("ABILITIES", elementIndex, element, "inputTypeName"),
|
|
517
|
-
outputSchemaFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "outputSchemaFile"),
|
|
518
|
-
outputTypeName: getRequiredStringProperty("ABILITIES", elementIndex, element, "outputTypeName"),
|
|
519
|
-
phpFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "phpFile"),
|
|
520
|
-
slug: getRequiredStringProperty("ABILITIES", elementIndex, element, "slug"),
|
|
521
|
-
typesFile: getRequiredStringProperty("ABILITIES", elementIndex, element, "typesFile"),
|
|
522
|
-
};
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
function parseEditorPluginEntries(arrayLiteral) {
|
|
526
|
-
return arrayLiteral.elements.map((element, elementIndex) => {
|
|
527
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
528
|
-
throw new Error(`EDITOR_PLUGINS[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
591
|
+
}
|
|
592
|
+
const exportName = descriptor.parse.exportName ?? descriptor.value?.name;
|
|
593
|
+
if (!exportName) {
|
|
594
|
+
throw new Error("Inventory parser descriptor is missing an export name.");
|
|
595
|
+
}
|
|
596
|
+
const exportedArray = findExportedArrayLiteral(sourceFile, exportName);
|
|
597
|
+
if (!exportedArray.found) {
|
|
598
|
+
if (descriptor.parse.required) {
|
|
599
|
+
throw new Error(`scripts/block-config.ts must export a ${exportName} array.`);
|
|
529
600
|
}
|
|
530
601
|
return {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
slot: getRequiredStringProperty("EDITOR_PLUGINS", elementIndex, element, "slot"),
|
|
602
|
+
entries: [],
|
|
603
|
+
found: false,
|
|
534
604
|
};
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (!ts.isObjectLiteralExpression(element)) {
|
|
540
|
-
throw new Error(`ADMIN_VIEWS[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
|
|
605
|
+
}
|
|
606
|
+
if (!exportedArray.array) {
|
|
607
|
+
if (descriptor.parse.required) {
|
|
608
|
+
throw new Error(`scripts/block-config.ts must export a ${exportName} array.`);
|
|
541
609
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
});
|
|
610
|
+
throw new Error(`scripts/block-config.ts must export ${exportName} as an array literal.`);
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
entries: parseInventoryEntries(exportedArray.array, descriptor.parse.entry),
|
|
614
|
+
found: true,
|
|
615
|
+
};
|
|
549
616
|
}
|
|
550
617
|
/**
|
|
551
618
|
* Parse workspace inventory entries from the source of `scripts/block-config.ts`.
|
|
@@ -556,82 +623,42 @@ function parseAdminViewEntries(arrayLiteral) {
|
|
|
556
623
|
*/
|
|
557
624
|
export function parseWorkspaceInventorySource(source) {
|
|
558
625
|
const sourceFile = ts.createSourceFile("block-config.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
throw new Error("scripts/block-config.ts must export BLOCK_TRANSFORMS as an array literal.");
|
|
581
|
-
}
|
|
582
|
-
if (patternArray.found && !patternArray.array) {
|
|
583
|
-
throw new Error("scripts/block-config.ts must export PATTERNS as an array literal.");
|
|
584
|
-
}
|
|
585
|
-
if (bindingSourceArray.found && !bindingSourceArray.array) {
|
|
586
|
-
throw new Error("scripts/block-config.ts must export BINDING_SOURCES as an array literal.");
|
|
587
|
-
}
|
|
588
|
-
if (restResourceArray.found && !restResourceArray.array) {
|
|
589
|
-
throw new Error("scripts/block-config.ts must export REST_RESOURCES as an array literal.");
|
|
590
|
-
}
|
|
591
|
-
if (abilityArray.found && !abilityArray.array) {
|
|
592
|
-
throw new Error("scripts/block-config.ts must export ABILITIES as an array literal.");
|
|
593
|
-
}
|
|
594
|
-
if (aiFeatureArray.found && !aiFeatureArray.array) {
|
|
595
|
-
throw new Error("scripts/block-config.ts must export AI_FEATURES as an array literal.");
|
|
596
|
-
}
|
|
597
|
-
if (adminViewArray.found && !adminViewArray.array) {
|
|
598
|
-
throw new Error("scripts/block-config.ts must export ADMIN_VIEWS as an array literal.");
|
|
599
|
-
}
|
|
600
|
-
if (editorPluginArray.found && !editorPluginArray.array) {
|
|
601
|
-
throw new Error("scripts/block-config.ts must export EDITOR_PLUGINS as an array literal.");
|
|
602
|
-
}
|
|
603
|
-
return {
|
|
604
|
-
abilities: abilityArray.array ? parseAbilityEntries(abilityArray.array) : [],
|
|
605
|
-
adminViews: adminViewArray.array ? parseAdminViewEntries(adminViewArray.array) : [],
|
|
606
|
-
aiFeatures: aiFeatureArray.array ? parseAiFeatureEntries(aiFeatureArray.array) : [],
|
|
607
|
-
bindingSources: bindingSourceArray.array
|
|
608
|
-
? parseBindingSourceEntries(bindingSourceArray.array)
|
|
609
|
-
: [],
|
|
610
|
-
blockStyles: blockStyleArray.array ? parseBlockStyleEntries(blockStyleArray.array) : [],
|
|
611
|
-
blockTransforms: blockTransformArray.array
|
|
612
|
-
? parseBlockTransformEntries(blockTransformArray.array)
|
|
613
|
-
: [],
|
|
614
|
-
blocks: parseBlockEntries(blockArray.array),
|
|
615
|
-
hasAbilitiesSection: abilityArray.found,
|
|
616
|
-
hasAdminViewsSection: adminViewArray.found,
|
|
617
|
-
hasAiFeaturesSection: aiFeatureArray.found,
|
|
618
|
-
hasBindingSourcesSection: bindingSourceArray.found,
|
|
619
|
-
hasBlockStylesSection: blockStyleArray.found,
|
|
620
|
-
hasBlockTransformsSection: blockTransformArray.found,
|
|
621
|
-
hasEditorPluginsSection: editorPluginArray.found,
|
|
622
|
-
hasPatternsSection: patternArray.found,
|
|
623
|
-
hasRestResourcesSection: restResourceArray.found,
|
|
624
|
-
hasVariationsSection: variationArray.found,
|
|
625
|
-
editorPlugins: editorPluginArray.array
|
|
626
|
-
? parseEditorPluginEntries(editorPluginArray.array)
|
|
627
|
-
: [],
|
|
628
|
-
patterns: patternArray.array ? parsePatternEntries(patternArray.array) : [],
|
|
629
|
-
restResources: restResourceArray.array
|
|
630
|
-
? parseRestResourceEntries(restResourceArray.array)
|
|
631
|
-
: [],
|
|
626
|
+
const parsedInventory = {
|
|
627
|
+
abilities: [],
|
|
628
|
+
adminViews: [],
|
|
629
|
+
aiFeatures: [],
|
|
630
|
+
bindingSources: [],
|
|
631
|
+
blockStyles: [],
|
|
632
|
+
blockTransforms: [],
|
|
633
|
+
blocks: parseInventorySection(sourceFile, BLOCK_INVENTORY_SECTION).entries,
|
|
634
|
+
editorPlugins: [],
|
|
635
|
+
hasAbilitiesSection: false,
|
|
636
|
+
hasAdminViewsSection: false,
|
|
637
|
+
hasAiFeaturesSection: false,
|
|
638
|
+
hasBindingSourcesSection: false,
|
|
639
|
+
hasBlockStylesSection: false,
|
|
640
|
+
hasBlockTransformsSection: false,
|
|
641
|
+
hasEditorPluginsSection: false,
|
|
642
|
+
hasPatternsSection: false,
|
|
643
|
+
hasRestResourcesSection: false,
|
|
644
|
+
hasVariationsSection: false,
|
|
645
|
+
patterns: [],
|
|
646
|
+
restResources: [],
|
|
632
647
|
source,
|
|
633
|
-
variations:
|
|
648
|
+
variations: [],
|
|
634
649
|
};
|
|
650
|
+
const mutableInventory = parsedInventory;
|
|
651
|
+
for (const section of INVENTORY_SECTIONS) {
|
|
652
|
+
if (!section.parse) {
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
const parsedSection = parseInventorySection(sourceFile, section);
|
|
656
|
+
mutableInventory[section.parse.entriesKey] = parsedSection.entries;
|
|
657
|
+
if (section.parse.hasSectionKey) {
|
|
658
|
+
mutableInventory[section.parse.hasSectionKey] = parsedSection.found;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return parsedInventory;
|
|
635
662
|
}
|
|
636
663
|
/**
|
|
637
664
|
* Read and parse the canonical workspace inventory file.
|