@wp-typia/project-tools 0.22.9 → 0.23.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.
Files changed (90) hide show
  1. package/dist/runtime/ai-artifacts.js +3 -4
  2. package/dist/runtime/ai-feature-artifacts.js +2 -4
  3. package/dist/runtime/cli-add-collision.d.ts +25 -0
  4. package/dist/runtime/cli-add-collision.js +76 -0
  5. package/dist/runtime/cli-add-filesystem.js +2 -15
  6. package/dist/runtime/cli-add-help.js +11 -2
  7. package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
  8. package/dist/runtime/cli-add-kind-ids.js +3 -0
  9. package/dist/runtime/cli-add-types.d.ts +117 -0
  10. package/dist/runtime/cli-add-types.js +29 -1
  11. package/dist/runtime/cli-add-validation.d.ts +90 -1
  12. package/dist/runtime/cli-add-validation.js +304 -1
  13. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +74 -19
  14. package/dist/runtime/cli-add-workspace-admin-view-source.js +11 -2
  15. package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +20 -2
  16. package/dist/runtime/cli-add-workspace-admin-view-templates.js +359 -3
  17. package/dist/runtime/cli-add-workspace-admin-view-types.d.ts +21 -0
  18. package/dist/runtime/cli-add-workspace-admin-view-types.js +22 -0
  19. package/dist/runtime/cli-add-workspace-ai-anchors.js +121 -31
  20. package/dist/runtime/cli-add-workspace-contract-source-emitters.d.ts +15 -0
  21. package/dist/runtime/cli-add-workspace-contract-source-emitters.js +42 -0
  22. package/dist/runtime/cli-add-workspace-contract.d.ts +15 -0
  23. package/dist/runtime/cli-add-workspace-contract.js +65 -0
  24. package/dist/runtime/cli-add-workspace-integration-env.d.ts +24 -0
  25. package/dist/runtime/cli-add-workspace-integration-env.js +391 -0
  26. package/dist/runtime/cli-add-workspace-post-meta-anchors.d.ts +23 -0
  27. package/dist/runtime/cli-add-workspace-post-meta-anchors.js +244 -0
  28. package/dist/runtime/cli-add-workspace-post-meta-source-emitters.d.ts +63 -0
  29. package/dist/runtime/cli-add-workspace-post-meta-source-emitters.js +179 -0
  30. package/dist/runtime/cli-add-workspace-post-meta.d.ts +15 -0
  31. package/dist/runtime/cli-add-workspace-post-meta.js +107 -0
  32. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +1 -0
  33. package/dist/runtime/cli-add-workspace-rest-anchors.js +285 -21
  34. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +90 -2
  35. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +302 -29
  36. package/dist/runtime/cli-add-workspace-rest.d.ts +15 -2
  37. package/dist/runtime/cli-add-workspace-rest.js +329 -21
  38. package/dist/runtime/cli-add-workspace.d.ts +15 -0
  39. package/dist/runtime/cli-add-workspace.js +15 -0
  40. package/dist/runtime/cli-add.d.ts +1 -1
  41. package/dist/runtime/cli-add.js +1 -1
  42. package/dist/runtime/cli-core.d.ts +2 -1
  43. package/dist/runtime/cli-core.js +2 -1
  44. package/dist/runtime/cli-doctor-environment.js +1 -3
  45. package/dist/runtime/cli-doctor-workspace-features.js +128 -10
  46. package/dist/runtime/cli-doctor-workspace-package.d.ts +25 -3
  47. package/dist/runtime/cli-doctor-workspace-package.js +35 -13
  48. package/dist/runtime/cli-doctor-workspace-shared.d.ts +2 -0
  49. package/dist/runtime/cli-doctor-workspace-shared.js +5 -0
  50. package/dist/runtime/cli-doctor-workspace.d.ts +1 -1
  51. package/dist/runtime/cli-doctor-workspace.js +16 -8
  52. package/dist/runtime/cli-doctor.js +1 -1
  53. package/dist/runtime/cli-help.js +7 -0
  54. package/dist/runtime/cli-init-templates.js +11 -1
  55. package/dist/runtime/contract-artifacts.d.ts +14 -0
  56. package/dist/runtime/contract-artifacts.js +15 -0
  57. package/dist/runtime/fs-async.d.ts +7 -0
  58. package/dist/runtime/fs-async.js +11 -2
  59. package/dist/runtime/index.d.ts +1 -1
  60. package/dist/runtime/index.js +1 -1
  61. package/dist/runtime/migration-maintenance-verify.js +3 -0
  62. package/dist/runtime/migration-render-generated.js +4 -0
  63. package/dist/runtime/package-versions.js +3 -7
  64. package/dist/runtime/rest-resource-artifacts.d.ts +57 -1
  65. package/dist/runtime/rest-resource-artifacts.js +97 -1
  66. package/dist/runtime/scaffold-repository-reference.js +3 -7
  67. package/dist/runtime/template-render.d.ts +1 -1
  68. package/dist/runtime/template-render.js +1 -1
  69. package/dist/runtime/template-source-cache-markers.d.ts +37 -0
  70. package/dist/runtime/template-source-cache-markers.js +125 -0
  71. package/dist/runtime/template-source-cache.d.ts +1 -4
  72. package/dist/runtime/template-source-cache.js +16 -122
  73. package/dist/runtime/template-source-external.d.ts +4 -2
  74. package/dist/runtime/template-source-external.js +4 -2
  75. package/dist/runtime/template-source-remote.d.ts +8 -4
  76. package/dist/runtime/template-source-remote.js +8 -4
  77. package/dist/runtime/typia-llm.js +3 -4
  78. package/dist/runtime/workspace-inventory-mutations.d.ts +24 -0
  79. package/dist/runtime/workspace-inventory-mutations.js +181 -0
  80. package/dist/runtime/workspace-inventory-parser.d.ts +53 -0
  81. package/dist/runtime/workspace-inventory-parser.js +632 -0
  82. package/dist/runtime/workspace-inventory-read.d.ts +51 -0
  83. package/dist/runtime/workspace-inventory-read.js +98 -0
  84. package/dist/runtime/workspace-inventory-templates.d.ts +50 -0
  85. package/dist/runtime/workspace-inventory-templates.js +268 -0
  86. package/dist/runtime/workspace-inventory-types.d.ts +220 -0
  87. package/dist/runtime/workspace-inventory-types.js +1 -0
  88. package/dist/runtime/workspace-inventory.d.ts +5 -252
  89. package/dist/runtime/workspace-inventory.js +4 -928
  90. package/package.json +2 -2
@@ -0,0 +1,632 @@
1
+ import ts from "typescript";
2
+ import { MANUAL_REST_CONTRACT_AUTH_IDS, MANUAL_REST_CONTRACT_HTTP_METHOD_IDS, REST_RESOURCE_METHOD_IDS, } from "./cli-add-shared.js";
3
+ import { getPropertyNameText } from "./ts-property-names.js";
4
+ import { ABILITY_CONFIG_ENTRY_MARKER, ABILITIES_CONST_SECTION, ABILITIES_INTERFACE_SECTION, ADMIN_VIEW_CONFIG_ENTRY_MARKER, ADMIN_VIEWS_CONST_SECTION, ADMIN_VIEWS_INTERFACE_SECTION, AI_FEATURES_CONST_SECTION, AI_FEATURES_INTERFACE_SECTION, AI_FEATURE_CONFIG_ENTRY_MARKER, BINDING_SOURCES_CONST_SECTION, BINDING_SOURCES_INTERFACE_SECTION, BINDING_SOURCE_CONFIG_ENTRY_MARKER, CONTRACTS_CONST_SECTION, CONTRACTS_INTERFACE_SECTION, CONTRACT_CONFIG_ENTRY_MARKER, BLOCK_CONFIG_ENTRY_MARKER, BLOCK_STYLES_CONST_SECTION, BLOCK_STYLES_INTERFACE_SECTION, BLOCK_STYLE_CONFIG_ENTRY_MARKER, BLOCK_TRANSFORMS_CONST_SECTION, BLOCK_TRANSFORMS_INTERFACE_SECTION, BLOCK_TRANSFORM_CONFIG_ENTRY_MARKER, EDITOR_PLUGINS_CONST_SECTION, EDITOR_PLUGINS_INTERFACE_SECTION, EDITOR_PLUGIN_CONFIG_ENTRY_MARKER, PATTERNS_CONST_SECTION, PATTERNS_INTERFACE_SECTION, PATTERN_CONFIG_ENTRY_MARKER, POST_META_CONFIG_ENTRY_MARKER, POST_META_CONST_SECTION, POST_META_INTERFACE_SECTION, REST_RESOURCES_CONST_SECTION, REST_RESOURCES_INTERFACE_SECTION, REST_RESOURCE_CONFIG_ENTRY_MARKER, VARIATIONS_CONST_SECTION, VARIATIONS_INTERFACE_SECTION, VARIATION_CONFIG_ENTRY_MARKER, } from "./workspace-inventory-templates.js";
5
+ function defineInventoryEntryParser() {
6
+ return (descriptor) => descriptor;
7
+ }
8
+ export const BLOCK_INVENTORY_SECTION = {
9
+ append: {
10
+ marker: BLOCK_CONFIG_ENTRY_MARKER,
11
+ optionKey: "blockEntries",
12
+ },
13
+ parse: {
14
+ entriesKey: "blocks",
15
+ entry: defineInventoryEntryParser()({
16
+ entryName: "BLOCKS",
17
+ fields: [
18
+ { key: "apiTypesFile" },
19
+ { key: "attributeTypeName" },
20
+ { key: "openApiFile" },
21
+ { key: "slug", required: true },
22
+ { key: "typesFile", required: true },
23
+ ],
24
+ }),
25
+ exportName: "BLOCKS",
26
+ required: true,
27
+ },
28
+ };
29
+ export const INVENTORY_SECTIONS = [
30
+ {
31
+ append: {
32
+ marker: VARIATION_CONFIG_ENTRY_MARKER,
33
+ optionKey: "variationEntries",
34
+ },
35
+ interface: {
36
+ name: "WorkspaceVariationConfig",
37
+ section: VARIATIONS_INTERFACE_SECTION,
38
+ },
39
+ parse: {
40
+ entriesKey: "variations",
41
+ entry: defineInventoryEntryParser()({
42
+ entryName: "VARIATIONS",
43
+ fields: [
44
+ { key: "block", required: true },
45
+ { key: "file", required: true },
46
+ { key: "slug", required: true },
47
+ ],
48
+ }),
49
+ hasSectionKey: "hasVariationsSection",
50
+ },
51
+ value: {
52
+ name: "VARIATIONS",
53
+ section: VARIATIONS_CONST_SECTION,
54
+ },
55
+ },
56
+ {
57
+ append: {
58
+ marker: BLOCK_STYLE_CONFIG_ENTRY_MARKER,
59
+ optionKey: "blockStyleEntries",
60
+ },
61
+ interface: {
62
+ name: "WorkspaceBlockStyleConfig",
63
+ section: BLOCK_STYLES_INTERFACE_SECTION,
64
+ },
65
+ parse: {
66
+ entriesKey: "blockStyles",
67
+ entry: defineInventoryEntryParser()({
68
+ entryName: "BLOCK_STYLES",
69
+ fields: [
70
+ { key: "block", required: true },
71
+ { key: "file", required: true },
72
+ { key: "slug", required: true },
73
+ ],
74
+ }),
75
+ hasSectionKey: "hasBlockStylesSection",
76
+ },
77
+ value: {
78
+ name: "BLOCK_STYLES",
79
+ section: BLOCK_STYLES_CONST_SECTION,
80
+ },
81
+ },
82
+ {
83
+ append: {
84
+ marker: BLOCK_TRANSFORM_CONFIG_ENTRY_MARKER,
85
+ optionKey: "blockTransformEntries",
86
+ },
87
+ interface: {
88
+ name: "WorkspaceBlockTransformConfig",
89
+ section: BLOCK_TRANSFORMS_INTERFACE_SECTION,
90
+ },
91
+ parse: {
92
+ entriesKey: "blockTransforms",
93
+ entry: defineInventoryEntryParser()({
94
+ entryName: "BLOCK_TRANSFORMS",
95
+ fields: [
96
+ { key: "block", required: true },
97
+ { key: "file", required: true },
98
+ { key: "from", required: true },
99
+ { key: "slug", required: true },
100
+ { key: "to", required: true },
101
+ ],
102
+ }),
103
+ hasSectionKey: "hasBlockTransformsSection",
104
+ },
105
+ value: {
106
+ name: "BLOCK_TRANSFORMS",
107
+ section: BLOCK_TRANSFORMS_CONST_SECTION,
108
+ },
109
+ },
110
+ {
111
+ append: {
112
+ marker: PATTERN_CONFIG_ENTRY_MARKER,
113
+ optionKey: "patternEntries",
114
+ },
115
+ interface: {
116
+ name: "WorkspacePatternConfig",
117
+ section: PATTERNS_INTERFACE_SECTION,
118
+ },
119
+ parse: {
120
+ entriesKey: "patterns",
121
+ entry: defineInventoryEntryParser()({
122
+ entryName: "PATTERNS",
123
+ fields: [
124
+ { key: "file", required: true },
125
+ { key: "slug", required: true },
126
+ ],
127
+ }),
128
+ hasSectionKey: "hasPatternsSection",
129
+ },
130
+ value: {
131
+ name: "PATTERNS",
132
+ section: PATTERNS_CONST_SECTION,
133
+ },
134
+ },
135
+ {
136
+ append: {
137
+ marker: BINDING_SOURCE_CONFIG_ENTRY_MARKER,
138
+ optionKey: "bindingSourceEntries",
139
+ },
140
+ interface: {
141
+ name: "WorkspaceBindingSourceConfig",
142
+ section: BINDING_SOURCES_INTERFACE_SECTION,
143
+ },
144
+ parse: {
145
+ entriesKey: "bindingSources",
146
+ entry: defineInventoryEntryParser()({
147
+ entryName: "BINDING_SOURCES",
148
+ fields: [
149
+ { key: "attribute" },
150
+ { key: "block" },
151
+ { key: "editorFile", required: true },
152
+ { key: "serverFile", required: true },
153
+ { key: "slug", required: true },
154
+ ],
155
+ }),
156
+ hasSectionKey: "hasBindingSourcesSection",
157
+ },
158
+ value: {
159
+ name: "BINDING_SOURCES",
160
+ section: BINDING_SOURCES_CONST_SECTION,
161
+ },
162
+ },
163
+ {
164
+ append: {
165
+ marker: CONTRACT_CONFIG_ENTRY_MARKER,
166
+ optionKey: "contractEntries",
167
+ },
168
+ interface: {
169
+ name: "WorkspaceContractConfig",
170
+ section: CONTRACTS_INTERFACE_SECTION,
171
+ },
172
+ parse: {
173
+ entriesKey: "contracts",
174
+ entry: defineInventoryEntryParser()({
175
+ entryName: "CONTRACTS",
176
+ fields: [
177
+ { key: "schemaFile", required: true },
178
+ { key: "slug", required: true },
179
+ { key: "sourceTypeName", required: true },
180
+ { key: "typesFile", required: true },
181
+ ],
182
+ }),
183
+ hasSectionKey: "hasContractsSection",
184
+ },
185
+ value: {
186
+ name: "CONTRACTS",
187
+ section: CONTRACTS_CONST_SECTION,
188
+ },
189
+ },
190
+ {
191
+ append: {
192
+ marker: REST_RESOURCE_CONFIG_ENTRY_MARKER,
193
+ optionKey: "restResourceEntries",
194
+ },
195
+ interface: {
196
+ name: "WorkspaceRestResourceConfig",
197
+ section: REST_RESOURCES_INTERFACE_SECTION,
198
+ },
199
+ parse: {
200
+ entriesKey: "restResources",
201
+ entry: defineInventoryEntryParser()({
202
+ entryName: "REST_RESOURCES",
203
+ fields: [
204
+ { key: "apiFile", required: true },
205
+ {
206
+ key: "auth",
207
+ validate: (value, context) => {
208
+ if (typeof value === "string" &&
209
+ !MANUAL_REST_CONTRACT_AUTH_IDS.includes(value)) {
210
+ throw new Error(`${context.entryName}[${context.elementIndex}].${context.key} must be one of: ${MANUAL_REST_CONTRACT_AUTH_IDS.join(", ")}.`);
211
+ }
212
+ },
213
+ },
214
+ { key: "bodyTypeName" },
215
+ { key: "clientFile", required: true },
216
+ { key: "controllerClass" },
217
+ { key: "controllerExtends" },
218
+ { key: "dataFile" },
219
+ {
220
+ key: "method",
221
+ validate: (value, context) => {
222
+ if (typeof value === "string" &&
223
+ !MANUAL_REST_CONTRACT_HTTP_METHOD_IDS.includes(value)) {
224
+ throw new Error(`${context.entryName}[${context.elementIndex}].${context.key} must be one of: ${MANUAL_REST_CONTRACT_HTTP_METHOD_IDS.join(", ")}.`);
225
+ }
226
+ },
227
+ },
228
+ {
229
+ key: "methods",
230
+ kind: "stringArray",
231
+ required: true,
232
+ validate: (value, context) => {
233
+ const methods = Array.isArray(value) ? value : [];
234
+ const invalidMethods = methods.filter((method) => !REST_RESOURCE_METHOD_IDS.includes(method));
235
+ if (invalidMethods.length > 0) {
236
+ throw new Error(`${context.entryName}[${context.elementIndex}].${context.key} includes unsupported values: ${invalidMethods.join(", ")}.`);
237
+ }
238
+ },
239
+ },
240
+ {
241
+ key: "mode",
242
+ validate: (value, context) => {
243
+ if (typeof value === "string" &&
244
+ value !== "generated" &&
245
+ value !== "manual") {
246
+ throw new Error(`${context.entryName}[${context.elementIndex}].${context.key} must be generated or manual.`);
247
+ }
248
+ },
249
+ },
250
+ { key: "namespace", required: true },
251
+ { key: "openApiFile", required: true },
252
+ { key: "pathPattern" },
253
+ { key: "permissionCallback" },
254
+ { key: "phpFile" },
255
+ { key: "queryTypeName" },
256
+ { key: "responseTypeName" },
257
+ { key: "routePattern" },
258
+ { key: "secretFieldName" },
259
+ { key: "secretStateFieldName" },
260
+ { key: "slug", required: true },
261
+ { key: "typesFile", required: true },
262
+ { key: "validatorsFile", required: true },
263
+ ],
264
+ }),
265
+ hasSectionKey: "hasRestResourcesSection",
266
+ },
267
+ value: {
268
+ name: "REST_RESOURCES",
269
+ section: REST_RESOURCES_CONST_SECTION,
270
+ },
271
+ },
272
+ {
273
+ append: {
274
+ marker: POST_META_CONFIG_ENTRY_MARKER,
275
+ optionKey: "postMetaEntries",
276
+ },
277
+ interface: {
278
+ name: "WorkspacePostMetaConfig",
279
+ section: POST_META_INTERFACE_SECTION,
280
+ },
281
+ parse: {
282
+ entriesKey: "postMeta",
283
+ entry: defineInventoryEntryParser()({
284
+ entryName: "POST_META",
285
+ fields: [
286
+ { key: "metaKey", required: true },
287
+ { key: "phpFile", required: true },
288
+ { key: "postType", required: true },
289
+ { key: "schemaFile", required: true },
290
+ { key: "showInRest", kind: "boolean", required: true },
291
+ { key: "slug", required: true },
292
+ { key: "sourceTypeName", required: true },
293
+ { key: "typesFile", required: true },
294
+ ],
295
+ }),
296
+ hasSectionKey: "hasPostMetaSection",
297
+ },
298
+ value: {
299
+ name: "POST_META",
300
+ section: POST_META_CONST_SECTION,
301
+ },
302
+ },
303
+ {
304
+ append: {
305
+ marker: ABILITY_CONFIG_ENTRY_MARKER,
306
+ optionKey: "abilityEntries",
307
+ },
308
+ interface: {
309
+ name: "WorkspaceAbilityConfig",
310
+ section: ABILITIES_INTERFACE_SECTION,
311
+ },
312
+ parse: {
313
+ entriesKey: "abilities",
314
+ entry: defineInventoryEntryParser()({
315
+ entryName: "ABILITIES",
316
+ fields: [
317
+ { key: "clientFile", required: true },
318
+ { key: "configFile", required: true },
319
+ { key: "dataFile", required: true },
320
+ { key: "inputSchemaFile", required: true },
321
+ { key: "inputTypeName", required: true },
322
+ { key: "outputSchemaFile", required: true },
323
+ { key: "outputTypeName", required: true },
324
+ { key: "phpFile", required: true },
325
+ { key: "slug", required: true },
326
+ { key: "typesFile", required: true },
327
+ ],
328
+ }),
329
+ hasSectionKey: "hasAbilitiesSection",
330
+ },
331
+ value: {
332
+ name: "ABILITIES",
333
+ section: ABILITIES_CONST_SECTION,
334
+ },
335
+ },
336
+ {
337
+ append: {
338
+ marker: AI_FEATURE_CONFIG_ENTRY_MARKER,
339
+ optionKey: "aiFeatureEntries",
340
+ },
341
+ interface: {
342
+ name: "WorkspaceAiFeatureConfig",
343
+ section: AI_FEATURES_INTERFACE_SECTION,
344
+ },
345
+ parse: {
346
+ entriesKey: "aiFeatures",
347
+ entry: defineInventoryEntryParser()({
348
+ entryName: "AI_FEATURES",
349
+ fields: [
350
+ { key: "aiSchemaFile", required: true },
351
+ { key: "apiFile", required: true },
352
+ { key: "clientFile", required: true },
353
+ { key: "dataFile", required: true },
354
+ { key: "namespace", required: true },
355
+ { key: "openApiFile", required: true },
356
+ { key: "phpFile", required: true },
357
+ { key: "slug", required: true },
358
+ { key: "typesFile", required: true },
359
+ { key: "validatorsFile", required: true },
360
+ ],
361
+ }),
362
+ hasSectionKey: "hasAiFeaturesSection",
363
+ },
364
+ value: {
365
+ name: "AI_FEATURES",
366
+ section: AI_FEATURES_CONST_SECTION,
367
+ },
368
+ },
369
+ {
370
+ append: {
371
+ marker: ADMIN_VIEW_CONFIG_ENTRY_MARKER,
372
+ optionKey: "adminViewEntries",
373
+ },
374
+ interface: {
375
+ name: "WorkspaceAdminViewConfig",
376
+ section: ADMIN_VIEWS_INTERFACE_SECTION,
377
+ },
378
+ parse: {
379
+ entriesKey: "adminViews",
380
+ entry: defineInventoryEntryParser()({
381
+ entryName: "ADMIN_VIEWS",
382
+ fields: [
383
+ { key: "file", required: true },
384
+ { key: "phpFile", required: true },
385
+ { key: "slug", required: true },
386
+ { key: "source" },
387
+ ],
388
+ }),
389
+ hasSectionKey: "hasAdminViewsSection",
390
+ },
391
+ value: {
392
+ name: "ADMIN_VIEWS",
393
+ section: ADMIN_VIEWS_CONST_SECTION,
394
+ },
395
+ },
396
+ {
397
+ append: {
398
+ marker: EDITOR_PLUGIN_CONFIG_ENTRY_MARKER,
399
+ optionKey: "editorPluginEntries",
400
+ },
401
+ interface: {
402
+ name: "WorkspaceEditorPluginConfig",
403
+ section: EDITOR_PLUGINS_INTERFACE_SECTION,
404
+ },
405
+ parse: {
406
+ entriesKey: "editorPlugins",
407
+ entry: defineInventoryEntryParser()({
408
+ entryName: "EDITOR_PLUGINS",
409
+ fields: [
410
+ { key: "file", required: true },
411
+ { key: "slug", required: true },
412
+ { key: "slot", required: true },
413
+ ],
414
+ }),
415
+ hasSectionKey: "hasEditorPluginsSection",
416
+ },
417
+ value: {
418
+ name: "EDITOR_PLUGINS",
419
+ section: EDITOR_PLUGINS_CONST_SECTION,
420
+ },
421
+ },
422
+ ];
423
+ function findExportedArrayLiteral(sourceFile, exportName) {
424
+ for (const statement of sourceFile.statements) {
425
+ if (!ts.isVariableStatement(statement)) {
426
+ continue;
427
+ }
428
+ if (!statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)) {
429
+ continue;
430
+ }
431
+ for (const declaration of statement.declarationList.declarations) {
432
+ if (!ts.isIdentifier(declaration.name) ||
433
+ declaration.name.text !== exportName) {
434
+ continue;
435
+ }
436
+ if (declaration.initializer &&
437
+ ts.isArrayLiteralExpression(declaration.initializer)) {
438
+ return {
439
+ array: declaration.initializer,
440
+ found: true,
441
+ };
442
+ }
443
+ return {
444
+ array: null,
445
+ found: true,
446
+ };
447
+ }
448
+ }
449
+ return {
450
+ array: null,
451
+ found: false,
452
+ };
453
+ }
454
+ function getOptionalStringProperty(entryName, elementIndex, objectLiteral, key) {
455
+ for (const property of objectLiteral.properties) {
456
+ if (!ts.isPropertyAssignment(property)) {
457
+ continue;
458
+ }
459
+ const propertyName = getPropertyNameText(property.name);
460
+ if (propertyName !== key) {
461
+ continue;
462
+ }
463
+ if (ts.isStringLiteralLike(property.initializer)) {
464
+ return property.initializer.text;
465
+ }
466
+ throw new Error(`${entryName}[${elementIndex}] must use a string literal for "${key}" in scripts/block-config.ts.`);
467
+ }
468
+ return undefined;
469
+ }
470
+ function getOptionalStringArrayProperty(entryName, elementIndex, objectLiteral, key) {
471
+ for (const property of objectLiteral.properties) {
472
+ if (!ts.isPropertyAssignment(property)) {
473
+ continue;
474
+ }
475
+ const propertyName = getPropertyNameText(property.name);
476
+ if (propertyName !== key) {
477
+ continue;
478
+ }
479
+ if (!ts.isArrayLiteralExpression(property.initializer)) {
480
+ throw new Error(`${entryName}[${elementIndex}] must use an array literal for "${key}" in scripts/block-config.ts.`);
481
+ }
482
+ return property.initializer.elements.map((element, itemIndex) => {
483
+ if (!ts.isStringLiteralLike(element)) {
484
+ throw new Error(`${entryName}[${elementIndex}].${key}[${itemIndex}] must use a string literal in scripts/block-config.ts.`);
485
+ }
486
+ return element.text;
487
+ });
488
+ }
489
+ return undefined;
490
+ }
491
+ function getOptionalBooleanProperty(entryName, elementIndex, objectLiteral, key) {
492
+ for (const property of objectLiteral.properties) {
493
+ if (!ts.isPropertyAssignment(property)) {
494
+ continue;
495
+ }
496
+ const propertyName = getPropertyNameText(property.name);
497
+ if (propertyName !== key) {
498
+ continue;
499
+ }
500
+ if (property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
501
+ return true;
502
+ }
503
+ if (property.initializer.kind === ts.SyntaxKind.FalseKeyword) {
504
+ return false;
505
+ }
506
+ throw new Error(`${entryName}[${elementIndex}] must use a boolean literal for "${key}" in scripts/block-config.ts.`);
507
+ }
508
+ return undefined;
509
+ }
510
+ function isMissingRequiredInventoryValue(value) {
511
+ return (value === undefined || (typeof value === "string" && value.length === 0));
512
+ }
513
+ function formatMissingRequiredInventoryFields(keys) {
514
+ return keys.length === 1
515
+ ? `required "${keys[0]}"`
516
+ : `required fields ${keys.map((key) => `"${key}"`).join(", ")}`;
517
+ }
518
+ function assertParsedInventoryEntry(entry, descriptor, elementIndex) {
519
+ const missingRequiredKeys = descriptor.fields
520
+ .filter((field) => field.required === true &&
521
+ isMissingRequiredInventoryValue(entry[field.key]))
522
+ .map((field) => field.key);
523
+ if (missingRequiredKeys.length > 0) {
524
+ throw new Error(`${descriptor.entryName}[${elementIndex}] is missing ${formatMissingRequiredInventoryFields(missingRequiredKeys)} in scripts/block-config.ts.`);
525
+ }
526
+ }
527
+ function parseInventoryEntries(arrayLiteral, descriptor) {
528
+ return arrayLiteral.elements.map((element, elementIndex) => {
529
+ if (!ts.isObjectLiteralExpression(element)) {
530
+ throw new Error(`${descriptor.entryName}[${elementIndex}] must be an object literal in scripts/block-config.ts.`);
531
+ }
532
+ const entry = {};
533
+ for (const field of descriptor.fields) {
534
+ const kind = field.kind ?? "string";
535
+ const value = kind === "stringArray"
536
+ ? getOptionalStringArrayProperty(descriptor.entryName, elementIndex, element, field.key)
537
+ : kind === "boolean"
538
+ ? getOptionalBooleanProperty(descriptor.entryName, elementIndex, element, field.key)
539
+ : getOptionalStringProperty(descriptor.entryName, elementIndex, element, field.key);
540
+ field.validate?.(value, {
541
+ elementIndex,
542
+ entryName: descriptor.entryName,
543
+ key: field.key,
544
+ });
545
+ entry[field.key] = value;
546
+ }
547
+ assertParsedInventoryEntry(entry, descriptor, elementIndex);
548
+ return entry;
549
+ });
550
+ }
551
+ function parseInventorySection(sourceFile, descriptor) {
552
+ if (!descriptor.parse) {
553
+ return {
554
+ entries: [],
555
+ found: false,
556
+ };
557
+ }
558
+ const exportName = descriptor.parse.exportName ?? descriptor.value?.name;
559
+ if (!exportName) {
560
+ throw new Error("Inventory parser descriptor is missing an export name.");
561
+ }
562
+ const exportedArray = findExportedArrayLiteral(sourceFile, exportName);
563
+ if (!exportedArray.found) {
564
+ if (descriptor.parse.required) {
565
+ throw new Error(`scripts/block-config.ts must export a ${exportName} array.`);
566
+ }
567
+ return {
568
+ entries: [],
569
+ found: false,
570
+ };
571
+ }
572
+ if (!exportedArray.array) {
573
+ if (descriptor.parse.required) {
574
+ throw new Error(`scripts/block-config.ts must export a ${exportName} array.`);
575
+ }
576
+ throw new Error(`scripts/block-config.ts must export ${exportName} as an array literal.`);
577
+ }
578
+ return {
579
+ entries: parseInventoryEntries(exportedArray.array, descriptor.parse.entry),
580
+ found: true,
581
+ };
582
+ }
583
+ /**
584
+ * Parse workspace inventory entries from the source of `scripts/block-config.ts`.
585
+ *
586
+ * @param source Raw TypeScript source from `scripts/block-config.ts`.
587
+ * @returns Parsed inventory sections without the resolved `blockConfigPath`.
588
+ * @throws {Error} When `BLOCKS` is missing or any inventory entry is malformed.
589
+ */
590
+ export function parseWorkspaceInventorySource(source) {
591
+ const sourceFile = ts.createSourceFile("block-config.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
592
+ const parsedInventory = {
593
+ abilities: [],
594
+ adminViews: [],
595
+ aiFeatures: [],
596
+ bindingSources: [],
597
+ blockStyles: [],
598
+ blockTransforms: [],
599
+ blocks: parseInventorySection(sourceFile, BLOCK_INVENTORY_SECTION).entries,
600
+ contracts: [],
601
+ editorPlugins: [],
602
+ hasAbilitiesSection: false,
603
+ hasAdminViewsSection: false,
604
+ hasAiFeaturesSection: false,
605
+ hasBindingSourcesSection: false,
606
+ hasBlockStylesSection: false,
607
+ hasBlockTransformsSection: false,
608
+ hasContractsSection: false,
609
+ hasEditorPluginsSection: false,
610
+ hasPatternsSection: false,
611
+ hasPostMetaSection: false,
612
+ hasRestResourcesSection: false,
613
+ hasVariationsSection: false,
614
+ patterns: [],
615
+ postMeta: [],
616
+ restResources: [],
617
+ source,
618
+ variations: [],
619
+ };
620
+ const mutableInventory = parsedInventory;
621
+ for (const section of INVENTORY_SECTIONS) {
622
+ if (!section.parse) {
623
+ continue;
624
+ }
625
+ const parsedSection = parseInventorySection(sourceFile, section);
626
+ mutableInventory[section.parse.entriesKey] = parsedSection.entries;
627
+ if (section.parse.hasSectionKey) {
628
+ mutableInventory[section.parse.hasSectionKey] = parsedSection.found;
629
+ }
630
+ }
631
+ return parsedInventory;
632
+ }
@@ -0,0 +1,51 @@
1
+ import type { WorkspaceBlockSelectOption, WorkspaceInventory } from "./workspace-inventory-types.js";
2
+ /**
3
+ * Synchronously read and parse the canonical workspace inventory file.
4
+ *
5
+ * This compatibility helper is intentionally sync-only for callers that expose
6
+ * synchronous APIs. Prefer `readWorkspaceInventoryAsync()` from async command
7
+ * paths so workspace reads do not block the event loop.
8
+ *
9
+ * @deprecated Since 0.22.10. Use `readWorkspaceInventoryAsync()` from async
10
+ * command paths. Removal target: not currently scheduled; this sync
11
+ * compatibility helper remains available until release notes announce a
12
+ * versioned target.
13
+ *
14
+ * @param projectDir Workspace root directory.
15
+ * @returns Parsed `WorkspaceInventory` including the resolved `blockConfigPath`.
16
+ * @throws {Error} When `scripts/block-config.ts` is missing or invalid.
17
+ */
18
+ export declare function readWorkspaceInventory(projectDir: string): WorkspaceInventory;
19
+ /**
20
+ * Asynchronously read and parse the canonical workspace inventory file.
21
+ *
22
+ * @param projectDir Workspace root directory.
23
+ * @returns Parsed `WorkspaceInventory` including the resolved `blockConfigPath`.
24
+ * @throws {Error} When `scripts/block-config.ts` is missing or invalid.
25
+ */
26
+ export declare function readWorkspaceInventoryAsync(projectDir: string): Promise<WorkspaceInventory>;
27
+ /**
28
+ * Synchronously return select options for the current workspace block inventory.
29
+ *
30
+ * The `description` field mirrors `block.typesFile`, while `name` and `value`
31
+ * both map to the block slug for use in interactive add flows.
32
+ *
33
+ * @deprecated Since 0.22.10. Use `getWorkspaceBlockSelectOptionsAsync()` from
34
+ * async command paths. Removal target: not currently scheduled; this sync
35
+ * compatibility helper remains available until release notes announce a
36
+ * versioned target.
37
+ *
38
+ * @param projectDir Workspace root directory.
39
+ * @returns Block options for variation-target selection.
40
+ */
41
+ export declare function getWorkspaceBlockSelectOptions(projectDir: string): WorkspaceBlockSelectOption[];
42
+ /**
43
+ * Asynchronously return select options for the current workspace block inventory.
44
+ *
45
+ * The returned option shape matches `getWorkspaceBlockSelectOptions()` while
46
+ * avoiding synchronous inventory reads in interactive or async command paths.
47
+ *
48
+ * @param projectDir Workspace root directory.
49
+ * @returns Block options for variation-target selection.
50
+ */
51
+ export declare function getWorkspaceBlockSelectOptionsAsync(projectDir: string): Promise<WorkspaceBlockSelectOption[]>;