vovk 3.5.1 → 3.7.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 (113) hide show
  1. package/dist/client/create-rpc.d.ts +13 -0
  2. package/dist/client/create-rpc.js +147 -0
  3. package/dist/client/default-handler.d.ts +6 -0
  4. package/dist/client/default-handler.js +25 -0
  5. package/dist/client/default-stream-handler.d.ts +16 -0
  6. package/dist/client/default-stream-handler.js +282 -0
  7. package/dist/client/fetcher.d.ts +1 -1
  8. package/dist/client/fetcher.js +2 -2
  9. package/dist/client/serialize-query.d.ts +13 -0
  10. package/dist/client/serialize-query.js +62 -0
  11. package/dist/core/apply-decorator-adapter.d.ts +7 -0
  12. package/dist/core/apply-decorator-adapter.js +50 -0
  13. package/dist/core/controllers-to-static-params.d.ts +13 -0
  14. package/dist/core/controllers-to-static-params.js +32 -0
  15. package/dist/core/create-decorator.d.ts +12 -0
  16. package/dist/core/create-decorator.js +52 -0
  17. package/dist/core/decorators.js +4 -4
  18. package/dist/core/get-schema.d.ts +21 -0
  19. package/dist/core/get-schema.js +31 -0
  20. package/dist/core/http-exception.d.ts +16 -0
  21. package/dist/core/http-exception.js +26 -0
  22. package/dist/core/init-segment.d.ts +33 -0
  23. package/dist/core/init-segment.js +62 -0
  24. package/dist/core/json-lines-responder.d.ts +42 -0
  25. package/dist/core/json-lines-responder.js +94 -0
  26. package/dist/core/resolve-generator-config-values.d.ts +19 -0
  27. package/dist/core/resolve-generator-config-values.js +59 -0
  28. package/dist/core/set-handler-schema.d.ts +4 -0
  29. package/dist/core/set-handler-schema.js +12 -0
  30. package/dist/core/to-download-response.d.ts +11 -0
  31. package/dist/core/to-download-response.js +25 -0
  32. package/dist/core/vovk-app.d.ts +36 -0
  33. package/dist/core/vovk-app.js +318 -0
  34. package/dist/index.d.ts +10 -10
  35. package/dist/index.js +10 -10
  36. package/dist/internal.d.ts +10 -10
  37. package/dist/internal.js +9 -9
  38. package/dist/openapi/error.js +1 -1
  39. package/dist/openapi/openapi-to-vovk-schema/apply-components-schemas.d.ts +23 -0
  40. package/dist/openapi/openapi-to-vovk-schema/apply-components-schemas.js +90 -0
  41. package/dist/openapi/openapi-to-vovk-schema/index.d.ts +5 -0
  42. package/dist/openapi/openapi-to-vovk-schema/index.js +179 -0
  43. package/dist/openapi/openapi-to-vovk-schema/inline-refs.d.ts +9 -0
  44. package/dist/openapi/openapi-to-vovk-schema/inline-refs.js +99 -0
  45. package/dist/openapi/openapi-to-vovk-schema/prune-components-schemas.d.ts +7 -0
  46. package/dist/openapi/openapi-to-vovk-schema/prune-components-schemas.js +51 -0
  47. package/dist/openapi/operation.js +1 -1
  48. package/dist/openapi/tool.js +1 -1
  49. package/dist/openapi/vovk-schema-to-openapi.d.ts +21 -0
  50. package/dist/openapi/vovk-schema-to-openapi.js +250 -0
  51. package/dist/req/buffer-body.d.ts +1 -0
  52. package/dist/req/buffer-body.js +30 -0
  53. package/dist/req/parse-body.d.ts +4 -0
  54. package/dist/req/parse-body.js +49 -0
  55. package/dist/req/parse-form.d.ts +1 -0
  56. package/dist/req/parse-form.js +24 -0
  57. package/dist/req/parse-query.d.ts +24 -0
  58. package/dist/req/parse-query.js +156 -0
  59. package/dist/req/req-meta.d.ts +2 -0
  60. package/dist/req/req-meta.js +10 -0
  61. package/dist/req/req-query.d.ts +2 -0
  62. package/dist/req/req-query.js +4 -0
  63. package/dist/req/validate-content-type.d.ts +1 -0
  64. package/dist/req/validate-content-type.js +32 -0
  65. package/dist/samples/create-code-samples.d.ts +20 -0
  66. package/dist/samples/create-code-samples.js +293 -0
  67. package/dist/samples/object-to-code.d.ts +8 -0
  68. package/dist/samples/object-to-code.js +38 -0
  69. package/dist/samples/schema-to-code.d.ts +11 -0
  70. package/dist/samples/schema-to-code.js +264 -0
  71. package/dist/samples/schema-to-object.d.ts +2 -0
  72. package/dist/samples/schema-to-object.js +164 -0
  73. package/dist/samples/schema-to-ts-type.d.ts +2 -0
  74. package/dist/samples/schema-to-ts-type.js +114 -0
  75. package/dist/tools/create-tool-factory.d.ts +135 -0
  76. package/dist/tools/create-tool-factory.js +62 -0
  77. package/dist/tools/create-tool.d.ts +126 -0
  78. package/dist/tools/create-tool.js +6 -0
  79. package/dist/tools/derive-tools.d.ts +46 -0
  80. package/dist/tools/derive-tools.js +131 -0
  81. package/dist/tools/to-model-output-default.d.ts +7 -0
  82. package/dist/tools/to-model-output-default.js +7 -0
  83. package/dist/tools/to-model-output-mcp.d.ts +30 -0
  84. package/dist/tools/to-model-output-mcp.js +54 -0
  85. package/dist/tools/to-model-output.d.ts +8 -0
  86. package/dist/tools/to-model-output.js +10 -0
  87. package/dist/types/client.d.ts +3 -3
  88. package/dist/types/core.d.ts +1 -1
  89. package/dist/types/inference.d.ts +1 -1
  90. package/dist/types/validation.d.ts +1 -1
  91. package/dist/utils/camel-case.d.ts +6 -0
  92. package/dist/utils/camel-case.js +34 -0
  93. package/dist/utils/deep-extend.d.ts +54 -0
  94. package/dist/utils/deep-extend.js +127 -0
  95. package/dist/utils/file-name-to-disposition.d.ts +1 -0
  96. package/dist/utils/file-name-to-disposition.js +3 -0
  97. package/dist/utils/to-kebab-case.d.ts +1 -0
  98. package/dist/utils/to-kebab-case.js +5 -0
  99. package/dist/utils/trim-path.d.ts +1 -0
  100. package/dist/utils/trim-path.js +1 -0
  101. package/dist/utils/upper-first.d.ts +1 -0
  102. package/dist/utils/upper-first.js +3 -0
  103. package/dist/validation/create-standard-validation.d.ts +268 -0
  104. package/dist/validation/create-standard-validation.js +45 -0
  105. package/dist/validation/create-validate-on-client.d.ts +14 -0
  106. package/dist/validation/create-validate-on-client.js +23 -0
  107. package/dist/validation/procedure.d.ts +24 -24
  108. package/dist/validation/procedure.js +1 -1
  109. package/dist/validation/validation-schemas-object-to-single-validation-schema.d.ts +17 -0
  110. package/dist/validation/validation-schemas-object-to-single-validation-schema.js +92 -0
  111. package/dist/validation/with-validation-library.d.ts +119 -0
  112. package/dist/validation/with-validation-library.js +184 -0
  113. package/package.json +13 -5
@@ -0,0 +1,38 @@
1
+ export function objectToCode(obj, options) {
2
+ const { stripQuotes = false, indent = 0, nestingIndent = 2, quote = '"' } = options || {};
3
+ // Use JSON.stringify with the nesting indent
4
+ let result = JSON.stringify(obj, null, nestingIndent);
5
+ // Replace double quotes with single quotes for string values if requested
6
+ if (quote === "'") {
7
+ // First, escape any existing single quotes in string values
8
+ result = result.replace(/"([^"]*)"/g, (match, content) => {
9
+ // Check if this is a key (followed by colon) or a value
10
+ const matchIndex = result.indexOf(match);
11
+ const afterMatch = result.substring(matchIndex + match.length);
12
+ if (afterMatch.startsWith(':')) {
13
+ // This is a key, keep it for now
14
+ return match;
15
+ }
16
+ // This is a value, replace quotes and escape single quotes
17
+ const escaped = content.replace(/'/g, "\\'");
18
+ return `'${escaped}'`;
19
+ });
20
+ }
21
+ // Strip quotes from keys if requested
22
+ if (stripQuotes) {
23
+ // Remove quotes from keys that are valid JavaScript identifiers
24
+ // Keep quotes for keys with special characters (like 'x-foo', spaces, etc.)
25
+ const keyQuote = quote === "'" ? "'" : '"';
26
+ const pattern = new RegExp(`${keyQuote}([a-zA-Z_$][a-zA-Z0-9_$]*)${keyQuote}:`, 'g');
27
+ result = result.replace(pattern, '$1:');
28
+ }
29
+ // Apply base indentation if specified
30
+ if (indent > 0) {
31
+ const indentStr = ' '.repeat(indent);
32
+ result = result
33
+ .split('\n')
34
+ .map((line, i) => (i === 0 ? line : indentStr + line))
35
+ .join('\n');
36
+ }
37
+ return result;
38
+ }
@@ -0,0 +1,11 @@
1
+ import type { VovkJSONSchemaBase } from '../types/json-schema.js';
2
+ interface SamplerOptions {
3
+ comment?: '//' | '#';
4
+ stripQuotes?: boolean;
5
+ indent?: number;
6
+ nestingIndent?: number;
7
+ ignoreBinary?: boolean;
8
+ }
9
+ export declare function schemaToCode(schema: VovkJSONSchemaBase, options: SamplerOptions, rootSchema?: VovkJSONSchemaBase): string;
10
+ export declare function getSampleValue(schema: VovkJSONSchemaBase, rootSchema?: VovkJSONSchemaBase, ignoreBinary?: boolean): unknown;
11
+ export {};
@@ -0,0 +1,264 @@
1
+ export function schemaToCode(schema, options, rootSchema) {
2
+ const { comment = '//', stripQuotes = false, indent = 0, nestingIndent = 4, ignoreBinary = false } = options;
3
+ if (!schema || typeof schema !== 'object')
4
+ return 'null';
5
+ // Use the input schema as the root if not provided
6
+ rootSchema = rootSchema || schema;
7
+ // Get the sample value
8
+ const sampleValue = getSampleValue(schema, rootSchema, ignoreBinary);
9
+ // Format the output with descriptions
10
+ return formatWithDescriptions(sampleValue, schema, rootSchema, comment, stripQuotes, indent, nestingIndent, ignoreBinary, true // isTopLevel
11
+ );
12
+ }
13
+ export function getSampleValue(schema, rootSchema, ignoreBinary) {
14
+ if (!schema || typeof schema !== 'object')
15
+ return null;
16
+ rootSchema = rootSchema || schema;
17
+ // Check if this is a binary string schema and should be ignored
18
+ if (ignoreBinary && schema.type === 'string' && schema.format === 'binary') {
19
+ return undefined;
20
+ }
21
+ // If there's an example, use it
22
+ if (schema.example !== undefined) {
23
+ return schema.example;
24
+ }
25
+ // If there are examples, use one of them
26
+ if (schema.examples && schema.examples.length > 0) {
27
+ return schema.examples[0];
28
+ }
29
+ // Handle const if present
30
+ if (schema.const !== undefined) {
31
+ return schema.const;
32
+ }
33
+ // Handle $ref if present
34
+ if (schema.$ref) {
35
+ return handleRef(schema.$ref, rootSchema, ignoreBinary);
36
+ }
37
+ // Handle enum if present
38
+ if (schema.enum && schema.enum.length > 0) {
39
+ return schema.enum[0];
40
+ }
41
+ // Handle oneOf, anyOf, allOf
42
+ if (schema.oneOf && schema.oneOf.length > 0) {
43
+ return getSampleValue(schema.oneOf[0], rootSchema, ignoreBinary);
44
+ }
45
+ if (schema.anyOf && schema.anyOf.length > 0) {
46
+ return getSampleValue(schema.anyOf[0], rootSchema, ignoreBinary);
47
+ }
48
+ if (schema.allOf && schema.allOf.length > 0) {
49
+ // Merge all schemas in allOf
50
+ const mergedSchema = schema.allOf.reduce((acc, s) => Object.assign(acc, s), {});
51
+ return getSampleValue(mergedSchema, rootSchema, ignoreBinary);
52
+ }
53
+ // Handle different types
54
+ if (schema.type) {
55
+ switch (schema.type) {
56
+ case 'string':
57
+ return handleString(schema);
58
+ case 'number':
59
+ case 'integer':
60
+ return handleNumber(schema);
61
+ case 'boolean':
62
+ return handleBoolean();
63
+ case 'object':
64
+ return handleObject(schema, rootSchema, ignoreBinary);
65
+ case 'array':
66
+ return handleArray(schema, rootSchema, ignoreBinary);
67
+ case 'null':
68
+ return null;
69
+ default:
70
+ return null;
71
+ }
72
+ }
73
+ // If type is not specified but properties are, treat it as an object
74
+ if (schema.properties) {
75
+ return handleObject(schema, rootSchema, ignoreBinary);
76
+ }
77
+ // Default fallback
78
+ return null;
79
+ }
80
+ function formatWithDescriptions(value, schema, rootSchema, comment, stripQuotes, indent, nestingIndent, ignoreBinary, isTopLevel) {
81
+ const indentStr = ' '.repeat(indent);
82
+ const nestIndentStr = ' '.repeat(nestingIndent); // Create nesting indent string
83
+ // Handle undefined (for ignored binary fields)
84
+ if (value === undefined) {
85
+ return '';
86
+ }
87
+ // Handle null
88
+ if (value === null) {
89
+ return 'null';
90
+ }
91
+ // Handle primitives
92
+ if (typeof value !== 'object' || value instanceof Date) {
93
+ return JSON.stringify(value);
94
+ }
95
+ // Handle arrays
96
+ if (Array.isArray(value)) {
97
+ if (value.length === 0)
98
+ return '[]';
99
+ const items = value.map((item) => {
100
+ const itemSchema = schema.items && typeof schema.items === 'object' ? schema.items : {};
101
+ const formattedItem = formatWithDescriptions(item, itemSchema, rootSchema, comment, stripQuotes, indent + nestingIndent, // Use nestingIndent instead of hardcoded 4
102
+ nestingIndent, ignoreBinary, false);
103
+ return `${indentStr}${nestIndentStr}${formattedItem}`; // Use nestIndentStr for item indentation
104
+ });
105
+ return `[\n${items.join(',\n')}\n${indentStr}]`;
106
+ }
107
+ // Handle objects
108
+ if (typeof value === 'object') {
109
+ const entries = Object.entries(value);
110
+ if (entries.length === 0)
111
+ return '{}';
112
+ const formattedEntries = [];
113
+ // Add top-level description for objects
114
+ if (isTopLevel && schema.type === 'object' && schema.description) {
115
+ const descLines = schema.description.split('\n');
116
+ formattedEntries.push(`${indentStr}${nestIndentStr}${comment} -----`);
117
+ descLines.forEach((line) => {
118
+ formattedEntries.push(`${indentStr}${nestIndentStr}${comment} ${line.trim()}`);
119
+ });
120
+ formattedEntries.push(`${indentStr}${nestIndentStr}${comment} -----`);
121
+ }
122
+ entries.forEach(([key, val], index) => {
123
+ const propSchema = schema.properties?.[key] ?? {};
124
+ // Handle $ref in property schema
125
+ let resolvedPropSchema = propSchema;
126
+ if (propSchema.$ref) {
127
+ resolvedPropSchema = resolveRef(propSchema.$ref, rootSchema);
128
+ }
129
+ // Add property description if it exists
130
+ if (resolvedPropSchema.description) {
131
+ const descLines = resolvedPropSchema.description.split('\n');
132
+ descLines.forEach((line) => {
133
+ formattedEntries.push(`${indentStr}${nestIndentStr}${comment} ${line.trim()}`);
134
+ });
135
+ }
136
+ // Format the key
137
+ const formattedKey = stripQuotes && /^[A-Za-z_$][0-9A-Za-z_$]*$/.test(key) ? key : JSON.stringify(key);
138
+ // Format the value
139
+ const formattedValue = formatWithDescriptions(val, resolvedPropSchema, rootSchema, comment, stripQuotes, indent + nestingIndent, nestingIndent, ignoreBinary, false);
140
+ formattedEntries.push(`${indentStr}${nestIndentStr}${formattedKey}: ${formattedValue}${index < entries.length - 1 ? ',' : ''}`);
141
+ });
142
+ return `{\n${formattedEntries.join('\n')}\n${indentStr}}`;
143
+ }
144
+ return JSON.stringify(value);
145
+ }
146
+ function resolveRef(ref, rootSchema) {
147
+ const path = ref.split('/').slice(1); // Remove the initial '#'
148
+ let current = rootSchema;
149
+ for (const segment of path) {
150
+ current = current[segment];
151
+ if (current === undefined) {
152
+ return {};
153
+ }
154
+ }
155
+ return current;
156
+ }
157
+ function handleRef(ref, rootSchema, ignoreBinary) {
158
+ const resolved = resolveRef(ref, rootSchema);
159
+ return getSampleValue(resolved, rootSchema, ignoreBinary);
160
+ }
161
+ function handleString(schema) {
162
+ if (schema.format) {
163
+ switch (schema.format) {
164
+ case 'email':
165
+ case 'idn-email':
166
+ return 'user@example.com';
167
+ case 'uri':
168
+ case 'url':
169
+ case 'iri':
170
+ return 'https://example.com';
171
+ case 'date':
172
+ return '2023-01-01';
173
+ case 'date-time':
174
+ return '2023-01-01T00:00:00Z';
175
+ case 'time':
176
+ return '12:00:00Z';
177
+ case 'duration':
178
+ return 'PT1H';
179
+ case 'uuid':
180
+ return '00000000-0000-0000-0000-000000000000';
181
+ case 'regex':
182
+ return '^[a-zA-Z0-9]+$';
183
+ case 'relative-json-pointer':
184
+ return '/some/relative/path';
185
+ case 'color':
186
+ return '#000000';
187
+ case 'hostname':
188
+ return 'example.com';
189
+ case 'zipcode':
190
+ return '12345';
191
+ case 'phone':
192
+ return '+123-456-7890';
193
+ case 'password':
194
+ return '******';
195
+ case 'binary':
196
+ return 'binary-data';
197
+ default:
198
+ return 'string';
199
+ }
200
+ }
201
+ if (schema.pattern) {
202
+ return 'pattern-string';
203
+ }
204
+ return 'string';
205
+ }
206
+ function handleNumber(schema) {
207
+ if (schema.minimum !== undefined && schema.maximum !== undefined) {
208
+ return schema.minimum;
209
+ }
210
+ else if (schema.minimum !== undefined) {
211
+ return schema.minimum;
212
+ }
213
+ else if (schema.maximum !== undefined) {
214
+ return schema.maximum;
215
+ }
216
+ return 0;
217
+ }
218
+ function handleBoolean() {
219
+ return true;
220
+ }
221
+ function handleObject(schema, rootSchema, ignoreBinary) {
222
+ const result = {};
223
+ if (schema.properties) {
224
+ const required = schema.required || [];
225
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
226
+ if (required.includes(key) || required.length === 0) {
227
+ const value = getSampleValue(propSchema, rootSchema, ignoreBinary);
228
+ // Only add the property if it's not undefined (which happens when ignoreBinary is true and it's a binary field)
229
+ if (value !== undefined) {
230
+ result[key] = value;
231
+ }
232
+ }
233
+ }
234
+ }
235
+ if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {
236
+ const value = getSampleValue(schema.additionalProperties, rootSchema, ignoreBinary);
237
+ if (value !== undefined) {
238
+ result.additionalProp = value;
239
+ }
240
+ }
241
+ return result;
242
+ }
243
+ function handleArray(schema, rootSchema, ignoreBinary) {
244
+ if (schema.items) {
245
+ // If items is a boolean, return empty array (true means any items allowed, false means no items)
246
+ if (typeof schema.items === 'boolean') {
247
+ return schema.items ? [null] : [];
248
+ }
249
+ const itemSchema = schema.items;
250
+ // Check if the items are binary strings that should be ignored
251
+ if (ignoreBinary && itemSchema.type === 'string' && itemSchema.format === 'binary') {
252
+ return undefined;
253
+ }
254
+ const minItems = schema.minItems || 1;
255
+ const numItems = Math.min(minItems, 3);
256
+ const items = Array.from({ length: numItems }, () => getSampleValue(itemSchema, rootSchema, ignoreBinary)).filter((item) => item !== undefined); // Filter out undefined values from ignored binary items
257
+ // If all items were filtered out (e.g., all were binary), return undefined instead of empty array
258
+ if (items.length === 0 && numItems > 0) {
259
+ return undefined;
260
+ }
261
+ return items;
262
+ }
263
+ return [];
264
+ }
@@ -0,0 +1,2 @@
1
+ import type { VovkJSONSchemaBase } from '../types/json-schema.js';
2
+ export declare function schemaToObject(schema: VovkJSONSchemaBase, rootSchema?: VovkJSONSchemaBase): unknown;
@@ -0,0 +1,164 @@
1
+ export function schemaToObject(schema, rootSchema) {
2
+ if (!schema || typeof schema !== 'object')
3
+ return null;
4
+ // Use the input schema as the root if not provided
5
+ rootSchema = rootSchema || schema;
6
+ // If there's an example, use it
7
+ if (schema.example !== undefined) {
8
+ return schema.example;
9
+ }
10
+ // If there are examples, use one of them
11
+ if (schema.examples && schema.examples.length > 0) {
12
+ return schema.examples[0];
13
+ }
14
+ // Handle const if present
15
+ if (schema.const !== undefined) {
16
+ return schema.const;
17
+ }
18
+ // Handle $ref if present
19
+ if (schema.$ref) {
20
+ return handleRef(schema.$ref, rootSchema);
21
+ }
22
+ // Handle enum if present
23
+ if (schema.enum && schema.enum.length > 0) {
24
+ return schema.enum[0];
25
+ }
26
+ // Handle oneOf, anyOf, allOf
27
+ if (schema.oneOf && schema.oneOf.length > 0) {
28
+ return schemaToObject(schema.oneOf[0], rootSchema);
29
+ }
30
+ if (schema.anyOf && schema.anyOf.length > 0) {
31
+ return schemaToObject(schema.anyOf[0], rootSchema);
32
+ }
33
+ if (schema.allOf && schema.allOf.length > 0) {
34
+ // Merge all schemas in allOf
35
+ const mergedSchema = schema.allOf.reduce((acc, s) => Object.assign(acc, s), {});
36
+ return schemaToObject(mergedSchema, rootSchema);
37
+ }
38
+ // Handle different types
39
+ if (schema.type) {
40
+ switch (schema.type) {
41
+ case 'string':
42
+ return handleString(schema);
43
+ case 'number':
44
+ case 'integer':
45
+ return handleNumber(schema);
46
+ case 'boolean':
47
+ return handleBoolean();
48
+ case 'object':
49
+ return handleObject(schema, rootSchema);
50
+ case 'array':
51
+ return handleArray(schema, rootSchema);
52
+ case 'null':
53
+ return null;
54
+ default:
55
+ return null;
56
+ }
57
+ }
58
+ // If type is not specified but properties are, treat it as an object
59
+ if (schema.properties) {
60
+ return handleObject(schema, rootSchema);
61
+ }
62
+ // Default fallback
63
+ return null;
64
+ }
65
+ function handleRef(ref, rootSchema) {
66
+ // Parse the reference path
67
+ const path = ref.split('/').slice(1); // Remove the initial '#'
68
+ // Navigate through the schema to find the referenced definition
69
+ let current = rootSchema;
70
+ for (const segment of path) {
71
+ current = current[segment];
72
+ if (current === undefined) {
73
+ return null; // Reference not found
74
+ }
75
+ }
76
+ // Process the referenced schema
77
+ return schemaToObject(current, rootSchema);
78
+ }
79
+ function handleString(schema) {
80
+ if (schema.format) {
81
+ switch (schema.format) {
82
+ case 'email':
83
+ case 'idn-email':
84
+ return 'user@example.com';
85
+ case 'uri':
86
+ case 'url':
87
+ case 'iri':
88
+ return 'https://example.com';
89
+ case 'date':
90
+ return '2023-01-01';
91
+ case 'date-time':
92
+ return '2023-01-01T00:00:00Z';
93
+ case 'time':
94
+ return '12:00:00Z';
95
+ case 'duration':
96
+ return 'PT1H';
97
+ case 'uuid':
98
+ return '00000000-0000-0000-0000-000000000000';
99
+ case 'regex':
100
+ return '^[a-zA-Z0-9]+$';
101
+ case 'relative-json-pointer':
102
+ return '/some/relative/path';
103
+ case 'color':
104
+ return '#000000';
105
+ case 'hostname':
106
+ return 'example.com';
107
+ case 'zipcode':
108
+ return '12345';
109
+ case 'phone':
110
+ return '+123-456-7890';
111
+ case 'password':
112
+ return '******';
113
+ default:
114
+ return 'string';
115
+ }
116
+ }
117
+ if (schema.pattern) {
118
+ // For simplicity, return a basic string for patterns
119
+ return 'pattern-string';
120
+ }
121
+ return 'string';
122
+ }
123
+ function handleNumber(schema) {
124
+ if (schema.minimum !== undefined && schema.maximum !== undefined) {
125
+ return schema.minimum;
126
+ }
127
+ else if (schema.minimum !== undefined) {
128
+ return schema.minimum;
129
+ }
130
+ else if (schema.maximum !== undefined) {
131
+ return schema.maximum;
132
+ }
133
+ return 0;
134
+ }
135
+ function handleBoolean() {
136
+ return true;
137
+ }
138
+ function handleObject(schema, rootSchema) {
139
+ const result = {};
140
+ if (schema.properties) {
141
+ const required = schema.required || [];
142
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
143
+ // Only include required properties or as a basic example
144
+ if (required.includes(key) || required.length === 0) {
145
+ result[key] = schemaToObject(propSchema, rootSchema);
146
+ }
147
+ }
148
+ }
149
+ // Handle additionalProperties
150
+ if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {
151
+ result.additionalProp = schemaToObject(schema.additionalProperties, rootSchema);
152
+ }
153
+ return result;
154
+ }
155
+ function handleArray(schema, rootSchema) {
156
+ if (schema.items && typeof schema.items === 'object') {
157
+ const itemSchema = schema.items;
158
+ const minItems = schema.minItems || 1;
159
+ // Create minimum number of items (capped at a reasonable max for examples)
160
+ const numItems = Math.min(minItems, 3);
161
+ return Array.from({ length: numItems }, () => schemaToObject(itemSchema, rootSchema));
162
+ }
163
+ return [];
164
+ }
@@ -0,0 +1,2 @@
1
+ import type { VovkJSONSchemaBase } from 'vovk';
2
+ export declare function schemaToTsType(jsonSchema: VovkJSONSchemaBase | boolean): string;
@@ -0,0 +1,114 @@
1
+ export function schemaToTsType(jsonSchema) {
2
+ if (jsonSchema === true)
3
+ return 'unknown';
4
+ if (jsonSchema === false)
5
+ return 'never';
6
+ if (jsonSchema === null || jsonSchema === undefined)
7
+ return 'unknown';
8
+ if (typeof jsonSchema !== 'object')
9
+ return 'unknown';
10
+ // Handle const
11
+ if ('const' in jsonSchema) {
12
+ return JSON.stringify(jsonSchema.const);
13
+ }
14
+ // Handle enum
15
+ if (jsonSchema.enum) {
16
+ return jsonSchema.enum.map((v) => JSON.stringify(v)).join(' | ') || 'never';
17
+ }
18
+ // Handle allOf (intersection)
19
+ if (jsonSchema.allOf) {
20
+ const parts = jsonSchema.allOf.map((s) => schemaToTsType(s));
21
+ return parts.length ? `(${parts.join(' & ')})` : 'unknown';
22
+ }
23
+ // Handle anyOf (union)
24
+ if (jsonSchema.anyOf) {
25
+ const parts = jsonSchema.anyOf.map((s) => schemaToTsType(s));
26
+ return parts.length ? `(${parts.join(' | ')})` : 'never';
27
+ }
28
+ // Handle oneOf (union)
29
+ if (jsonSchema.oneOf) {
30
+ const parts = jsonSchema.oneOf.map((s) => schemaToTsType(s));
31
+ return parts.length ? `(${parts.join(' | ')})` : 'never';
32
+ }
33
+ // Handle not (negate - approximate as unknown)
34
+ if (jsonSchema.not) {
35
+ return 'unknown';
36
+ }
37
+ // Handle type as array (union of types)
38
+ if (Array.isArray(jsonSchema.type)) {
39
+ const types = jsonSchema.type.map((t) => schemaToTsType({ ...jsonSchema, type: t }));
40
+ return types.length ? `(${types.join(' | ')})` : 'unknown';
41
+ }
42
+ const type = jsonSchema.type;
43
+ // Primitives
44
+ if (type === 'string')
45
+ return 'string';
46
+ if (type === 'number' || type === 'integer')
47
+ return 'number';
48
+ if (type === 'boolean')
49
+ return 'boolean';
50
+ if (type === 'null')
51
+ return 'null';
52
+ // Object
53
+ if (type === 'object' || jsonSchema.properties || jsonSchema.additionalProperties !== undefined) {
54
+ const props = jsonSchema.properties || {};
55
+ const required = jsonSchema.required || [];
56
+ const propEntries = Object.entries(props);
57
+ const propStrings = propEntries.map(([key, value]) => {
58
+ const isRequired = required.includes(key);
59
+ const safeName = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
60
+ return `${safeName}${isRequired ? '' : '?'}: ${schemaToTsType(value)}`;
61
+ });
62
+ // Handle additionalProperties
63
+ let additionalType = null;
64
+ if (jsonSchema.additionalProperties === true) {
65
+ additionalType = 'unknown';
66
+ }
67
+ else if (jsonSchema.additionalProperties && typeof jsonSchema.additionalProperties === 'object') {
68
+ additionalType = schemaToTsType(jsonSchema.additionalProperties);
69
+ }
70
+ if (propStrings.length === 0 && additionalType) {
71
+ return `{ [key: string]: ${additionalType} }`;
72
+ }
73
+ if (propStrings.length === 0 && !additionalType) {
74
+ return jsonSchema.additionalProperties === false ? '{}' : '{ [key: string]: unknown }';
75
+ }
76
+ let result = `{ ${propStrings.join('; ')} }`;
77
+ if (additionalType) {
78
+ result = `(${result} & { [key: string]: ${additionalType} })`;
79
+ }
80
+ return result;
81
+ }
82
+ // Array
83
+ if (type === 'array' || jsonSchema.items || jsonSchema.prefixItems) {
84
+ // Tuple (prefixItems)
85
+ if (jsonSchema.prefixItems) {
86
+ const tupleTypes = jsonSchema.prefixItems.map((s) => schemaToTsType(s));
87
+ if (jsonSchema.items === false) {
88
+ return `[${tupleTypes.join(', ')}]`;
89
+ }
90
+ const restType = jsonSchema.items ? schemaToTsType(jsonSchema.items) : 'unknown';
91
+ return `[${tupleTypes.join(', ')}, ...${restType}[]]`;
92
+ }
93
+ // Regular array
94
+ if (jsonSchema.items) {
95
+ if (Array.isArray(jsonSchema.items)) {
96
+ // Legacy tuple syntax
97
+ const tupleTypes = jsonSchema.items.map((s) => schemaToTsType(s));
98
+ if (jsonSchema.additionalItems === false) {
99
+ return `[${tupleTypes.join(', ')}]`;
100
+ }
101
+ const restType = jsonSchema.additionalItems ? schemaToTsType(jsonSchema.additionalItems) : 'unknown';
102
+ return `[${tupleTypes.join(', ')}, ...${restType}[]]`;
103
+ }
104
+ return `${schemaToTsType(jsonSchema.items)}[]`;
105
+ }
106
+ return 'unknown[]';
107
+ }
108
+ // No type specified - try to infer from structure
109
+ if (jsonSchema.properties) {
110
+ return schemaToTsType({ ...jsonSchema, type: 'object' });
111
+ }
112
+ // Fallback for empty or unknown schema
113
+ return 'unknown';
114
+ }