swagger-typescript-api 10.0.2 → 11.0.0--alpha
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/README.md +263 -41
- package/index.d.ts +97 -0
- package/index.js +242 -115
- package/package.json +121 -116
- package/src/code-formatter.js +101 -0
- package/src/code-gen-process.js +456 -0
- package/src/configuration.js +425 -0
- package/src/constants.js +14 -31
- package/src/index.js +20 -271
- package/src/schema-components-map.js +60 -0
- package/src/schema-parser/schema-formatters.js +145 -0
- package/src/schema-parser/schema-parser.js +497 -0
- package/src/schema-parser/schema-routes.js +902 -0
- package/src/swagger-schema-resolver.js +187 -0
- package/src/templates.js +174 -155
- package/src/translators/JavaScript.js +3 -14
- package/src/type-name.js +79 -0
- package/src/util/file-system.js +76 -0
- package/src/{utils → util}/id.js +9 -9
- package/src/util/internal-case.js +5 -0
- package/src/util/logger.js +100 -0
- package/src/{utils/resolveName.js → util/name-resolver.js} +94 -97
- package/src/util/object-assign.js +11 -0
- package/src/util/pascal-case.js +5 -0
- package/src/{utils → util}/random.js +14 -14
- package/templates/base/data-contract-jsdoc.ejs +29 -24
- package/templates/base/data-contracts.ejs +3 -3
- package/templates/base/interface-data-contract.ejs +1 -0
- package/templates/base/route-docs.ejs +3 -4
- package/templates/base/route-type.ejs +2 -2
- package/templates/default/procedure-call.ejs +2 -2
- package/templates/default/route-types.ejs +2 -2
- package/templates/modular/api.ejs +2 -2
- package/templates/modular/procedure-call.ejs +2 -2
- package/templates/modular/route-types.ejs +2 -2
- package/src/apiConfig.js +0 -30
- package/src/common.js +0 -28
- package/src/components.js +0 -91
- package/src/config.js +0 -106
- package/src/filePrefix.js +0 -14
- package/src/files.js +0 -56
- package/src/formatFileContent.js +0 -81
- package/src/logger.js +0 -59
- package/src/modelNames.js +0 -78
- package/src/modelTypes.js +0 -31
- package/src/output.js +0 -165
- package/src/prettierOptions.js +0 -23
- package/src/render/utils/fmtToJSDocLine.js +0 -10
- package/src/render/utils/index.js +0 -31
- package/src/render/utils/templateRequire.js +0 -17
- package/src/routeNames.js +0 -46
- package/src/routes.js +0 -809
- package/src/schema.js +0 -474
- package/src/swagger.js +0 -152
- package/src/typeFormatters.js +0 -121
package/src/schema.js
DELETED
|
@@ -1,474 +0,0 @@
|
|
|
1
|
-
const _ = require("lodash");
|
|
2
|
-
const { inlineExtraFormatters } = require("./typeFormatters");
|
|
3
|
-
const { isValidName, formatModelName, formatEnumKey } = require("./modelNames");
|
|
4
|
-
const { formatDescription, internalCase } = require("./common");
|
|
5
|
-
const { JS_PRIMITIVE_TYPES, JS_EMPTY_TYPES, TS_KEYWORDS, SCHEMA_TYPES } = require("./constants");
|
|
6
|
-
const { config } = require("./config");
|
|
7
|
-
const { isObject } = require("lodash");
|
|
8
|
-
|
|
9
|
-
const types = {
|
|
10
|
-
/** { type: "integer" } -> { type: "number" } */
|
|
11
|
-
integer: TS_KEYWORDS.NUMBER,
|
|
12
|
-
number: TS_KEYWORDS.NUMBER,
|
|
13
|
-
boolean: TS_KEYWORDS.BOOLEAN,
|
|
14
|
-
object: TS_KEYWORDS.OBJECT,
|
|
15
|
-
file: TS_KEYWORDS.FILE,
|
|
16
|
-
string: {
|
|
17
|
-
$default: TS_KEYWORDS.STRING,
|
|
18
|
-
|
|
19
|
-
/** formats */
|
|
20
|
-
binary: TS_KEYWORDS.FILE,
|
|
21
|
-
},
|
|
22
|
-
array: ({ items, ...schemaPart }) => {
|
|
23
|
-
const content = getInlineParseContent(items);
|
|
24
|
-
return checkAndAddNull(schemaPart, `(${content})[]`);
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
// TODO: probably it can be needed
|
|
28
|
-
// date: "Date",
|
|
29
|
-
// dateTime: "Date",
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const stealTypeFromSchema = (rawSchema) => {
|
|
33
|
-
const schema = rawSchema || {};
|
|
34
|
-
|
|
35
|
-
if (schema.type) {
|
|
36
|
-
return schema.type;
|
|
37
|
-
}
|
|
38
|
-
if (schema.enum) {
|
|
39
|
-
const enumFieldType = typeof schema.enum[0];
|
|
40
|
-
if (enumFieldType === TS_KEYWORDS.UNDEFINED) return;
|
|
41
|
-
|
|
42
|
-
return enumFieldType;
|
|
43
|
-
}
|
|
44
|
-
if (_.keys(schema.properties).length) {
|
|
45
|
-
return SCHEMA_TYPES.OBJECT;
|
|
46
|
-
}
|
|
47
|
-
if (!!schema.items) {
|
|
48
|
-
return SCHEMA_TYPES.ARRAY;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const getTypeAlias = (rawSchema) => {
|
|
53
|
-
const schema = rawSchema || {};
|
|
54
|
-
const type = internalCase(stealTypeFromSchema(schema));
|
|
55
|
-
const format = internalCase(schema.format);
|
|
56
|
-
const typeAlias = _.get(types, [type, format]) || _.get(types, [type, "$default"]) || types[type];
|
|
57
|
-
|
|
58
|
-
if (_.isFunction(typeAlias)) {
|
|
59
|
-
return typeAlias(schema);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return typeAlias || type;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const getEnumNames = (schema) => {
|
|
66
|
-
return schema["x-enumNames"] || schema["xEnumNames"] || schema["x-enumnames"] || schema["x-enum-varnames"];
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const getInternalSchemaType = (schema) => {
|
|
70
|
-
if (!_.isEmpty(schema.enum) || !_.isEmpty(getEnumNames(schema))) return SCHEMA_TYPES.ENUM;
|
|
71
|
-
if (schema.allOf || schema.oneOf || schema.anyOf || schema.not) return SCHEMA_TYPES.COMPLEX;
|
|
72
|
-
if (!_.isEmpty(schema.properties)) return SCHEMA_TYPES.OBJECT;
|
|
73
|
-
|
|
74
|
-
return SCHEMA_TYPES.PRIMITIVE;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const isNeedToAddNull = (contract, value) => {
|
|
78
|
-
const { nullable, type } = contract || {};
|
|
79
|
-
return (
|
|
80
|
-
(nullable || !!_.get(contract, "x-nullable") || type === TS_KEYWORDS.NULL) &&
|
|
81
|
-
(!_.isString(value) || (!value.includes(` ${TS_KEYWORDS.NULL}`) && !value.includes(`${TS_KEYWORDS.NULL} `)))
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const checkAndAddRequiredKeys = (schema, resultType) => {
|
|
86
|
-
if ("$$requiredKeys" in schema && schema.$$requiredKeys.length) {
|
|
87
|
-
config.internalTemplateOptions.addUtilRequiredKeysType = true;
|
|
88
|
-
return `UtilRequiredKeys<${resultType}, ${schema.$$requiredKeys.map((k) => `"${k}"`).join(" | ")}>`;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return resultType;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const checkAndAddNull = (schema, value) => {
|
|
95
|
-
const { nullable, type } = schema || {};
|
|
96
|
-
return (nullable || !!_.get(schema, "x-nullable") || type === TS_KEYWORDS.NULL) &&
|
|
97
|
-
_.isString(value) &&
|
|
98
|
-
!value.includes(` ${TS_KEYWORDS.NULL}`) &&
|
|
99
|
-
!value.includes(`${TS_KEYWORDS.NULL} `)
|
|
100
|
-
? `${value} | ${TS_KEYWORDS.NULL}`
|
|
101
|
-
: value;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const isRef = (property) => {
|
|
105
|
-
return !!(property && property["$ref"]);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const getRefType = (schema) => {
|
|
109
|
-
const ref = schema && schema["$ref"];
|
|
110
|
-
return config.componentsMap[ref] || null;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const getType = (schema) => {
|
|
114
|
-
if (!schema) return TS_KEYWORDS.ANY;
|
|
115
|
-
|
|
116
|
-
const refTypeInfo = getRefType(schema);
|
|
117
|
-
|
|
118
|
-
if (refTypeInfo) {
|
|
119
|
-
return checkAndAddRequiredKeys(schema, checkAndAddNull(schema, formatModelName(refTypeInfo.typeName)));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const primitiveType = getTypeAlias(schema);
|
|
123
|
-
return primitiveType ? checkAndAddRequiredKeys(schema, checkAndAddNull(schema, primitiveType)) : TS_KEYWORDS.ANY;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const isRequired = (property, name, requiredProperties) => {
|
|
127
|
-
if (property["x-omitempty"] === false) {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const isRequired = _.isBoolean(property.required)
|
|
132
|
-
? !!property.required
|
|
133
|
-
: _.isArray(requiredProperties)
|
|
134
|
-
? requiredProperties.includes(name)
|
|
135
|
-
: !!requiredProperties;
|
|
136
|
-
|
|
137
|
-
if (config.convertedFromSwagger2) {
|
|
138
|
-
return typeof property.nullable === TS_KEYWORDS.UNDEFINED ? isRequired : !property.nullable;
|
|
139
|
-
}
|
|
140
|
-
return isRequired;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const getObjectTypeContent = (schema) => {
|
|
144
|
-
const { properties, additionalProperties, required: requiredProperties } = schema || {};
|
|
145
|
-
|
|
146
|
-
const propertiesContent = _.map(properties, (property, name) => {
|
|
147
|
-
const required = isRequired(property, name, requiredProperties);
|
|
148
|
-
const rawTypeData = _.get(getRefType(property), "rawTypeData", {});
|
|
149
|
-
const nullable = !!(rawTypeData.nullable || property.nullable);
|
|
150
|
-
const fieldName = isValidName(name) ? name : `"${name}"`;
|
|
151
|
-
const fieldValue = getInlineParseContent(property);
|
|
152
|
-
const readOnly = property.readOnly;
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
$$raw: property,
|
|
156
|
-
title: property.title,
|
|
157
|
-
description: _.compact([
|
|
158
|
-
property.description ||
|
|
159
|
-
_.compact(_.map(property[getComplexType(property)], "description"))[0] ||
|
|
160
|
-
rawTypeData.description ||
|
|
161
|
-
_.compact(_.map(rawTypeData[getComplexType(rawTypeData)], "description"))[0] ||
|
|
162
|
-
"",
|
|
163
|
-
!_.isUndefined(property.deprecated) && `@deprecated`,
|
|
164
|
-
!_.isUndefined(property.format) && `@format ${property.format}`,
|
|
165
|
-
!_.isUndefined(property.minimum) && `@min ${property.minimum}`,
|
|
166
|
-
!_.isUndefined(property.maximum) && `@max ${property.maximum}`,
|
|
167
|
-
!_.isUndefined(property.pattern) && `@pattern ${property.pattern}`,
|
|
168
|
-
!_.isUndefined(property.example) &&
|
|
169
|
-
`@example ${_.isObject(property.example) ? JSON.stringify(property.example) : property.example}`,
|
|
170
|
-
]).join("\n"),
|
|
171
|
-
isRequired: required,
|
|
172
|
-
isNullable: nullable,
|
|
173
|
-
name: fieldName,
|
|
174
|
-
value: fieldValue,
|
|
175
|
-
field: _.compact([
|
|
176
|
-
readOnly && config.addReadonly && "readonly ",
|
|
177
|
-
fieldName,
|
|
178
|
-
!required && "?",
|
|
179
|
-
": ",
|
|
180
|
-
fieldValue,
|
|
181
|
-
]).join(""),
|
|
182
|
-
};
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
if (additionalProperties === true) {
|
|
186
|
-
propertiesContent.push({
|
|
187
|
-
$$raw: { additionalProperties },
|
|
188
|
-
description: "",
|
|
189
|
-
isRequired: false,
|
|
190
|
-
field: `[key: ${TS_KEYWORDS.STRING}]: ${TS_KEYWORDS.ANY}`,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return propertiesContent;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const filterContents = (contents, types) => _.uniq(_.filter(contents, (type) => !_.includes(types, type)));
|
|
198
|
-
|
|
199
|
-
const makeAddRequiredToChildSchema = (parentSchema, childSchema) => {
|
|
200
|
-
if (!childSchema) return childSchema;
|
|
201
|
-
|
|
202
|
-
const required = _.uniq([...(parentSchema.required || []), ...(childSchema.required || [])]);
|
|
203
|
-
|
|
204
|
-
const refData = getRefType(childSchema);
|
|
205
|
-
|
|
206
|
-
if (refData) {
|
|
207
|
-
const refObjectProperties = _.keys((refData.rawTypeData && refData.rawTypeData.properties) || {});
|
|
208
|
-
const existedRequiredKeys = refObjectProperties.filter((key) => required.includes(key));
|
|
209
|
-
|
|
210
|
-
if (!existedRequiredKeys.length) return childSchema;
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
...childSchema,
|
|
214
|
-
$$requiredKeys: existedRequiredKeys,
|
|
215
|
-
};
|
|
216
|
-
} else if (childSchema.properties) {
|
|
217
|
-
const childSchemaProperties = _.keys(childSchema.properties);
|
|
218
|
-
const existedRequiredKeys = childSchemaProperties.filter((key) => required.includes(key));
|
|
219
|
-
|
|
220
|
-
if (!existedRequiredKeys.length) return childSchema;
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
required: _.uniq([...(childSchema.required || []), ...existedRequiredKeys]),
|
|
224
|
-
...childSchema,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return childSchema;
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const complexSchemaParsers = {
|
|
232
|
-
// T1 | T2
|
|
233
|
-
[SCHEMA_TYPES.COMPLEX_ONE_OF]: (schema) => {
|
|
234
|
-
const combined = _.map(schema.oneOf, (childSchema) =>
|
|
235
|
-
getInlineParseContent(makeAddRequiredToChildSchema(schema, childSchema)),
|
|
236
|
-
);
|
|
237
|
-
const filtered = filterContents(combined, [TS_KEYWORDS.ANY]);
|
|
238
|
-
|
|
239
|
-
const type = filtered.join(" | ");
|
|
240
|
-
|
|
241
|
-
return checkAndAddNull(schema, type);
|
|
242
|
-
},
|
|
243
|
-
// T1 & T2
|
|
244
|
-
[SCHEMA_TYPES.COMPLEX_ALL_OF]: (schema) => {
|
|
245
|
-
const combined = _.map(schema.allOf, (childSchema) =>
|
|
246
|
-
getInlineParseContent(makeAddRequiredToChildSchema(schema, childSchema)),
|
|
247
|
-
);
|
|
248
|
-
const filtered = filterContents(combined, [...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]);
|
|
249
|
-
|
|
250
|
-
const type = filtered.join(TS_KEYWORDS.TYPE_AND_OPERATOR);
|
|
251
|
-
|
|
252
|
-
return checkAndAddNull(schema, type);
|
|
253
|
-
},
|
|
254
|
-
// T1 | T2 | (T1 & T2)
|
|
255
|
-
[SCHEMA_TYPES.COMPLEX_ANY_OF]: (schema) => {
|
|
256
|
-
const combined = _.map(schema.anyOf, (childSchema) =>
|
|
257
|
-
getInlineParseContent(makeAddRequiredToChildSchema(schema, childSchema)),
|
|
258
|
-
);
|
|
259
|
-
const filtered = filterContents(combined, [...JS_PRIMITIVE_TYPES, TS_KEYWORDS.ANY]);
|
|
260
|
-
|
|
261
|
-
const type = _.compact([
|
|
262
|
-
...filtered,
|
|
263
|
-
filtered.length > 1 && `(${filtered.join(TS_KEYWORDS.TYPE_AND_OPERATOR)})`,
|
|
264
|
-
]).join(TS_KEYWORDS.TYPE_OR_OPERATOR);
|
|
265
|
-
|
|
266
|
-
return checkAndAddNull(schema, type);
|
|
267
|
-
},
|
|
268
|
-
// TODO
|
|
269
|
-
[SCHEMA_TYPES.COMPLEX_NOT]: (schema) => {
|
|
270
|
-
// TODO
|
|
271
|
-
return TS_KEYWORDS.ANY;
|
|
272
|
-
},
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const getComplexType = (schema) => {
|
|
276
|
-
if (schema.oneOf) return SCHEMA_TYPES.COMPLEX_ONE_OF;
|
|
277
|
-
if (schema.allOf) return SCHEMA_TYPES.COMPLEX_ALL_OF;
|
|
278
|
-
if (schema.anyOf) return SCHEMA_TYPES.COMPLEX_ANY_OF;
|
|
279
|
-
// TODO :(
|
|
280
|
-
if (schema.not) return SCHEMA_TYPES.COMPLEX_NOT;
|
|
281
|
-
|
|
282
|
-
return SCHEMA_TYPES.COMPLEX_UNKNOWN;
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const attachParsedRef = (originalSchema, parsedSchema) => {
|
|
286
|
-
const parsedSchemaAfterHook = config.hooks.onParseSchema(originalSchema, parsedSchema) || parsedSchema;
|
|
287
|
-
|
|
288
|
-
if (originalSchema) {
|
|
289
|
-
originalSchema.$parsed = parsedSchemaAfterHook;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
return parsedSchemaAfterHook;
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
const schemaParsers = {
|
|
296
|
-
[SCHEMA_TYPES.ENUM]: (schema, typeName) => {
|
|
297
|
-
const refType = getRefType(schema);
|
|
298
|
-
const $ref = (refType && refType.$ref) || null;
|
|
299
|
-
const enumNamesAsValues = config.enumNamesAsValues;
|
|
300
|
-
const keyType = getType(schema);
|
|
301
|
-
const enumNames = getEnumNames(schema);
|
|
302
|
-
const isIntegerOrBooleanEnum = keyType === types.number || keyType === types.boolean;
|
|
303
|
-
let content = null;
|
|
304
|
-
|
|
305
|
-
if (_.isArray(enumNames) && _.size(enumNames)) {
|
|
306
|
-
content = _.map(enumNames, (enumName, index) => {
|
|
307
|
-
const enumValue = _.get(schema.enum, index);
|
|
308
|
-
const formattedKey = (enumName && formatEnumKey(enumName)) || formatEnumKey(enumValue);
|
|
309
|
-
|
|
310
|
-
if (enumNamesAsValues || _.isUndefined(enumValue)) {
|
|
311
|
-
return {
|
|
312
|
-
key: formattedKey,
|
|
313
|
-
type: TS_KEYWORDS.STRING,
|
|
314
|
-
value: `"${enumName}"`,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return {
|
|
319
|
-
key: formattedKey,
|
|
320
|
-
type: keyType,
|
|
321
|
-
value: enumValue === null ? enumValue : isIntegerOrBooleanEnum ? `${enumValue}` : `"${enumValue}"`,
|
|
322
|
-
};
|
|
323
|
-
});
|
|
324
|
-
} else {
|
|
325
|
-
content = _.map(schema.enum, (key) => {
|
|
326
|
-
return {
|
|
327
|
-
key: isIntegerOrBooleanEnum ? key : formatEnumKey(key),
|
|
328
|
-
type: keyType,
|
|
329
|
-
value: key === null ? key : isIntegerOrBooleanEnum ? `${key}` : `"${key}"`,
|
|
330
|
-
};
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return attachParsedRef(schema, {
|
|
335
|
-
...(_.isObject(schema) ? schema : {}),
|
|
336
|
-
$ref: $ref,
|
|
337
|
-
typeName: typeName || ($ref && refType.typeName) || null,
|
|
338
|
-
$parsedSchema: true,
|
|
339
|
-
schemaType: SCHEMA_TYPES.ENUM,
|
|
340
|
-
type: SCHEMA_TYPES.ENUM,
|
|
341
|
-
keyType: keyType,
|
|
342
|
-
typeIdentifier:
|
|
343
|
-
config.generateUnionEnums || (!enumNames && isIntegerOrBooleanEnum) ? TS_KEYWORDS.TYPE : TS_KEYWORDS.ENUM,
|
|
344
|
-
name: typeName,
|
|
345
|
-
description: formatDescription(schema.description),
|
|
346
|
-
content,
|
|
347
|
-
});
|
|
348
|
-
},
|
|
349
|
-
[SCHEMA_TYPES.OBJECT]: (schema, typeName) => {
|
|
350
|
-
const content = getObjectTypeContent(schema);
|
|
351
|
-
|
|
352
|
-
return attachParsedRef(schema, {
|
|
353
|
-
...(isObject(schema) ? schema : {}),
|
|
354
|
-
$parsedSchema: true,
|
|
355
|
-
schemaType: SCHEMA_TYPES.OBJECT,
|
|
356
|
-
type: SCHEMA_TYPES.OBJECT,
|
|
357
|
-
typeIdentifier: TS_KEYWORDS.INTERFACE,
|
|
358
|
-
name: typeName,
|
|
359
|
-
description: formatDescription(schema.description),
|
|
360
|
-
allFieldsAreOptional: !_.some(_.values(content), (part) => part.isRequired),
|
|
361
|
-
content: content,
|
|
362
|
-
});
|
|
363
|
-
},
|
|
364
|
-
[SCHEMA_TYPES.COMPLEX]: (schema, typeName) => {
|
|
365
|
-
const complexType = getComplexType(schema);
|
|
366
|
-
const simpleSchema = _.omit(_.clone(schema), _.keys(complexSchemaParsers));
|
|
367
|
-
const complexSchemaContent = complexSchemaParsers[complexType](schema);
|
|
368
|
-
|
|
369
|
-
return attachParsedRef(schema, {
|
|
370
|
-
...(isObject(schema) ? schema : {}),
|
|
371
|
-
$parsedSchema: true,
|
|
372
|
-
schemaType: SCHEMA_TYPES.COMPLEX,
|
|
373
|
-
type: SCHEMA_TYPES.PRIMITIVE,
|
|
374
|
-
typeIdentifier: TS_KEYWORDS.TYPE,
|
|
375
|
-
name: typeName,
|
|
376
|
-
description: formatDescription(
|
|
377
|
-
schema.description || _.compact(_.map(schema[complexType], "description"))[0] || "",
|
|
378
|
-
),
|
|
379
|
-
content:
|
|
380
|
-
_.uniq(
|
|
381
|
-
_.compact([
|
|
382
|
-
complexSchemaContent && `(${complexSchemaContent})`,
|
|
383
|
-
getInternalSchemaType(simpleSchema) === SCHEMA_TYPES.OBJECT && `(${getInlineParseContent(simpleSchema)})`,
|
|
384
|
-
]),
|
|
385
|
-
).join(" & ") || TS_KEYWORDS.ANY,
|
|
386
|
-
});
|
|
387
|
-
},
|
|
388
|
-
[SCHEMA_TYPES.PRIMITIVE]: (schema, typeName) => {
|
|
389
|
-
let contentType = null;
|
|
390
|
-
const { additionalProperties, type, description, $$requiredKeys } = schema || {};
|
|
391
|
-
|
|
392
|
-
if (type === TS_KEYWORDS.OBJECT && additionalProperties) {
|
|
393
|
-
const fieldType = _.isObject(additionalProperties)
|
|
394
|
-
? getInlineParseContent(additionalProperties)
|
|
395
|
-
: TS_KEYWORDS.ANY;
|
|
396
|
-
contentType = `Record<${TS_KEYWORDS.STRING}, ${fieldType}>`;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
if (_.isArray(type) && type.length) {
|
|
400
|
-
contentType = complexSchemaParsers.oneOf({
|
|
401
|
-
...(_.isObject(schema) ? schema : {}),
|
|
402
|
-
oneOf: type.map((type) => ({ type })),
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
return attachParsedRef(schema, {
|
|
407
|
-
...(isObject(schema) ? schema : {}),
|
|
408
|
-
$parsedSchema: true,
|
|
409
|
-
schemaType: SCHEMA_TYPES.PRIMITIVE,
|
|
410
|
-
type: SCHEMA_TYPES.PRIMITIVE,
|
|
411
|
-
typeIdentifier: TS_KEYWORDS.TYPE,
|
|
412
|
-
name: typeName,
|
|
413
|
-
description: formatDescription(description),
|
|
414
|
-
// TODO: probably it should be refactored. `type === 'null'` is not flexible
|
|
415
|
-
content: type === TS_KEYWORDS.NULL ? type : contentType || getType(schema),
|
|
416
|
-
});
|
|
417
|
-
},
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
const checkAndFixSchema = (schema) => {
|
|
421
|
-
if (schema.items && !schema.type) {
|
|
422
|
-
schema.type = SCHEMA_TYPES.ARRAY;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
return schema;
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
/** @returns {{ type, typeIdentifier, name, description, content }} */
|
|
429
|
-
const parseSchema = (rawSchema, typeName, formattersMap) => {
|
|
430
|
-
if (!rawSchema) return schemaParsers.primitive(null, typeName);
|
|
431
|
-
|
|
432
|
-
let schemaType = null;
|
|
433
|
-
let parsedSchema = null;
|
|
434
|
-
|
|
435
|
-
if (typeof rawSchema === "string") {
|
|
436
|
-
return rawSchema;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
if (rawSchema.$parsed) {
|
|
440
|
-
schemaType = rawSchema.$parsed.schemaType;
|
|
441
|
-
parsedSchema = rawSchema.$parsed;
|
|
442
|
-
} else {
|
|
443
|
-
if (!typeName && isRef(rawSchema)) {
|
|
444
|
-
typeName = getType(rawSchema);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
const fixedRawSchema = checkAndFixSchema(rawSchema);
|
|
448
|
-
schemaType = getInternalSchemaType(fixedRawSchema);
|
|
449
|
-
parsedSchema = schemaParsers[schemaType](fixedRawSchema, typeName);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
return (formattersMap && formattersMap[schemaType] && formattersMap[schemaType](parsedSchema)) || parsedSchema;
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
const parseSchemas = (components) =>
|
|
456
|
-
_.map(_.get(components, "schemas"), (schema, typeName) => parseSchema(schema, typeName));
|
|
457
|
-
|
|
458
|
-
const getInlineParseContent = (rawTypeData, typeName = null) =>
|
|
459
|
-
parseSchema(rawTypeData, typeName, inlineExtraFormatters).content;
|
|
460
|
-
|
|
461
|
-
const getParseContent = (rawTypeData, typeName = null) => parseSchema(rawTypeData, typeName).content;
|
|
462
|
-
|
|
463
|
-
module.exports = {
|
|
464
|
-
types,
|
|
465
|
-
parseSchema,
|
|
466
|
-
parseSchemas,
|
|
467
|
-
getInlineParseContent,
|
|
468
|
-
getParseContent,
|
|
469
|
-
isNeedToAddNull,
|
|
470
|
-
getType,
|
|
471
|
-
getRefType,
|
|
472
|
-
SCHEMA_TYPES,
|
|
473
|
-
checkAndAddNull,
|
|
474
|
-
};
|
package/src/swagger.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
const _ = require("lodash");
|
|
2
|
-
const yaml = require("js-yaml");
|
|
3
|
-
const axios = require("axios");
|
|
4
|
-
const converter = require("swagger2openapi");
|
|
5
|
-
const https = require("https");
|
|
6
|
-
const { addToConfig, config } = require("./config");
|
|
7
|
-
const { pathIsExist, getFileContent } = require("./files");
|
|
8
|
-
const { logger } = require("./logger");
|
|
9
|
-
|
|
10
|
-
const parseSwaggerFile = (file) => {
|
|
11
|
-
if (typeof file !== "string") return file;
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
return JSON.parse(file);
|
|
15
|
-
} catch (e) {
|
|
16
|
-
return yaml.load(file);
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const getSwaggerFile = (pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy, authorizationToken) =>
|
|
21
|
-
new Promise((resolve, reject) => {
|
|
22
|
-
if (pathIsExist(pathToSwagger)) {
|
|
23
|
-
logger.log(`try to get swagger by path "${pathToSwagger}"`);
|
|
24
|
-
resolve(getFileContent(pathToSwagger));
|
|
25
|
-
} else {
|
|
26
|
-
logger.log(`try to get swagger by URL "${urlToSwagger}"`);
|
|
27
|
-
// setup options for Axios
|
|
28
|
-
const axiosOptions = {
|
|
29
|
-
maxContentLength: Infinity,
|
|
30
|
-
maxBodyLength: Infinity,
|
|
31
|
-
};
|
|
32
|
-
//
|
|
33
|
-
if (disableStrictSSL) {
|
|
34
|
-
axiosOptions.httpsAgent = new https.Agent({
|
|
35
|
-
rejectUnauthorized: false,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
//
|
|
39
|
-
if (authorizationToken) {
|
|
40
|
-
axiosOptions.headers = {
|
|
41
|
-
Authorization: authorizationToken,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
//
|
|
45
|
-
if (disableProxy) axiosOptions.proxy = false;
|
|
46
|
-
//
|
|
47
|
-
axios
|
|
48
|
-
.get(urlToSwagger, axiosOptions)
|
|
49
|
-
.then((res) => resolve(res.data))
|
|
50
|
-
.catch((error) => {
|
|
51
|
-
const message = `error while getting swagger by URL ${urlToSwagger}`;
|
|
52
|
-
|
|
53
|
-
logger.error(message, "response" in error ? error.response : error);
|
|
54
|
-
|
|
55
|
-
reject(message);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const getSwaggerObject = (
|
|
61
|
-
pathToSwagger,
|
|
62
|
-
urlToSwagger,
|
|
63
|
-
disableStrictSSL,
|
|
64
|
-
disableProxy,
|
|
65
|
-
authorizationToken,
|
|
66
|
-
converterOptions,
|
|
67
|
-
) =>
|
|
68
|
-
getSwaggerFile(pathToSwagger, urlToSwagger, disableStrictSSL, disableProxy, authorizationToken).then((file) =>
|
|
69
|
-
convertSwaggerObject(parseSwaggerFile(file), converterOptions),
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const convertSwaggerObject = (swaggerSchema, converterOptions) => {
|
|
73
|
-
return new Promise((resolve) => {
|
|
74
|
-
swaggerSchema.info = _.merge(
|
|
75
|
-
{
|
|
76
|
-
title: "No title",
|
|
77
|
-
version: "",
|
|
78
|
-
},
|
|
79
|
-
swaggerSchema.info,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
if (!swaggerSchema.openapi) {
|
|
83
|
-
swaggerSchema.paths = _.merge({}, swaggerSchema.paths);
|
|
84
|
-
|
|
85
|
-
converter.convertObj(
|
|
86
|
-
swaggerSchema,
|
|
87
|
-
{
|
|
88
|
-
...converterOptions,
|
|
89
|
-
warnOnly: true,
|
|
90
|
-
refSiblings: "preserve",
|
|
91
|
-
rbname: "requestBodyName",
|
|
92
|
-
},
|
|
93
|
-
function (err, options) {
|
|
94
|
-
const parsedSwaggerSchema = _.get(err, "options.openapi", _.get(options, "openapi"));
|
|
95
|
-
if (!parsedSwaggerSchema && err) {
|
|
96
|
-
throw new Error(err);
|
|
97
|
-
}
|
|
98
|
-
addToConfig({ convertedFromSwagger2: true });
|
|
99
|
-
resolve({
|
|
100
|
-
usageSchema: parsedSwaggerSchema,
|
|
101
|
-
originalSchema: swaggerSchema,
|
|
102
|
-
});
|
|
103
|
-
},
|
|
104
|
-
);
|
|
105
|
-
} else {
|
|
106
|
-
resolve({
|
|
107
|
-
usageSchema: swaggerSchema,
|
|
108
|
-
originalSchema: swaggerSchema,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const fixSwaggerScheme = (usage, original) => {
|
|
115
|
-
const usagePaths = _.get(usage, "paths");
|
|
116
|
-
const originalPaths = _.get(original, "paths");
|
|
117
|
-
|
|
118
|
-
// walk by routes
|
|
119
|
-
_.each(usagePaths, (usagePathObject, route) => {
|
|
120
|
-
const originalPathObject = _.get(originalPaths, route);
|
|
121
|
-
|
|
122
|
-
// walk by methods
|
|
123
|
-
_.each(usagePathObject, (usageRouteInfo, methodName) => {
|
|
124
|
-
const originalRouteInfo = _.get(originalPathObject, methodName);
|
|
125
|
-
const usageRouteParams = _.get(usageRouteInfo, "parameters", []);
|
|
126
|
-
const originalRouteParams = _.get(originalRouteInfo, "parameters", []);
|
|
127
|
-
|
|
128
|
-
usageRouteInfo.consumes = _.uniq(
|
|
129
|
-
_.compact([...(usageRouteInfo.consumes || []), ...(originalRouteInfo.consumes || [])]),
|
|
130
|
-
);
|
|
131
|
-
usageRouteInfo.produces = _.uniq(
|
|
132
|
-
_.compact([...(usageRouteInfo.produces || []), ...(originalRouteInfo.produces || [])]),
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
_.each(originalRouteParams, (originalRouteParam) => {
|
|
136
|
-
const existUsageParam = _.find(
|
|
137
|
-
usageRouteParams,
|
|
138
|
-
(param) => originalRouteParam.in === param.in && originalRouteParam.name === param.name,
|
|
139
|
-
);
|
|
140
|
-
if (!existUsageParam) {
|
|
141
|
-
usageRouteParams.push(originalRouteParam);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
module.exports = {
|
|
149
|
-
getSwaggerObject,
|
|
150
|
-
fixSwaggerScheme,
|
|
151
|
-
convertSwaggerObject,
|
|
152
|
-
};
|