metal-orm 1.0.90 → 1.0.91

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.
@@ -1,191 +1,191 @@
1
- import type { ColumnDef } from '../../schema/column-types.js';
2
- import type { OpenApiType } from './types.js';
3
-
4
- export interface TypeMappingStrategy {
5
- supports(columnType: string): boolean;
6
- getOpenApiType(): OpenApiType;
7
- getFormat(columnType: string): string | undefined;
8
- }
9
-
10
- export class IntegerTypeStrategy implements TypeMappingStrategy {
11
- private readonly types = ['INT', 'INTEGER'];
12
-
13
- supports(type: string): boolean {
14
- return this.types.includes(type.toUpperCase());
15
- }
16
-
17
- getOpenApiType(): OpenApiType {
18
- return 'integer';
19
- }
20
-
21
- getFormat(): string | undefined {
22
- return 'int32';
23
- }
24
- }
25
-
26
- export class BigIntTypeStrategy implements TypeMappingStrategy {
27
- private readonly types = ['BIGINT'];
28
-
29
- supports(type: string): boolean {
30
- return this.types.includes(type.toUpperCase());
31
- }
32
-
33
- getOpenApiType(): OpenApiType {
34
- return 'integer';
35
- }
36
-
37
- getFormat(): string | undefined {
38
- return 'int64';
39
- }
40
- }
41
-
42
- export class DecimalTypeStrategy implements TypeMappingStrategy {
43
- private readonly types = ['DECIMAL', 'FLOAT', 'DOUBLE'];
44
-
45
- supports(type: string): boolean {
46
- return this.types.includes(type.toUpperCase());
47
- }
48
-
49
- getOpenApiType(): OpenApiType {
50
- return 'number';
51
- }
52
-
53
- getFormat(): string | undefined {
54
- return 'double';
55
- }
56
- }
57
-
58
- export class BooleanTypeStrategy implements TypeMappingStrategy {
59
- private readonly types = ['BOOLEAN'];
60
-
61
- supports(type: string): boolean {
62
- return this.types.includes(type.toUpperCase());
63
- }
64
-
65
- getOpenApiType(): OpenApiType {
66
- return 'boolean';
67
- }
68
-
69
- getFormat(): undefined {
70
- return undefined;
71
- }
72
- }
73
-
74
- export class UuidTypeStrategy implements TypeMappingStrategy {
75
- private readonly types = ['UUID'];
76
-
77
- supports(type: string): boolean {
78
- return this.types.includes(type.toUpperCase());
79
- }
80
-
81
- getOpenApiType(): OpenApiType {
82
- return 'string';
83
- }
84
-
85
- getFormat(): string {
86
- return 'uuid';
87
- }
88
- }
89
-
90
- export class DateTimeTypeStrategy implements TypeMappingStrategy {
91
- private readonly types = ['DATE', 'DATETIME', 'TIMESTAMP', 'TIMESTAMPTZ'];
92
-
93
- supports(type: string): boolean {
94
- return this.types.includes(type.toUpperCase());
95
- }
96
-
97
- getOpenApiType(): OpenApiType {
98
- return 'string';
99
- }
100
-
101
- getFormat(columnType: string = 'DATETIME'): string {
102
- return columnType.toUpperCase() === 'DATE' ? 'date' : 'date-time';
103
- }
104
- }
105
-
106
- export class StringTypeStrategy implements TypeMappingStrategy {
107
- private readonly types = [
108
- 'JSON', 'TEXT', 'VARCHAR', 'CHAR', 'BINARY',
109
- 'VARBINARY', 'BLOB', 'ENUM'
110
- ];
111
-
112
- supports(type: string): boolean {
113
- return this.types.includes(type.toUpperCase());
114
- }
115
-
116
- getOpenApiType(): OpenApiType {
117
- return 'string';
118
- }
119
-
120
- getFormat(): undefined {
121
- return undefined;
122
- }
123
- }
124
-
125
- export class DefaultTypeStrategy implements TypeMappingStrategy {
126
- supports(): boolean {
127
- return true;
128
- }
129
-
130
- getOpenApiType(): OpenApiType {
131
- return 'string';
132
- }
133
-
134
- getFormat(): undefined {
135
- return undefined;
136
- }
137
- }
138
-
139
- export class TypeMappingService {
140
- private readonly strategies: TypeMappingStrategy[];
141
-
142
- constructor() {
143
- this.strategies = [
144
- new IntegerTypeStrategy(),
145
- new BigIntTypeStrategy(),
146
- new DecimalTypeStrategy(),
147
- new BooleanTypeStrategy(),
148
- new DateTimeTypeStrategy(),
149
- new UuidTypeStrategy(),
150
- new StringTypeStrategy(),
151
- new DefaultTypeStrategy(),
152
- ];
153
- }
154
-
155
- getOpenApiType(column: ColumnDef): OpenApiType {
156
- const strategy = this.findStrategy(column.type);
157
- return strategy.getOpenApiType();
158
- }
159
-
160
- getFormat(column: ColumnDef): string | undefined {
161
- const strategy = this.findStrategy(column.type);
162
- return strategy.getFormat(column.type);
163
- }
164
-
165
- private findStrategy(columnType: string): TypeMappingStrategy {
166
- for (const strategy of this.strategies) {
167
- if (strategy.supports(columnType)) {
168
- return strategy;
169
- }
170
- }
171
- return this.strategies[this.strategies.length - 1];
172
- }
173
-
174
- registerStrategy(strategy: TypeMappingStrategy, index?: number): void {
175
- if (index !== undefined) {
176
- this.strategies.splice(index, 0, strategy);
177
- } else {
178
- this.strategies.push(strategy);
179
- }
180
- }
181
- }
182
-
183
- export const typeMappingService = new TypeMappingService();
184
-
185
- export function columnTypeToOpenApiType(col: ColumnDef): OpenApiType {
186
- return typeMappingService.getOpenApiType(col);
187
- }
188
-
189
- export function columnTypeToOpenApiFormat(col: ColumnDef): string | undefined {
190
- return typeMappingService.getFormat(col);
191
- }
1
+ import type { ColumnDef } from '../../schema/column-types.js';
2
+ import type { OpenApiType } from './types.js';
3
+
4
+ export interface TypeMappingStrategy {
5
+ supports(columnType: string): boolean;
6
+ getOpenApiType(): OpenApiType;
7
+ getFormat(columnType: string): string | undefined;
8
+ }
9
+
10
+ export class IntegerTypeStrategy implements TypeMappingStrategy {
11
+ private readonly types = ['INT', 'INTEGER'];
12
+
13
+ supports(type: string): boolean {
14
+ return this.types.includes(type.toUpperCase());
15
+ }
16
+
17
+ getOpenApiType(): OpenApiType {
18
+ return 'integer';
19
+ }
20
+
21
+ getFormat(): string | undefined {
22
+ return 'int32';
23
+ }
24
+ }
25
+
26
+ export class BigIntTypeStrategy implements TypeMappingStrategy {
27
+ private readonly types = ['BIGINT'];
28
+
29
+ supports(type: string): boolean {
30
+ return this.types.includes(type.toUpperCase());
31
+ }
32
+
33
+ getOpenApiType(): OpenApiType {
34
+ return 'integer';
35
+ }
36
+
37
+ getFormat(): string | undefined {
38
+ return 'int64';
39
+ }
40
+ }
41
+
42
+ export class DecimalTypeStrategy implements TypeMappingStrategy {
43
+ private readonly types = ['DECIMAL', 'FLOAT', 'DOUBLE'];
44
+
45
+ supports(type: string): boolean {
46
+ return this.types.includes(type.toUpperCase());
47
+ }
48
+
49
+ getOpenApiType(): OpenApiType {
50
+ return 'number';
51
+ }
52
+
53
+ getFormat(): string | undefined {
54
+ return 'double';
55
+ }
56
+ }
57
+
58
+ export class BooleanTypeStrategy implements TypeMappingStrategy {
59
+ private readonly types = ['BOOLEAN'];
60
+
61
+ supports(type: string): boolean {
62
+ return this.types.includes(type.toUpperCase());
63
+ }
64
+
65
+ getOpenApiType(): OpenApiType {
66
+ return 'boolean';
67
+ }
68
+
69
+ getFormat(): undefined {
70
+ return undefined;
71
+ }
72
+ }
73
+
74
+ export class UuidTypeStrategy implements TypeMappingStrategy {
75
+ private readonly types = ['UUID'];
76
+
77
+ supports(type: string): boolean {
78
+ return this.types.includes(type.toUpperCase());
79
+ }
80
+
81
+ getOpenApiType(): OpenApiType {
82
+ return 'string';
83
+ }
84
+
85
+ getFormat(): string {
86
+ return 'uuid';
87
+ }
88
+ }
89
+
90
+ export class DateTimeTypeStrategy implements TypeMappingStrategy {
91
+ private readonly types = ['DATE', 'DATETIME', 'TIMESTAMP', 'TIMESTAMPTZ'];
92
+
93
+ supports(type: string): boolean {
94
+ return this.types.includes(type.toUpperCase());
95
+ }
96
+
97
+ getOpenApiType(): OpenApiType {
98
+ return 'string';
99
+ }
100
+
101
+ getFormat(columnType: string = 'DATETIME'): string {
102
+ return columnType.toUpperCase() === 'DATE' ? 'date' : 'date-time';
103
+ }
104
+ }
105
+
106
+ export class StringTypeStrategy implements TypeMappingStrategy {
107
+ private readonly types = [
108
+ 'JSON', 'TEXT', 'VARCHAR', 'CHAR', 'BINARY',
109
+ 'VARBINARY', 'BLOB', 'ENUM'
110
+ ];
111
+
112
+ supports(type: string): boolean {
113
+ return this.types.includes(type.toUpperCase());
114
+ }
115
+
116
+ getOpenApiType(): OpenApiType {
117
+ return 'string';
118
+ }
119
+
120
+ getFormat(): undefined {
121
+ return undefined;
122
+ }
123
+ }
124
+
125
+ export class DefaultTypeStrategy implements TypeMappingStrategy {
126
+ supports(): boolean {
127
+ return true;
128
+ }
129
+
130
+ getOpenApiType(): OpenApiType {
131
+ return 'string';
132
+ }
133
+
134
+ getFormat(): undefined {
135
+ return undefined;
136
+ }
137
+ }
138
+
139
+ export class TypeMappingService {
140
+ private readonly strategies: TypeMappingStrategy[];
141
+
142
+ constructor() {
143
+ this.strategies = [
144
+ new IntegerTypeStrategy(),
145
+ new BigIntTypeStrategy(),
146
+ new DecimalTypeStrategy(),
147
+ new BooleanTypeStrategy(),
148
+ new DateTimeTypeStrategy(),
149
+ new UuidTypeStrategy(),
150
+ new StringTypeStrategy(),
151
+ new DefaultTypeStrategy(),
152
+ ];
153
+ }
154
+
155
+ getOpenApiType(column: ColumnDef): OpenApiType {
156
+ const strategy = this.findStrategy(column.type);
157
+ return strategy.getOpenApiType();
158
+ }
159
+
160
+ getFormat(column: ColumnDef): string | undefined {
161
+ const strategy = this.findStrategy(column.type);
162
+ return strategy.getFormat(column.type);
163
+ }
164
+
165
+ private findStrategy(columnType: string): TypeMappingStrategy {
166
+ for (const strategy of this.strategies) {
167
+ if (strategy.supports(columnType)) {
168
+ return strategy;
169
+ }
170
+ }
171
+ return this.strategies[this.strategies.length - 1];
172
+ }
173
+
174
+ registerStrategy(strategy: TypeMappingStrategy, index?: number): void {
175
+ if (index !== undefined) {
176
+ this.strategies.splice(index, 0, strategy);
177
+ } else {
178
+ this.strategies.push(strategy);
179
+ }
180
+ }
181
+ }
182
+
183
+ export const typeMappingService = new TypeMappingService();
184
+
185
+ export function columnTypeToOpenApiType(col: ColumnDef): OpenApiType {
186
+ return typeMappingService.getOpenApiType(col);
187
+ }
188
+
189
+ export function columnTypeToOpenApiFormat(col: ColumnDef): string | undefined {
190
+ return typeMappingService.getFormat(col);
191
+ }
@@ -1,83 +1,90 @@
1
- export type OpenApiType =
2
- | 'string'
3
- | 'number'
4
- | 'integer'
5
- | 'boolean'
6
- | 'array'
7
- | 'object'
8
- | 'null';
9
-
10
- export interface OpenApiSchema {
11
- type?: OpenApiType | OpenApiType[];
12
- properties?: Record<string, OpenApiSchema>;
13
- items?: OpenApiSchema;
14
- required?: string[];
15
- enum?: unknown[];
16
- format?: string;
17
- description?: string;
18
- example?: unknown;
19
- nullable?: boolean;
20
- minimum?: number;
21
- maximum?: number;
22
- default?: unknown;
23
- $ref?: string;
24
- allOf?: OpenApiSchema[];
25
- oneOf?: OpenApiSchema[];
26
- }
27
-
28
- export interface OpenApiParameter {
29
- name: string;
30
- in: 'query' | 'path' | 'header' | 'cookie';
31
- required?: boolean;
32
- schema?: OpenApiSchema;
33
- description?: string;
34
- }
35
-
36
- export interface OpenApiOperation {
37
- summary?: string;
38
- description?: string;
39
- parameters?: OpenApiParameter[];
40
- requestBody?: {
41
- description?: string;
42
- required?: boolean;
43
- content: {
44
- 'application/json': {
45
- schema: OpenApiSchema;
46
- };
47
- };
48
- };
49
- responses?: Record<string, {
50
- description: string;
51
- content?: {
52
- 'application/json': {
53
- schema: OpenApiSchema;
54
- };
55
- };
56
- }>;
57
- }
58
-
59
- export interface OpenApiDocumentInfo {
60
- title: string;
61
- version: string;
62
- description?: string;
63
- }
64
-
65
- export interface ApiRouteDefinition {
66
- path: string;
67
- method: 'get' | 'post' | 'put' | 'patch' | 'delete';
68
- operation: OpenApiOperation;
69
- }
70
-
71
- export interface PaginationParams {
72
- page?: number;
73
- pageSize?: number;
74
- sortBy?: string;
75
- sortOrder?: 'asc' | 'desc';
76
- }
77
-
78
- export interface OpenApiComponent {
79
- schemas?: Record<string, OpenApiSchema>;
80
- parameters?: Record<string, OpenApiSchema>;
81
- responses?: Record<string, OpenApiSchema>;
82
- securitySchemes?: Record<string, unknown>;
83
- }
1
+ export type OpenApiType =
2
+ | 'string'
3
+ | 'number'
4
+ | 'integer'
5
+ | 'boolean'
6
+ | 'array'
7
+ | 'object'
8
+ | 'null';
9
+
10
+ export interface OpenApiSchema {
11
+ type?: OpenApiType | OpenApiType[];
12
+ properties?: Record<string, OpenApiSchema>;
13
+ items?: OpenApiSchema;
14
+ required?: string[];
15
+ enum?: unknown[];
16
+ format?: string;
17
+ description?: string;
18
+ example?: unknown;
19
+ nullable?: boolean;
20
+ minimum?: number;
21
+ maximum?: number;
22
+ default?: unknown;
23
+ $ref?: string;
24
+ allOf?: OpenApiSchema[];
25
+ oneOf?: OpenApiSchema[];
26
+ }
27
+
28
+ export interface OpenApiParameter {
29
+ name: string;
30
+ in: 'query' | 'path' | 'header' | 'cookie';
31
+ required?: boolean;
32
+ schema?: OpenApiSchema;
33
+ description?: string;
34
+ }
35
+
36
+ export interface OpenApiOperation {
37
+ summary?: string;
38
+ description?: string;
39
+ parameters?: OpenApiParameter[];
40
+ requestBody?: {
41
+ description?: string;
42
+ required?: boolean;
43
+ content: {
44
+ 'application/json': {
45
+ schema: OpenApiSchema;
46
+ };
47
+ };
48
+ };
49
+ responses?: Record<string, {
50
+ description: string;
51
+ content?: {
52
+ 'application/json': {
53
+ schema: OpenApiSchema;
54
+ };
55
+ };
56
+ }>;
57
+ }
58
+
59
+ export interface OpenApiDocumentInfo {
60
+ title: string;
61
+ version: string;
62
+ description?: string;
63
+ }
64
+
65
+ export interface ApiRouteDefinition {
66
+ path: string;
67
+ method: 'get' | 'post' | 'put' | 'patch' | 'delete';
68
+ operation: OpenApiOperation;
69
+ }
70
+
71
+ export interface PaginationParams {
72
+ page?: number;
73
+ pageSize?: number;
74
+ sortBy?: string;
75
+ sortOrder?: 'asc' | 'desc';
76
+ }
77
+
78
+ export interface OpenApiComponent {
79
+ schemas?: Record<string, OpenApiSchema>;
80
+ parameters?: Record<string, OpenApiSchema>;
81
+ responses?: Record<string, OpenApiSchema>;
82
+ securitySchemes?: Record<string, unknown>;
83
+ }
84
+
85
+ export interface OpenApiDocument {
86
+ openapi: string;
87
+ info: OpenApiDocumentInfo;
88
+ paths: Record<string, Record<string, OpenApiOperation>>;
89
+ components?: OpenApiComponent;
90
+ }
@@ -1,45 +1,45 @@
1
- import type { OpenApiSchema, OpenApiOperation, OpenApiDocumentInfo, ApiRouteDefinition } from './types.js';
2
-
3
- export function schemaToJson(schema: OpenApiSchema): string {
4
- return JSON.stringify(schema, null, 2);
5
- }
6
-
7
- export function deepCloneSchema(schema: OpenApiSchema): OpenApiSchema {
8
- return JSON.parse(JSON.stringify(schema));
9
- }
10
-
11
- export function mergeSchemas(base: OpenApiSchema, override: Partial<OpenApiSchema>): OpenApiSchema {
12
- return {
13
- ...base,
14
- ...override,
15
- properties: {
16
- ...base.properties,
17
- ...(override.properties || {}),
18
- },
19
- required: override.required ?? base.required,
20
- };
21
- }
22
-
23
- export function generateOpenApiDocument(
24
- info: OpenApiDocumentInfo,
25
- routes: ApiRouteDefinition[]
26
- ): Record<string, unknown> {
27
- const paths: Record<string, Record<string, OpenApiOperation>> = {};
28
-
29
- for (const route of routes) {
30
- if (!paths[route.path]) {
31
- paths[route.path] = {};
32
- }
33
- paths[route.path][route.method] = route.operation;
34
- }
35
-
36
- return {
37
- openapi: '3.1.0',
38
- info: {
39
- title: info.title,
40
- version: info.version,
41
- description: info.description,
42
- },
43
- paths,
44
- };
45
- }
1
+ import type { OpenApiSchema, OpenApiOperation, OpenApiDocumentInfo, ApiRouteDefinition, OpenApiDocument } from './types.js';
2
+
3
+ export function schemaToJson(schema: OpenApiSchema): string {
4
+ return JSON.stringify(schema, null, 2);
5
+ }
6
+
7
+ export function deepCloneSchema(schema: OpenApiSchema): OpenApiSchema {
8
+ return JSON.parse(JSON.stringify(schema));
9
+ }
10
+
11
+ export function mergeSchemas(base: OpenApiSchema, override: Partial<OpenApiSchema>): OpenApiSchema {
12
+ return {
13
+ ...base,
14
+ ...override,
15
+ properties: {
16
+ ...base.properties,
17
+ ...(override.properties || {}),
18
+ },
19
+ required: override.required ?? base.required,
20
+ };
21
+ }
22
+
23
+ export function generateOpenApiDocument(
24
+ info: OpenApiDocumentInfo,
25
+ routes: ApiRouteDefinition[]
26
+ ): OpenApiDocument {
27
+ const paths: Record<string, Record<string, OpenApiOperation>> = {};
28
+
29
+ for (const route of routes) {
30
+ if (!paths[route.path]) {
31
+ paths[route.path] = {};
32
+ }
33
+ paths[route.path][route.method] = route.operation;
34
+ }
35
+
36
+ return {
37
+ openapi: '3.1.0',
38
+ info: {
39
+ title: info.title,
40
+ version: info.version,
41
+ description: info.description,
42
+ },
43
+ paths,
44
+ };
45
+ }