@goast/core 0.5.2 → 0.6.0-beta.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 (52) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +67 -67
  3. package/esm/src/parse/parser.js +2 -1
  4. package/package.json +1 -1
  5. package/script/src/parse/parser.js +2 -1
  6. package/src/_dnt.shims.ts +0 -69
  7. package/src/mod.ts +0 -35
  8. package/src/src/ast/node.ts +0 -46
  9. package/src/src/codegen/config.ts +0 -41
  10. package/src/src/codegen/endpoints-generator.ts +0 -72
  11. package/src/src/codegen/generator.ts +0 -192
  12. package/src/src/codegen/internal-utils.ts +0 -6
  13. package/src/src/codegen/schemas-generator.ts +0 -87
  14. package/src/src/codegen/services-generator.ts +0 -77
  15. package/src/src/codegen/types.ts +0 -37
  16. package/src/src/collect/collector.ts +0 -142
  17. package/src/src/collect/helpers.ts +0 -36
  18. package/src/src/collect/types.ts +0 -21
  19. package/src/src/internal-utils.ts +0 -5
  20. package/src/src/parse/deref-proxy.ts +0 -70
  21. package/src/src/parse/openapi-types.ts +0 -949
  22. package/src/src/parse/parser.ts +0 -206
  23. package/src/src/parse/types.ts +0 -28
  24. package/src/src/transform/api-types.ts +0 -245
  25. package/src/src/transform/helpers.ts +0 -218
  26. package/src/src/transform/transform-document.ts +0 -35
  27. package/src/src/transform/transform-endpoint.ts +0 -331
  28. package/src/src/transform/transform-schema.ts +0 -217
  29. package/src/src/transform/transformer.ts +0 -53
  30. package/src/src/transform/types.ts +0 -52
  31. package/src/src/utils/action-provider.ts +0 -58
  32. package/src/src/utils/api-data.utils.ts +0 -48
  33. package/src/src/utils/array.utils.ts +0 -7
  34. package/src/src/utils/asset-manager.ts +0 -51
  35. package/src/src/utils/class.utils.ts +0 -40
  36. package/src/src/utils/common.utils.ts +0 -86
  37. package/src/src/utils/condition.ts +0 -7
  38. package/src/src/utils/endpoint.utils.ts +0 -10
  39. package/src/src/utils/error.utils.ts +0 -3
  40. package/src/src/utils/factory.ts +0 -42
  41. package/src/src/utils/file-system.utils.ts +0 -61
  42. package/src/src/utils/generator.utils.ts +0 -6
  43. package/src/src/utils/object.utils.ts +0 -32
  44. package/src/src/utils/schema.utils.ts +0 -148
  45. package/src/src/utils/source-builder.ts +0 -597
  46. package/src/src/utils/string-builder/options.ts +0 -19
  47. package/src/src/utils/string-builder/string-builder.ts +0 -165
  48. package/src/src/utils/string-builder/utils.ts +0 -69
  49. package/src/src/utils/string.utils.ts +0 -369
  50. package/src/src/utils/string.utils.types.ts +0 -179
  51. package/src/src/utils/type.utils.ts +0 -93
  52. package/src/src/utils/yaml-info.ts +0 -48
@@ -1,35 +0,0 @@
1
- import type { OpenApiDocument, OpenApiTag } from '../parse/openapi-types.js';
2
- import type { Deref } from '../parse/types.js';
3
- import type { ApiService } from './api-types.js';
4
- import { getOpenApiObjectIdentifier } from './helpers.js';
5
- import type { OpenApiTransformerContext } from './types.js';
6
-
7
- export function transformDocument(context: OpenApiTransformerContext, document: Deref<OpenApiDocument>) {
8
- for (const tag of document.tags ?? []) {
9
- transformTag(context, tag);
10
- }
11
- }
12
-
13
- function transformTag(context: OpenApiTransformerContext, tag: Deref<OpenApiTag>, isReference = false) {
14
- const openApiObjectId = getOpenApiObjectIdentifier(tag);
15
- const existing = context.transformed.services.get(openApiObjectId);
16
- if (existing) return existing;
17
-
18
- const ref = tag.$ref ? transformTag(context, tag.$ref, true) : undefined;
19
- const id = context.idGenerator.generateId('service');
20
- const service: ApiService = {
21
- $src: {
22
- ...tag.$src,
23
- component: tag,
24
- },
25
- $ref: ref,
26
- id,
27
- name: tag.name ?? id,
28
- description: tag.description,
29
- endpoints: [],
30
- };
31
-
32
- context.transformed.services.set(openApiObjectId, service);
33
- if (!isReference) context.services.set(service.name, service);
34
- return service;
35
- }
@@ -1,331 +0,0 @@
1
- import type { OpenApiCollectorEndpointInfo } from '../collect/types.js';
2
- import { isOpenApiObjectProperty } from '../internal-utils.js';
3
- import type {
4
- OpenApiHeader,
5
- OpenApiMediaType,
6
- OpenApiParameter,
7
- OpenApiPathItem,
8
- OpenApiRequestBody,
9
- OpenApiResponse,
10
- OpenApiSchema,
11
- } from '../parse/openapi-types.js';
12
- import type { Deref } from '../parse/types.js';
13
- import type {
14
- ApiContent,
15
- ApiEndpoint,
16
- ApiHeader,
17
- ApiParameter,
18
- ApiParameterTarget,
19
- ApiPath,
20
- ApiRequestBody,
21
- ApiResponse,
22
- } from './api-types.js';
23
- import { determineEndpointName, getCustomFields, getOpenApiObjectIdentifier } from './helpers.js';
24
- import { transformSchema } from './transform-schema.js';
25
- import type { OpenApiTransformerContext } from './types.js';
26
-
27
- export function transformEndpoint(context: OpenApiTransformerContext, endpointInfo: OpenApiCollectorEndpointInfo) {
28
- const apiPath = transformApiPath(context, endpointInfo.path, endpointInfo.pathItem);
29
- const endpoint: ApiEndpoint = {
30
- $src: {
31
- ...endpointInfo.operation.$src,
32
- component: endpointInfo.operation,
33
- },
34
- $ref: undefined,
35
- id: context.idGenerator.generateId('endpoint'),
36
- name: determineEndpointName(endpointInfo),
37
- path: endpointInfo.path,
38
- pathInfo: apiPath,
39
- method: endpointInfo.method,
40
- summary: endpointInfo.operation.summary,
41
- description: endpointInfo.operation.description,
42
- parameters: combineParameters(
43
- apiPath.parameters,
44
- endpointInfo.operation.parameters?.map((p) => transformParameter(context, p)) ?? [],
45
- ),
46
- deprecated: endpointInfo.operation.deprecated ?? false,
47
- requestBody: endpointInfo.operation.requestBody
48
- ? transformRequestBody(context, endpointInfo.operation.requestBody)
49
- : undefined,
50
- responses: transformResponses(context, endpointInfo.operation.responses),
51
- tags: endpointInfo.operation.tags ?? [],
52
- custom: getCustomFields(endpointInfo.operation),
53
- };
54
-
55
- const tags = endpoint.tags.length === 0 ? [''] : endpoint.tags;
56
- for (const tag of tags) {
57
- let service = context.services.get(tag);
58
- if (!service) {
59
- const id = context.idGenerator.generateId('service');
60
- service = {
61
- $ref: undefined,
62
- id,
63
- name: tag || id,
64
- description: undefined,
65
- endpoints: [],
66
- };
67
- context.services.set(tag, service);
68
- }
69
-
70
- service.endpoints.push(endpoint);
71
- }
72
-
73
- apiPath[endpointInfo.method] = endpoint;
74
- context.endpoints.set(`${endpointInfo.method}:${endpointInfo.path}`, endpoint);
75
- return endpoint;
76
- }
77
-
78
- function transformApiPath(
79
- context: OpenApiTransformerContext,
80
- path: string,
81
- pathItem: Deref<OpenApiPathItem>,
82
- isReference = false,
83
- ): ApiPath {
84
- const existingPath = context.paths.get(path);
85
- if (existingPath) return existingPath;
86
-
87
- const openApiObjectId = getOpenApiObjectIdentifier(pathItem);
88
- const existing = context.transformed.paths.get(openApiObjectId);
89
- if (existing) return existing;
90
-
91
- const ref = pathItem.$ref ? transformApiPath(context, path, pathItem.$ref, true) : undefined;
92
- const apiPath: ApiPath = {
93
- $src: {
94
- ...pathItem.$src,
95
- component: pathItem,
96
- },
97
- $ref: ref,
98
- id: context.idGenerator.generateId('path'),
99
- summary: pathItem.summary,
100
- description: pathItem.description,
101
- path: path,
102
- parameters: pathItem.parameters?.map((p) => transformParameter(context, p)) ?? [],
103
-
104
- // HTTP methods are added later (see transformEndpoint)
105
- get: undefined,
106
- put: undefined,
107
- post: undefined,
108
- delete: undefined,
109
- options: undefined,
110
- head: undefined,
111
- patch: undefined,
112
- trace: undefined,
113
- };
114
-
115
- context.transformed.paths.set(openApiObjectId, apiPath);
116
- if (!isReference) context.paths.set(path, apiPath);
117
- return apiPath;
118
- }
119
-
120
- function transformParameter(context: OpenApiTransformerContext, parameter: Deref<OpenApiParameter>): ApiParameter {
121
- const openApiObjectId = getOpenApiObjectIdentifier(parameter);
122
- const existing = context.transformed.parameters.get(openApiObjectId);
123
- if (existing) return existing;
124
-
125
- const ref = parameter.$ref ? transformParameter(context, parameter.$ref) : undefined;
126
- const id = context.idGenerator.generateId('parameter');
127
- const p: ApiParameter = {
128
- $src: {
129
- ...parameter.$src,
130
- component: parameter,
131
- },
132
- $ref: ref,
133
- id: id,
134
- name: parameter.name ?? id,
135
- target: parameter.in as ApiParameterTarget,
136
- description: parameter.description,
137
- required: parameter.required ?? false,
138
- deprecated: parameter.deprecated ?? false,
139
- allowEmptyValue: parameter.allowEmptyValue,
140
- style: parameter.style,
141
- explode: parameter.explode,
142
- allowReserved: parameter.allowReserved,
143
- schema: parameter.schema ? transformSchema(context, parameter.schema) : undefined,
144
- };
145
-
146
- context.transformed.parameters.set(openApiObjectId, p);
147
- return p;
148
- }
149
-
150
- function transformRequestBody(
151
- context: OpenApiTransformerContext,
152
- requestBody: Deref<OpenApiRequestBody>,
153
- ): ApiRequestBody {
154
- const openApiObjectId = getOpenApiObjectIdentifier(requestBody);
155
- const existing = context.transformed.requestBodies.get(openApiObjectId);
156
- if (existing) return existing;
157
-
158
- const ref = requestBody.$ref ? transformRequestBody(context, requestBody.$ref) : undefined;
159
- const rb: ApiRequestBody = {
160
- $src: {
161
- ...requestBody.$src,
162
- component: requestBody,
163
- },
164
- $ref: ref,
165
- id: context.idGenerator.generateId('requestBody'),
166
- description: requestBody.description,
167
- required: requestBody.required ?? false,
168
- content: transformContent(context, requestBody.content),
169
- };
170
-
171
- context.transformed.requestBodies.set(openApiObjectId, rb);
172
- return rb;
173
- }
174
-
175
- function transformResponses(
176
- context: OpenApiTransformerContext,
177
- responses?: Record<string, Deref<OpenApiResponse>>,
178
- ): ApiResponse[] {
179
- if (!responses) return [];
180
- const result: ApiResponse[] = [];
181
- for (const status of Object.keys(responses)) {
182
- if (!isOpenApiObjectProperty(status)) continue;
183
- result.push(transformResponse(context, responses[status], status));
184
- }
185
- return result;
186
- }
187
-
188
- function transformResponse(
189
- context: OpenApiTransformerContext,
190
- response: Deref<OpenApiResponse>,
191
- status: string,
192
- ): ApiResponse {
193
- const openApiObjectId = getOpenApiObjectIdentifier(response);
194
- const existing = context.transformed.responses.get(openApiObjectId);
195
- if (existing) return existing;
196
-
197
- const ref = response.$ref ? transformResponse(context, response.$ref, status) : undefined;
198
- const r: ApiResponse = {
199
- $src: {
200
- ...response.$src,
201
- component: response,
202
- },
203
- $ref: ref,
204
- id: context.idGenerator.generateId('response'),
205
- statusCode: Number(status) || undefined,
206
- description: response.description,
207
- headers: transformHeaders(context, response.headers),
208
- contentOptions: transformContent(context, response.content),
209
- };
210
-
211
- context.transformed.responses.set(openApiObjectId, r);
212
- return r;
213
- }
214
-
215
- function transformContent(
216
- context: OpenApiTransformerContext,
217
- content?: Record<string, Deref<OpenApiMediaType>>,
218
- ): ApiContent[] {
219
- if (!content) return [];
220
- const result: ApiContent[] = [];
221
- for (const media of Object.keys(content)) {
222
- if (!isOpenApiObjectProperty(media)) continue;
223
- result.push(transformMediaType(context, content[media], media));
224
- }
225
- return result;
226
- }
227
-
228
- function transformMediaType(
229
- context: OpenApiTransformerContext,
230
- mediaType: Deref<OpenApiMediaType>,
231
- media: string,
232
- ): ApiContent {
233
- const openApiObjectId = getOpenApiObjectIdentifier(mediaType);
234
- const existing = context.transformed.content.get(openApiObjectId);
235
- if (existing) return existing;
236
-
237
- const ref = mediaType.$ref ? transformMediaType(context, mediaType.$ref, media) : undefined;
238
- const mt: ApiContent = {
239
- $src: {
240
- ...mediaType.$src,
241
- component: mediaType,
242
- },
243
- $ref: ref,
244
- id: context.idGenerator.generateId('content'),
245
- type: media,
246
- schema: mediaType.schema ? transformSchema(context, mediaType.schema) : undefined,
247
- };
248
-
249
- context.transformed.content.set(openApiObjectId, mt);
250
- return mt;
251
- }
252
-
253
- function combineParameters(pathParams: ApiParameter[], operationParams: ApiParameter[]): ApiParameter[] {
254
- const result = [...pathParams];
255
- for (const opParam of operationParams) {
256
- const existingParam = result.findIndex((p) => p.name === opParam.name);
257
- if (existingParam >= 0) {
258
- result[existingParam] = opParam;
259
- } else {
260
- result.push(opParam);
261
- }
262
- }
263
- return result;
264
- }
265
-
266
- function isSchema(obj: Record<string, unknown>): obj is Deref<OpenApiSchema> {
267
- return obj && typeof obj === 'object' && obj['type'] !== undefined;
268
- }
269
-
270
- function transformHeaders(
271
- context: OpenApiTransformerContext,
272
- headers?: Record<string, Deref<OpenApiHeader> | Deref<OpenApiSchema>>,
273
- ): ApiHeader[] {
274
- if (!headers) return [];
275
- const result: ApiHeader[] = [];
276
- for (const name of Object.keys(headers)) {
277
- if (!isOpenApiObjectProperty(name)) continue;
278
- result.push(transformHeader(context, headers[name], name));
279
- }
280
- return result;
281
- }
282
-
283
- function transformHeader(
284
- context: OpenApiTransformerContext,
285
- header: Deref<OpenApiHeader> | Deref<OpenApiSchema>,
286
- name: string,
287
- ): ApiHeader {
288
- const openApiObjectId = getOpenApiObjectIdentifier(header);
289
- const existing = context.transformed.headers.get(openApiObjectId);
290
- if (existing) return existing;
291
-
292
- let h: ApiHeader;
293
- const ref = header.$ref ? transformHeader(context, header.$ref, name) : undefined;
294
- const id = context.idGenerator.generateId('header');
295
- if (isSchema(header)) {
296
- h = {
297
- // deno-lint-ignore no-explicit-any
298
- $src: Object.assign({}, header.$src, { component: header }) as any,
299
- $ref: ref as ApiHeader['$ref'],
300
- id,
301
- name,
302
- description: header.description,
303
- required: false,
304
- deprecated: false,
305
- allowEmptyValue: undefined,
306
- style: undefined,
307
- explode: undefined,
308
- allowReserved: undefined,
309
- schema: transformSchema(context, header),
310
- };
311
- } else {
312
- h = {
313
- // deno-lint-ignore no-explicit-any
314
- $src: Object.assign({}, header.$src, { component: header }) as any,
315
- $ref: ref as ApiHeader['$ref'],
316
- id,
317
- name,
318
- description: header.description,
319
- required: header.required ?? false,
320
- deprecated: header.deprecated ?? false,
321
- allowEmptyValue: header.allowEmptyValue,
322
- style: header.style,
323
- explode: header.explode,
324
- allowReserved: header.allowReserved,
325
- schema: header.schema ? transformSchema(context, header.schema) : undefined,
326
- };
327
- }
328
-
329
- context.transformed.headers.set(openApiObjectId, h);
330
- return h;
331
- }
@@ -1,217 +0,0 @@
1
- import type { OpenApiSchema } from '../parse/openapi-types.js';
2
- import type { Deref } from '../parse/types.js';
3
- import { createOverwriteProxy } from '../utils/object.utils.js';
4
- import type { ApiSchema, ApiSchemaExtensions, ApiSchemaKind } from './api-types.js';
5
- import {
6
- determineSchemaAccessibility,
7
- determineSchemaKind,
8
- determineSchemaName,
9
- getCustomFields,
10
- getOpenApiObjectIdentifier,
11
- transformAdditionalProperties,
12
- transformSchemaProperties,
13
- } from './helpers.js';
14
- import type { IncompleteApiSchema, OpenApiTransformerContext } from './types.js';
15
-
16
- export function transformSchema<T extends Deref<OpenApiSchema>>(ctx: OpenApiTransformerContext, schema: T): ApiSchema {
17
- if (!schema) {
18
- throw new Error('Schema is required.');
19
- }
20
- const schemaSource = `${schema.$src.file}:${schema.$src.path}`;
21
- const existingSchema = ctx.schemas.get(schemaSource) ?? ctx.incompleteSchemas.get(schemaSource);
22
- if (existingSchema) return existingSchema as ApiSchema;
23
-
24
- const openApiObjectId = getOpenApiObjectIdentifier(schema);
25
- const existing = ctx.transformed.schemas.get(openApiObjectId);
26
- if (existing) return existing;
27
-
28
- let kind = determineSchemaKind(ctx, schema);
29
- let nullable = kind === 'null';
30
- if (kind === 'multi-type') {
31
- const types = schema.type as string[];
32
- let isSingleType = types.length === 1;
33
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
34
- if (types.includes('null') || types.includes(null!)) {
35
- nullable = true;
36
- isSingleType = types.length === 2;
37
- }
38
-
39
- if (isSingleType) {
40
- const newType = types.filter((t) => t !== 'null' && t !== null)[0];
41
- schema = createOverwriteProxy(schema);
42
- schema.type = newType;
43
- kind = determineSchemaKind(ctx, schema);
44
- } else {
45
- schema.type = types.filter((t) => t !== 'null' && t !== null);
46
- }
47
- }
48
-
49
- const id = ctx.idGenerator.generateId('schema');
50
- const nameInfo = determineSchemaName(schema, id);
51
- const incompleteSchema: IncompleteApiSchema = {
52
- $src: {
53
- ...schema.$src,
54
- component: schema,
55
- },
56
- $ref: undefined,
57
- id,
58
- name: nameInfo.name,
59
- isNameGenerated: nameInfo.isGenerated,
60
- description: schema.description,
61
- deprecated: schema.deprecated ?? false,
62
- accessibility: determineSchemaAccessibility(schema),
63
- kind,
64
- enum: schema.enum,
65
- default: schema.default,
66
- example: schema.example,
67
- nullable: nullable || schema.nullable === true,
68
- required: new Set(schema.required),
69
- custom: getCustomFields(schema),
70
- not: schema.not ? transformSchema(ctx, schema.not) : undefined,
71
- const: schema.const,
72
- discriminator: schema.discriminator
73
- ? {
74
- propertyName: typeof schema.discriminator === 'string'
75
- ? schema.discriminator
76
- : schema.discriminator.propertyName,
77
- mapping: {},
78
- }
79
- : undefined,
80
- inheritedSchemas: [],
81
- };
82
- ctx.incompleteSchemas.set(schemaSource, incompleteSchema);
83
-
84
- if (schema.$ref) {
85
- incompleteSchema.$ref = transformSchema(ctx, schema.$ref);
86
- }
87
- const extensions = schemaTransformers[kind](schema, ctx);
88
- const completeSchema = Object.assign(incompleteSchema, extensions) as
89
- & IncompleteApiSchema
90
- & ApiSchemaExtensions<ApiSchemaKind>;
91
- resolveDescriminatorMapping(ctx, completeSchema);
92
-
93
- ctx.incompleteSchemas.delete(schemaSource);
94
- ctx.transformed.schemas.set(openApiObjectId, completeSchema);
95
- ctx.schemas.set(schemaSource, completeSchema);
96
- return completeSchema;
97
- }
98
-
99
- function allExtensionsTransformer(schema: Deref<OpenApiSchema>, context: OpenApiTransformerContext) {
100
- return {
101
- oneOf: schema.oneOf?.map((s) => transformSchema(context, s)) ?? [],
102
- format: schema.format,
103
- pattern: schema.pattern,
104
- minLength: schema.minLength,
105
- maxLength: schema.maxLength,
106
- minimum: schema.minimum,
107
- maximum: schema.maximum,
108
- properties: transformSchemaProperties<Deref<OpenApiSchema>>(context, schema, transformSchema),
109
- additionalProperties: transformAdditionalProperties(context, schema, transformSchema),
110
- allOf: schema.allOf?.map((s) => transformSchema(context, s)) ?? [],
111
- anyOf: schema.anyOf?.map((s) => transformSchema(context, s)) ?? [],
112
- items: schema.items ? transformSchema(context, schema.items) : undefined,
113
- minItems: schema.minItems,
114
- maxItems: schema.maxItems,
115
- };
116
- }
117
-
118
- const schemaTransformers: {
119
- [K in ApiSchemaKind]: (
120
- schema: Deref<OpenApiSchema>,
121
- context: OpenApiTransformerContext,
122
- ) => Omit<ApiSchemaExtensions<K>, 'kind'>;
123
- } = {
124
- oneOf: (schema, context) => ({
125
- ...allExtensionsTransformer(schema, context),
126
- }),
127
- string: (schema, context) => ({
128
- type: 'string',
129
- ...allExtensionsTransformer(schema, context),
130
- }),
131
- number: (schema, context) => ({
132
- type: 'number',
133
- ...allExtensionsTransformer(schema, context),
134
- }),
135
- boolean: (schema, context) => ({ type: 'boolean', ...allExtensionsTransformer(schema, context) }),
136
- object: (schema, context) => ({
137
- type: 'object',
138
- ...allExtensionsTransformer(schema, context),
139
- }),
140
- integer: (schema, context) => ({
141
- type: 'integer',
142
- ...allExtensionsTransformer(schema, context),
143
- }),
144
- array: (schema, context) => ({
145
- type: 'array',
146
- ...allExtensionsTransformer(schema, context),
147
- }),
148
- combined: (schema, context) => ({
149
- ...allExtensionsTransformer(schema, context),
150
- }),
151
- 'multi-type': (schema, context) => ({
152
- type: schema.type as string[],
153
- ...allExtensionsTransformer(schema, context),
154
- }),
155
- null: () => ({ type: 'null' }),
156
- unknown: () => ({}),
157
- };
158
-
159
- function resolveDescriminatorMapping(context: OpenApiTransformerContext, schema: ApiSchema) {
160
- const discriminator = schema.$src.component.discriminator;
161
- if (discriminator && typeof discriminator === 'object' && discriminator.mapping) {
162
- for (const key of Object.keys(discriminator.mapping)) {
163
- const mappedSchemaRef = discriminator.mapping[key];
164
- const mappedSchema = transformSchema(context, mappedSchemaRef);
165
- if (schema.discriminator) {
166
- schema.discriminator.mapping[key] = mappedSchema;
167
- const hasInheritedSchema = mappedSchema.inheritedSchemas.some((x) => x.id === schema.id);
168
- if (!hasInheritedSchema) {
169
- mappedSchema.inheritedSchemas.push(
170
- schema as ApiSchema & { discriminator: NonNullable<ApiSchema['discriminator']> },
171
- );
172
- }
173
- }
174
- }
175
- }
176
-
177
- if (schema.kind === 'combined' && schema.allOf) {
178
- for (const s of schema.allOf) {
179
- const base = findDiscriminatedSchema(s);
180
- if (!base) continue;
181
- if (base.discriminator && base.discriminator.propertyName) {
182
- const origDiscriminator = base.$src.component.discriminator;
183
- if (
184
- origDiscriminator &&
185
- typeof origDiscriminator === 'object' &&
186
- origDiscriminator.mapping &&
187
- Object.values(origDiscriminator.mapping).some(
188
- (x) => x.$src.file === schema.$src.file && x.$src.path === schema.$src.path,
189
- )
190
- ) {
191
- continue;
192
- }
193
-
194
- const mappingKey = schema.isNameGenerated ? null : schema.name;
195
- if (!mappingKey) {
196
- continue;
197
- }
198
-
199
- base.discriminator.mapping[mappingKey] = schema;
200
- const hasInheritedSchema = schema.inheritedSchemas.some((x) => x.id === base.id);
201
- if (!hasInheritedSchema) {
202
- schema.inheritedSchemas.push(base as ApiSchema & { discriminator: NonNullable<ApiSchema['discriminator']> });
203
- }
204
- }
205
- }
206
- }
207
- }
208
-
209
- function findDiscriminatedSchema(
210
- schema: ApiSchema,
211
- ): (ApiSchema & { discriminator: NonNullable<ApiSchema['discriminator']> }) | null {
212
- const origDiscriminator = schema.$src.originalComponent.discriminator;
213
- if (origDiscriminator && (typeof origDiscriminator === 'string' || origDiscriminator.propertyName)) {
214
- return schema as ApiSchema & { discriminator: NonNullable<ApiSchema['discriminator']> };
215
- }
216
- return schema.$ref ? findDiscriminatedSchema(schema.$ref) : null;
217
- }
@@ -1,53 +0,0 @@
1
- import type { OpenApiCollectorData } from '../collect/types.js';
2
- import type { ApiData } from './api-types.js';
3
- import { IdGenerator } from './helpers.js';
4
- import { transformDocument } from './transform-document.js';
5
- import { transformEndpoint } from './transform-endpoint.js';
6
- import { transformSchema } from './transform-schema.js';
7
- import {
8
- defaultOpenApiTransformerOptions,
9
- type OpenApiTransformerContext,
10
- type OpenApiTransformerOptions,
11
- } from './types.js';
12
-
13
- export function transformOpenApi(data: OpenApiCollectorData, options?: Partial<OpenApiTransformerOptions>): ApiData {
14
- const context: OpenApiTransformerContext = {
15
- config: { ...defaultOpenApiTransformerOptions, ...options },
16
-
17
- idGenerator: new IdGenerator(),
18
- input: data,
19
- incompleteSchemas: new Map(),
20
- paths: new Map(),
21
- services: new Map(),
22
- endpoints: new Map(),
23
- schemas: new Map(),
24
-
25
- transformed: {
26
- services: new Map(),
27
- paths: new Map(),
28
- parameters: new Map(),
29
- requestBodies: new Map(),
30
- responses: new Map(),
31
- content: new Map(),
32
- headers: new Map(),
33
- schemas: new Map(),
34
- },
35
- };
36
-
37
- for (const document of data.documents) {
38
- transformDocument(context, document);
39
- }
40
- for (const schema of context.input.schemas.values()) {
41
- transformSchema(context, schema);
42
- }
43
- for (const endpoint of context.input.endpoints.values()) {
44
- transformEndpoint(context, endpoint);
45
- }
46
-
47
- return {
48
- documents: context.input.documents,
49
- services: Array.from(context.services.values()),
50
- endpoints: Array.from(context.endpoints.values()),
51
- schemas: Array.from(context.schemas.values()),
52
- };
53
- }
@@ -1,52 +0,0 @@
1
- import type { OpenApiCollectorData } from '../collect/types.js';
2
- import type { ArrayItem } from '../utils/type.utils.js';
3
- import type {
4
- ApiContent,
5
- ApiData,
6
- ApiHeader,
7
- ApiParameter,
8
- ApiPath,
9
- ApiRequestBody,
10
- ApiResponse,
11
- ApiSchema,
12
- ApiSchemaExtensions,
13
- ApiSchemaKind,
14
- ApiService,
15
- } from './api-types.js';
16
- import type { IdGenerator } from './helpers.js';
17
-
18
- export type OpenApiTransformerOptions = {
19
- /**
20
- * Determines how schemas without a `type` property should be treated.
21
- * - `keep-unknown`: Keep the schema as-is.
22
- * - `object-if-properties`: Treat the schema as an object schema only if it has properties.
23
- * - `always-object`: Treat the schema as an object schema.
24
- * @default 'object-if-properties'
25
- */
26
- unknownTypeBehavior: 'keep-unknown' | 'object-if-properties' | 'always-object';
27
- };
28
-
29
- export const defaultOpenApiTransformerOptions: OpenApiTransformerOptions = {
30
- unknownTypeBehavior: 'object-if-properties',
31
- };
32
-
33
- export type IncompleteApiSchema = Omit<ApiSchema, Exclude<keyof ApiSchemaExtensions<ApiSchemaKind>, 'kind'>>;
34
- export type OpenApiTransformerContext = {
35
- config: OpenApiTransformerOptions;
36
-
37
- idGenerator: IdGenerator;
38
- input: OpenApiCollectorData;
39
- incompleteSchemas: Map<string, IncompleteApiSchema>;
40
- paths: Map<string, ApiPath>;
41
-
42
- transformed: {
43
- services: Map<string, ApiService>;
44
- paths: Map<string, ApiPath>;
45
- parameters: Map<string, ApiParameter>;
46
- requestBodies: Map<string, ApiRequestBody>;
47
- responses: Map<string, ApiResponse>;
48
- content: Map<string, ApiContent>;
49
- headers: Map<string, ApiHeader>;
50
- schemas: Map<string, ApiSchema>;
51
- };
52
- } & { [K in Exclude<keyof ApiData, 'documents'>]: Map<string, ArrayItem<ApiData[K]>> };