@wp-typia/project-tools 0.22.7 → 0.22.9

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 (63) hide show
  1. package/dist/runtime/block-targets.d.ts +40 -0
  2. package/dist/runtime/block-targets.js +71 -0
  3. package/dist/runtime/built-in-block-artifact-types.js +2 -1
  4. package/dist/runtime/built-in-block-attribute-specs.js +2 -1
  5. package/dist/runtime/built-in-block-code-artifacts.js +2 -0
  6. package/dist/runtime/built-in-block-non-ts-family-artifacts.js +12 -9
  7. package/dist/runtime/built-in-block-non-ts-render-utils.js +2 -0
  8. package/dist/runtime/cli-add-block-config.js +2 -1
  9. package/dist/runtime/cli-add-block.js +16 -4
  10. package/dist/runtime/cli-add-types.d.ts +8 -0
  11. package/dist/runtime/cli-add-types.js +11 -0
  12. package/dist/runtime/cli-add-workspace-ability-scaffold.js +21 -15
  13. package/dist/runtime/cli-add-workspace-ability.js +2 -2
  14. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +17 -13
  15. package/dist/runtime/cli-add-workspace-admin-view.js +2 -2
  16. package/dist/runtime/cli-add-workspace-ai.js +2 -2
  17. package/dist/runtime/cli-add-workspace-assets.js +42 -48
  18. package/dist/runtime/cli-add-workspace-rest.js +2 -2
  19. package/dist/runtime/cli-add-workspace.js +6 -38
  20. package/dist/runtime/cli-add.d.ts +3 -2
  21. package/dist/runtime/cli-add.js +2 -2
  22. package/dist/runtime/cli-core.d.ts +4 -2
  23. package/dist/runtime/cli-core.js +3 -2
  24. package/dist/runtime/cli-diagnostics.js +6 -0
  25. package/dist/runtime/cli-doctor-workspace.js +2 -0
  26. package/dist/runtime/cli-scaffold.js +5 -4
  27. package/dist/runtime/create-template-validation.d.ts +10 -0
  28. package/dist/runtime/create-template-validation.js +95 -0
  29. package/dist/runtime/id-suggestions.d.ts +21 -0
  30. package/dist/runtime/id-suggestions.js +48 -0
  31. package/dist/runtime/index.d.ts +5 -2
  32. package/dist/runtime/index.js +3 -1
  33. package/dist/runtime/migration-maintenance-verify.js +2 -0
  34. package/dist/runtime/package-versions.js +15 -2
  35. package/dist/runtime/php-utils.js +66 -0
  36. package/dist/runtime/scaffold-answer-resolution.js +5 -108
  37. package/dist/runtime/scaffold-apply-utils.js +3 -2
  38. package/dist/runtime/scaffold-identifiers.js +4 -3
  39. package/dist/runtime/scaffold-template-assertions.d.ts +6 -0
  40. package/dist/runtime/scaffold-template-assertions.js +33 -0
  41. package/dist/runtime/scaffold-template-variable-groups.d.ts +2 -0
  42. package/dist/runtime/scaffold-template-variable-groups.js +7 -0
  43. package/dist/runtime/scaffold.js +3 -3
  44. package/dist/runtime/string-case.d.ts +2 -4
  45. package/dist/runtime/string-case.js +13 -4
  46. package/dist/runtime/template-builtins.js +11 -8
  47. package/dist/runtime/template-layers.js +2 -2
  48. package/dist/runtime/template-source-cache-policy.d.ts +53 -0
  49. package/dist/runtime/template-source-cache-policy.js +135 -0
  50. package/dist/runtime/template-source-cache.d.ts +1 -45
  51. package/dist/runtime/template-source-cache.js +9 -152
  52. package/dist/runtime/template-source-external.d.ts +3 -0
  53. package/dist/runtime/template-source-external.js +5 -2
  54. package/dist/runtime/template-source-remote.d.ts +6 -0
  55. package/dist/runtime/template-source-remote.js +8 -2
  56. package/dist/runtime/template-source-seeds.d.ts +13 -0
  57. package/dist/runtime/template-source-seeds.js +36 -8
  58. package/dist/runtime/template-source.js +2 -2
  59. package/dist/runtime/ts-property-names.d.ts +11 -0
  60. package/dist/runtime/ts-property-names.js +16 -0
  61. package/dist/runtime/workspace-inventory.d.ts +33 -7
  62. package/dist/runtime/workspace-inventory.js +94 -41
  63. package/package.json +11 -1
@@ -0,0 +1,16 @@
1
+ import ts from "typescript";
2
+ /**
3
+ * Extract the literal text for TypeScript property names this runtime supports.
4
+ *
5
+ * Computed property names are intentionally not resolved because their runtime
6
+ * values are not statically knowable from the syntax node alone.
7
+ *
8
+ * @param name TypeScript property name node.
9
+ * @returns Identifier, string-literal, or numeric-literal text; otherwise `null`.
10
+ */
11
+ export function getPropertyNameText(name) {
12
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) {
13
+ return name.text;
14
+ }
15
+ return null;
16
+ }
@@ -142,6 +142,11 @@ export interface WorkspaceInventory {
142
142
  source: string;
143
143
  variations: WorkspaceVariationInventoryEntry[];
144
144
  }
145
+ export type WorkspaceBlockSelectOption = {
146
+ description: string;
147
+ name: string;
148
+ value: string;
149
+ };
145
150
  export declare const BLOCK_CONFIG_ENTRY_MARKER = "\t// wp-typia add block entries";
146
151
  export declare const VARIATION_CONFIG_ENTRY_MARKER = "\t// wp-typia add variation entries";
147
152
  export declare const BLOCK_STYLE_CONFIG_ENTRY_MARKER = "\t// wp-typia add style entries";
@@ -179,7 +184,11 @@ type WorkspaceInventoryUpdateOptions = {
179
184
  */
180
185
  export declare function parseWorkspaceInventorySource(source: string): Omit<WorkspaceInventory, "blockConfigPath">;
181
186
  /**
182
- * Read and parse the canonical workspace inventory file.
187
+ * Synchronously read and parse the canonical workspace inventory file.
188
+ *
189
+ * This compatibility helper is intentionally sync-only for callers that expose
190
+ * synchronous APIs. Prefer `readWorkspaceInventoryAsync()` from async command
191
+ * paths so workspace reads do not block the event loop.
183
192
  *
184
193
  * @param projectDir Workspace root directory.
185
194
  * @returns Parsed `WorkspaceInventory` including the resolved `blockConfigPath`.
@@ -187,19 +196,36 @@ export declare function parseWorkspaceInventorySource(source: string): Omit<Work
187
196
  */
188
197
  export declare function readWorkspaceInventory(projectDir: string): WorkspaceInventory;
189
198
  /**
190
- * Return select options for the current workspace block inventory.
199
+ * Asynchronously read and parse the canonical workspace inventory file.
200
+ *
201
+ * @param projectDir Workspace root directory.
202
+ * @returns Parsed `WorkspaceInventory` including the resolved `blockConfigPath`.
203
+ * @throws {Error} When `scripts/block-config.ts` is missing or invalid.
204
+ */
205
+ export declare function readWorkspaceInventoryAsync(projectDir: string): Promise<WorkspaceInventory>;
206
+ /**
207
+ * Synchronously return select options for the current workspace block inventory.
191
208
  *
192
209
  * The `description` field mirrors `block.typesFile`, while `name` and `value`
193
210
  * both map to the block slug for use in interactive add flows.
194
211
  *
212
+ * @deprecated Use `getWorkspaceBlockSelectOptionsAsync()` from async command
213
+ * paths. This helper intentionally remains sync-only for compatibility callers.
214
+ *
195
215
  * @param projectDir Workspace root directory.
196
216
  * @returns Block options for variation-target selection.
197
217
  */
198
- export declare function getWorkspaceBlockSelectOptions(projectDir: string): Array<{
199
- description: string;
200
- name: string;
201
- value: string;
202
- }>;
218
+ export declare function getWorkspaceBlockSelectOptions(projectDir: string): WorkspaceBlockSelectOption[];
219
+ /**
220
+ * Asynchronously return select options for the current workspace block inventory.
221
+ *
222
+ * The returned option shape matches `getWorkspaceBlockSelectOptions()` while
223
+ * avoiding synchronous inventory reads in interactive or async command paths.
224
+ *
225
+ * @param projectDir Workspace root directory.
226
+ * @returns Block options for variation-target selection.
227
+ */
228
+ export declare function getWorkspaceBlockSelectOptionsAsync(projectDir: string): Promise<WorkspaceBlockSelectOption[]>;
203
229
  /**
204
230
  * Update `scripts/block-config.ts` source text with additional inventory entries.
205
231
  *
@@ -1,11 +1,12 @@
1
- import fs from "node:fs";
1
+ import { readFileSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  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;
7
+ import { getPropertyNameText } from "./ts-property-names.js";
8
+ function defineInventoryEntryParser() {
9
+ return (descriptor) => descriptor;
9
10
  }
10
11
  export const BLOCK_CONFIG_ENTRY_MARKER = "\t// wp-typia add block entries";
11
12
  export const VARIATION_CONFIG_ENTRY_MARKER = "\t// wp-typia add variation entries";
@@ -212,7 +213,7 @@ const BLOCK_INVENTORY_SECTION = {
212
213
  },
213
214
  parse: {
214
215
  entriesKey: "blocks",
215
- entry: defineInventoryEntryParser({
216
+ entry: defineInventoryEntryParser()({
216
217
  entryName: "BLOCKS",
217
218
  fields: [
218
219
  { key: "apiTypesFile" },
@@ -238,7 +239,7 @@ const INVENTORY_SECTIONS = [
238
239
  },
239
240
  parse: {
240
241
  entriesKey: "variations",
241
- entry: defineInventoryEntryParser({
242
+ entry: defineInventoryEntryParser()({
242
243
  entryName: "VARIATIONS",
243
244
  fields: [
244
245
  { key: "block", required: true },
@@ -264,7 +265,7 @@ const INVENTORY_SECTIONS = [
264
265
  },
265
266
  parse: {
266
267
  entriesKey: "blockStyles",
267
- entry: defineInventoryEntryParser({
268
+ entry: defineInventoryEntryParser()({
268
269
  entryName: "BLOCK_STYLES",
269
270
  fields: [
270
271
  { key: "block", required: true },
@@ -290,7 +291,7 @@ const INVENTORY_SECTIONS = [
290
291
  },
291
292
  parse: {
292
293
  entriesKey: "blockTransforms",
293
- entry: defineInventoryEntryParser({
294
+ entry: defineInventoryEntryParser()({
294
295
  entryName: "BLOCK_TRANSFORMS",
295
296
  fields: [
296
297
  { key: "block", required: true },
@@ -318,7 +319,7 @@ const INVENTORY_SECTIONS = [
318
319
  },
319
320
  parse: {
320
321
  entriesKey: "patterns",
321
- entry: defineInventoryEntryParser({
322
+ entry: defineInventoryEntryParser()({
322
323
  entryName: "PATTERNS",
323
324
  fields: [
324
325
  { key: "file", required: true },
@@ -343,7 +344,7 @@ const INVENTORY_SECTIONS = [
343
344
  },
344
345
  parse: {
345
346
  entriesKey: "bindingSources",
346
- entry: defineInventoryEntryParser({
347
+ entry: defineInventoryEntryParser()({
347
348
  entryName: "BINDING_SOURCES",
348
349
  fields: [
349
350
  { key: "attribute" },
@@ -371,7 +372,7 @@ const INVENTORY_SECTIONS = [
371
372
  },
372
373
  parse: {
373
374
  entriesKey: "restResources",
374
- entry: defineInventoryEntryParser({
375
+ entry: defineInventoryEntryParser()({
375
376
  entryName: "REST_RESOURCES",
376
377
  fields: [
377
378
  { key: "apiFile", required: true },
@@ -415,7 +416,7 @@ const INVENTORY_SECTIONS = [
415
416
  },
416
417
  parse: {
417
418
  entriesKey: "abilities",
418
- entry: defineInventoryEntryParser({
419
+ entry: defineInventoryEntryParser()({
419
420
  entryName: "ABILITIES",
420
421
  fields: [
421
422
  { key: "clientFile", required: true },
@@ -448,7 +449,7 @@ const INVENTORY_SECTIONS = [
448
449
  },
449
450
  parse: {
450
451
  entriesKey: "aiFeatures",
451
- entry: defineInventoryEntryParser({
452
+ entry: defineInventoryEntryParser()({
452
453
  entryName: "AI_FEATURES",
453
454
  fields: [
454
455
  { key: "aiSchemaFile", required: true },
@@ -481,7 +482,7 @@ const INVENTORY_SECTIONS = [
481
482
  },
482
483
  parse: {
483
484
  entriesKey: "adminViews",
484
- entry: defineInventoryEntryParser({
485
+ entry: defineInventoryEntryParser()({
485
486
  entryName: "ADMIN_VIEWS",
486
487
  fields: [
487
488
  { key: "file", required: true },
@@ -508,7 +509,7 @@ const INVENTORY_SECTIONS = [
508
509
  },
509
510
  parse: {
510
511
  entriesKey: "editorPlugins",
511
- entry: defineInventoryEntryParser({
512
+ entry: defineInventoryEntryParser()({
512
513
  entryName: "EDITOR_PLUGINS",
513
514
  fields: [
514
515
  { key: "file", required: true },
@@ -524,12 +525,6 @@ const INVENTORY_SECTIONS = [
524
525
  },
525
526
  },
526
527
  ];
527
- function getPropertyNameText(name) {
528
- if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
529
- return name.text;
530
- }
531
- return null;
532
- }
533
528
  function findExportedArrayLiteral(sourceFile, exportName) {
534
529
  for (const statement of sourceFile.statements) {
535
530
  if (!ts.isVariableStatement(statement)) {
@@ -575,14 +570,7 @@ function getOptionalStringProperty(entryName, elementIndex, objectLiteral, key)
575
570
  }
576
571
  return undefined;
577
572
  }
578
- function getRequiredStringProperty(entryName, elementIndex, objectLiteral, key) {
579
- const value = getOptionalStringProperty(entryName, elementIndex, objectLiteral, key);
580
- if (!value) {
581
- throw new Error(`${entryName}[${elementIndex}] is missing required "${key}" in scripts/block-config.ts.`);
582
- }
583
- return value;
584
- }
585
- function getRequiredStringArrayProperty(entryName, elementIndex, objectLiteral, key) {
573
+ function getOptionalStringArrayProperty(entryName, elementIndex, objectLiteral, key) {
586
574
  for (const property of objectLiteral.properties) {
587
575
  if (!ts.isPropertyAssignment(property)) {
588
576
  continue;
@@ -601,7 +589,24 @@ function getRequiredStringArrayProperty(entryName, elementIndex, objectLiteral,
601
589
  return element.text;
602
590
  });
603
591
  }
604
- throw new Error(`${entryName}[${elementIndex}] is missing required "${key}" in scripts/block-config.ts.`);
592
+ return undefined;
593
+ }
594
+ function isMissingRequiredInventoryValue(value) {
595
+ return value === undefined || (typeof value === "string" && value.length === 0);
596
+ }
597
+ function formatMissingRequiredInventoryFields(keys) {
598
+ return keys.length === 1
599
+ ? `required "${keys[0]}"`
600
+ : `required fields ${keys.map((key) => `"${key}"`).join(", ")}`;
601
+ }
602
+ function assertParsedInventoryEntry(entry, descriptor, elementIndex) {
603
+ const missingRequiredKeys = descriptor.fields
604
+ .filter((field) => field.required === true &&
605
+ isMissingRequiredInventoryValue(entry[field.key]))
606
+ .map((field) => field.key);
607
+ if (missingRequiredKeys.length > 0) {
608
+ throw new Error(`${descriptor.entryName}[${elementIndex}] is missing ${formatMissingRequiredInventoryFields(missingRequiredKeys)} in scripts/block-config.ts.`);
609
+ }
605
610
  }
606
611
  function parseInventoryEntries(arrayLiteral, descriptor) {
607
612
  return arrayLiteral.elements.map((element, elementIndex) => {
@@ -612,10 +617,8 @@ function parseInventoryEntries(arrayLiteral, descriptor) {
612
617
  for (const field of descriptor.fields) {
613
618
  const kind = field.kind ?? "string";
614
619
  const value = kind === "stringArray"
615
- ? getRequiredStringArrayProperty(descriptor.entryName, elementIndex, element, field.key)
616
- : field.required
617
- ? getRequiredStringProperty(descriptor.entryName, elementIndex, element, field.key)
618
- : getOptionalStringProperty(descriptor.entryName, elementIndex, element, field.key);
620
+ ? getOptionalStringArrayProperty(descriptor.entryName, elementIndex, element, field.key)
621
+ : getOptionalStringProperty(descriptor.entryName, elementIndex, element, field.key);
619
622
  field.validate?.(value, {
620
623
  elementIndex,
621
624
  entryName: descriptor.entryName,
@@ -623,6 +626,7 @@ function parseInventoryEntries(arrayLiteral, descriptor) {
623
626
  });
624
627
  entry[field.key] = value;
625
628
  }
629
+ assertParsedInventoryEntry(entry, descriptor, elementIndex);
626
630
  return entry;
627
631
  });
628
632
  }
@@ -705,7 +709,11 @@ export function parseWorkspaceInventorySource(source) {
705
709
  return parsedInventory;
706
710
  }
707
711
  /**
708
- * Read and parse the canonical workspace inventory file.
712
+ * Synchronously read and parse the canonical workspace inventory file.
713
+ *
714
+ * This compatibility helper is intentionally sync-only for callers that expose
715
+ * synchronous APIs. Prefer `readWorkspaceInventoryAsync()` from async command
716
+ * paths so workspace reads do not block the event loop.
709
717
  *
710
718
  * @param projectDir Workspace root directory.
711
719
  * @returns Parsed `WorkspaceInventory` including the resolved `blockConfigPath`.
@@ -715,7 +723,7 @@ export function readWorkspaceInventory(projectDir) {
715
723
  const blockConfigPath = path.join(projectDir, "scripts", "block-config.ts");
716
724
  let source;
717
725
  try {
718
- source = fs.readFileSync(blockConfigPath, "utf8");
726
+ source = readFileSync(blockConfigPath, "utf8");
719
727
  }
720
728
  catch (error) {
721
729
  if (typeof error === "object" &&
@@ -732,20 +740,65 @@ export function readWorkspaceInventory(projectDir) {
732
740
  };
733
741
  }
734
742
  /**
735
- * Return select options for the current workspace block inventory.
743
+ * Asynchronously read and parse the canonical workspace inventory file.
744
+ *
745
+ * @param projectDir Workspace root directory.
746
+ * @returns Parsed `WorkspaceInventory` including the resolved `blockConfigPath`.
747
+ * @throws {Error} When `scripts/block-config.ts` is missing or invalid.
748
+ */
749
+ export async function readWorkspaceInventoryAsync(projectDir) {
750
+ const blockConfigPath = path.join(projectDir, "scripts", "block-config.ts");
751
+ let source;
752
+ try {
753
+ source = await readFile(blockConfigPath, "utf8");
754
+ }
755
+ catch (error) {
756
+ if (typeof error === "object" &&
757
+ error !== null &&
758
+ "code" in error &&
759
+ error.code === "ENOENT") {
760
+ throw new Error(`Workspace inventory file is missing at ${blockConfigPath}. Expected scripts/block-config.ts to exist.`);
761
+ }
762
+ throw error;
763
+ }
764
+ return {
765
+ blockConfigPath,
766
+ ...parseWorkspaceInventorySource(source),
767
+ };
768
+ }
769
+ function toWorkspaceBlockSelectOptions(blocks) {
770
+ return blocks.map((block) => ({
771
+ description: block.typesFile,
772
+ name: block.slug,
773
+ value: block.slug,
774
+ }));
775
+ }
776
+ /**
777
+ * Synchronously return select options for the current workspace block inventory.
736
778
  *
737
779
  * The `description` field mirrors `block.typesFile`, while `name` and `value`
738
780
  * both map to the block slug for use in interactive add flows.
739
781
  *
782
+ * @deprecated Use `getWorkspaceBlockSelectOptionsAsync()` from async command
783
+ * paths. This helper intentionally remains sync-only for compatibility callers.
784
+ *
740
785
  * @param projectDir Workspace root directory.
741
786
  * @returns Block options for variation-target selection.
742
787
  */
743
788
  export function getWorkspaceBlockSelectOptions(projectDir) {
744
- return readWorkspaceInventory(projectDir).blocks.map((block) => ({
745
- description: block.typesFile,
746
- name: block.slug,
747
- value: block.slug,
748
- }));
789
+ return toWorkspaceBlockSelectOptions(readWorkspaceInventory(projectDir).blocks);
790
+ }
791
+ /**
792
+ * Asynchronously return select options for the current workspace block inventory.
793
+ *
794
+ * The returned option shape matches `getWorkspaceBlockSelectOptions()` while
795
+ * avoiding synchronous inventory reads in interactive or async command paths.
796
+ *
797
+ * @param projectDir Workspace root directory.
798
+ * @returns Block options for variation-target selection.
799
+ */
800
+ export async function getWorkspaceBlockSelectOptionsAsync(projectDir) {
801
+ return toWorkspaceBlockSelectOptions((await readWorkspaceInventoryAsync(projectDir)).blocks);
749
802
  }
750
803
  function ensureWorkspaceInventorySections(source) {
751
804
  let nextSource = source.trimEnd();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wp-typia/project-tools",
3
- "version": "0.22.7",
3
+ "version": "0.22.9",
4
4
  "description": "Project orchestration and programmatic tooling for wp-typia",
5
5
  "packageManager": "bun@1.3.11",
6
6
  "type": "module",
@@ -47,6 +47,16 @@
47
47
  "import": "./dist/runtime/cli-scaffold.js",
48
48
  "default": "./dist/runtime/cli-scaffold.js"
49
49
  },
50
+ "./create-template-validation": {
51
+ "types": "./dist/runtime/create-template-validation.d.ts",
52
+ "import": "./dist/runtime/create-template-validation.js",
53
+ "default": "./dist/runtime/create-template-validation.js"
54
+ },
55
+ "./id-suggestions": {
56
+ "types": "./dist/runtime/id-suggestions.d.ts",
57
+ "import": "./dist/runtime/id-suggestions.js",
58
+ "default": "./dist/runtime/id-suggestions.js"
59
+ },
50
60
  "./ai-artifacts": {
51
61
  "types": "./dist/runtime/ai-artifacts.d.ts",
52
62
  "import": "./dist/runtime/ai-artifacts.js",