@goast/core 0.3.2 → 0.3.4
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.
- package/cjs/lib/codegen/config.js +2 -0
- package/cjs/lib/codegen/generator.js +5 -1
- package/cjs/lib/parse/parser.js +4 -2
- package/cjs/lib/parse/types.js +3 -0
- package/cjs/lib/transform/helpers.js +38 -4
- package/cjs/lib/transform/transform-schema.js +96 -80
- package/cjs/lib/transform/transformer.js +3 -1
- package/cjs/lib/transform/types.js +4 -0
- package/cjs/lib/utils/object.utils.js +11 -0
- package/cjs/lib/utils/schema.utils.js +3 -0
- package/esm/lib/codegen/config.js +2 -0
- package/esm/lib/codegen/generator.js +5 -1
- package/esm/lib/parse/parser.js +4 -2
- package/esm/lib/parse/types.js +2 -1
- package/esm/lib/transform/helpers.js +38 -4
- package/esm/lib/transform/transform-schema.js +96 -80
- package/esm/lib/transform/transformer.js +3 -1
- package/esm/lib/transform/types.js +3 -1
- package/esm/lib/utils/object.utils.js +10 -0
- package/esm/lib/utils/schema.utils.js +3 -0
- package/package.json +1 -1
- package/types/lib/codegen/config.d.ts +2 -1
- package/types/lib/codegen/generator.d.ts +1 -0
- package/types/lib/parse/parser.d.ts +3 -1
- package/types/lib/parse/types.d.ts +5 -0
- package/types/lib/transform/helpers.d.ts +5 -2
- package/types/lib/transform/transform-schema.d.ts +1 -1
- package/types/lib/transform/transformer.d.ts +2 -1
- package/types/lib/transform/types.d.ts +12 -0
- package/types/lib/utils/object.utils.d.ts +1 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.defaultOpenApiGeneratorConfig = void 0;
|
|
4
|
+
const types_1 = require("../transform/types");
|
|
4
5
|
const source_builder_1 = require("../utils/source-builder");
|
|
5
6
|
exports.defaultOpenApiGeneratorConfig = {
|
|
6
7
|
...source_builder_1.defaultSourceBuilderOptions,
|
|
8
|
+
...types_1.defaultOpenApiTransformerOptions,
|
|
7
9
|
outputDir: 'generated',
|
|
8
10
|
clearOutputDir: true,
|
|
9
11
|
};
|
|
@@ -59,7 +59,11 @@ class _OpenApiGenerator {
|
|
|
59
59
|
}
|
|
60
60
|
class OpenApiGenerator extends _OpenApiGenerator {
|
|
61
61
|
constructor(config) {
|
|
62
|
-
super(
|
|
62
|
+
super(...OpenApiGenerator.getCtorArgs(config));
|
|
63
|
+
}
|
|
64
|
+
static getCtorArgs(config) {
|
|
65
|
+
const c = { ...config_1.defaultOpenApiGeneratorConfig, ...config };
|
|
66
|
+
return [c, [], new parser_1.OpenApiParser(c)];
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
exports.OpenApiGenerator = OpenApiGenerator;
|
package/cjs/lib/parse/parser.js
CHANGED
|
@@ -9,12 +9,14 @@ const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
|
9
9
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
10
10
|
const yaml_1 = tslib_1.__importDefault(require("yaml"));
|
|
11
11
|
const deref_proxy_1 = require("./deref-proxy");
|
|
12
|
+
const types_1 = require("./types");
|
|
12
13
|
const collector_1 = require("../collect/collector");
|
|
13
14
|
const transformer_1 = require("../transform/transformer");
|
|
14
15
|
const utils_1 = require("../utils");
|
|
15
16
|
class OpenApiParser {
|
|
16
|
-
constructor() {
|
|
17
|
+
constructor(config) {
|
|
17
18
|
this._loadedDocuments = new Map();
|
|
19
|
+
this._config = { ...types_1.defaultOpenApiParserOptions, ...config };
|
|
18
20
|
}
|
|
19
21
|
async parseApisAndTransform(...fileNames) {
|
|
20
22
|
const flatFileNames = [].concat(...fileNames);
|
|
@@ -29,7 +31,7 @@ class OpenApiParser {
|
|
|
29
31
|
}
|
|
30
32
|
transformApis(apis) {
|
|
31
33
|
const collectedData = (0, collector_1.collectOpenApi)(apis);
|
|
32
|
-
const transformedData = (0, transformer_1.transformOpenApi)(collectedData);
|
|
34
|
+
const transformedData = (0, transformer_1.transformOpenApi)(collectedData, this._config);
|
|
33
35
|
return transformedData;
|
|
34
36
|
}
|
|
35
37
|
async dereference(file, path, value) {
|
package/cjs/lib/parse/types.js
CHANGED
|
@@ -11,13 +11,15 @@ exports.transformAdditionalProperties = transformAdditionalProperties;
|
|
|
11
11
|
exports.transformSchemaProperties = transformSchemaProperties;
|
|
12
12
|
exports.getOpenApiObjectIdentifier = getOpenApiObjectIdentifier;
|
|
13
13
|
const internal_utils_1 = require("../internal-utils");
|
|
14
|
+
const utils_1 = require("../utils");
|
|
14
15
|
const common_utils_1 = require("../utils/common.utils");
|
|
15
|
-
function determineSchemaKind(schema) {
|
|
16
|
+
function determineSchemaKind(ctx, schema) {
|
|
16
17
|
if (schema.oneOf) {
|
|
17
18
|
return 'oneOf';
|
|
18
19
|
}
|
|
19
20
|
else if (schema.type !== 'object' && (schema.allOf || schema.anyOf)) {
|
|
20
|
-
|
|
21
|
+
const hasProperties = (schema.properties && Object.keys(schema.properties).length > 0) || schema.additionalProperties;
|
|
22
|
+
return hasProperties ? 'object' : 'combined';
|
|
21
23
|
}
|
|
22
24
|
else if (Array.isArray(schema.type)) {
|
|
23
25
|
return 'multi-type';
|
|
@@ -31,9 +33,14 @@ function determineSchemaKind(schema) {
|
|
|
31
33
|
schema.type === 'array') {
|
|
32
34
|
return schema.type;
|
|
33
35
|
}
|
|
34
|
-
|
|
36
|
+
const treadAsObject = ctx.config.unknownTypeBehavior === 'always-object' ||
|
|
37
|
+
(ctx.config.unknownTypeBehavior === 'object-if-properties' &&
|
|
38
|
+
schema.properties &&
|
|
39
|
+
Object.keys(schema.properties).length > 0);
|
|
40
|
+
return treadAsObject ? 'object' : 'unknown';
|
|
35
41
|
}
|
|
36
42
|
function determineSchemaName(schema, id) {
|
|
43
|
+
var _a, _b, _c, _d, _e, _f;
|
|
37
44
|
if (schema.title)
|
|
38
45
|
return { name: schema.title, isGenerated: false };
|
|
39
46
|
if (!schema.$src) {
|
|
@@ -46,7 +53,34 @@ function determineSchemaName(schema, id) {
|
|
|
46
53
|
const responseMatch = schema.$src.path.match(/\/paths\/(?<path>.+)\/(?<method>.+)\/responses\/(?<status>\d+)\//);
|
|
47
54
|
if (responseMatch && responseMatch.groups) {
|
|
48
55
|
const { path, method, status } = responseMatch.groups;
|
|
49
|
-
|
|
56
|
+
const operation = (_c = (_b = (_a = schema.$src.document.paths) === null || _a === void 0 ? void 0 : _a[path]) === null || _b === void 0 ? void 0 : _b[method]) !== null && _c !== void 0 ? _c : {};
|
|
57
|
+
return {
|
|
58
|
+
name: `${determineEndpointName({ method, path: `/${path}`, operation })}_${status}_Response`,
|
|
59
|
+
isGenerated: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const responseCompMatch = schema.$src.path.match(/\/components\/responses\/([^/]+)\/content\/.+\/schema/);
|
|
63
|
+
if (responseCompMatch) {
|
|
64
|
+
return {
|
|
65
|
+
name: responseCompMatch[1].toLowerCase().endsWith('response')
|
|
66
|
+
? responseCompMatch[1]
|
|
67
|
+
: responseCompMatch[1] + 'Response',
|
|
68
|
+
isGenerated: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const requestBodyMatch = schema.$src.path.match(/\/paths\/(?<path>.+)\/(?<method>.+)\/requestBody\//);
|
|
72
|
+
if (requestBodyMatch && requestBodyMatch.groups) {
|
|
73
|
+
const { path, method } = requestBodyMatch.groups;
|
|
74
|
+
const operation = (_f = (_e = (_d = schema.$src.document.paths) === null || _d === void 0 ? void 0 : _d[path]) === null || _e === void 0 ? void 0 : _e[method]) !== null && _f !== void 0 ? _f : {};
|
|
75
|
+
return { name: `${determineEndpointName({ method, path: `/${path}`, operation })}_Request`, isGenerated: true };
|
|
76
|
+
}
|
|
77
|
+
const parentSchemaMatch = schema.$src.path.match(/(.*)\/properties\/([^/]*)$/);
|
|
78
|
+
if (parentSchemaMatch) {
|
|
79
|
+
const parentSchema = (0, utils_1.getDeepProperty)(schema.$src.document, parentSchemaMatch[1].split('/').filter(Boolean));
|
|
80
|
+
const parentSchemaName = determineSchemaName({ title: parentSchema === null || parentSchema === void 0 ? void 0 : parentSchema.title, $src: { path: parentSchemaMatch[1], document: schema.$src.document } }, id);
|
|
81
|
+
if (!parentSchemaName.isGenerated) {
|
|
82
|
+
return { name: `${parentSchemaName.name}_${parentSchemaMatch[2]}`, isGenerated: true };
|
|
83
|
+
}
|
|
50
84
|
}
|
|
51
85
|
return { name: id, isGenerated: true };
|
|
52
86
|
}
|
|
@@ -3,20 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.transformSchema = transformSchema;
|
|
4
4
|
const helpers_1 = require("./helpers");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
|
-
function transformSchema(
|
|
6
|
+
function transformSchema(ctx, schema) {
|
|
7
7
|
var _a, _b;
|
|
8
8
|
if (!schema) {
|
|
9
9
|
throw new Error('Schema is required.');
|
|
10
10
|
}
|
|
11
11
|
const schemaSource = `${schema.$src.file}:${schema.$src.path}`;
|
|
12
|
-
const existingSchema = (_a =
|
|
12
|
+
const existingSchema = (_a = ctx.schemas.get(schemaSource)) !== null && _a !== void 0 ? _a : ctx.incompleteSchemas.get(schemaSource);
|
|
13
13
|
if (existingSchema)
|
|
14
14
|
return existingSchema;
|
|
15
15
|
const openApiObjectId = (0, helpers_1.getOpenApiObjectIdentifier)(schema);
|
|
16
|
-
const existing =
|
|
16
|
+
const existing = ctx.transformed.schemas.get(openApiObjectId);
|
|
17
17
|
if (existing)
|
|
18
18
|
return existing;
|
|
19
|
-
let kind = (0, helpers_1.determineSchemaKind)(schema);
|
|
19
|
+
let kind = (0, helpers_1.determineSchemaKind)(ctx, schema);
|
|
20
20
|
let nullable = kind === 'null';
|
|
21
21
|
if (kind === 'multi-type') {
|
|
22
22
|
const types = schema.type;
|
|
@@ -30,13 +30,13 @@ function transformSchema(context, schema) {
|
|
|
30
30
|
const newType = types.filter((t) => t !== 'null' && t !== null)[0];
|
|
31
31
|
schema = (0, utils_1.createOverwriteProxy)(schema);
|
|
32
32
|
schema.type = newType;
|
|
33
|
-
kind = (0, helpers_1.determineSchemaKind)(schema);
|
|
33
|
+
kind = (0, helpers_1.determineSchemaKind)(ctx, schema);
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
36
|
schema.type = types.filter((t) => t !== 'null' && t !== null);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
const id =
|
|
39
|
+
const id = ctx.idGenerator.generateId('schema');
|
|
40
40
|
const nameInfo = (0, helpers_1.determineSchemaName)(schema, id);
|
|
41
41
|
const incompleteSchema = {
|
|
42
42
|
$src: {
|
|
@@ -57,7 +57,7 @@ function transformSchema(context, schema) {
|
|
|
57
57
|
nullable: nullable || schema.nullable === true,
|
|
58
58
|
required: new Set(schema.required),
|
|
59
59
|
custom: (0, helpers_1.getCustomFields)(schema),
|
|
60
|
-
not: schema.not ? transformSchema(
|
|
60
|
+
not: schema.not ? transformSchema(ctx, schema.not) : undefined,
|
|
61
61
|
const: schema.const,
|
|
62
62
|
discriminator: schema.discriminator
|
|
63
63
|
? {
|
|
@@ -67,101 +67,117 @@ function transformSchema(context, schema) {
|
|
|
67
67
|
: undefined,
|
|
68
68
|
inheritedSchemas: [],
|
|
69
69
|
};
|
|
70
|
-
|
|
70
|
+
ctx.incompleteSchemas.set(schemaSource, incompleteSchema);
|
|
71
71
|
if (schema.$ref) {
|
|
72
|
-
incompleteSchema.$ref = transformSchema(
|
|
72
|
+
incompleteSchema.$ref = transformSchema(ctx, schema.$ref);
|
|
73
73
|
}
|
|
74
|
-
const extensions = schemaTransformers[kind](schema,
|
|
74
|
+
const extensions = schemaTransformers[kind](schema, ctx);
|
|
75
75
|
const completeSchema = Object.assign(incompleteSchema, extensions);
|
|
76
|
-
resolveDescriminatorMapping(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
resolveDescriminatorMapping(ctx, completeSchema);
|
|
77
|
+
ctx.incompleteSchemas.delete(schemaSource);
|
|
78
|
+
ctx.transformed.schemas.set(openApiObjectId, completeSchema);
|
|
79
|
+
ctx.schemas.set(schemaSource, completeSchema);
|
|
80
80
|
return completeSchema;
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
oneOf: (_b = (_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
87
|
-
});
|
|
88
|
-
},
|
|
89
|
-
string: (schema) => ({
|
|
90
|
-
type: 'string',
|
|
82
|
+
function allExtensionsTransformer(schema, context) {
|
|
83
|
+
var _a, _b, _c, _d, _e, _f;
|
|
84
|
+
return {
|
|
85
|
+
oneOf: (_b = (_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
91
86
|
format: schema.format,
|
|
92
87
|
pattern: schema.pattern,
|
|
93
88
|
minLength: schema.minLength,
|
|
94
89
|
maxLength: schema.maxLength,
|
|
95
|
-
}),
|
|
96
|
-
number: (schema) => ({
|
|
97
|
-
type: 'number',
|
|
98
|
-
format: schema.format,
|
|
99
90
|
minimum: schema.minimum,
|
|
100
91
|
maximum: schema.maximum,
|
|
92
|
+
properties: (0, helpers_1.transformSchemaProperties)(context, schema, transformSchema),
|
|
93
|
+
additionalProperties: (0, helpers_1.transformAdditionalProperties)(context, schema, transformSchema),
|
|
94
|
+
allOf: (_d = (_c = schema.allOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
95
|
+
anyOf: (_f = (_e = schema.anyOf) === null || _e === void 0 ? void 0 : _e.map((s) => transformSchema(context, s))) !== null && _f !== void 0 ? _f : [],
|
|
96
|
+
items: schema.items ? transformSchema(context, schema.items) : undefined,
|
|
97
|
+
minItems: schema.minItems,
|
|
98
|
+
maxItems: schema.maxItems,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const schemaTransformers = {
|
|
102
|
+
oneOf: (schema, context) => ({
|
|
103
|
+
...allExtensionsTransformer(schema, context),
|
|
104
|
+
}),
|
|
105
|
+
string: (schema, context) => ({
|
|
106
|
+
type: 'string',
|
|
107
|
+
...allExtensionsTransformer(schema, context),
|
|
108
|
+
}),
|
|
109
|
+
number: (schema, context) => ({
|
|
110
|
+
type: 'number',
|
|
111
|
+
...allExtensionsTransformer(schema, context),
|
|
101
112
|
}),
|
|
102
|
-
boolean: (schema) => ({ type: 'boolean',
|
|
103
|
-
object: (schema, context) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
format: schema.format,
|
|
109
|
-
additionalProperties: (0, helpers_1.transformAdditionalProperties)(context, schema, transformSchema),
|
|
110
|
-
allOf: (_b = (_a = schema.allOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
111
|
-
anyOf: (_d = (_c = schema.anyOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
112
|
-
});
|
|
113
|
-
},
|
|
114
|
-
integer: (schema) => ({
|
|
113
|
+
boolean: (schema, context) => ({ type: 'boolean', ...allExtensionsTransformer(schema, context) }),
|
|
114
|
+
object: (schema, context) => ({
|
|
115
|
+
type: 'object',
|
|
116
|
+
...allExtensionsTransformer(schema, context),
|
|
117
|
+
}),
|
|
118
|
+
integer: (schema, context) => ({
|
|
115
119
|
type: 'integer',
|
|
116
|
-
|
|
117
|
-
minimum: schema.minimum,
|
|
118
|
-
maximum: schema.maximum,
|
|
120
|
+
...allExtensionsTransformer(schema, context),
|
|
119
121
|
}),
|
|
120
122
|
array: (schema, context) => ({
|
|
121
123
|
type: 'array',
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
...allExtensionsTransformer(schema, context),
|
|
125
|
+
}),
|
|
126
|
+
combined: (schema, context) => ({
|
|
127
|
+
...allExtensionsTransformer(schema, context),
|
|
128
|
+
}),
|
|
129
|
+
'multi-type': (schema, context) => ({
|
|
130
|
+
type: schema.type,
|
|
131
|
+
...allExtensionsTransformer(schema, context),
|
|
125
132
|
}),
|
|
126
|
-
combined: (schema, context) => {
|
|
127
|
-
var _a, _b, _c, _d;
|
|
128
|
-
return ({
|
|
129
|
-
allOf: (_b = (_a = schema.allOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
130
|
-
anyOf: (_d = (_c = schema.anyOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
'multi-type': (schema, context) => {
|
|
134
|
-
var _a, _b, _c, _d;
|
|
135
|
-
return ({
|
|
136
|
-
type: schema.type,
|
|
137
|
-
items: schema.items ? transformSchema(context, schema.items) : undefined,
|
|
138
|
-
minItems: schema.minItems,
|
|
139
|
-
maxItems: schema.maxItems,
|
|
140
|
-
minimum: schema.minimum,
|
|
141
|
-
maximum: schema.maximum,
|
|
142
|
-
format: schema.format,
|
|
143
|
-
properties: (0, helpers_1.transformSchemaProperties)(context, schema, transformSchema),
|
|
144
|
-
additionalProperties: (0, helpers_1.transformAdditionalProperties)(context, schema, transformSchema),
|
|
145
|
-
allOf: (_b = (_a = schema.allOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
146
|
-
anyOf: (_d = (_c = schema.anyOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
147
|
-
maxLength: schema.maxLength,
|
|
148
|
-
minLength: schema.minLength,
|
|
149
|
-
pattern: schema.pattern,
|
|
150
|
-
});
|
|
151
|
-
},
|
|
152
133
|
null: () => ({ type: 'null' }),
|
|
153
134
|
unknown: () => ({}),
|
|
154
135
|
};
|
|
155
136
|
function resolveDescriminatorMapping(context, schema) {
|
|
156
137
|
const discriminator = schema.$src.component.discriminator;
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
138
|
+
if (discriminator && typeof discriminator === 'object' && discriminator.mapping) {
|
|
139
|
+
for (const key of Object.keys(discriminator.mapping)) {
|
|
140
|
+
const mappedSchemaRef = discriminator.mapping[key];
|
|
141
|
+
const mappedSchema = transformSchema(context, mappedSchemaRef);
|
|
142
|
+
if (schema.discriminator) {
|
|
143
|
+
schema.discriminator.mapping[key] = mappedSchema;
|
|
144
|
+
const hasInheritedSchema = mappedSchema.inheritedSchemas.some((x) => x.id === schema.id);
|
|
145
|
+
if (!hasInheritedSchema) {
|
|
146
|
+
mappedSchema.inheritedSchemas.push(schema);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
165
149
|
}
|
|
166
150
|
}
|
|
151
|
+
if (schema.kind === 'combined' && schema.allOf) {
|
|
152
|
+
for (const s of schema.allOf) {
|
|
153
|
+
const base = findDiscriminatedSchema(s);
|
|
154
|
+
if (!base)
|
|
155
|
+
continue;
|
|
156
|
+
if (base.discriminator && base.discriminator.propertyName) {
|
|
157
|
+
const origDiscriminator = base.$src.component.discriminator;
|
|
158
|
+
if (origDiscriminator &&
|
|
159
|
+
typeof origDiscriminator === 'object' &&
|
|
160
|
+
origDiscriminator.mapping &&
|
|
161
|
+
Object.values(origDiscriminator.mapping).some((x) => x.$src.file === schema.$src.file && x.$src.path === schema.$src.path)) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const mappingKey = schema.isNameGenerated ? null : schema.name;
|
|
165
|
+
if (!mappingKey) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
base.discriminator.mapping[mappingKey] = schema;
|
|
169
|
+
const hasInheritedSchema = schema.inheritedSchemas.some((x) => x.id === base.id);
|
|
170
|
+
if (!hasInheritedSchema) {
|
|
171
|
+
schema.inheritedSchemas.push(base);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function findDiscriminatedSchema(schema) {
|
|
178
|
+
const origDiscriminator = schema.$src.originalComponent.discriminator;
|
|
179
|
+
if (origDiscriminator && (typeof origDiscriminator === 'string' || origDiscriminator.propertyName)) {
|
|
180
|
+
return schema;
|
|
181
|
+
}
|
|
182
|
+
return schema.$ref ? findDiscriminatedSchema(schema.$ref) : null;
|
|
167
183
|
}
|
|
@@ -5,8 +5,10 @@ const helpers_1 = require("./helpers");
|
|
|
5
5
|
const transform_document_1 = require("./transform-document");
|
|
6
6
|
const transform_endpoint_1 = require("./transform-endpoint");
|
|
7
7
|
const transform_schema_1 = require("./transform-schema");
|
|
8
|
-
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
function transformOpenApi(data, options) {
|
|
9
10
|
const context = {
|
|
11
|
+
config: { ...types_1.defaultOpenApiTransformerOptions, ...options },
|
|
10
12
|
idGenerator: new helpers_1.IdGenerator(),
|
|
11
13
|
input: data,
|
|
12
14
|
incompleteSchemas: new Map(),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createOverwriteProxy = createOverwriteProxy;
|
|
4
|
+
exports.getDeepProperty = getDeepProperty;
|
|
4
5
|
function createOverwriteProxy(target, values) {
|
|
5
6
|
const proxy = new Proxy(target, new OverwriteProxyHandler());
|
|
6
7
|
if (values) {
|
|
@@ -8,6 +9,16 @@ function createOverwriteProxy(target, values) {
|
|
|
8
9
|
}
|
|
9
10
|
return proxy;
|
|
10
11
|
}
|
|
12
|
+
function getDeepProperty(obj, path) {
|
|
13
|
+
let current = obj;
|
|
14
|
+
for (const key of path) {
|
|
15
|
+
if (!current || typeof current !== 'object') {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
current = current[key];
|
|
19
|
+
}
|
|
20
|
+
return current;
|
|
21
|
+
}
|
|
11
22
|
class OverwriteProxyHandler {
|
|
12
23
|
constructor() {
|
|
13
24
|
this._overwrittenValues = {};
|
|
@@ -9,6 +9,9 @@ function resolveAnyOfAndAllOf(schema, ignoreNonObjectParts) {
|
|
|
9
9
|
}
|
|
10
10
|
const required = new Set(schema.required);
|
|
11
11
|
const properties = new Map();
|
|
12
|
+
if ('properties' in schema) {
|
|
13
|
+
schema.properties.forEach((prop) => properties.set(prop.name, prop));
|
|
14
|
+
}
|
|
12
15
|
collectSubSchemaProperties(schema.allOf, properties, required, false);
|
|
13
16
|
collectSubSchemaProperties(schema.anyOf, properties, required, true);
|
|
14
17
|
const initialAdditionalProperties = schema.kind === 'object' ? schema.additionalProperties : undefined;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { defaultOpenApiTransformerOptions } from '../transform/types';
|
|
1
2
|
import { defaultSourceBuilderOptions } from '../utils/source-builder';
|
|
2
3
|
export const defaultOpenApiGeneratorConfig = {
|
|
3
4
|
...defaultSourceBuilderOptions,
|
|
5
|
+
...defaultOpenApiTransformerOptions,
|
|
4
6
|
outputDir: 'generated',
|
|
5
7
|
clearOutputDir: true,
|
|
6
8
|
};
|
|
@@ -56,7 +56,11 @@ class _OpenApiGenerator {
|
|
|
56
56
|
}
|
|
57
57
|
export class OpenApiGenerator extends _OpenApiGenerator {
|
|
58
58
|
constructor(config) {
|
|
59
|
-
super(
|
|
59
|
+
super(...OpenApiGenerator.getCtorArgs(config));
|
|
60
|
+
}
|
|
61
|
+
static getCtorArgs(config) {
|
|
62
|
+
const c = { ...defaultOpenApiGeneratorConfig, ...config };
|
|
63
|
+
return [c, [], new OpenApiParser(c)];
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
function mergeDeep(target, ...sources) {
|
package/esm/lib/parse/parser.js
CHANGED
|
@@ -5,12 +5,14 @@ import fs from 'fs-extra';
|
|
|
5
5
|
import nodeFetch from 'node-fetch';
|
|
6
6
|
import YAML from 'yaml';
|
|
7
7
|
import { createDerefProxy } from './deref-proxy';
|
|
8
|
+
import { defaultOpenApiParserOptions } from './types';
|
|
8
9
|
import { collectOpenApi } from '../collect/collector';
|
|
9
10
|
import { transformOpenApi } from '../transform/transformer';
|
|
10
11
|
import { isNullish } from '../utils';
|
|
11
12
|
export class OpenApiParser {
|
|
12
|
-
constructor() {
|
|
13
|
+
constructor(config) {
|
|
13
14
|
this._loadedDocuments = new Map();
|
|
15
|
+
this._config = { ...defaultOpenApiParserOptions, ...config };
|
|
14
16
|
}
|
|
15
17
|
async parseApisAndTransform(...fileNames) {
|
|
16
18
|
const flatFileNames = [].concat(...fileNames);
|
|
@@ -25,7 +27,7 @@ export class OpenApiParser {
|
|
|
25
27
|
}
|
|
26
28
|
transformApis(apis) {
|
|
27
29
|
const collectedData = collectOpenApi(apis);
|
|
28
|
-
const transformedData = transformOpenApi(collectedData);
|
|
30
|
+
const transformedData = transformOpenApi(collectedData, this._config);
|
|
29
31
|
return transformedData;
|
|
30
32
|
}
|
|
31
33
|
async dereference(file, path, value) {
|
package/esm/lib/parse/types.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { defaultOpenApiTransformerOptions } from '../transform/types';
|
|
2
|
+
export const defaultOpenApiParserOptions = { ...defaultOpenApiTransformerOptions };
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { isOpenApiObjectProperty } from '../internal-utils';
|
|
2
|
+
import { getDeepProperty } from '../utils';
|
|
2
3
|
import { isNullish } from '../utils/common.utils';
|
|
3
|
-
export function determineSchemaKind(schema) {
|
|
4
|
+
export function determineSchemaKind(ctx, schema) {
|
|
4
5
|
if (schema.oneOf) {
|
|
5
6
|
return 'oneOf';
|
|
6
7
|
}
|
|
7
8
|
else if (schema.type !== 'object' && (schema.allOf || schema.anyOf)) {
|
|
8
|
-
|
|
9
|
+
const hasProperties = (schema.properties && Object.keys(schema.properties).length > 0) || schema.additionalProperties;
|
|
10
|
+
return hasProperties ? 'object' : 'combined';
|
|
9
11
|
}
|
|
10
12
|
else if (Array.isArray(schema.type)) {
|
|
11
13
|
return 'multi-type';
|
|
@@ -19,9 +21,14 @@ export function determineSchemaKind(schema) {
|
|
|
19
21
|
schema.type === 'array') {
|
|
20
22
|
return schema.type;
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
const treadAsObject = ctx.config.unknownTypeBehavior === 'always-object' ||
|
|
25
|
+
(ctx.config.unknownTypeBehavior === 'object-if-properties' &&
|
|
26
|
+
schema.properties &&
|
|
27
|
+
Object.keys(schema.properties).length > 0);
|
|
28
|
+
return treadAsObject ? 'object' : 'unknown';
|
|
23
29
|
}
|
|
24
30
|
export function determineSchemaName(schema, id) {
|
|
31
|
+
var _a, _b, _c, _d, _e, _f;
|
|
25
32
|
if (schema.title)
|
|
26
33
|
return { name: schema.title, isGenerated: false };
|
|
27
34
|
if (!schema.$src) {
|
|
@@ -34,7 +41,34 @@ export function determineSchemaName(schema, id) {
|
|
|
34
41
|
const responseMatch = schema.$src.path.match(/\/paths\/(?<path>.+)\/(?<method>.+)\/responses\/(?<status>\d+)\//);
|
|
35
42
|
if (responseMatch && responseMatch.groups) {
|
|
36
43
|
const { path, method, status } = responseMatch.groups;
|
|
37
|
-
|
|
44
|
+
const operation = (_c = (_b = (_a = schema.$src.document.paths) === null || _a === void 0 ? void 0 : _a[path]) === null || _b === void 0 ? void 0 : _b[method]) !== null && _c !== void 0 ? _c : {};
|
|
45
|
+
return {
|
|
46
|
+
name: `${determineEndpointName({ method, path: `/${path}`, operation })}_${status}_Response`,
|
|
47
|
+
isGenerated: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const responseCompMatch = schema.$src.path.match(/\/components\/responses\/([^/]+)\/content\/.+\/schema/);
|
|
51
|
+
if (responseCompMatch) {
|
|
52
|
+
return {
|
|
53
|
+
name: responseCompMatch[1].toLowerCase().endsWith('response')
|
|
54
|
+
? responseCompMatch[1]
|
|
55
|
+
: responseCompMatch[1] + 'Response',
|
|
56
|
+
isGenerated: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const requestBodyMatch = schema.$src.path.match(/\/paths\/(?<path>.+)\/(?<method>.+)\/requestBody\//);
|
|
60
|
+
if (requestBodyMatch && requestBodyMatch.groups) {
|
|
61
|
+
const { path, method } = requestBodyMatch.groups;
|
|
62
|
+
const operation = (_f = (_e = (_d = schema.$src.document.paths) === null || _d === void 0 ? void 0 : _d[path]) === null || _e === void 0 ? void 0 : _e[method]) !== null && _f !== void 0 ? _f : {};
|
|
63
|
+
return { name: `${determineEndpointName({ method, path: `/${path}`, operation })}_Request`, isGenerated: true };
|
|
64
|
+
}
|
|
65
|
+
const parentSchemaMatch = schema.$src.path.match(/(.*)\/properties\/([^/]*)$/);
|
|
66
|
+
if (parentSchemaMatch) {
|
|
67
|
+
const parentSchema = getDeepProperty(schema.$src.document, parentSchemaMatch[1].split('/').filter(Boolean));
|
|
68
|
+
const parentSchemaName = determineSchemaName({ title: parentSchema === null || parentSchema === void 0 ? void 0 : parentSchema.title, $src: { path: parentSchemaMatch[1], document: schema.$src.document } }, id);
|
|
69
|
+
if (!parentSchemaName.isGenerated) {
|
|
70
|
+
return { name: `${parentSchemaName.name}_${parentSchemaMatch[2]}`, isGenerated: true };
|
|
71
|
+
}
|
|
38
72
|
}
|
|
39
73
|
return { name: id, isGenerated: true };
|
|
40
74
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { determineSchemaAccessibility, determineSchemaKind, determineSchemaName, getCustomFields, getOpenApiObjectIdentifier, transformAdditionalProperties, transformSchemaProperties, } from './helpers';
|
|
2
2
|
import { createOverwriteProxy } from '../utils';
|
|
3
|
-
export function transformSchema(
|
|
3
|
+
export function transformSchema(ctx, schema) {
|
|
4
4
|
var _a, _b;
|
|
5
5
|
if (!schema) {
|
|
6
6
|
throw new Error('Schema is required.');
|
|
7
7
|
}
|
|
8
8
|
const schemaSource = `${schema.$src.file}:${schema.$src.path}`;
|
|
9
|
-
const existingSchema = (_a =
|
|
9
|
+
const existingSchema = (_a = ctx.schemas.get(schemaSource)) !== null && _a !== void 0 ? _a : ctx.incompleteSchemas.get(schemaSource);
|
|
10
10
|
if (existingSchema)
|
|
11
11
|
return existingSchema;
|
|
12
12
|
const openApiObjectId = getOpenApiObjectIdentifier(schema);
|
|
13
|
-
const existing =
|
|
13
|
+
const existing = ctx.transformed.schemas.get(openApiObjectId);
|
|
14
14
|
if (existing)
|
|
15
15
|
return existing;
|
|
16
|
-
let kind = determineSchemaKind(schema);
|
|
16
|
+
let kind = determineSchemaKind(ctx, schema);
|
|
17
17
|
let nullable = kind === 'null';
|
|
18
18
|
if (kind === 'multi-type') {
|
|
19
19
|
const types = schema.type;
|
|
@@ -27,13 +27,13 @@ export function transformSchema(context, schema) {
|
|
|
27
27
|
const newType = types.filter((t) => t !== 'null' && t !== null)[0];
|
|
28
28
|
schema = createOverwriteProxy(schema);
|
|
29
29
|
schema.type = newType;
|
|
30
|
-
kind = determineSchemaKind(schema);
|
|
30
|
+
kind = determineSchemaKind(ctx, schema);
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
schema.type = types.filter((t) => t !== 'null' && t !== null);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
const id =
|
|
36
|
+
const id = ctx.idGenerator.generateId('schema');
|
|
37
37
|
const nameInfo = determineSchemaName(schema, id);
|
|
38
38
|
const incompleteSchema = {
|
|
39
39
|
$src: {
|
|
@@ -54,7 +54,7 @@ export function transformSchema(context, schema) {
|
|
|
54
54
|
nullable: nullable || schema.nullable === true,
|
|
55
55
|
required: new Set(schema.required),
|
|
56
56
|
custom: getCustomFields(schema),
|
|
57
|
-
not: schema.not ? transformSchema(
|
|
57
|
+
not: schema.not ? transformSchema(ctx, schema.not) : undefined,
|
|
58
58
|
const: schema.const,
|
|
59
59
|
discriminator: schema.discriminator
|
|
60
60
|
? {
|
|
@@ -64,101 +64,117 @@ export function transformSchema(context, schema) {
|
|
|
64
64
|
: undefined,
|
|
65
65
|
inheritedSchemas: [],
|
|
66
66
|
};
|
|
67
|
-
|
|
67
|
+
ctx.incompleteSchemas.set(schemaSource, incompleteSchema);
|
|
68
68
|
if (schema.$ref) {
|
|
69
|
-
incompleteSchema.$ref = transformSchema(
|
|
69
|
+
incompleteSchema.$ref = transformSchema(ctx, schema.$ref);
|
|
70
70
|
}
|
|
71
|
-
const extensions = schemaTransformers[kind](schema,
|
|
71
|
+
const extensions = schemaTransformers[kind](schema, ctx);
|
|
72
72
|
const completeSchema = Object.assign(incompleteSchema, extensions);
|
|
73
|
-
resolveDescriminatorMapping(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
resolveDescriminatorMapping(ctx, completeSchema);
|
|
74
|
+
ctx.incompleteSchemas.delete(schemaSource);
|
|
75
|
+
ctx.transformed.schemas.set(openApiObjectId, completeSchema);
|
|
76
|
+
ctx.schemas.set(schemaSource, completeSchema);
|
|
77
77
|
return completeSchema;
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
oneOf: (_b = (_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
string: (schema) => ({
|
|
87
|
-
type: 'string',
|
|
79
|
+
function allExtensionsTransformer(schema, context) {
|
|
80
|
+
var _a, _b, _c, _d, _e, _f;
|
|
81
|
+
return {
|
|
82
|
+
oneOf: (_b = (_a = schema.oneOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
88
83
|
format: schema.format,
|
|
89
84
|
pattern: schema.pattern,
|
|
90
85
|
minLength: schema.minLength,
|
|
91
86
|
maxLength: schema.maxLength,
|
|
92
|
-
}),
|
|
93
|
-
number: (schema) => ({
|
|
94
|
-
type: 'number',
|
|
95
|
-
format: schema.format,
|
|
96
87
|
minimum: schema.minimum,
|
|
97
88
|
maximum: schema.maximum,
|
|
89
|
+
properties: transformSchemaProperties(context, schema, transformSchema),
|
|
90
|
+
additionalProperties: transformAdditionalProperties(context, schema, transformSchema),
|
|
91
|
+
allOf: (_d = (_c = schema.allOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
92
|
+
anyOf: (_f = (_e = schema.anyOf) === null || _e === void 0 ? void 0 : _e.map((s) => transformSchema(context, s))) !== null && _f !== void 0 ? _f : [],
|
|
93
|
+
items: schema.items ? transformSchema(context, schema.items) : undefined,
|
|
94
|
+
minItems: schema.minItems,
|
|
95
|
+
maxItems: schema.maxItems,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const schemaTransformers = {
|
|
99
|
+
oneOf: (schema, context) => ({
|
|
100
|
+
...allExtensionsTransformer(schema, context),
|
|
101
|
+
}),
|
|
102
|
+
string: (schema, context) => ({
|
|
103
|
+
type: 'string',
|
|
104
|
+
...allExtensionsTransformer(schema, context),
|
|
105
|
+
}),
|
|
106
|
+
number: (schema, context) => ({
|
|
107
|
+
type: 'number',
|
|
108
|
+
...allExtensionsTransformer(schema, context),
|
|
98
109
|
}),
|
|
99
|
-
boolean: (schema) => ({ type: 'boolean',
|
|
100
|
-
object: (schema, context) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
format: schema.format,
|
|
106
|
-
additionalProperties: transformAdditionalProperties(context, schema, transformSchema),
|
|
107
|
-
allOf: (_b = (_a = schema.allOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
108
|
-
anyOf: (_d = (_c = schema.anyOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
109
|
-
});
|
|
110
|
-
},
|
|
111
|
-
integer: (schema) => ({
|
|
110
|
+
boolean: (schema, context) => ({ type: 'boolean', ...allExtensionsTransformer(schema, context) }),
|
|
111
|
+
object: (schema, context) => ({
|
|
112
|
+
type: 'object',
|
|
113
|
+
...allExtensionsTransformer(schema, context),
|
|
114
|
+
}),
|
|
115
|
+
integer: (schema, context) => ({
|
|
112
116
|
type: 'integer',
|
|
113
|
-
|
|
114
|
-
minimum: schema.minimum,
|
|
115
|
-
maximum: schema.maximum,
|
|
117
|
+
...allExtensionsTransformer(schema, context),
|
|
116
118
|
}),
|
|
117
119
|
array: (schema, context) => ({
|
|
118
120
|
type: 'array',
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
...allExtensionsTransformer(schema, context),
|
|
122
|
+
}),
|
|
123
|
+
combined: (schema, context) => ({
|
|
124
|
+
...allExtensionsTransformer(schema, context),
|
|
125
|
+
}),
|
|
126
|
+
'multi-type': (schema, context) => ({
|
|
127
|
+
type: schema.type,
|
|
128
|
+
...allExtensionsTransformer(schema, context),
|
|
122
129
|
}),
|
|
123
|
-
combined: (schema, context) => {
|
|
124
|
-
var _a, _b, _c, _d;
|
|
125
|
-
return ({
|
|
126
|
-
allOf: (_b = (_a = schema.allOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
127
|
-
anyOf: (_d = (_c = schema.anyOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
128
|
-
});
|
|
129
|
-
},
|
|
130
|
-
'multi-type': (schema, context) => {
|
|
131
|
-
var _a, _b, _c, _d;
|
|
132
|
-
return ({
|
|
133
|
-
type: schema.type,
|
|
134
|
-
items: schema.items ? transformSchema(context, schema.items) : undefined,
|
|
135
|
-
minItems: schema.minItems,
|
|
136
|
-
maxItems: schema.maxItems,
|
|
137
|
-
minimum: schema.minimum,
|
|
138
|
-
maximum: schema.maximum,
|
|
139
|
-
format: schema.format,
|
|
140
|
-
properties: transformSchemaProperties(context, schema, transformSchema),
|
|
141
|
-
additionalProperties: transformAdditionalProperties(context, schema, transformSchema),
|
|
142
|
-
allOf: (_b = (_a = schema.allOf) === null || _a === void 0 ? void 0 : _a.map((s) => transformSchema(context, s))) !== null && _b !== void 0 ? _b : [],
|
|
143
|
-
anyOf: (_d = (_c = schema.anyOf) === null || _c === void 0 ? void 0 : _c.map((s) => transformSchema(context, s))) !== null && _d !== void 0 ? _d : [],
|
|
144
|
-
maxLength: schema.maxLength,
|
|
145
|
-
minLength: schema.minLength,
|
|
146
|
-
pattern: schema.pattern,
|
|
147
|
-
});
|
|
148
|
-
},
|
|
149
130
|
null: () => ({ type: 'null' }),
|
|
150
131
|
unknown: () => ({}),
|
|
151
132
|
};
|
|
152
133
|
function resolveDescriminatorMapping(context, schema) {
|
|
153
134
|
const discriminator = schema.$src.component.discriminator;
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
135
|
+
if (discriminator && typeof discriminator === 'object' && discriminator.mapping) {
|
|
136
|
+
for (const key of Object.keys(discriminator.mapping)) {
|
|
137
|
+
const mappedSchemaRef = discriminator.mapping[key];
|
|
138
|
+
const mappedSchema = transformSchema(context, mappedSchemaRef);
|
|
139
|
+
if (schema.discriminator) {
|
|
140
|
+
schema.discriminator.mapping[key] = mappedSchema;
|
|
141
|
+
const hasInheritedSchema = mappedSchema.inheritedSchemas.some((x) => x.id === schema.id);
|
|
142
|
+
if (!hasInheritedSchema) {
|
|
143
|
+
mappedSchema.inheritedSchemas.push(schema);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
162
146
|
}
|
|
163
147
|
}
|
|
148
|
+
if (schema.kind === 'combined' && schema.allOf) {
|
|
149
|
+
for (const s of schema.allOf) {
|
|
150
|
+
const base = findDiscriminatedSchema(s);
|
|
151
|
+
if (!base)
|
|
152
|
+
continue;
|
|
153
|
+
if (base.discriminator && base.discriminator.propertyName) {
|
|
154
|
+
const origDiscriminator = base.$src.component.discriminator;
|
|
155
|
+
if (origDiscriminator &&
|
|
156
|
+
typeof origDiscriminator === 'object' &&
|
|
157
|
+
origDiscriminator.mapping &&
|
|
158
|
+
Object.values(origDiscriminator.mapping).some((x) => x.$src.file === schema.$src.file && x.$src.path === schema.$src.path)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const mappingKey = schema.isNameGenerated ? null : schema.name;
|
|
162
|
+
if (!mappingKey) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
base.discriminator.mapping[mappingKey] = schema;
|
|
166
|
+
const hasInheritedSchema = schema.inheritedSchemas.some((x) => x.id === base.id);
|
|
167
|
+
if (!hasInheritedSchema) {
|
|
168
|
+
schema.inheritedSchemas.push(base);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function findDiscriminatedSchema(schema) {
|
|
175
|
+
const origDiscriminator = schema.$src.originalComponent.discriminator;
|
|
176
|
+
if (origDiscriminator && (typeof origDiscriminator === 'string' || origDiscriminator.propertyName)) {
|
|
177
|
+
return schema;
|
|
178
|
+
}
|
|
179
|
+
return schema.$ref ? findDiscriminatedSchema(schema.$ref) : null;
|
|
164
180
|
}
|
|
@@ -2,8 +2,10 @@ import { IdGenerator } from './helpers';
|
|
|
2
2
|
import { transformDocument } from './transform-document';
|
|
3
3
|
import { transformEndpoint } from './transform-endpoint';
|
|
4
4
|
import { transformSchema } from './transform-schema';
|
|
5
|
-
|
|
5
|
+
import { defaultOpenApiTransformerOptions } from './types';
|
|
6
|
+
export function transformOpenApi(data, options) {
|
|
6
7
|
const context = {
|
|
8
|
+
config: { ...defaultOpenApiTransformerOptions, ...options },
|
|
7
9
|
idGenerator: new IdGenerator(),
|
|
8
10
|
input: data,
|
|
9
11
|
incompleteSchemas: new Map(),
|
|
@@ -5,6 +5,16 @@ export function createOverwriteProxy(target, values) {
|
|
|
5
5
|
}
|
|
6
6
|
return proxy;
|
|
7
7
|
}
|
|
8
|
+
export function getDeepProperty(obj, path) {
|
|
9
|
+
let current = obj;
|
|
10
|
+
for (const key of path) {
|
|
11
|
+
if (!current || typeof current !== 'object') {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
current = current[key];
|
|
15
|
+
}
|
|
16
|
+
return current;
|
|
17
|
+
}
|
|
8
18
|
class OverwriteProxyHandler {
|
|
9
19
|
constructor() {
|
|
10
20
|
this._overwrittenValues = {};
|
|
@@ -5,6 +5,9 @@ export function resolveAnyOfAndAllOf(schema, ignoreNonObjectParts) {
|
|
|
5
5
|
}
|
|
6
6
|
const required = new Set(schema.required);
|
|
7
7
|
const properties = new Map();
|
|
8
|
+
if ('properties' in schema) {
|
|
9
|
+
schema.properties.forEach((prop) => properties.set(prop.name, prop));
|
|
10
|
+
}
|
|
8
11
|
collectSubSchemaProperties(schema.allOf, properties, required, false);
|
|
9
12
|
collectSubSchemaProperties(schema.anyOf, properties, required, true);
|
|
10
13
|
const initialAdditionalProperties = schema.kind === 'object' ? schema.additionalProperties : undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goast/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"repository": "https://github.com/MaSch0212/goast.git",
|
|
5
5
|
"description": "A tool designed to transform OpenAPI specifications into various forms with flexibility and extensibility at its core.",
|
|
6
6
|
"keywords": [
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { OpenApiParserOptions } from '../parse';
|
|
1
2
|
import { SourceBuilderOptions } from '../utils/source-builder';
|
|
2
|
-
export type OpenApiGeneratorConfig = SourceBuilderOptions & {
|
|
3
|
+
export type OpenApiGeneratorConfig = SourceBuilderOptions & OpenApiParserOptions & {
|
|
3
4
|
/**
|
|
4
5
|
* The directory where the generated files should be saved.
|
|
5
6
|
* @default 'generated'
|
|
@@ -27,6 +27,7 @@ declare class _OpenApiGenerator<TOutput extends OpenApiGeneratorInput> {
|
|
|
27
27
|
}
|
|
28
28
|
export declare class OpenApiGenerator extends _OpenApiGenerator<{}> {
|
|
29
29
|
constructor(config?: Partial<OpenApiGeneratorConfig>);
|
|
30
|
+
private static getCtorArgs;
|
|
30
31
|
}
|
|
31
32
|
export type DefaultGenerationProviderConfig<T extends AnyConfig> = Omit<T, keyof OpenApiGeneratorConfig> & Partial<Pick<T, keyof OpenApiGeneratorConfig>>;
|
|
32
33
|
export declare abstract class OpenApiGenerationProviderBase<TInput extends OpenApiGeneratorInput, TOutput extends OpenApiGeneratorOutput, TConfig extends AnyConfig, TContext extends OpenApiGenerationProviderContext<TInput, TConfig>> implements OpenApiGenerationProvider<TInput, TOutput, TConfig> {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { OpenApiDocument } from './openapi-types';
|
|
2
|
-
import { Deref } from './types';
|
|
2
|
+
import { Deref, OpenApiParserOptions } from './types';
|
|
3
3
|
import { ApiData } from '../transform';
|
|
4
4
|
export declare class OpenApiParser {
|
|
5
5
|
private readonly _loadedDocuments;
|
|
6
|
+
private readonly _config;
|
|
7
|
+
constructor(config?: Partial<OpenApiParserOptions>);
|
|
6
8
|
parseApisAndTransform(...fileNames: (string | string[])[]): Promise<ApiData>;
|
|
7
9
|
parseApi(fileName: string): Promise<Deref<OpenApiDocument>>;
|
|
8
10
|
transformApis(apis: Deref<OpenApiDocument>[]): ApiData;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { OpenApiDiscriminator, OpenApiDocument, OpenApiReference, OpenApiSchema } from './openapi-types';
|
|
2
|
+
import { OpenApiTransformerOptions } from '../transform/types';
|
|
2
3
|
export type DerefSource<T> = {
|
|
3
4
|
file: string;
|
|
4
5
|
path: string;
|
|
@@ -15,4 +16,8 @@ type _Deref<T extends object> = T extends OpenApiDiscriminator ? _DerefDiscrimin
|
|
|
15
16
|
$ref?: Deref<T>;
|
|
16
17
|
};
|
|
17
18
|
export type Deref<T> = T extends object ? (T extends (infer A)[] ? Deref<A>[] : _Deref<T>) : T;
|
|
19
|
+
export type OpenApiParserOptions = OpenApiTransformerOptions;
|
|
20
|
+
export declare const defaultOpenApiParserOptions: {
|
|
21
|
+
unknownTypeBehavior: "keep-unknown" | "object-if-properties" | "always-object";
|
|
22
|
+
};
|
|
18
23
|
export {};
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { ApiSchemaKind, ApiSchemaAccessibility, ApiSchema, ApiSchemaProperty } from './api-types';
|
|
2
2
|
import { OpenApiTransformerContext } from './types';
|
|
3
|
-
import { Deref, OpenApiObject } from '../parse';
|
|
3
|
+
import { Deref, OpenApiDocument, OpenApiObject } from '../parse';
|
|
4
4
|
export declare function determineSchemaKind<T extends {
|
|
5
5
|
oneOf?: unknown;
|
|
6
6
|
allOf?: unknown;
|
|
7
7
|
anyOf?: unknown;
|
|
8
8
|
type?: string | string[];
|
|
9
|
-
|
|
9
|
+
properties?: Record<string, unknown>;
|
|
10
|
+
additionalProperties?: unknown;
|
|
11
|
+
}>(ctx: OpenApiTransformerContext, schema: T): ApiSchemaKind;
|
|
10
12
|
export declare function determineSchemaName(schema: {
|
|
11
13
|
title?: string;
|
|
12
14
|
$src: {
|
|
13
15
|
path: string;
|
|
16
|
+
document: Deref<OpenApiDocument>;
|
|
14
17
|
};
|
|
15
18
|
}, id: string): {
|
|
16
19
|
name: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ApiSchema } from './api-types';
|
|
2
2
|
import { OpenApiTransformerContext } from './types';
|
|
3
3
|
import { Deref, OpenApiSchema } from '../parse';
|
|
4
|
-
export declare function transformSchema<T extends Deref<OpenApiSchema>>(
|
|
4
|
+
export declare function transformSchema<T extends Deref<OpenApiSchema>>(ctx: OpenApiTransformerContext, schema: T): ApiSchema;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ApiData } from './api-types';
|
|
2
|
+
import { OpenApiTransformerOptions } from './types';
|
|
2
3
|
import { OpenApiCollectorData } from '../collect';
|
|
3
|
-
export declare function transformOpenApi(data: OpenApiCollectorData): ApiData;
|
|
4
|
+
export declare function transformOpenApi(data: OpenApiCollectorData, options?: Partial<OpenApiTransformerOptions>): ApiData;
|
|
@@ -2,8 +2,20 @@ import { ApiSchema, ApiSchemaExtensions, ApiSchemaKind, ApiPath, ApiData, ApiSer
|
|
|
2
2
|
import { IdGenerator } from './helpers';
|
|
3
3
|
import { OpenApiCollectorData } from '../collect/types';
|
|
4
4
|
import { ArrayItem } from '../utils/type.utils';
|
|
5
|
+
export type OpenApiTransformerOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Determines how schemas without a `type` property should be treated.
|
|
8
|
+
* - `keep-unknown`: Keep the schema as-is.
|
|
9
|
+
* - `object-if-properties`: Treat the schema as an object schema only if it has properties.
|
|
10
|
+
* - `always-object`: Treat the schema as an object schema.
|
|
11
|
+
* @default 'object-if-properties'
|
|
12
|
+
*/
|
|
13
|
+
unknownTypeBehavior: 'keep-unknown' | 'object-if-properties' | 'always-object';
|
|
14
|
+
};
|
|
15
|
+
export declare const defaultOpenApiTransformerOptions: OpenApiTransformerOptions;
|
|
5
16
|
export type IncompleteApiSchema = Omit<ApiSchema, Exclude<keyof ApiSchemaExtensions<ApiSchemaKind>, 'kind'>>;
|
|
6
17
|
export type OpenApiTransformerContext = {
|
|
18
|
+
config: OpenApiTransformerOptions;
|
|
7
19
|
idGenerator: IdGenerator;
|
|
8
20
|
input: OpenApiCollectorData;
|
|
9
21
|
incompleteSchemas: Map<string, IncompleteApiSchema>;
|