metal-orm 1.0.88 → 1.0.90

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 (49) hide show
  1. package/dist/index.cjs +3818 -3783
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +765 -236
  4. package/dist/index.d.ts +765 -236
  5. package/dist/index.js +3763 -3775
  6. package/dist/index.js.map +1 -1
  7. package/package.json +3 -2
  8. package/src/codegen/typescript.ts +29 -40
  9. package/src/core/ast/expression-builders.ts +34 -53
  10. package/src/core/ast/expression-nodes.ts +51 -72
  11. package/src/core/ast/expression-visitor.ts +219 -252
  12. package/src/core/ast/expression.ts +20 -21
  13. package/src/core/dialect/abstract.ts +55 -81
  14. package/src/core/execution/db-executor.ts +4 -5
  15. package/src/core/execution/executors/mysql-executor.ts +7 -9
  16. package/src/decorators/bootstrap.ts +11 -8
  17. package/src/dto/apply-filter.ts +281 -0
  18. package/src/dto/dto-types.ts +229 -0
  19. package/src/dto/filter-types.ts +193 -0
  20. package/src/dto/index.ts +97 -0
  21. package/src/dto/openapi/generators/base.ts +29 -0
  22. package/src/dto/openapi/generators/column.ts +34 -0
  23. package/src/dto/openapi/generators/dto.ts +94 -0
  24. package/src/dto/openapi/generators/filter.ts +74 -0
  25. package/src/dto/openapi/generators/nested-dto.ts +532 -0
  26. package/src/dto/openapi/generators/pagination.ts +111 -0
  27. package/src/dto/openapi/generators/relation-filter.ts +210 -0
  28. package/src/dto/openapi/index.ts +17 -0
  29. package/src/dto/openapi/type-mappings.ts +191 -0
  30. package/src/dto/openapi/types.ts +83 -0
  31. package/src/dto/openapi/utilities.ts +45 -0
  32. package/src/dto/pagination-utils.ts +150 -0
  33. package/src/dto/transform.ts +193 -0
  34. package/src/index.ts +67 -65
  35. package/src/orm/unit-of-work.ts +13 -25
  36. package/src/query-builder/query-ast-service.ts +287 -300
  37. package/src/query-builder/relation-filter-utils.ts +159 -160
  38. package/src/query-builder/select.ts +137 -192
  39. package/src/core/ast/ast-validation.ts +0 -19
  40. package/src/core/ast/param-proxy.ts +0 -47
  41. package/src/core/ast/query-visitor.ts +0 -273
  42. package/src/openapi/index.ts +0 -4
  43. package/src/openapi/query-parameters.ts +0 -207
  44. package/src/openapi/schema-extractor-input.ts +0 -139
  45. package/src/openapi/schema-extractor-output.ts +0 -427
  46. package/src/openapi/schema-extractor-utils.ts +0 -110
  47. package/src/openapi/schema-extractor.ts +0 -111
  48. package/src/openapi/schema-types.ts +0 -176
  49. package/src/openapi/type-mappers.ts +0 -227
@@ -1,427 +0,0 @@
1
- import type { TableDef } from '../schema/table.js';
2
- import type { RelationDef } from '../schema/relation.js';
3
- import type { HydrationPlan, HydrationRelationPlan } from '../core/hydration/types.js';
4
- import type { ProjectionNode } from '../query-builder/select-query-state.js';
5
-
6
- import type {
7
- OpenApiSchema,
8
- SchemaExtractionContext,
9
- OutputSchemaOptions,
10
- JsonSchemaProperty,
11
- JsonSchemaType
12
- } from './schema-types.js';
13
- import { mapColumnType, mapRelationType } from './type-mappers.js';
14
- import {
15
- buildCircularReferenceSchema,
16
- ensureComponentRef,
17
- hasComputedProjection,
18
- resolveComponentName,
19
- resolveSelectedComponentName,
20
- shouldUseSelectedSchema
21
- } from './schema-extractor-utils.js';
22
-
23
- /**
24
- * Output schema extraction (query results)
25
- */
26
- export const extractOutputSchema = (
27
- table: TableDef,
28
- plan: HydrationPlan | undefined,
29
- projectionNodes: ProjectionNode[] | undefined,
30
- context: SchemaExtractionContext,
31
- options: OutputSchemaOptions
32
- ): OpenApiSchema => {
33
- const hasComputedFields = hasComputedProjection(projectionNodes);
34
-
35
- if (hasComputedFields) {
36
- return extractFromProjectionNodes(table, projectionNodes!, context, options);
37
- }
38
-
39
- if (shouldUseSelectedSchema(options, plan, projectionNodes)) {
40
- return extractSelectedSchema(table, plan, context, options);
41
- }
42
-
43
- return extractFullTableSchema(table, context, options);
44
- };
45
-
46
- /**
47
- * Extracts schema from projection nodes (handles computed fields)
48
- */
49
- const extractFromProjectionNodes = (
50
- table: TableDef,
51
- projectionNodes: ProjectionNode[],
52
- context: SchemaExtractionContext,
53
- options: OutputSchemaOptions
54
- ): OpenApiSchema => {
55
- const properties: Record<string, JsonSchemaProperty> = {};
56
- const required: string[] = [];
57
- const includeDescriptions = Boolean(options.includeDescriptions);
58
-
59
- for (const node of projectionNodes) {
60
- if (!node || typeof node !== 'object') continue;
61
-
62
- const projection = node as { type: string; alias?: string; fn?: string; value?: unknown };
63
- const propertyName = projection.alias ?? '';
64
-
65
- if (!propertyName) continue;
66
-
67
- if (projection.type === 'Column') {
68
- const columnNode = node as { table: string; name: string };
69
- const column = table.columns[columnNode.name];
70
- if (!column) continue;
71
-
72
- const property = mapColumnType(column, options);
73
- properties[propertyName] = property;
74
-
75
- if (column.notNull || column.primary) {
76
- required.push(propertyName);
77
- }
78
- } else if (projection.type === 'Function' || projection.type === 'WindowFunction') {
79
- const fnNode = node as { fn?: string; name?: string };
80
- const functionName = fnNode.fn?.toUpperCase() ?? fnNode.name?.toUpperCase() ?? '';
81
- const propertySchema = projection.type === 'Function'
82
- ? mapFunctionNodeToSchema(functionName, includeDescriptions)
83
- : mapWindowFunctionToSchema(functionName, includeDescriptions);
84
-
85
- properties[propertyName] = propertySchema;
86
-
87
- const isCountFunction = functionName === 'COUNT';
88
- const isWindowRankFunction = functionName === 'ROW_NUMBER' || functionName === 'RANK';
89
-
90
- if (isCountFunction || isWindowRankFunction) {
91
- required.push(propertyName);
92
- }
93
- } else if (projection.type === 'CaseExpression') {
94
- const propertySchema: JsonSchemaProperty = {
95
- type: 'string' as JsonSchemaType,
96
- nullable: true
97
- };
98
- if (includeDescriptions) {
99
- propertySchema.description = 'Computed CASE expression';
100
- }
101
- properties[propertyName] = propertySchema;
102
- } else if (projection.type === 'ScalarSubquery') {
103
- const propertySchema: JsonSchemaProperty = {
104
- type: 'object' as JsonSchemaType,
105
- nullable: true
106
- };
107
- if (includeDescriptions) {
108
- propertySchema.description = 'Subquery result';
109
- }
110
- properties[propertyName] = propertySchema;
111
- } else if (projection.type === 'CastExpression') {
112
- const propertySchema: JsonSchemaProperty = {
113
- type: 'string' as JsonSchemaType,
114
- nullable: true
115
- };
116
- if (includeDescriptions) {
117
- propertySchema.description = 'CAST expression result';
118
- }
119
- properties[propertyName] = propertySchema;
120
- }
121
- }
122
-
123
- return {
124
- type: 'object',
125
- properties,
126
- required
127
- };
128
- };
129
-
130
- /**
131
- * Maps SQL aggregate functions to OpenAPI types
132
- */
133
- const mapFunctionNodeToSchema = (
134
- functionName: string,
135
- includeDescriptions: boolean
136
- ): JsonSchemaProperty => {
137
- const upperName = functionName.toUpperCase();
138
-
139
- switch (upperName) {
140
- case 'COUNT':
141
- case 'SUM':
142
- case 'AVG':
143
- case 'MIN':
144
- case 'MAX':
145
- return withOptionalDescription({
146
- type: 'number' as JsonSchemaType,
147
- nullable: false
148
- }, includeDescriptions, `${upperName} aggregate function result`);
149
-
150
- case 'GROUP_CONCAT':
151
- case 'STRING_AGG':
152
- case 'ARRAY_AGG':
153
- return withOptionalDescription({
154
- type: 'string' as JsonSchemaType,
155
- nullable: true
156
- }, includeDescriptions, `${upperName} aggregate function result`);
157
-
158
- case 'JSON_ARRAYAGG':
159
- case 'JSON_OBJECTAGG':
160
- return withOptionalDescription({
161
- type: 'object' as JsonSchemaType,
162
- nullable: true
163
- }, includeDescriptions, `${upperName} aggregate function result`);
164
-
165
- default:
166
- return withOptionalDescription({
167
- type: 'string' as JsonSchemaType,
168
- nullable: true
169
- }, includeDescriptions, `Unknown function: ${functionName}`);
170
- }
171
- };
172
-
173
- /**
174
- * Maps SQL window functions to OpenAPI types
175
- */
176
- const mapWindowFunctionToSchema = (
177
- functionName: string,
178
- includeDescriptions: boolean
179
- ): JsonSchemaProperty => {
180
- const upperName = functionName.toUpperCase();
181
-
182
- switch (upperName) {
183
- case 'ROW_NUMBER':
184
- case 'RANK':
185
- case 'DENSE_RANK':
186
- case 'NTILE':
187
- return withOptionalDescription({
188
- type: 'integer' as JsonSchemaType,
189
- nullable: false
190
- }, includeDescriptions, `${upperName} window function result`);
191
-
192
- case 'LAG':
193
- case 'LEAD':
194
- case 'FIRST_VALUE':
195
- case 'LAST_VALUE':
196
- return withOptionalDescription({
197
- type: 'string' as JsonSchemaType,
198
- nullable: true
199
- }, includeDescriptions, `${upperName} window function result`);
200
-
201
- default:
202
- return withOptionalDescription({
203
- type: 'string' as JsonSchemaType,
204
- nullable: true
205
- }, includeDescriptions, `Unknown window function: ${functionName}`);
206
- }
207
- };
208
-
209
- const withOptionalDescription = (
210
- schema: JsonSchemaProperty,
211
- includeDescriptions: boolean,
212
- description: string
213
- ): JsonSchemaProperty => {
214
- if (includeDescriptions) {
215
- return { ...schema, description };
216
- }
217
- return schema;
218
- };
219
-
220
- /**
221
- * Extracts schema with only selected columns and relations
222
- */
223
- const extractSelectedSchema = (
224
- table: TableDef,
225
- plan: HydrationPlan,
226
- context: SchemaExtractionContext,
227
- options: OutputSchemaOptions
228
- ): OpenApiSchema => {
229
- const properties: Record<string, JsonSchemaProperty> = {};
230
- const required: string[] = [];
231
-
232
- plan.rootColumns.forEach(columnName => {
233
- const column = table.columns[columnName];
234
- if (!column) return;
235
-
236
- properties[columnName] = mapColumnType(column, options);
237
-
238
- if (column.notNull || column.primary) {
239
- required.push(columnName);
240
- }
241
- });
242
-
243
- plan.relations.forEach(relationPlan => {
244
- const relation = table.relations[relationPlan.name];
245
- if (!relation) return;
246
-
247
- const relationSchema = extractRelationSchema(
248
- relation,
249
- relationPlan,
250
- relationPlan.columns,
251
- context,
252
- options
253
- );
254
-
255
- properties[relationPlan.name] = relationSchema;
256
-
257
- const { isNullable } = mapRelationType(relation.type);
258
- if (!isNullable && relationPlan.name) {
259
- required.push(relationPlan.name);
260
- }
261
- });
262
-
263
- return {
264
- type: 'object',
265
- properties,
266
- required
267
- };
268
- };
269
-
270
- /**
271
- * Extracts full table schema (all columns, all relations)
272
- */
273
- const extractFullTableSchema = (
274
- table: TableDef,
275
- context: SchemaExtractionContext,
276
- options: OutputSchemaOptions
277
- ): OpenApiSchema => {
278
- const cacheKey = table.name;
279
-
280
- if (context.schemaCache.has(cacheKey)) {
281
- return context.schemaCache.get(cacheKey)!;
282
- }
283
-
284
- if (context.visitedTables.has(cacheKey) && context.depth > 0) {
285
- return buildCircularReferenceSchema(table.name, 'output');
286
- }
287
-
288
- context.visitedTables.add(cacheKey);
289
-
290
- const properties: Record<string, JsonSchemaProperty> = {};
291
- const required: string[] = [];
292
-
293
- Object.entries(table.columns).forEach(([columnName, column]) => {
294
- properties[columnName] = mapColumnType(column, options);
295
-
296
- if (column.notNull || column.primary) {
297
- required.push(columnName);
298
- }
299
- });
300
-
301
- Object.entries(table.relations).forEach(([relationName, relation]) => {
302
- if (context.depth >= context.maxDepth) {
303
- return;
304
- }
305
-
306
- const relationSchema = extractRelationSchema(
307
- relation,
308
- undefined,
309
- [],
310
- { ...context, depth: context.depth + 1 },
311
- options
312
- );
313
-
314
- properties[relationName] = relationSchema;
315
-
316
- const { isNullable } = mapRelationType(relation.type);
317
- if (!isNullable) {
318
- required.push(relationName);
319
- }
320
- });
321
-
322
- const schema: OpenApiSchema = {
323
- type: 'object',
324
- properties,
325
- required
326
- };
327
-
328
- context.schemaCache.set(cacheKey, schema);
329
- return schema;
330
- };
331
-
332
- /**
333
- * Extracts schema for a single relation
334
- */
335
- const extractRelationSchema = (
336
- relation: RelationDef,
337
- relationPlan: HydrationRelationPlan | undefined,
338
- selectedColumns: string[],
339
- context: SchemaExtractionContext,
340
- options: OutputSchemaOptions
341
- ): JsonSchemaProperty => {
342
- const targetTable = relation.target;
343
- const { type: relationType, isNullable } = mapRelationType(relation.type);
344
-
345
- if (options.refMode === 'components' && context.components) {
346
- if (relationPlan && selectedColumns.length > 0 && options.selectedRefMode === 'components') {
347
- const plan: HydrationPlan = {
348
- rootTable: targetTable.name,
349
- rootPrimaryKey: relationPlan.targetPrimaryKey,
350
- rootColumns: selectedColumns,
351
- relations: []
352
- };
353
- const componentName = resolveSelectedComponentName(targetTable, plan, options);
354
- const ref = ensureComponentRef(
355
- targetTable,
356
- componentName,
357
- context,
358
- () => extractSelectedSchema(targetTable, plan, context, options)
359
- );
360
-
361
- if (relationType === 'array') {
362
- return {
363
- type: 'array',
364
- items: ref,
365
- nullable: isNullable
366
- };
367
- }
368
-
369
- return {
370
- ...ref,
371
- nullable: isNullable
372
- };
373
- }
374
-
375
- const componentName = resolveComponentName(targetTable, options);
376
- const ref = ensureComponentRef(
377
- targetTable,
378
- componentName,
379
- context,
380
- () => extractFullTableSchema(targetTable, context, options)
381
- );
382
-
383
- if (relationType === 'array') {
384
- return {
385
- type: 'array',
386
- items: ref,
387
- nullable: isNullable
388
- };
389
- }
390
-
391
- return {
392
- ...ref,
393
- nullable: isNullable
394
- };
395
- }
396
-
397
- let targetSchema: OpenApiSchema;
398
-
399
- if (relationPlan && selectedColumns.length > 0) {
400
- const plan: HydrationPlan = {
401
- rootTable: targetTable.name,
402
- rootPrimaryKey: relationPlan.targetPrimaryKey,
403
- rootColumns: selectedColumns,
404
- relations: []
405
- };
406
-
407
- targetSchema = extractSelectedSchema(targetTable, plan, context, options);
408
- } else {
409
- targetSchema = extractFullTableSchema(targetTable, context, options);
410
- }
411
-
412
- if (relationType === 'array') {
413
- return {
414
- type: 'array',
415
- items: targetSchema as JsonSchemaProperty,
416
- nullable: isNullable
417
- };
418
- }
419
-
420
- return {
421
- type: 'object' as JsonSchemaType,
422
- properties: targetSchema.properties,
423
- required: targetSchema.required,
424
- nullable: isNullable,
425
- description: targetSchema.description
426
- };
427
- };
@@ -1,110 +0,0 @@
1
- import type { TableDef } from '../schema/table.js';
2
- import type { HydrationPlan } from '../core/hydration/types.js';
3
- import type { ProjectionNode } from '../query-builder/select-query-state.js';
4
- import type {
5
- OpenApiSchema,
6
- SchemaExtractionContext,
7
- OutputSchemaOptions,
8
- JsonSchemaProperty,
9
- JsonSchemaType
10
- } from './schema-types.js';
11
-
12
- export const hasComputedProjection = (projectionNodes?: ProjectionNode[]): boolean =>
13
- Boolean(projectionNodes && projectionNodes.some(node => node.type !== 'Column'));
14
-
15
- export const shouldUseSelectedSchema = (
16
- options: OutputSchemaOptions,
17
- plan: HydrationPlan | undefined,
18
- projectionNodes: ProjectionNode[] | undefined
19
- ): boolean => {
20
- if (!plan || options.mode !== 'selected') return false;
21
- if (hasComputedProjection(projectionNodes)) return false;
22
- if (options.refMode === 'components' && options.selectedRefMode !== 'components') return false;
23
- return true;
24
- };
25
-
26
- export const resolveComponentName = (table: TableDef, options: OutputSchemaOptions): string =>
27
- options.componentName ? options.componentName(table) : table.name;
28
-
29
- const normalizeColumns = (columns: string[]): string[] =>
30
- Array.from(new Set(columns)).sort((a, b) => a.localeCompare(b));
31
-
32
- const buildSelectionSignature = (plan: HydrationPlan): string => {
33
- const relations = plan.relations
34
- .map(relation => ({
35
- name: relation.name,
36
- columns: normalizeColumns(relation.columns)
37
- }))
38
- .sort((a, b) => a.name.localeCompare(b.name));
39
-
40
- return JSON.stringify({
41
- root: normalizeColumns(plan.rootColumns),
42
- relations
43
- });
44
- };
45
-
46
- const hashString = (value: string): string => {
47
- let hash = 2166136261;
48
- for (let i = 0; i < value.length; i += 1) {
49
- hash ^= value.charCodeAt(i);
50
- hash = (hash * 16777619) >>> 0;
51
- }
52
- return hash.toString(16).padStart(8, '0');
53
- };
54
-
55
- export const resolveSelectedComponentName = (
56
- table: TableDef,
57
- plan: HydrationPlan,
58
- options: OutputSchemaOptions
59
- ): string => {
60
- const base = resolveComponentName(table, options);
61
- const signature = buildSelectionSignature(plan);
62
- return `${base}__sel_${hashString(signature)}`;
63
- };
64
-
65
- export const ensureComponentRef = (
66
- table: TableDef,
67
- componentName: string,
68
- context: SchemaExtractionContext,
69
- schemaFactory: () => OpenApiSchema
70
- ): JsonSchemaProperty => {
71
- if (context.components && !context.components.schemas[componentName]) {
72
- if (!context.visitedTables.has(table.name)) {
73
- context.components.schemas[componentName] = schemaFactory();
74
- }
75
- }
76
-
77
- return { $ref: `#/components/schemas/${componentName}` };
78
- };
79
-
80
- export const registerComponentSchema = (
81
- name: string,
82
- schema: OpenApiSchema,
83
- context: SchemaExtractionContext
84
- ): void => {
85
- if (!context.components) return;
86
- if (!context.components.schemas[name]) {
87
- context.components.schemas[name] = schema;
88
- }
89
- };
90
-
91
- export const createContext = (maxDepth: number): SchemaExtractionContext => ({
92
- visitedTables: new Set(),
93
- schemaCache: new Map(),
94
- depth: 0,
95
- maxDepth
96
- });
97
-
98
- export const buildCircularReferenceSchema = (
99
- tableName: string,
100
- kind: 'input' | 'output'
101
- ): OpenApiSchema => ({
102
- type: 'object',
103
- properties: {
104
- _ref: {
105
- type: 'string' as JsonSchemaType,
106
- description: `Circular ${kind} reference to ${tableName}`
107
- }
108
- },
109
- required: []
110
- });
@@ -1,111 +0,0 @@
1
- import type { TableDef } from '../schema/table.js';
2
- import type { HydrationPlan } from '../core/hydration/types.js';
3
- import type { ProjectionNode } from '../query-builder/select-query-state.js';
4
-
5
- import type {
6
- OpenApiSchema,
7
- OpenApiSchemaBundle,
8
- SchemaOptions,
9
- OutputSchemaOptions,
10
- InputSchemaOptions
11
- } from './schema-types.js';
12
- import { extractInputSchema } from './schema-extractor-input.js';
13
- import { extractOutputSchema } from './schema-extractor-output.js';
14
- import {
15
- createContext,
16
- hasComputedProjection,
17
- registerComponentSchema,
18
- resolveComponentName,
19
- resolveSelectedComponentName,
20
- shouldUseSelectedSchema
21
- } from './schema-extractor-utils.js';
22
-
23
- const DEFAULT_MAX_DEPTH = 5;
24
-
25
- /**
26
- * Extracts OpenAPI 3.1 schemas for output and optional input payloads.
27
- */
28
- export const extractSchema = (
29
- table: TableDef,
30
- plan: HydrationPlan | undefined,
31
- projectionNodes: ProjectionNode[] | undefined,
32
- options: SchemaOptions = {}
33
- ): OpenApiSchemaBundle => {
34
- const outputOptions = resolveOutputOptions(options);
35
- const outputContext = createContext(outputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
36
- if (outputOptions.refMode === 'components') {
37
- outputContext.components = { schemas: {} };
38
- }
39
- const output = extractOutputSchema(table, plan, projectionNodes, outputContext, outputOptions);
40
- const useSelected = shouldUseSelectedSchema(outputOptions, plan, projectionNodes);
41
- const hasComputedFields = hasComputedProjection(projectionNodes);
42
-
43
- if (outputOptions.refMode === 'components' && outputContext.components && !hasComputedFields) {
44
- const componentName = useSelected && plan
45
- ? resolveSelectedComponentName(table, plan, outputOptions)
46
- : resolveComponentName(table, outputOptions);
47
- registerComponentSchema(componentName, output, outputContext);
48
- }
49
-
50
- const inputOptions = resolveInputOptions(options);
51
- if (!inputOptions) {
52
- return {
53
- output,
54
- components: outputContext.components && Object.keys(outputContext.components.schemas).length
55
- ? outputContext.components
56
- : undefined
57
- };
58
- }
59
-
60
- const inputContext = createContext(inputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
61
- const input = extractInputSchema(table, inputContext, inputOptions);
62
-
63
- return {
64
- output,
65
- input,
66
- components: outputContext.components && Object.keys(outputContext.components.schemas).length
67
- ? outputContext.components
68
- : undefined
69
- };
70
- };
71
-
72
- const resolveOutputOptions = (options: SchemaOptions): OutputSchemaOptions => ({
73
- mode: options.mode ?? 'full',
74
- includeDescriptions: options.includeDescriptions,
75
- includeEnums: options.includeEnums,
76
- includeExamples: options.includeExamples,
77
- includeDefaults: options.includeDefaults,
78
- includeNullable: options.includeNullable,
79
- maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
80
- refMode: options.refMode ?? 'inline',
81
- selectedRefMode: options.selectedRefMode ?? 'inline',
82
- componentName: options.componentName
83
- });
84
-
85
- const resolveInputOptions = (options: SchemaOptions): InputSchemaOptions | undefined => {
86
- if (options.input === false) return undefined;
87
- const input = options.input ?? {};
88
- const mode = input.mode ?? 'create';
89
-
90
- return {
91
- mode,
92
- includeRelations: input.includeRelations ?? true,
93
- relationMode: input.relationMode ?? 'mixed',
94
- includeDescriptions: input.includeDescriptions ?? options.includeDescriptions,
95
- includeEnums: input.includeEnums ?? options.includeEnums,
96
- includeExamples: input.includeExamples ?? options.includeExamples,
97
- includeDefaults: input.includeDefaults ?? options.includeDefaults,
98
- includeNullable: input.includeNullable ?? options.includeNullable,
99
- maxDepth: input.maxDepth ?? options.maxDepth ?? DEFAULT_MAX_DEPTH,
100
- omitReadOnly: input.omitReadOnly ?? true,
101
- excludePrimaryKey: input.excludePrimaryKey ?? false,
102
- requirePrimaryKey: input.requirePrimaryKey ?? (mode === 'update')
103
- };
104
- };
105
-
106
- /**
107
- * Converts a schema to a JSON string with optional pretty printing
108
- */
109
- export const schemaToJson = (schema: OpenApiSchema, pretty = false): string => {
110
- return JSON.stringify(schema, null, pretty ? 2 : 0);
111
- };