@wp-typia/project-tools 0.23.1 → 0.24.1

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 (157) hide show
  1. package/dist/runtime/built-in-block-non-ts-basic-artifacts.d.ts +9 -0
  2. package/dist/runtime/built-in-block-non-ts-basic-artifacts.js +84 -0
  3. package/dist/runtime/built-in-block-non-ts-compound-artifacts.d.ts +9 -0
  4. package/dist/runtime/built-in-block-non-ts-compound-artifacts.js +36 -0
  5. package/dist/runtime/built-in-block-non-ts-compound-templates.d.ts +23 -0
  6. package/dist/runtime/built-in-block-non-ts-compound-templates.js +453 -0
  7. package/dist/runtime/built-in-block-non-ts-family-artifacts.d.ts +8 -26
  8. package/dist/runtime/built-in-block-non-ts-family-artifacts.js +8 -1034
  9. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.d.ts +9 -0
  10. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.js +83 -0
  11. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.d.ts +9 -0
  12. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.js +33 -0
  13. package/dist/runtime/built-in-block-non-ts-persistence-templates.d.ts +23 -0
  14. package/dist/runtime/built-in-block-non-ts-persistence-templates.js +395 -0
  15. package/dist/runtime/cli-add-collision.js +8 -0
  16. package/dist/runtime/cli-add-help.js +11 -7
  17. package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
  18. package/dist/runtime/cli-add-kind-ids.js +1 -0
  19. package/dist/runtime/cli-add-types.d.ts +28 -1
  20. package/dist/runtime/cli-add-types.js +2 -0
  21. package/dist/runtime/cli-add-workspace-ability-anchors.d.ts +24 -0
  22. package/dist/runtime/cli-add-workspace-ability-anchors.js +294 -0
  23. package/dist/runtime/cli-add-workspace-ability-registry.d.ts +10 -0
  24. package/dist/runtime/cli-add-workspace-ability-registry.js +51 -0
  25. package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +1 -1
  26. package/dist/runtime/cli-add-workspace-ability-scaffold.js +5 -311
  27. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +1 -1
  28. package/dist/runtime/cli-add-workspace-ai-anchors.d.ts +4 -4
  29. package/dist/runtime/cli-add-workspace-ai-anchors.js +4 -232
  30. package/dist/runtime/cli-add-workspace-ai-scaffold.js +4 -2
  31. package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +1 -4
  32. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +3 -171
  33. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.d.ts +5 -0
  34. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.js +236 -0
  35. package/dist/runtime/cli-add-workspace-ai-sync-script-source.d.ts +4 -0
  36. package/dist/runtime/cli-add-workspace-ai-sync-script-source.js +145 -0
  37. package/dist/runtime/cli-add-workspace-assets.d.ts +6 -63
  38. package/dist/runtime/cli-add-workspace-assets.js +6 -950
  39. package/dist/runtime/cli-add-workspace-binding-source-anchors.d.ts +23 -0
  40. package/dist/runtime/cli-add-workspace-binding-source-anchors.js +112 -0
  41. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.d.ts +33 -0
  42. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.js +436 -0
  43. package/dist/runtime/cli-add-workspace-binding-source-types.d.ts +20 -0
  44. package/dist/runtime/cli-add-workspace-binding-source-types.js +1 -0
  45. package/dist/runtime/cli-add-workspace-binding-source.d.ts +40 -0
  46. package/dist/runtime/cli-add-workspace-binding-source.js +275 -0
  47. package/dist/runtime/cli-add-workspace-block-style.d.ts +22 -0
  48. package/dist/runtime/cli-add-workspace-block-style.js +148 -0
  49. package/dist/runtime/cli-add-workspace-block-transform.d.ts +32 -0
  50. package/dist/runtime/cli-add-workspace-block-transform.js +197 -0
  51. package/dist/runtime/cli-add-workspace-contract.js +1 -1
  52. package/dist/runtime/cli-add-workspace-core-variation.d.ts +22 -0
  53. package/dist/runtime/cli-add-workspace-core-variation.js +429 -0
  54. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.d.ts +37 -0
  55. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.js +206 -0
  56. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.d.ts +47 -0
  57. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.js +219 -0
  58. package/dist/runtime/cli-add-workspace-editor-plugin.d.ts +22 -0
  59. package/dist/runtime/cli-add-workspace-editor-plugin.js +78 -0
  60. package/dist/runtime/cli-add-workspace-hooked-block.d.ts +23 -0
  61. package/dist/runtime/cli-add-workspace-hooked-block.js +57 -0
  62. package/dist/runtime/cli-add-workspace-integration-env-files.d.ts +33 -0
  63. package/dist/runtime/cli-add-workspace-integration-env-files.js +65 -0
  64. package/dist/runtime/cli-add-workspace-integration-env-package-json.d.ts +38 -0
  65. package/dist/runtime/cli-add-workspace-integration-env-package-json.js +122 -0
  66. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.d.ts +44 -0
  67. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.js +262 -0
  68. package/dist/runtime/cli-add-workspace-integration-env.js +5 -345
  69. package/dist/runtime/cli-add-workspace-pattern-anchors.d.ts +10 -0
  70. package/dist/runtime/cli-add-workspace-pattern-anchors.js +95 -0
  71. package/dist/runtime/cli-add-workspace-pattern-options.d.ts +20 -0
  72. package/dist/runtime/cli-add-workspace-pattern-options.js +113 -0
  73. package/dist/runtime/cli-add-workspace-pattern-source-emitters.d.ts +20 -0
  74. package/dist/runtime/cli-add-workspace-pattern-source-emitters.js +57 -0
  75. package/dist/runtime/cli-add-workspace-pattern.d.ts +42 -0
  76. package/dist/runtime/cli-add-workspace-pattern.js +99 -0
  77. package/dist/runtime/cli-add-workspace-post-meta.js +1 -1
  78. package/dist/runtime/cli-add-workspace-registration-hooks.d.ts +50 -0
  79. package/dist/runtime/cli-add-workspace-registration-hooks.js +162 -0
  80. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +6 -9
  81. package/dist/runtime/cli-add-workspace-rest-anchors.js +6 -466
  82. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.d.ts +17 -0
  83. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.js +108 -0
  84. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.d.ts +9 -0
  85. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.js +142 -0
  86. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.d.ts +51 -0
  87. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.js +415 -0
  88. package/dist/runtime/cli-add-workspace-rest-generated.js +5 -3
  89. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.d.ts +80 -0
  90. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.js +238 -0
  91. package/dist/runtime/cli-add-workspace-rest-manual.js +3 -16
  92. package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +1 -7
  93. package/dist/runtime/cli-add-workspace-rest-php-templates.js +3 -322
  94. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.d.ts +33 -0
  95. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.js +145 -0
  96. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.d.ts +9 -0
  97. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.js +162 -0
  98. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.d.ts +7 -0
  99. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.js +193 -0
  100. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +5 -99
  101. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +5 -663
  102. package/dist/runtime/cli-add-workspace-rest-source-utils.d.ts +17 -0
  103. package/dist/runtime/cli-add-workspace-rest-source-utils.js +50 -0
  104. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.d.ts +56 -0
  105. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.js +122 -0
  106. package/dist/runtime/cli-add-workspace-rest-types.d.ts +3 -3
  107. package/dist/runtime/cli-add-workspace-variation.d.ts +22 -0
  108. package/dist/runtime/cli-add-workspace-variation.js +162 -0
  109. package/dist/runtime/cli-add-workspace.d.ts +42 -107
  110. package/dist/runtime/cli-add-workspace.js +42 -674
  111. package/dist/runtime/cli-add.d.ts +3 -3
  112. package/dist/runtime/cli-add.js +2 -2
  113. package/dist/runtime/cli-core.d.ts +2 -1
  114. package/dist/runtime/cli-core.js +1 -1
  115. package/dist/runtime/cli-doctor-workspace-bindings.js +59 -0
  116. package/dist/runtime/cli-doctor-workspace-block-addons.js +33 -5
  117. package/dist/runtime/cli-doctor.d.ts +2 -0
  118. package/dist/runtime/cli-doctor.js +13 -2
  119. package/dist/runtime/cli-help.js +7 -4
  120. package/dist/runtime/index.d.ts +5 -2
  121. package/dist/runtime/index.js +4 -2
  122. package/dist/runtime/json-utils.d.ts +2 -5
  123. package/dist/runtime/json-utils.js +2 -5
  124. package/dist/runtime/local-dev-presets.js +2 -1
  125. package/dist/runtime/package-versions.d.ts +1 -0
  126. package/dist/runtime/package-versions.js +15 -8
  127. package/dist/runtime/pattern-catalog-section-roles.d.ts +101 -0
  128. package/dist/runtime/pattern-catalog-section-roles.js +276 -0
  129. package/dist/runtime/pattern-catalog.d.ts +67 -0
  130. package/dist/runtime/pattern-catalog.js +225 -0
  131. package/dist/runtime/post-meta-binding-fields.d.ts +46 -0
  132. package/dist/runtime/post-meta-binding-fields.js +135 -0
  133. package/dist/runtime/template-source-cache-markers.js +7 -2
  134. package/dist/runtime/typia-llm-json-schema.d.ts +24 -0
  135. package/dist/runtime/typia-llm-json-schema.js +33 -0
  136. package/dist/runtime/typia-llm-openapi-constraints.d.ts +20 -0
  137. package/dist/runtime/typia-llm-openapi-constraints.js +254 -0
  138. package/dist/runtime/typia-llm-projection.d.ts +25 -0
  139. package/dist/runtime/typia-llm-projection.js +58 -0
  140. package/dist/runtime/typia-llm-render.d.ts +21 -0
  141. package/dist/runtime/typia-llm-render.js +252 -0
  142. package/dist/runtime/typia-llm-sync.d.ts +10 -0
  143. package/dist/runtime/typia-llm-sync.js +63 -0
  144. package/dist/runtime/typia-llm-types.d.ts +197 -0
  145. package/dist/runtime/typia-llm-types.js +1 -0
  146. package/dist/runtime/typia-llm.d.ts +9 -255
  147. package/dist/runtime/typia-llm.js +5 -634
  148. package/dist/runtime/workspace-inventory-mutations.js +13 -0
  149. package/dist/runtime/workspace-inventory-section-descriptors.js +9 -1
  150. package/dist/runtime/workspace-inventory-templates.d.ts +2 -2
  151. package/dist/runtime/workspace-inventory-templates.js +9 -1
  152. package/dist/runtime/workspace-inventory-types.d.ts +9 -1
  153. package/package.json +8 -3
  154. package/templates/_shared/compound/core/scripts/block-config.ts.mustache +22 -0
  155. package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +103 -2
  156. package/templates/_shared/compound/core/src/inner-blocks-templates.ts.mustache +13 -0
  157. package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +22 -1
@@ -0,0 +1,135 @@
1
+ import path from "node:path";
2
+ import { readJsonFile, readJsonFileSync } from "./json-utils.js";
3
+ const SUPPORTED_SCHEMA_TYPES = new Set([
4
+ "array",
5
+ "boolean",
6
+ "integer",
7
+ "number",
8
+ "object",
9
+ "string",
10
+ ]);
11
+ function isJsonRecord(value) {
12
+ return typeof value === "object" && value !== null && !Array.isArray(value);
13
+ }
14
+ function resolveSchemaType(schema) {
15
+ const type = schema.type;
16
+ if (typeof type === "string" && SUPPORTED_SCHEMA_TYPES.has(type)) {
17
+ return type;
18
+ }
19
+ if (Array.isArray(type) &&
20
+ type.every((entry) => typeof entry === "string")) {
21
+ const nonNullType = type.find((entry) => entry !== "null" && SUPPORTED_SCHEMA_TYPES.has(entry));
22
+ if (nonNullType) {
23
+ return nonNullType;
24
+ }
25
+ }
26
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) {
27
+ return "string";
28
+ }
29
+ return "unknown";
30
+ }
31
+ function resolveFallbackValue(name, schema, schemaType) {
32
+ const enumValue = Array.isArray(schema.enum)
33
+ ? schema.enum.find((entry) => typeof entry === "string")
34
+ : undefined;
35
+ if (typeof enumValue === "string") {
36
+ return enumValue;
37
+ }
38
+ switch (schemaType) {
39
+ case "array":
40
+ return "[]";
41
+ case "boolean":
42
+ return "false";
43
+ case "integer":
44
+ case "number":
45
+ return "0";
46
+ case "object":
47
+ return "{}";
48
+ default:
49
+ return `${name} preview`;
50
+ }
51
+ }
52
+ function resolveFieldLabel(name) {
53
+ return name
54
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
55
+ .replace(/[_-]+/g, " ")
56
+ .replace(/\s+/g, " ")
57
+ .trim()
58
+ .replace(/\b\w/g, (match) => match.toUpperCase());
59
+ }
60
+ function extractPostMetaBindingFields(schema, context) {
61
+ if (!isJsonRecord(schema) || !isJsonRecord(schema.properties)) {
62
+ throw new Error(`${context} must expose an object schema with top-level properties before it can back a binding source.`);
63
+ }
64
+ const required = Array.isArray(schema.required)
65
+ ? new Set(schema.required.filter((entry) => typeof entry === "string"))
66
+ : new Set();
67
+ const fields = Object.entries(schema.properties).map(([name, propertySchema]) => {
68
+ const property = isJsonRecord(propertySchema) ? propertySchema : {};
69
+ const schemaType = resolveSchemaType(property);
70
+ return {
71
+ fallbackValue: resolveFallbackValue(name, property, schemaType),
72
+ label: resolveFieldLabel(name),
73
+ name,
74
+ required: required.has(name),
75
+ schemaType,
76
+ };
77
+ });
78
+ if (fields.length === 0) {
79
+ throw new Error(`${context} does not expose any top-level properties that can back binding fields.`);
80
+ }
81
+ return fields;
82
+ }
83
+ /**
84
+ * Load and extract binding fields from a post-meta JSON Schema artifact.
85
+ *
86
+ * @param projectDir Workspace root directory.
87
+ * @param postMeta Post-meta inventory entry that points to the schema file.
88
+ * @returns Promise resolving to the extracted top-level binding fields.
89
+ * @throws If the schema cannot be read or does not expose object properties.
90
+ */
91
+ export async function loadPostMetaBindingFields(projectDir, postMeta) {
92
+ const schemaPath = path.join(projectDir, postMeta.schemaFile);
93
+ const schema = await readJsonFile(schemaPath, {
94
+ context: `post meta schema for ${postMeta.slug}`,
95
+ });
96
+ return extractPostMetaBindingFields(schema, postMeta.schemaFile);
97
+ }
98
+ /**
99
+ * Synchronously load and extract binding fields from a post-meta JSON Schema artifact.
100
+ *
101
+ * @param projectDir Workspace root directory.
102
+ * @param postMeta Post-meta inventory entry that points to the schema file.
103
+ * @returns Extracted top-level binding fields.
104
+ * @throws If the schema cannot be read or does not expose object properties.
105
+ */
106
+ export function loadPostMetaBindingFieldsSync(projectDir, postMeta) {
107
+ const schemaPath = path.join(projectDir, postMeta.schemaFile);
108
+ const schema = readJsonFileSync(schemaPath, {
109
+ context: `post meta schema for ${postMeta.slug}`,
110
+ });
111
+ return extractPostMetaBindingFields(schema, postMeta.schemaFile);
112
+ }
113
+ /**
114
+ * Validate and resolve a top-level post-meta binding path.
115
+ *
116
+ * @param fields Binding fields extracted from the post-meta schema.
117
+ * @param postMetaSlug Post-meta contract slug used in diagnostics.
118
+ * @param metaPath User-provided field path to validate.
119
+ * @returns The matching binding field.
120
+ * @throws If the path is empty, nested, or missing from the schema fields.
121
+ */
122
+ export function assertPostMetaBindingPath(fields, postMetaSlug, metaPath) {
123
+ const trimmed = metaPath.trim();
124
+ if (!trimmed) {
125
+ throw new Error("Post meta binding path must include a value.");
126
+ }
127
+ if (trimmed.includes(".")) {
128
+ throw new Error(`Nested post meta path "${trimmed}" for "${postMetaSlug}" is not supported yet. Use one of the top-level fields: ${fields.map((field) => field.name).join(", ")}.`);
129
+ }
130
+ const field = fields.find((candidate) => candidate.name === trimmed);
131
+ if (!field) {
132
+ throw new Error(`Post meta path "${trimmed}" does not exist in the "${postMetaSlug}" schema. Expected one of: ${fields.map((candidate) => candidate.name).join(", ")}.`);
133
+ }
134
+ return field;
135
+ }
@@ -1,3 +1,4 @@
1
+ import { safeJsonParse } from './json-utils.js';
1
2
  /**
2
3
  * Marker file written after a cache entry is fully populated.
3
4
  */
@@ -41,7 +42,9 @@ export function sanitizeExternalTemplateCacheMetadata(metadata) {
41
42
  export function parseExternalTemplateCacheEntryMarker(markerText) {
42
43
  let marker;
43
44
  try {
44
- marker = JSON.parse(markerText);
45
+ marker = safeJsonParse(markerText, {
46
+ context: 'external template cache entry marker',
47
+ });
45
48
  }
46
49
  catch {
47
50
  return null;
@@ -78,7 +81,9 @@ export function isExternalTemplateCacheEntryFreshForTtl(createdAtMs, nowMs, ttlM
78
81
  export function parseExternalTemplateCachePruneMarker(markerText) {
79
82
  let marker;
80
83
  try {
81
- marker = JSON.parse(markerText);
84
+ marker = safeJsonParse(markerText, {
85
+ context: 'external template cache prune marker',
86
+ });
82
87
  }
83
88
  catch {
84
89
  return null;
@@ -0,0 +1,24 @@
1
+ import type { JsonSchemaObject } from './schema-core.js';
2
+ /**
3
+ * Clone a JSON-compatible value when the caller has provided one.
4
+ *
5
+ * @template T JSON-compatible value type.
6
+ * @param value Optional value to clone with the shared JSON clone helper.
7
+ * @returns A cloned value, or undefined when the input is undefined.
8
+ */
9
+ export declare function cloneJsonValueIfDefined<T>(value: T | undefined): T | undefined;
10
+ /**
11
+ * Check whether a candidate is a non-null JSON Schema object.
12
+ *
13
+ * @param value Candidate value to narrow.
14
+ * @returns True when the value is an object and not an array.
15
+ */
16
+ export declare function isJsonSchemaObject(value: unknown): value is JsonSchemaObject;
17
+ /**
18
+ * Narrow a `typia.llm` artifact field before applying JSON Schema mutations.
19
+ *
20
+ * @param value Candidate schema value emitted by `typia.llm`.
21
+ * @param context Human-readable artifact path for diagnostics.
22
+ * @returns The value narrowed to the shared JSON Schema object shape.
23
+ */
24
+ export declare function assertJsonSchemaObject(value: unknown, context: string): JsonSchemaObject;
@@ -0,0 +1,33 @@
1
+ import { cloneJsonValue } from './json-utils.js';
2
+ /**
3
+ * Clone a JSON-compatible value when the caller has provided one.
4
+ *
5
+ * @template T JSON-compatible value type.
6
+ * @param value Optional value to clone with the shared JSON clone helper.
7
+ * @returns A cloned value, or undefined when the input is undefined.
8
+ */
9
+ export function cloneJsonValueIfDefined(value) {
10
+ return value === undefined ? undefined : cloneJsonValue(value);
11
+ }
12
+ /**
13
+ * Check whether a candidate is a non-null JSON Schema object.
14
+ *
15
+ * @param value Candidate value to narrow.
16
+ * @returns True when the value is an object and not an array.
17
+ */
18
+ export function isJsonSchemaObject(value) {
19
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
20
+ }
21
+ /**
22
+ * Narrow a `typia.llm` artifact field before applying JSON Schema mutations.
23
+ *
24
+ * @param value Candidate schema value emitted by `typia.llm`.
25
+ * @param context Human-readable artifact path for diagnostics.
26
+ * @returns The value narrowed to the shared JSON Schema object shape.
27
+ */
28
+ export function assertJsonSchemaObject(value, context) {
29
+ if (isJsonSchemaObject(value)) {
30
+ return value;
31
+ }
32
+ throw new Error(`${context} must be a JSON Schema object.`);
33
+ }
@@ -0,0 +1,20 @@
1
+ import type { ApplyOpenApiConstraintsToTypiaLlmFunctionArtifactOptions, ProjectedTypiaLlmFunctionArtifact } from './typia-llm-types.js';
2
+ /**
3
+ * Clone a projected function artifact before mutation-oriented constraint work.
4
+ *
5
+ * @param functionArtifact Projected artifact to clone.
6
+ * @returns A cloned artifact with parameters and optional output deep-cloned,
7
+ * and tags shallow-copied when present.
8
+ */
9
+ export declare function cloneProjectedTypiaLlmFunctionArtifact(functionArtifact: ProjectedTypiaLlmFunctionArtifact): ProjectedTypiaLlmFunctionArtifact;
10
+ /**
11
+ * Restores canonical request and response constraints from an endpoint-aware
12
+ * OpenAPI document onto one projected `typia.llm` function artifact.
13
+ *
14
+ * Query-only inputs merge into the root parameter object. Mixed body/query
15
+ * inputs merge into the generated `body` and `query` properties.
16
+ *
17
+ * @param options Projected artifact plus the canonical OpenAPI document.
18
+ * @returns A cloned artifact enriched with OpenAPI-backed constraints when available.
19
+ */
20
+ export declare function applyOpenApiConstraintsToTypiaLlmFunctionArtifact({ functionArtifact, openApiDocument, operationId, }: ApplyOpenApiConstraintsToTypiaLlmFunctionArtifactOptions): ProjectedTypiaLlmFunctionArtifact;
@@ -0,0 +1,254 @@
1
+ import { cloneJsonValue } from './json-utils.js';
2
+ import { assertJsonSchemaObject, cloneJsonValueIfDefined, isJsonSchemaObject, } from './typia-llm-json-schema.js';
3
+ const JSON_SCHEMA_CONSTRAINT_KEYS = [
4
+ 'additionalProperties',
5
+ 'const',
6
+ 'default',
7
+ 'enum',
8
+ 'exclusiveMaximum',
9
+ 'exclusiveMinimum',
10
+ 'format',
11
+ 'maxItems',
12
+ 'maxLength',
13
+ 'maximum',
14
+ 'minItems',
15
+ 'minLength',
16
+ 'minimum',
17
+ 'multipleOf',
18
+ 'pattern',
19
+ 'type',
20
+ ];
21
+ function decodeJsonPointerSegment(segment) {
22
+ return segment.replace(/~1/g, '/').replace(/~0/g, '~');
23
+ }
24
+ function resolveOpenApiReferenceTarget(document, reference) {
25
+ if (!reference.startsWith('#/')) {
26
+ throw new Error(`Unsupported OpenAPI schema reference "${reference}".`);
27
+ }
28
+ let current = document;
29
+ for (const rawSegment of reference.slice(2).split('/')) {
30
+ const segment = decodeJsonPointerSegment(rawSegment);
31
+ if (Array.isArray(current)) {
32
+ const index = Number.parseInt(segment, 10);
33
+ current = Number.isInteger(index) ? current[index] : undefined;
34
+ continue;
35
+ }
36
+ if (!isJsonSchemaObject(current)) {
37
+ current = undefined;
38
+ break;
39
+ }
40
+ current = current[segment];
41
+ }
42
+ if (!isJsonSchemaObject(current)) {
43
+ throw new Error(`Unable to resolve OpenAPI schema reference "${reference}".`);
44
+ }
45
+ return current;
46
+ }
47
+ function resolveOpenApiSchemaObject(document, schema, seenReferences = new Set()) {
48
+ if (!isJsonSchemaObject(schema)) {
49
+ return {};
50
+ }
51
+ const reference = schema.$ref;
52
+ if (typeof reference !== 'string') {
53
+ return schema;
54
+ }
55
+ if (seenReferences.has(reference)) {
56
+ return schema;
57
+ }
58
+ return resolveOpenApiSchemaObject(document, resolveOpenApiReferenceTarget(document, reference), new Set([...seenReferences, reference]));
59
+ }
60
+ function collectOpenApiSeenReferences(schema, seenReferences) {
61
+ const reference = schema.$ref;
62
+ if (typeof reference !== 'string' || seenReferences.has(reference)) {
63
+ return seenReferences;
64
+ }
65
+ return new Set([...seenReferences, reference]);
66
+ }
67
+ /**
68
+ * Copy constraint-oriented JSON Schema keywords from `source` into `target`.
69
+ *
70
+ * This helper intentionally mutates and returns `target` so nested OpenAPI
71
+ * constraint restoration can preserve the projected typia.llm schema shape.
72
+ * Callers that need immutable behavior should clone the target before calling.
73
+ */
74
+ function mergeJsonSchemaConstraintProperties(document, target, source, seenReferences = new Set()) {
75
+ const nextSeenReferences = collectOpenApiSeenReferences(source, seenReferences);
76
+ const resolvedSource = resolveOpenApiSchemaObject(document, source, seenReferences);
77
+ const merged = target;
78
+ for (const key of JSON_SCHEMA_CONSTRAINT_KEYS) {
79
+ if (resolvedSource[key] !== undefined) {
80
+ merged[key] = cloneJsonValue(resolvedSource[key]);
81
+ }
82
+ }
83
+ if (Array.isArray(resolvedSource.required)) {
84
+ merged.required = resolvedSource.required.filter((value) => typeof value === 'string');
85
+ }
86
+ if (Array.isArray(resolvedSource.items)) {
87
+ merged.items = cloneJsonValue(resolvedSource.items);
88
+ }
89
+ else if (isJsonSchemaObject(resolvedSource.items)) {
90
+ const nextItems = isJsonSchemaObject(merged.items) ? merged.items : {};
91
+ merged.items = mergeJsonSchemaConstraintProperties(document, nextItems, resolvedSource.items, nextSeenReferences);
92
+ }
93
+ if (isJsonSchemaObject(resolvedSource.properties)) {
94
+ const targetProperties = isJsonSchemaObject(merged.properties)
95
+ ? merged.properties
96
+ : {};
97
+ for (const [propertyName, propertySchema] of Object.entries(resolvedSource.properties)) {
98
+ if (!isJsonSchemaObject(propertySchema)) {
99
+ continue;
100
+ }
101
+ const nextProperty = isJsonSchemaObject(targetProperties[propertyName])
102
+ ? targetProperties[propertyName]
103
+ : {};
104
+ targetProperties[propertyName] = mergeJsonSchemaConstraintProperties(document, nextProperty, propertySchema, nextSeenReferences);
105
+ }
106
+ merged.properties = targetProperties;
107
+ }
108
+ return merged;
109
+ }
110
+ function findOpenApiOperationById(document, operationId) {
111
+ for (const pathItem of Object.values(document.paths)) {
112
+ if (!isJsonSchemaObject(pathItem)) {
113
+ continue;
114
+ }
115
+ for (const method of ['delete', 'get', 'patch', 'post', 'put']) {
116
+ const operation = resolveOpenApiSchemaObject(document, pathItem[method]);
117
+ if (!isJsonSchemaObject(operation) ||
118
+ typeof operation.operationId !== 'string') {
119
+ continue;
120
+ }
121
+ if (operation.operationId === operationId) {
122
+ return operation;
123
+ }
124
+ }
125
+ }
126
+ return null;
127
+ }
128
+ function resolveOpenApiRequestBodySchema(operation, document) {
129
+ const requestBody = resolveOpenApiSchemaObject(document, operation.requestBody);
130
+ const content = isJsonSchemaObject(requestBody.content)
131
+ ? requestBody.content
132
+ : null;
133
+ const jsonMediaType = content && isJsonSchemaObject(content['application/json'])
134
+ ? content['application/json']
135
+ : null;
136
+ const schema = jsonMediaType?.schema;
137
+ if (!isJsonSchemaObject(schema)) {
138
+ return null;
139
+ }
140
+ return resolveOpenApiSchemaObject(document, schema);
141
+ }
142
+ function resolveOpenApiSuccessResponseSchema(operation, document) {
143
+ for (const [statusCode, response] of Object.entries(operation.responses)) {
144
+ const resolvedResponse = resolveOpenApiSchemaObject(document, response);
145
+ if (!/^2(?:\d\d|XX)$/u.test(statusCode) ||
146
+ !isJsonSchemaObject(resolvedResponse)) {
147
+ continue;
148
+ }
149
+ const content = isJsonSchemaObject(resolvedResponse.content)
150
+ ? resolvedResponse.content
151
+ : null;
152
+ const jsonMediaType = content && isJsonSchemaObject(content['application/json'])
153
+ ? content['application/json']
154
+ : null;
155
+ const schema = jsonMediaType?.schema;
156
+ if (!isJsonSchemaObject(schema)) {
157
+ continue;
158
+ }
159
+ return resolveOpenApiSchemaObject(document, schema);
160
+ }
161
+ return null;
162
+ }
163
+ function getOrCreateObjectProperty(target, propertyName) {
164
+ const targetProperties = isJsonSchemaObject(target.properties)
165
+ ? target.properties
166
+ : {};
167
+ const nextProperty = isJsonSchemaObject(targetProperties[propertyName])
168
+ ? targetProperties[propertyName]
169
+ : {};
170
+ targetProperties[propertyName] = nextProperty;
171
+ target.properties = targetProperties;
172
+ return nextProperty;
173
+ }
174
+ function applyOpenApiQueryParameterConstraints(target, operation, document) {
175
+ for (const parameter of operation.parameters ?? []) {
176
+ const resolvedParameter = resolveOpenApiSchemaObject(document, parameter);
177
+ if (!isJsonSchemaObject(resolvedParameter) ||
178
+ resolvedParameter.in !== 'query' ||
179
+ typeof resolvedParameter.name !== 'string') {
180
+ continue;
181
+ }
182
+ const propertyTarget = getOrCreateObjectProperty(target, resolvedParameter.name);
183
+ mergeJsonSchemaConstraintProperties(document, propertyTarget, resolveOpenApiSchemaObject(document, resolvedParameter.schema));
184
+ if (resolvedParameter.required === true) {
185
+ const required = new Set(Array.isArray(target.required)
186
+ ? target.required.filter((value) => typeof value === 'string')
187
+ : []);
188
+ required.add(resolvedParameter.name);
189
+ target.required = [...required];
190
+ }
191
+ }
192
+ }
193
+ /**
194
+ * Clone a projected function artifact before mutation-oriented constraint work.
195
+ *
196
+ * @param functionArtifact Projected artifact to clone.
197
+ * @returns A cloned artifact with parameters and optional output deep-cloned,
198
+ * and tags shallow-copied when present.
199
+ */
200
+ export function cloneProjectedTypiaLlmFunctionArtifact(functionArtifact) {
201
+ return {
202
+ description: functionArtifact.description,
203
+ name: functionArtifact.name,
204
+ output: cloneJsonValueIfDefined(functionArtifact.output),
205
+ parameters: cloneJsonValue(functionArtifact.parameters),
206
+ ...(functionArtifact.tags ? { tags: [...functionArtifact.tags] } : {}),
207
+ };
208
+ }
209
+ /**
210
+ * Restores canonical request and response constraints from an endpoint-aware
211
+ * OpenAPI document onto one projected `typia.llm` function artifact.
212
+ *
213
+ * Query-only inputs merge into the root parameter object. Mixed body/query
214
+ * inputs merge into the generated `body` and `query` properties.
215
+ *
216
+ * @param options Projected artifact plus the canonical OpenAPI document.
217
+ * @returns A cloned artifact enriched with OpenAPI-backed constraints when available.
218
+ */
219
+ export function applyOpenApiConstraintsToTypiaLlmFunctionArtifact({ functionArtifact, openApiDocument, operationId, }) {
220
+ const constrainedArtifact = cloneProjectedTypiaLlmFunctionArtifact(functionArtifact);
221
+ const operation = findOpenApiOperationById(openApiDocument, operationId);
222
+ if (!operation) {
223
+ return constrainedArtifact;
224
+ }
225
+ const hasQueryParameters = (operation.parameters ?? []).some((parameter) => {
226
+ const resolvedParameter = resolveOpenApiSchemaObject(openApiDocument, parameter);
227
+ return (isJsonSchemaObject(resolvedParameter) &&
228
+ resolvedParameter.in === 'query' &&
229
+ typeof resolvedParameter.name === 'string');
230
+ });
231
+ const requestBodySchema = resolveOpenApiRequestBodySchema(operation, openApiDocument);
232
+ const parameterSchema = assertJsonSchemaObject(constrainedArtifact.parameters, `typia.llm parameters for "${constrainedArtifact.name}"`);
233
+ if (requestBodySchema) {
234
+ if (hasQueryParameters) {
235
+ mergeJsonSchemaConstraintProperties(openApiDocument, getOrCreateObjectProperty(parameterSchema, 'body'), requestBodySchema);
236
+ }
237
+ else {
238
+ mergeJsonSchemaConstraintProperties(openApiDocument, parameterSchema, requestBodySchema);
239
+ }
240
+ }
241
+ if (hasQueryParameters) {
242
+ applyOpenApiQueryParameterConstraints(requestBodySchema
243
+ ? getOrCreateObjectProperty(parameterSchema, 'query')
244
+ : parameterSchema, operation, openApiDocument);
245
+ }
246
+ if (constrainedArtifact.output) {
247
+ const outputSchema = assertJsonSchemaObject(constrainedArtifact.output, `typia.llm output for "${constrainedArtifact.name}"`);
248
+ const responseSchema = resolveOpenApiSuccessResponseSchema(operation, openApiDocument);
249
+ if (responseSchema) {
250
+ mergeJsonSchemaConstraintProperties(openApiDocument, outputSchema, responseSchema);
251
+ }
252
+ }
253
+ return constrainedArtifact;
254
+ }
@@ -0,0 +1,25 @@
1
+ import type { ProjectedTypiaLlmApplicationArtifact, ProjectedTypiaLlmFunctionArtifact, ProjectedTypiaLlmStructuredOutputArtifact, ProjectTypiaLlmApplicationArtifactOptions, ProjectTypiaLlmStructuredOutputArtifactOptions, TypiaLlmFunctionLike } from './typia-llm-types.js';
2
+ /**
3
+ * Projects one compiled `typia.llm` function schema into a JSON-friendly
4
+ * artifact record.
5
+ *
6
+ * @param functionSchema Function schema from a compiled `typia.llm.application(...)`.
7
+ * @returns JSON-friendly function artifact.
8
+ */
9
+ export declare function projectTypiaLlmApplicationFunction(functionSchema: TypiaLlmFunctionLike): ProjectedTypiaLlmFunctionArtifact;
10
+ /**
11
+ * Projects a compiled `typia.llm.application(...)` result into a JSON-friendly
12
+ * downstream adapter artifact.
13
+ *
14
+ * @param options Compiled application value and source metadata.
15
+ * @returns JSON-friendly application artifact.
16
+ */
17
+ export declare function projectTypiaLlmApplicationArtifact({ application, generatedFrom, openApiProjection, transformFunction, }: ProjectTypiaLlmApplicationArtifactOptions): ProjectedTypiaLlmApplicationArtifact;
18
+ /**
19
+ * Projects a compiled `typia.llm.structuredOutput(...)` result into a
20
+ * JSON-friendly downstream adapter artifact.
21
+ *
22
+ * @param options Compiled structured-output value and source metadata.
23
+ * @returns JSON-friendly structured-output artifact.
24
+ */
25
+ export declare function projectTypiaLlmStructuredOutputArtifact({ generatedFrom, structuredOutput, }: ProjectTypiaLlmStructuredOutputArtifactOptions): ProjectedTypiaLlmStructuredOutputArtifact;
@@ -0,0 +1,58 @@
1
+ import { cloneJsonValue } from './json-utils.js';
2
+ import { cloneJsonValueIfDefined } from './typia-llm-json-schema.js';
3
+ import { applyOpenApiConstraintsToTypiaLlmFunctionArtifact, cloneProjectedTypiaLlmFunctionArtifact, } from './typia-llm-openapi-constraints.js';
4
+ /**
5
+ * Projects one compiled `typia.llm` function schema into a JSON-friendly
6
+ * artifact record.
7
+ *
8
+ * @param functionSchema Function schema from a compiled `typia.llm.application(...)`.
9
+ * @returns JSON-friendly function artifact.
10
+ */
11
+ export function projectTypiaLlmApplicationFunction(functionSchema) {
12
+ return {
13
+ description: functionSchema.description,
14
+ name: functionSchema.name,
15
+ output: cloneJsonValueIfDefined(functionSchema.output),
16
+ parameters: cloneJsonValue(functionSchema.parameters),
17
+ ...(functionSchema.tags ? { tags: [...functionSchema.tags] } : {}),
18
+ };
19
+ }
20
+ /**
21
+ * Projects a compiled `typia.llm.application(...)` result into a JSON-friendly
22
+ * downstream adapter artifact.
23
+ *
24
+ * @param options Compiled application value and source metadata.
25
+ * @returns JSON-friendly application artifact.
26
+ */
27
+ export function projectTypiaLlmApplicationArtifact({ application, generatedFrom, openApiProjection, transformFunction, }) {
28
+ return {
29
+ functions: application.functions.map((functionSchema) => {
30
+ const functionArtifact = projectTypiaLlmApplicationFunction(functionSchema);
31
+ const openApiAlignedArtifact = openApiProjection
32
+ ? applyOpenApiConstraintsToTypiaLlmFunctionArtifact({
33
+ functionArtifact,
34
+ openApiDocument: openApiProjection.openApiDocument,
35
+ operationId: openApiProjection.resolveOperationId?.(functionSchema, functionArtifact) ?? functionSchema.name,
36
+ })
37
+ : functionArtifact;
38
+ const transformedArtifact = transformFunction
39
+ ? transformFunction(openApiAlignedArtifact, functionSchema)
40
+ : openApiAlignedArtifact;
41
+ return cloneProjectedTypiaLlmFunctionArtifact(transformedArtifact);
42
+ }),
43
+ generatedFrom: cloneJsonValue(generatedFrom),
44
+ };
45
+ }
46
+ /**
47
+ * Projects a compiled `typia.llm.structuredOutput(...)` result into a
48
+ * JSON-friendly downstream adapter artifact.
49
+ *
50
+ * @param options Compiled structured-output value and source metadata.
51
+ * @returns JSON-friendly structured-output artifact.
52
+ */
53
+ export function projectTypiaLlmStructuredOutputArtifact({ generatedFrom, structuredOutput, }) {
54
+ return {
55
+ generatedFrom: cloneJsonValue(generatedFrom),
56
+ parameters: cloneJsonValue(structuredOutput.parameters),
57
+ };
58
+ }
@@ -0,0 +1,21 @@
1
+ import type { EndpointManifestDefinition } from '@wp-typia/block-runtime/metadata-core';
2
+ import type { RenderTypiaLlmModuleOptions, TypiaLlmEndpointMethodDescriptor } from './typia-llm-types.js';
3
+ export declare function renderTypiaLlmModuleFromMethodDescriptors({ applicationExportName, interfaceName, structuredOutputExportName, structuredOutputTypeName, typesImportPath, }: Omit<RenderTypiaLlmModuleOptions, 'manifest'>, methods: readonly TypiaLlmEndpointMethodDescriptor[]): string;
4
+ /**
5
+ * Builds the generated controller method descriptors that bridge endpoint
6
+ * manifests to `typia.llm` TypeScript interfaces.
7
+ *
8
+ * @param manifest Endpoint manifest that owns operation and source type names.
9
+ * @returns Ordered method descriptors matching the manifest endpoints.
10
+ * @throws When an endpoint has ambiguous query/body input mapping.
11
+ * @throws When an endpoint references a missing input or output contract.
12
+ */
13
+ export declare function buildTypiaLlmEndpointMethodDescriptors(manifest: EndpointManifestDefinition): TypiaLlmEndpointMethodDescriptor[];
14
+ /**
15
+ * Renders a build-time-only TypeScript module that invokes `typia.llm` against
16
+ * canonical manifest-owned contracts.
17
+ *
18
+ * @param options Render options for the generated adapter module.
19
+ * @returns The generated TypeScript source.
20
+ */
21
+ export declare function renderTypiaLlmModule({ applicationExportName, interfaceName, manifest, structuredOutputExportName, structuredOutputTypeName, typesImportPath, }: RenderTypiaLlmModuleOptions): string;