swaggie 1.5.3-beta.3 → 1.5.3-beta.5
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/dist/gen/createBarrel.js +4 -4
- package/dist/gen/genOperations.js +39 -20
- package/dist/index.js +11 -12
- package/dist/swagger/typesExtractor.js +26 -20
- package/dist/types.d.ts +21 -0
- package/dist/utils/utils.js +35 -4
- package/package.json +1 -1
package/dist/gen/createBarrel.js
CHANGED
|
@@ -15,13 +15,13 @@ var _utils = require('../utils');
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const viewData = {
|
|
18
|
-
servicePrefix: clientOptions.servicePrefix
|
|
18
|
+
servicePrefix: clientOptions.servicePrefix,
|
|
19
19
|
clients: files
|
|
20
20
|
.filter((c) => c)
|
|
21
21
|
.map((c) => ({
|
|
22
|
-
fileName:
|
|
23
|
-
className: `${
|
|
24
|
-
camelCaseName: _case.camel.call(void 0, `${
|
|
22
|
+
fileName: clientOptions.servicePrefix + c,
|
|
23
|
+
className: `${clientOptions.servicePrefix + c}Client`,
|
|
24
|
+
camelCaseName: _case.camel.call(void 0, `${clientOptions.servicePrefix + c}Client`),
|
|
25
25
|
})),
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -25,7 +25,7 @@ var _jsDocs = require('./jsDocs');
|
|
|
25
25
|
) {
|
|
26
26
|
const operations = _swagger.getOperations.call(void 0, spec);
|
|
27
27
|
const groups = _utils.groupOperationsByGroupName.call(void 0, operations);
|
|
28
|
-
const servicePrefix =
|
|
28
|
+
const servicePrefix = options.servicePrefix;
|
|
29
29
|
let result = _utils.renderFile.call(void 0, 'baseClient.ejs', {
|
|
30
30
|
servicePrefix,
|
|
31
31
|
baseUrl: options.baseUrl,
|
|
@@ -34,7 +34,7 @@ var _jsDocs = require('./jsDocs');
|
|
|
34
34
|
|
|
35
35
|
for (const name in groups) {
|
|
36
36
|
const group = groups[name];
|
|
37
|
-
const clientData = prepareClient(servicePrefix + name, group, options);
|
|
37
|
+
const clientData = prepareClient(servicePrefix + name, group, spec.components, options);
|
|
38
38
|
|
|
39
39
|
if (!clientData) {
|
|
40
40
|
continue;
|
|
@@ -56,9 +56,10 @@ var _jsDocs = require('./jsDocs');
|
|
|
56
56
|
function prepareClient(
|
|
57
57
|
name,
|
|
58
58
|
operations,
|
|
59
|
+
components,
|
|
59
60
|
options
|
|
60
61
|
) {
|
|
61
|
-
const preparedOperations = prepareOperations(operations, options);
|
|
62
|
+
const preparedOperations = prepareOperations(operations, options, components);
|
|
62
63
|
|
|
63
64
|
if (preparedOperations.length === 0) {
|
|
64
65
|
return null;
|
|
@@ -86,7 +87,8 @@ function prepareClient(
|
|
|
86
87
|
*/
|
|
87
88
|
function prepareOperations(
|
|
88
89
|
operations,
|
|
89
|
-
options
|
|
90
|
+
options,
|
|
91
|
+
components
|
|
90
92
|
) {
|
|
91
93
|
let ops = fixDuplicateOperations(operations);
|
|
92
94
|
|
|
@@ -95,10 +97,10 @@ function prepareClient(
|
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
return ops.map((op) => {
|
|
98
|
-
const [respObject, responseContentType] = _utils.getBestResponse.call(void 0, op);
|
|
100
|
+
const [respObject, responseContentType] = _utils.getBestResponse.call(void 0, op, components);
|
|
99
101
|
const returnType = _swagger.getParameterType.call(void 0, respObject, options);
|
|
100
102
|
|
|
101
|
-
const body = getRequestBody(op.requestBody, options);
|
|
103
|
+
const body = getRequestBody(op.requestBody, components, options);
|
|
102
104
|
const queryParams = getParams(op.parameters , options, ['query']);
|
|
103
105
|
const params = getParams(op.parameters , options);
|
|
104
106
|
|
|
@@ -279,23 +281,40 @@ function prepareUrl(path) {
|
|
|
279
281
|
} exports.getParamName = getParamName;
|
|
280
282
|
|
|
281
283
|
function getRequestBody(
|
|
282
|
-
|
|
284
|
+
rawReqBody,
|
|
285
|
+
components,
|
|
283
286
|
options
|
|
284
287
|
) {
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
contentType,
|
|
297
|
-
};
|
|
288
|
+
if (!rawReqBody) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
let reqBody;
|
|
293
|
+
if ('$ref' in rawReqBody) {
|
|
294
|
+
const refName = rawReqBody.$ref.replace('#/components/requestBodies/', '');
|
|
295
|
+
const resolved = _optionalChain([components, 'optionalAccess', _8 => _8.requestBodies, 'optionalAccess', _9 => _9[refName]]);
|
|
296
|
+
if (!resolved || '$ref' in resolved) {
|
|
297
|
+
console.error(`RequestBody $ref '${rawReqBody.$ref}' not found in components/requestBodies`);
|
|
298
|
+
return null;
|
|
298
299
|
}
|
|
300
|
+
reqBody = resolved;
|
|
301
|
+
} else {
|
|
302
|
+
reqBody = rawReqBody;
|
|
299
303
|
}
|
|
304
|
+
|
|
305
|
+
const [bodyContent, contentType] = _utils.getBestContentType.call(void 0, reqBody);
|
|
306
|
+
const isFormData = contentType === 'form-data';
|
|
307
|
+
|
|
308
|
+
if (bodyContent) {
|
|
309
|
+
return {
|
|
310
|
+
originalName: _nullishCoalesce(reqBody['x-name'], () => ( 'body')),
|
|
311
|
+
name: getParamName(_nullishCoalesce(reqBody['x-name'], () => ( 'body'))),
|
|
312
|
+
type: isFormData ? 'FormData' : _swagger.getParameterType.call(void 0, bodyContent, options),
|
|
313
|
+
optional: !reqBody.required,
|
|
314
|
+
original: reqBody,
|
|
315
|
+
contentType,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
300
319
|
return null;
|
|
301
320
|
}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var _gen = require('./gen'); var _gen2 = _interopRequireDefault(_gen);
|
|
5
5
|
|
|
6
|
+
var _types = require('./types');
|
|
6
7
|
var _utils = require('./utils');
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -33,7 +34,7 @@ function verifyOptions(options) {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
function gen(spec, options) {
|
|
36
|
-
_utils.loadAllTemplateFiles.call(void 0, options.template
|
|
37
|
+
_utils.loadAllTemplateFiles.call(void 0, options.template);
|
|
37
38
|
|
|
38
39
|
return _gen2.default.call(void 0, spec, options);
|
|
39
40
|
}
|
|
@@ -68,20 +69,16 @@ function readFile(filePath) {
|
|
|
68
69
|
|
|
69
70
|
|
|
70
71
|
|
|
71
|
-
const defaultQueryParamsConfig = {
|
|
72
|
-
allowDots: true,
|
|
73
|
-
arrayFormat: 'repeat' ,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
72
|
/**
|
|
77
73
|
* CLI options are flat, but within the app we use nested objects.
|
|
78
74
|
* This function converts flat options structure to the nested one and
|
|
79
|
-
* merges it with the default values
|
|
80
|
-
*
|
|
81
|
-
|
|
75
|
+
* merges it with the default values, producing a fully-initialized AppOptions
|
|
76
|
+
* object where every defaultable field is guaranteed to be present.
|
|
77
|
+
*/
|
|
78
|
+
function prepareAppOptions(cliOpts) {
|
|
82
79
|
const { allowDots, arrayFormat, template, queryParamsSerialization = {}, ...rest } = cliOpts;
|
|
83
80
|
const mergedQueryParamsSerialization = {
|
|
84
|
-
...
|
|
81
|
+
..._types.APP_DEFAULTS.queryParamsSerialization,
|
|
85
82
|
...Object.fromEntries(
|
|
86
83
|
Object.entries(queryParamsSerialization).filter(([_, v]) => v !== undefined)
|
|
87
84
|
),
|
|
@@ -91,7 +88,9 @@ function prepareAppOptions(cliOpts) {
|
|
|
91
88
|
|
|
92
89
|
return {
|
|
93
90
|
...rest,
|
|
91
|
+
template: _nullishCoalesce(template, () => ( _types.APP_DEFAULTS.template)),
|
|
92
|
+
servicePrefix: _nullishCoalesce(rest.servicePrefix, () => ( _types.APP_DEFAULTS.servicePrefix)),
|
|
93
|
+
nullableStrategy: _nullishCoalesce(rest.nullableStrategy, () => ( _types.APP_DEFAULTS.nullableStrategy)),
|
|
94
94
|
queryParamsSerialization: mergedQueryParamsSerialization,
|
|
95
|
-
template: _nullishCoalesce(template, () => ( 'axios')),
|
|
96
95
|
};
|
|
97
|
-
}
|
|
96
|
+
} exports.prepareAppOptions = prepareAppOptions;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
3
|
var _utils = require('../utils');
|
|
4
4
|
|
|
@@ -24,7 +24,7 @@ var _utils = require('../utils');
|
|
|
24
24
|
return unknownType;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
return
|
|
27
|
+
return getTypeFromSchemaResolved(param.schema, options);
|
|
28
28
|
} exports.getParameterType = getParameterType;
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -36,6 +36,17 @@ var _utils = require('../utils');
|
|
|
36
36
|
function getTypeFromSchema(
|
|
37
37
|
schema,
|
|
38
38
|
options
|
|
39
|
+
) {
|
|
40
|
+
return getTypeFromSchemaResolved(schema, options);
|
|
41
|
+
} exports.getTypeFromSchema = getTypeFromSchema;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Internal implementation of getTypeFromSchema that operates on fully-resolved AppOptions.
|
|
45
|
+
* All private functions in this module call this version directly to avoid redundant resolution.
|
|
46
|
+
*/
|
|
47
|
+
function getTypeFromSchemaResolved(
|
|
48
|
+
schema,
|
|
49
|
+
options
|
|
39
50
|
) {
|
|
40
51
|
const unknownType = options.preferAny ? 'any' : 'unknown';
|
|
41
52
|
|
|
@@ -59,25 +70,21 @@ var _utils = require('../utils');
|
|
|
59
70
|
|
|
60
71
|
// OpenAPI 3.0 nullable: nullable: true
|
|
61
72
|
const isNullable = 'nullable' in schema && schema.nullable === true;
|
|
62
|
-
const
|
|
63
|
-
const isNullableSuffix = isNullable && strategy === 'include' ? ' | null' : '';
|
|
73
|
+
const isNullableSuffix = isNullable && options.nullableStrategy === 'include' ? ' | null' : '';
|
|
64
74
|
const type = getTypeFromSchemaInternal(schema, options);
|
|
65
75
|
|
|
66
76
|
if (isNullableSuffix && type.endsWith('| null')) {
|
|
67
77
|
return type;
|
|
68
78
|
}
|
|
69
79
|
return type + isNullableSuffix;
|
|
70
|
-
}
|
|
80
|
+
}
|
|
71
81
|
|
|
72
82
|
/**
|
|
73
83
|
* Handles OpenAPI 3.1 schemas where `type` is an array (e.g. `["string", "null"]`).
|
|
74
84
|
* The presence of `"null"` in the array is the OA3.1 way of marking a field as nullable.
|
|
75
85
|
* Respects `nullableStrategy` the same way as OA3.0 `nullable: true`.
|
|
76
86
|
*/
|
|
77
|
-
function getTypeFromOA31ArrayType(
|
|
78
|
-
schema,
|
|
79
|
-
options
|
|
80
|
-
) {
|
|
87
|
+
function getTypeFromOA31ArrayType(schema, options) {
|
|
81
88
|
const unknownType = options.preferAny ? 'any' : 'unknown';
|
|
82
89
|
const types = schema.type ;
|
|
83
90
|
const isNullable = types.includes('null');
|
|
@@ -107,8 +114,7 @@ function getTypeFromOA31ArrayType(
|
|
|
107
114
|
return 'null';
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
if (strategy === 'include') {
|
|
117
|
+
if (options.nullableStrategy === 'include') {
|
|
112
118
|
// We don't want multiple nulls in the type string
|
|
113
119
|
if (baseType.endsWith('| null')) {
|
|
114
120
|
return baseType;
|
|
@@ -162,24 +168,22 @@ function getNestedTypeFromSchema(
|
|
|
162
168
|
schema,
|
|
163
169
|
options
|
|
164
170
|
) {
|
|
165
|
-
const strategy = _nullishCoalesce(options.nullableStrategy, () => ( 'ignore'));
|
|
166
|
-
|
|
167
171
|
// OA3.0 nullable: true
|
|
168
172
|
const isOA30NullableAndActive =
|
|
169
|
-
'nullable' in schema && schema.nullable === true &&
|
|
173
|
+
'nullable' in schema && schema.nullable === true && options.nullableStrategy === 'include';
|
|
170
174
|
|
|
171
175
|
// OA3.1 nullable: type array containing 'null'
|
|
172
176
|
const isOA31NullableAndActive =
|
|
173
177
|
'type' in schema &&
|
|
174
178
|
Array.isArray(schema.type) &&
|
|
175
179
|
schema.type.includes('null') &&
|
|
176
|
-
|
|
180
|
+
options.nullableStrategy === 'include';
|
|
177
181
|
|
|
178
182
|
if (isOA30NullableAndActive || isOA31NullableAndActive || ('enum' in schema && schema.enum)) {
|
|
179
|
-
return `(${
|
|
183
|
+
return `(${getTypeFromSchemaResolved(schema, options)})`;
|
|
180
184
|
}
|
|
181
185
|
|
|
182
|
-
return
|
|
186
|
+
return getTypeFromSchemaResolved(schema, options);
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
/**
|
|
@@ -195,7 +199,7 @@ function getTypeFromObject(
|
|
|
195
199
|
if (schema.additionalProperties) {
|
|
196
200
|
const extraProps = schema.additionalProperties;
|
|
197
201
|
return `{ [key: string]: ${
|
|
198
|
-
extraProps === true ? 'any' :
|
|
202
|
+
extraProps === true ? 'any' : getTypeFromSchemaResolved(extraProps, options)
|
|
199
203
|
} }`;
|
|
200
204
|
}
|
|
201
205
|
|
|
@@ -209,7 +213,7 @@ function getTypeFromObject(
|
|
|
209
213
|
const isRequired = required.includes(prop);
|
|
210
214
|
const safePropName = _utils.escapePropName.call(void 0, prop);
|
|
211
215
|
result.push(
|
|
212
|
-
`${safePropName}${isRequired ? '' : '?'}: ${
|
|
216
|
+
`${safePropName}${isRequired ? '' : '?'}: ${getTypeFromSchemaResolved(propDefinition, options)};`
|
|
213
217
|
);
|
|
214
218
|
}
|
|
215
219
|
|
|
@@ -225,7 +229,9 @@ function getTypeFromObject(
|
|
|
225
229
|
function getTypeFromComposites(schema, options) {
|
|
226
230
|
const composite = schema.allOf || schema.oneOf || schema.anyOf;
|
|
227
231
|
|
|
228
|
-
return composite
|
|
232
|
+
return composite
|
|
233
|
+
.map((s) => getTypeFromSchemaResolved(s, options))
|
|
234
|
+
.join(schema.allOf ? ' & ' : ' | ');
|
|
229
235
|
}
|
|
230
236
|
|
|
231
237
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -50,6 +50,27 @@ export type HttpMethod = 'get' | 'put' | 'post' | 'delete' | 'options' | 'head'
|
|
|
50
50
|
export type DateSupport = 'string' | 'Date';
|
|
51
51
|
export type ArrayFormat = 'indices' | 'repeat' | 'brackets';
|
|
52
52
|
export type NullableStrategy = 'include' | 'nullableAsOptional' | 'ignore';
|
|
53
|
+
/**
|
|
54
|
+
* Internal options type used throughout the app after `prepareAppOptions` has run.
|
|
55
|
+
* All fields that have defaults are required here so the rest of the codebase never
|
|
56
|
+
* needs to perform its own `?? fallback` logic.
|
|
57
|
+
*/
|
|
58
|
+
export interface AppOptions extends ClientOptions {
|
|
59
|
+
template: Template;
|
|
60
|
+
servicePrefix: string;
|
|
61
|
+
nullableStrategy: NullableStrategy;
|
|
62
|
+
queryParamsSerialization: {
|
|
63
|
+
allowDots: boolean;
|
|
64
|
+
arrayFormat: ArrayFormat;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Default values applied to every field of AppOptions that has a default. */
|
|
68
|
+
export declare const APP_DEFAULTS: Partial<AppOptions>;
|
|
69
|
+
/**
|
|
70
|
+
* Fills in all AppOptions defaults for a partial ClientOptions object.
|
|
71
|
+
* Used at the boundary between public API / test helpers and the internal pipeline.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveOptions(opts: Partial<ClientOptions>): AppOptions;
|
|
53
74
|
/**
|
|
54
75
|
* Local type that represent Operation as understood by Swaggie
|
|
55
76
|
**/
|
package/dist/utils/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _nodefs = require('node:fs');
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _nodefs = require('node:fs');
|
|
2
2
|
var _nodepath = require('node:path');
|
|
3
3
|
|
|
4
4
|
|
|
@@ -171,11 +171,15 @@ const reservedKeywords = new Set([
|
|
|
171
171
|
* Other media types are not supported at this time.
|
|
172
172
|
* @returns Response or reference of the success response
|
|
173
173
|
*/
|
|
174
|
-
function getBestResponse(
|
|
174
|
+
function getBestResponse(
|
|
175
|
+
op,
|
|
176
|
+
components
|
|
177
|
+
) {
|
|
175
178
|
const NOT_FOUND = 100000;
|
|
176
179
|
const lowestCode = _nullishCoalesce(Object.keys(op.responses).sort().shift(), () => ( NOT_FOUND));
|
|
177
180
|
|
|
178
|
-
const
|
|
181
|
+
const rawResp = lowestCode === NOT_FOUND ? op.responses[0] : op.responses[lowestCode.toString()];
|
|
182
|
+
const resp = resolveResponseRef(rawResp, components);
|
|
179
183
|
|
|
180
184
|
if (resp && 'content' in resp) {
|
|
181
185
|
return getBestContentType(resp);
|
|
@@ -183,6 +187,33 @@ const reservedKeywords = new Set([
|
|
|
183
187
|
return [null, null];
|
|
184
188
|
} exports.getBestResponse = getBestResponse;
|
|
185
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Resolves a $ref in a response object to the actual response object from components/responses.
|
|
192
|
+
* If the response is already an object (not a reference), it is returned as-is.
|
|
193
|
+
*/
|
|
194
|
+
function resolveResponseRef(
|
|
195
|
+
resp,
|
|
196
|
+
components
|
|
197
|
+
) {
|
|
198
|
+
if (!resp) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!('$ref' in resp)) {
|
|
203
|
+
return resp;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const refName = resp.$ref.replace('#/components/responses/', '');
|
|
207
|
+
const resolved = _optionalChain([components, 'optionalAccess', _ => _.responses, 'optionalAccess', _2 => _2[refName]]);
|
|
208
|
+
|
|
209
|
+
if (!resolved) {
|
|
210
|
+
console.error(`Response $ref '${resp.$ref}' not found in components/responses`);
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return resolved ;
|
|
215
|
+
}
|
|
216
|
+
|
|
186
217
|
/** This method tries to fix potentially wrong out parameter given from commandline */
|
|
187
218
|
function prepareOutputFilename(out) {
|
|
188
219
|
if (!out) {
|
|
@@ -206,7 +237,7 @@ const reservedKeywords = new Set([
|
|
|
206
237
|
return arr.concat().sort(sortByKey(key));
|
|
207
238
|
} exports.orderBy = orderBy;
|
|
208
239
|
|
|
209
|
-
const sortByKey = (key) => (a, b) => a[key] > b[key] ? 1 : b[key] > a[key] ? -1 : 0;
|
|
240
|
+
const sortByKey = (key) => (a, b) => (a[key] > b[key] ? 1 : b[key] > a[key] ? -1 : 0);
|
|
210
241
|
|
|
211
242
|
const orderedContentTypes = [
|
|
212
243
|
'application/json',
|