@wp-typia/project-tools 0.22.3 → 0.22.4

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 (40) hide show
  1. package/dist/runtime/cli-add-block-json.d.ts +31 -0
  2. package/dist/runtime/cli-add-block-json.js +65 -0
  3. package/dist/runtime/cli-add-collision.d.ts +129 -0
  4. package/dist/runtime/cli-add-collision.js +293 -0
  5. package/dist/runtime/cli-add-filesystem.d.ts +29 -0
  6. package/dist/runtime/cli-add-filesystem.js +77 -0
  7. package/dist/runtime/cli-add-help.d.ts +4 -0
  8. package/dist/runtime/cli-add-help.js +41 -0
  9. package/dist/runtime/cli-add-shared.d.ts +6 -304
  10. package/dist/runtime/cli-add-shared.js +6 -524
  11. package/dist/runtime/cli-add-types.d.ts +247 -0
  12. package/dist/runtime/cli-add-types.js +64 -0
  13. package/dist/runtime/cli-add-validation.d.ts +87 -0
  14. package/dist/runtime/cli-add-validation.js +147 -0
  15. package/dist/runtime/cli-add-workspace-ability-scaffold.js +46 -72
  16. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +35 -61
  17. package/dist/runtime/cli-add-workspace-ai-scaffold.js +53 -57
  18. package/dist/runtime/cli-add-workspace-ai-templates.js +2 -0
  19. package/dist/runtime/cli-add-workspace-mutation.d.ts +30 -0
  20. package/dist/runtime/cli-add-workspace-mutation.js +60 -0
  21. package/dist/runtime/cli-add-workspace.js +1 -79
  22. package/dist/runtime/cli-add.d.ts +2 -2
  23. package/dist/runtime/cli-add.js +2 -2
  24. package/dist/runtime/cli-doctor-workspace-blocks.js +1 -66
  25. package/dist/runtime/index.d.ts +2 -0
  26. package/dist/runtime/index.js +1 -0
  27. package/dist/runtime/migration-utils.d.ts +2 -1
  28. package/dist/runtime/migration-utils.js +3 -11
  29. package/dist/runtime/package-managers.d.ts +19 -0
  30. package/dist/runtime/package-managers.js +62 -0
  31. package/dist/runtime/template-source-cache.d.ts +59 -0
  32. package/dist/runtime/template-source-cache.js +160 -0
  33. package/dist/runtime/ts-source-masking.d.ts +28 -0
  34. package/dist/runtime/ts-source-masking.js +104 -0
  35. package/dist/runtime/typia-llm.d.ts +9 -1
  36. package/dist/runtime/typia-llm.js +20 -5
  37. package/dist/runtime/workspace-inventory.js +116 -59
  38. package/dist/runtime/workspace-project.d.ts +1 -1
  39. package/dist/runtime/workspace-project.js +2 -10
  40. package/package.json +2 -2
@@ -0,0 +1,104 @@
1
+ function maskSourceSegment(segment) {
2
+ return segment.replace(/[^\n\r]/gu, " ");
3
+ }
4
+ function testPattern(source, pattern) {
5
+ pattern.lastIndex = 0;
6
+ const matched = pattern.test(source);
7
+ pattern.lastIndex = 0;
8
+ return matched;
9
+ }
10
+ /**
11
+ * Masks TypeScript comments with spaces while preserving newlines and offsets.
12
+ */
13
+ export function maskTypeScriptComments(source) {
14
+ return source
15
+ .replace(/\/\*[\s\S]*?\*\//gu, maskSourceSegment)
16
+ .replace(/\/\/[^\n\r]*/gu, maskSourceSegment);
17
+ }
18
+ /**
19
+ * Masks TypeScript comments and quoted/template literals with spaces while
20
+ * preserving source offsets. This is a lightweight lexer for runtime checks,
21
+ * not a full TypeScript parser, so template interpolation and regex/division
22
+ * ambiguity are intentionally left to callers that need deeper syntax analysis.
23
+ */
24
+ export function maskTypeScriptCommentsAndLiterals(source) {
25
+ let maskedSource = "";
26
+ let index = 0;
27
+ while (index < source.length) {
28
+ const current = source[index];
29
+ const next = source[index + 1];
30
+ if (current === "/" && next === "/") {
31
+ const start = index;
32
+ index += 2;
33
+ while (index < source.length &&
34
+ source[index] !== "\n" &&
35
+ source[index] !== "\r") {
36
+ index += 1;
37
+ }
38
+ maskedSource += maskSourceSegment(source.slice(start, index));
39
+ continue;
40
+ }
41
+ if (current === "/" && next === "*") {
42
+ const start = index;
43
+ index += 2;
44
+ while (index < source.length &&
45
+ !(source[index] === "*" && source[index + 1] === "/")) {
46
+ index += 1;
47
+ }
48
+ index = Math.min(index + 2, source.length);
49
+ maskedSource += maskSourceSegment(source.slice(start, index));
50
+ continue;
51
+ }
52
+ if (current === "'" || current === '"' || current === "`") {
53
+ const start = index;
54
+ const quote = current;
55
+ index += 1;
56
+ while (index < source.length) {
57
+ const char = source[index];
58
+ if (char === "\\") {
59
+ index += 2;
60
+ continue;
61
+ }
62
+ index += 1;
63
+ if (char === quote) {
64
+ break;
65
+ }
66
+ }
67
+ maskedSource += maskSourceSegment(source.slice(start, index));
68
+ continue;
69
+ }
70
+ maskedSource += current;
71
+ index += 1;
72
+ }
73
+ return maskedSource;
74
+ }
75
+ /**
76
+ * Tests for a pattern after hiding comments and quoted/template literals.
77
+ */
78
+ export function hasExecutablePattern(source, pattern) {
79
+ return testPattern(maskTypeScriptCommentsAndLiterals(source), pattern);
80
+ }
81
+ /**
82
+ * Tests for a pattern after hiding comments while leaving literals intact.
83
+ */
84
+ export function hasUncommentedPattern(source, pattern) {
85
+ return testPattern(maskTypeScriptComments(source), pattern);
86
+ }
87
+ /**
88
+ * Finds the first masked-source match that maps back to the original source.
89
+ */
90
+ export function findExecutablePatternMatch(source, patterns) {
91
+ const maskedSource = maskTypeScriptCommentsAndLiterals(source);
92
+ for (const pattern of patterns) {
93
+ pattern.lastIndex = 0;
94
+ const match = pattern.exec(maskedSource);
95
+ pattern.lastIndex = 0;
96
+ if (match && match.index !== undefined) {
97
+ return {
98
+ end: match.index + match[0].length,
99
+ start: match.index,
100
+ };
101
+ }
102
+ }
103
+ return undefined;
104
+ }
@@ -1,6 +1,6 @@
1
1
  import type { ArtifactSyncExecutionOptions, EndpointManifestDefinition, EndpointManifestEndpointDefinition } from '@wp-typia/block-runtime/metadata-core';
2
2
  import type { ILlmFunction, ILlmSchema, ILlmStructuredOutput } from 'typia';
3
- import { type EndpointAuthIntent, type EndpointWordPressAuthDefinition, type OpenApiDocument } from './schema-core.js';
3
+ import { type EndpointAuthIntent, type EndpointWordPressAuthDefinition, type JsonSchemaObject, type OpenApiDocument } from './schema-core.js';
4
4
  /**
5
5
  * Method-level descriptor projected from an endpoint manifest for a generated
6
6
  * `typia.llm` controller interface.
@@ -186,6 +186,14 @@ export interface ProjectTypiaLlmStructuredOutputArtifactOptions {
186
186
  /** Compiled structured-output value produced by `typia.llm.structuredOutput(...)`. */
187
187
  structuredOutput: TypiaLlmStructuredOutputLike;
188
188
  }
189
+ /**
190
+ * Narrow a `typia.llm` artifact field before applying JSON Schema mutations.
191
+ *
192
+ * @param value Candidate schema value emitted by `typia.llm`.
193
+ * @param context Human-readable artifact path for diagnostics.
194
+ * @returns The value narrowed to the shared JSON Schema object shape.
195
+ */
196
+ export declare function assertJsonSchemaObject(value: unknown, context: string): JsonSchemaObject;
189
197
  /**
190
198
  * Builds the generated controller method descriptors that bridge endpoint
191
199
  * manifests to `typia.llm` TypeScript interfaces.
@@ -105,6 +105,19 @@ function cloneJsonValueIfDefined(value) {
105
105
  function isJsonSchemaObject(value) {
106
106
  return typeof value === 'object' && value !== null && !Array.isArray(value);
107
107
  }
108
+ /**
109
+ * Narrow a `typia.llm` artifact field before applying JSON Schema mutations.
110
+ *
111
+ * @param value Candidate schema value emitted by `typia.llm`.
112
+ * @param context Human-readable artifact path for diagnostics.
113
+ * @returns The value narrowed to the shared JSON Schema object shape.
114
+ */
115
+ export function assertJsonSchemaObject(value, context) {
116
+ if (isJsonSchemaObject(value)) {
117
+ return value;
118
+ }
119
+ throw new Error(`${context} must be a JSON Schema object.`);
120
+ }
108
121
  function decodeJsonPointerSegment(segment) {
109
122
  return segment.replace(/~1/g, '/').replace(/~0/g, '~');
110
123
  }
@@ -551,23 +564,25 @@ export function applyOpenApiConstraintsToTypiaLlmFunctionArtifact({ functionArti
551
564
  typeof resolvedParameter.name === 'string');
552
565
  });
553
566
  const requestBodySchema = resolveOpenApiRequestBodySchema(operation, openApiDocument);
567
+ const parameterSchema = assertJsonSchemaObject(constrainedArtifact.parameters, `typia.llm parameters for "${constrainedArtifact.name}"`);
554
568
  if (requestBodySchema) {
555
569
  if (hasQueryParameters) {
556
- mergeJsonSchemaConstraintProperties(openApiDocument, getOrCreateObjectProperty(constrainedArtifact.parameters, 'body'), requestBodySchema);
570
+ mergeJsonSchemaConstraintProperties(openApiDocument, getOrCreateObjectProperty(parameterSchema, 'body'), requestBodySchema);
557
571
  }
558
572
  else {
559
- mergeJsonSchemaConstraintProperties(openApiDocument, constrainedArtifact.parameters, requestBodySchema);
573
+ mergeJsonSchemaConstraintProperties(openApiDocument, parameterSchema, requestBodySchema);
560
574
  }
561
575
  }
562
576
  if (hasQueryParameters) {
563
577
  applyOpenApiQueryParameterConstraints(requestBodySchema
564
- ? getOrCreateObjectProperty(constrainedArtifact.parameters, 'query')
565
- : constrainedArtifact.parameters, operation, openApiDocument);
578
+ ? getOrCreateObjectProperty(parameterSchema, 'query')
579
+ : parameterSchema, operation, openApiDocument);
566
580
  }
567
581
  if (constrainedArtifact.output) {
582
+ const outputSchema = assertJsonSchemaObject(constrainedArtifact.output, `typia.llm output for "${constrainedArtifact.name}"`);
568
583
  const responseSchema = resolveOpenApiSuccessResponseSchema(operation, openApiDocument);
569
584
  if (responseSchema) {
570
- mergeJsonSchemaConstraintProperties(openApiDocument, constrainedArtifact.output, responseSchema);
585
+ mergeJsonSchemaConstraintProperties(openApiDocument, outputSchema, responseSchema);
571
586
  }
572
587
  }
573
588
  return constrainedArtifact;
@@ -202,6 +202,108 @@ export const EDITOR_PLUGINS: WorkspaceEditorPluginConfig[] = [
202
202
  \t// wp-typia add editor-plugin entries
203
203
  ];
204
204
  `;
205
+ const INVENTORY_SECTIONS = [
206
+ {
207
+ interface: {
208
+ name: "WorkspaceVariationConfig",
209
+ section: VARIATIONS_INTERFACE_SECTION,
210
+ },
211
+ value: {
212
+ name: "VARIATIONS",
213
+ section: VARIATIONS_CONST_SECTION,
214
+ },
215
+ },
216
+ {
217
+ interface: {
218
+ name: "WorkspaceBlockStyleConfig",
219
+ section: BLOCK_STYLES_INTERFACE_SECTION,
220
+ },
221
+ value: {
222
+ name: "BLOCK_STYLES",
223
+ section: BLOCK_STYLES_CONST_SECTION,
224
+ },
225
+ },
226
+ {
227
+ interface: {
228
+ name: "WorkspaceBlockTransformConfig",
229
+ section: BLOCK_TRANSFORMS_INTERFACE_SECTION,
230
+ },
231
+ value: {
232
+ name: "BLOCK_TRANSFORMS",
233
+ section: BLOCK_TRANSFORMS_CONST_SECTION,
234
+ },
235
+ },
236
+ {
237
+ interface: {
238
+ name: "WorkspacePatternConfig",
239
+ section: PATTERNS_INTERFACE_SECTION,
240
+ },
241
+ value: {
242
+ name: "PATTERNS",
243
+ section: PATTERNS_CONST_SECTION,
244
+ },
245
+ },
246
+ {
247
+ interface: {
248
+ name: "WorkspaceBindingSourceConfig",
249
+ section: BINDING_SOURCES_INTERFACE_SECTION,
250
+ },
251
+ value: {
252
+ name: "BINDING_SOURCES",
253
+ section: BINDING_SOURCES_CONST_SECTION,
254
+ },
255
+ },
256
+ {
257
+ interface: {
258
+ name: "WorkspaceRestResourceConfig",
259
+ section: REST_RESOURCES_INTERFACE_SECTION,
260
+ },
261
+ value: {
262
+ name: "REST_RESOURCES",
263
+ section: REST_RESOURCES_CONST_SECTION,
264
+ },
265
+ },
266
+ {
267
+ interface: {
268
+ name: "WorkspaceAbilityConfig",
269
+ section: ABILITIES_INTERFACE_SECTION,
270
+ },
271
+ value: {
272
+ name: "ABILITIES",
273
+ section: ABILITIES_CONST_SECTION,
274
+ },
275
+ },
276
+ {
277
+ interface: {
278
+ name: "WorkspaceAiFeatureConfig",
279
+ section: AI_FEATURES_INTERFACE_SECTION,
280
+ },
281
+ value: {
282
+ name: "AI_FEATURES",
283
+ section: AI_FEATURES_CONST_SECTION,
284
+ },
285
+ },
286
+ {
287
+ interface: {
288
+ name: "WorkspaceAdminViewConfig",
289
+ section: ADMIN_VIEWS_INTERFACE_SECTION,
290
+ },
291
+ value: {
292
+ name: "ADMIN_VIEWS",
293
+ section: ADMIN_VIEWS_CONST_SECTION,
294
+ },
295
+ },
296
+ {
297
+ interface: {
298
+ name: "WorkspaceEditorPluginConfig",
299
+ section: EDITOR_PLUGINS_INTERFACE_SECTION,
300
+ },
301
+ value: {
302
+ name: "EDITOR_PLUGINS",
303
+ section: EDITOR_PLUGINS_CONST_SECTION,
304
+ },
305
+ },
306
+ ];
205
307
  function getPropertyNameText(name) {
206
308
  if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
207
309
  return name.text;
@@ -576,68 +678,23 @@ export function getWorkspaceBlockSelectOptions(projectDir) {
576
678
  }
577
679
  function ensureWorkspaceInventorySections(source) {
578
680
  let nextSource = source.trimEnd();
579
- if (!/export\s+interface\s+WorkspaceVariationConfig\b/u.test(nextSource)) {
580
- nextSource += VARIATIONS_INTERFACE_SECTION;
581
- }
582
- if (!/export\s+const\s+VARIATIONS\b/u.test(nextSource)) {
583
- nextSource += VARIATIONS_CONST_SECTION;
584
- }
585
- if (!/export\s+interface\s+WorkspaceBlockStyleConfig\b/u.test(nextSource)) {
586
- nextSource += BLOCK_STYLES_INTERFACE_SECTION;
587
- }
588
- if (!/export\s+const\s+BLOCK_STYLES\b/u.test(nextSource)) {
589
- nextSource += BLOCK_STYLES_CONST_SECTION;
590
- }
591
- if (!/export\s+interface\s+WorkspaceBlockTransformConfig\b/u.test(nextSource)) {
592
- nextSource += BLOCK_TRANSFORMS_INTERFACE_SECTION;
593
- }
594
- if (!/export\s+const\s+BLOCK_TRANSFORMS\b/u.test(nextSource)) {
595
- nextSource += BLOCK_TRANSFORMS_CONST_SECTION;
596
- }
597
- if (!/export\s+interface\s+WorkspacePatternConfig\b/u.test(nextSource)) {
598
- nextSource += PATTERNS_INTERFACE_SECTION;
599
- }
600
- if (!/export\s+const\s+PATTERNS\b/u.test(nextSource)) {
601
- nextSource += PATTERNS_CONST_SECTION;
602
- }
603
- if (!/export\s+interface\s+WorkspaceBindingSourceConfig\b/u.test(nextSource)) {
604
- nextSource += BINDING_SOURCES_INTERFACE_SECTION;
605
- }
606
- if (!/export\s+const\s+BINDING_SOURCES\b/u.test(nextSource)) {
607
- nextSource += BINDING_SOURCES_CONST_SECTION;
608
- }
609
- if (!/export\s+interface\s+WorkspaceRestResourceConfig\b/u.test(nextSource)) {
610
- nextSource += REST_RESOURCES_INTERFACE_SECTION;
611
- }
612
- if (!/export\s+const\s+REST_RESOURCES\b/u.test(nextSource)) {
613
- nextSource += REST_RESOURCES_CONST_SECTION;
614
- }
615
- if (!/export\s+interface\s+WorkspaceAbilityConfig\b/u.test(nextSource)) {
616
- nextSource += ABILITIES_INTERFACE_SECTION;
617
- }
618
- if (!/export\s+const\s+ABILITIES\b/u.test(nextSource)) {
619
- nextSource += ABILITIES_CONST_SECTION;
620
- }
621
- if (!/export\s+interface\s+WorkspaceAiFeatureConfig\b/u.test(nextSource)) {
622
- nextSource += AI_FEATURES_INTERFACE_SECTION;
623
- }
624
- if (!/export\s+const\s+AI_FEATURES\b/u.test(nextSource)) {
625
- nextSource += AI_FEATURES_CONST_SECTION;
626
- }
627
- if (!/export\s+interface\s+WorkspaceAdminViewConfig\b/u.test(nextSource)) {
628
- nextSource += ADMIN_VIEWS_INTERFACE_SECTION;
629
- }
630
- if (!/export\s+const\s+ADMIN_VIEWS\b/u.test(nextSource)) {
631
- nextSource += ADMIN_VIEWS_CONST_SECTION;
632
- }
633
- if (!/export\s+interface\s+WorkspaceEditorPluginConfig\b/u.test(nextSource)) {
634
- nextSource += EDITOR_PLUGINS_INTERFACE_SECTION;
635
- }
636
- if (!/export\s+const\s+EDITOR_PLUGINS\b/u.test(nextSource)) {
637
- nextSource += EDITOR_PLUGINS_CONST_SECTION;
681
+ for (const section of INVENTORY_SECTIONS) {
682
+ if (section.interface &&
683
+ !hasExportedInterface(nextSource, section.interface.name)) {
684
+ nextSource += section.interface.section;
685
+ }
686
+ if (section.value && !hasExportedConst(nextSource, section.value.name)) {
687
+ nextSource += section.value.section;
688
+ }
638
689
  }
639
690
  return `${nextSource}\n`;
640
691
  }
692
+ function hasExportedInterface(source, interfaceName) {
693
+ return new RegExp(`export\\s+interface\\s+${escapeRegex(interfaceName)}\\b`, "u").test(source);
694
+ }
695
+ function hasExportedConst(source, constName) {
696
+ return new RegExp(`export\\s+const\\s+${escapeRegex(constName)}\\b`, "u").test(source);
697
+ }
641
698
  function appendEntriesAtMarker(source, marker, entries) {
642
699
  if (entries.length === 0) {
643
700
  return source;
@@ -1,4 +1,4 @@
1
- import type { PackageManagerId } from "./package-managers.js";
1
+ import { type PackageManagerId } from "./package-managers.js";
2
2
  export declare const WORKSPACE_TEMPLATE_PACKAGE = "@wp-typia/create-workspace-template";
3
3
  export interface WorkspacePackageJson {
4
4
  author?: string;
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { parsePackageManagerField, } from "./package-managers.js";
3
4
  export const WORKSPACE_TEMPLATE_PACKAGE = "@wp-typia/create-workspace-template";
4
5
  function hasNonEmptyString(value) {
5
6
  return typeof value === "string" && value.trim().length > 0;
@@ -81,16 +82,7 @@ export function getInvalidWorkspaceProjectReason(startDir) {
81
82
  * field is missing or unsupported.
82
83
  */
83
84
  export function parseWorkspacePackageManagerId(packageManagerField) {
84
- const packageManagerId = packageManagerField?.split("@", 1)[0];
85
- switch (packageManagerId) {
86
- case "bun":
87
- case "npm":
88
- case "pnpm":
89
- case "yarn":
90
- return packageManagerId;
91
- default:
92
- return "npm";
93
- }
85
+ return parsePackageManagerField(packageManagerField) ?? "npm";
94
86
  }
95
87
  /**
96
88
  * Try to resolve the nearest official wp-typia workspace from `startDir`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wp-typia/project-tools",
3
- "version": "0.22.3",
3
+ "version": "0.22.4",
4
4
  "description": "Project orchestration and programmatic tooling for wp-typia",
5
5
  "packageManager": "bun@1.3.11",
6
6
  "type": "module",
@@ -147,7 +147,7 @@
147
147
  "dependencies": {
148
148
  "@wp-typia/api-client": "^0.4.5",
149
149
  "@wp-typia/block-runtime": "^0.5.0",
150
- "@wp-typia/rest": "^0.3.12",
150
+ "@wp-typia/rest": "^0.3.13",
151
151
  "@wp-typia/block-types": "^0.2.4",
152
152
  "mustache": "^4.2.0",
153
153
  "npm-package-arg": "^13.0.0",