swaggie 1.5.3-beta.2 → 1.5.3-beta.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/README.md +5 -5
- package/dist/gen/createBarrel.js +4 -4
- package/dist/gen/genOperations.js +2 -5
- package/dist/gen/genTypes.js +21 -6
- package/dist/index.js +11 -12
- package/dist/swagger/typesExtractor.js +89 -14
- package/dist/types.d.ts +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -313,14 +313,14 @@ function error(e) {
|
|
|
313
313
|
|
|
314
314
|
| Supported | Not supported |
|
|
315
315
|
| ------------------------------------------------------------------------------ | ----------------------------------------------- |
|
|
316
|
-
| OpenAPI 3
|
|
316
|
+
| OpenAPI 3, OpenAPI 3.1, OpenAPI 3.2 | Swagger, Open API 2.0 |
|
|
317
317
|
| `allOf`, `oneOf`, `anyOf`, `$ref` to schemas | `not` |
|
|
318
|
-
| Spec formats: `JSON`, `YAML` |
|
|
318
|
+
| Spec formats: `JSON`, `YAML` | VERY complex query params |
|
|
319
319
|
| Extensions: `x-position`, `x-name`, `x-enumNames`, `x-enum-varnames` | Multiple response types (only one will be used) |
|
|
320
320
|
| Content types: `JSON`, `text`, `multipart/form-data` | Multiple request types (only one will be used) |
|
|
321
|
-
| Content types: `application/x-www-form-urlencoded`, `application/octet-stream` | References to
|
|
322
|
-
| Different types of enum definitions
|
|
323
|
-
| Paths inheritance, comments (descriptions), nullable
|
|
321
|
+
| Content types: `application/x-www-form-urlencoded`, `application/octet-stream` | References to external spec files |
|
|
322
|
+
| Different types of enum definitions | OpenAPI callbacks |
|
|
323
|
+
| Paths inheritance, comments (descriptions), nullable, `["<TYPE>", null]` | OpenAPI webhooks |
|
|
324
324
|
| Getting documents from remote locations or as path reference (local file) | |
|
|
325
325
|
| Grouping endpoints by tags + handle gracefully duplicate operation ids | |
|
|
326
326
|
|
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,
|
|
@@ -84,10 +84,7 @@ function prepareClient(
|
|
|
84
84
|
* @param options
|
|
85
85
|
* @returns List of operations prepared for client generation
|
|
86
86
|
*/
|
|
87
|
-
function prepareOperations(
|
|
88
|
-
operations,
|
|
89
|
-
options
|
|
90
|
-
) {
|
|
87
|
+
function prepareOperations(operations, options) {
|
|
91
88
|
let ops = fixDuplicateOperations(operations);
|
|
92
89
|
|
|
93
90
|
if (options.skipDeprecated) {
|
package/dist/gen/genTypes.js
CHANGED
|
@@ -201,12 +201,7 @@ function renderTypeProp(
|
|
|
201
201
|
lines.push(_jsDocs.renderComment.call(void 0, _nullishCoalesce(definition.description, () => ( definition.title))));
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
const isNullableAsOptional =
|
|
206
|
-
options.nullableStrategy === 'nullableAsOptional' &&
|
|
207
|
-
!('$ref' in definition) &&
|
|
208
|
-
(definition ).nullable === true;
|
|
209
|
-
const isOptional = !required || isNullableAsOptional;
|
|
204
|
+
const isOptional = !required || isNullableAsOptional(definition, options);
|
|
210
205
|
const optionalMark = isOptional ? '?' : '';
|
|
211
206
|
// If prop name is not a valid identifier, we need to wrap it in quotes.
|
|
212
207
|
// We can't use getSafeIdentifier here because it will affect the data model.
|
|
@@ -216,6 +211,26 @@ function renderTypeProp(
|
|
|
216
211
|
return lines.join('\n');
|
|
217
212
|
}
|
|
218
213
|
|
|
214
|
+
/**
|
|
215
|
+
* When nullableAsOptional strategy is set, nullable properties are treated as optional.
|
|
216
|
+
* Supports both OA3.0 (nullable: true) and OA3.1 (type: ["string", "null"]).
|
|
217
|
+
* @returns True if the property should be treated as optional, false otherwise.
|
|
218
|
+
*/
|
|
219
|
+
function isNullableAsOptional(
|
|
220
|
+
definition,
|
|
221
|
+
options
|
|
222
|
+
) {
|
|
223
|
+
if ('$ref' in definition) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
options.nullableStrategy === 'nullableAsOptional' &&
|
|
229
|
+
(definition.nullable === true ||
|
|
230
|
+
(Array.isArray(definition.type) && definition.type.includes('null')))
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
219
234
|
function getMergedCompositeObjects(schema) {
|
|
220
235
|
const { allOf, oneOf, anyOf, ...safeSchema } = schema;
|
|
221
236
|
const composite = allOf || oneOf || anyOf || [];
|
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
|
|
|
@@ -52,16 +63,69 @@ var _utils = require('../utils');
|
|
|
52
63
|
return 'null';
|
|
53
64
|
}
|
|
54
65
|
|
|
66
|
+
// OpenAPI 3.1 nullable: type is an array containing 'null', e.g. ["string", "null"]
|
|
67
|
+
if (Array.isArray(schema.type)) {
|
|
68
|
+
return getTypeFromOA31ArrayType(schema , options);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// OpenAPI 3.0 nullable: nullable: true
|
|
55
72
|
const isNullable = 'nullable' in schema && schema.nullable === true;
|
|
56
|
-
const
|
|
57
|
-
const isNullableSuffix = isNullable && strategy === 'include' ? ' | null' : '';
|
|
73
|
+
const isNullableSuffix = isNullable && options.nullableStrategy === 'include' ? ' | null' : '';
|
|
58
74
|
const type = getTypeFromSchemaInternal(schema, options);
|
|
59
75
|
|
|
60
76
|
if (isNullableSuffix && type.endsWith('| null')) {
|
|
61
77
|
return type;
|
|
62
78
|
}
|
|
63
79
|
return type + isNullableSuffix;
|
|
64
|
-
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Handles OpenAPI 3.1 schemas where `type` is an array (e.g. `["string", "null"]`).
|
|
84
|
+
* The presence of `"null"` in the array is the OA3.1 way of marking a field as nullable.
|
|
85
|
+
* Respects `nullableStrategy` the same way as OA3.0 `nullable: true`.
|
|
86
|
+
*/
|
|
87
|
+
function getTypeFromOA31ArrayType(schema, options) {
|
|
88
|
+
const unknownType = options.preferAny ? 'any' : 'unknown';
|
|
89
|
+
const types = schema.type ;
|
|
90
|
+
const isNullable = types.includes('null');
|
|
91
|
+
const nonNullTypes = types.filter((t) => t !== 'null');
|
|
92
|
+
|
|
93
|
+
// Build the base type from the non-null types
|
|
94
|
+
let baseType;
|
|
95
|
+
if (nonNullTypes.length === 0) {
|
|
96
|
+
baseType = 'null';
|
|
97
|
+
} else if (nonNullTypes.length === 1) {
|
|
98
|
+
// Synthesize a single-type schema to reuse existing resolution logic
|
|
99
|
+
const singleTypeSchema = { ...schema, type: nonNullTypes[0] } ;
|
|
100
|
+
baseType = getTypeFromSchemaInternal(singleTypeSchema, options);
|
|
101
|
+
} else {
|
|
102
|
+
// Multiple non-null types — resolve each independently and join as a union
|
|
103
|
+
baseType = nonNullTypes
|
|
104
|
+
.map((t) => getTypeFromSchemaInternal({ ...schema, type: t } , options))
|
|
105
|
+
.join(' | ');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!isNullable) {
|
|
109
|
+
return baseType || unknownType;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// All types were 'null' — just return 'null' regardless of strategy
|
|
113
|
+
if (nonNullTypes.length === 0) {
|
|
114
|
+
return 'null';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (options.nullableStrategy === 'include') {
|
|
118
|
+
// We don't want multiple nulls in the type string
|
|
119
|
+
if (baseType.endsWith('| null')) {
|
|
120
|
+
return baseType;
|
|
121
|
+
}
|
|
122
|
+
return `${baseType} | null`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 'ignore' and 'nullableAsOptional' — null is stripped from the type itself
|
|
126
|
+
// (for nullableAsOptional, the optionality is applied at the property level in genTypes.ts)
|
|
127
|
+
return baseType || unknownType;
|
|
128
|
+
}
|
|
65
129
|
|
|
66
130
|
function getTypeFromSchemaInternal(
|
|
67
131
|
schema,
|
|
@@ -104,13 +168,22 @@ function getNestedTypeFromSchema(
|
|
|
104
168
|
schema,
|
|
105
169
|
options
|
|
106
170
|
) {
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
'nullable' in schema && schema.nullable === true &&
|
|
110
|
-
|
|
111
|
-
|
|
171
|
+
// OA3.0 nullable: true
|
|
172
|
+
const isOA30NullableAndActive =
|
|
173
|
+
'nullable' in schema && schema.nullable === true && options.nullableStrategy === 'include';
|
|
174
|
+
|
|
175
|
+
// OA3.1 nullable: type array containing 'null'
|
|
176
|
+
const isOA31NullableAndActive =
|
|
177
|
+
'type' in schema &&
|
|
178
|
+
Array.isArray(schema.type) &&
|
|
179
|
+
schema.type.includes('null') &&
|
|
180
|
+
options.nullableStrategy === 'include';
|
|
181
|
+
|
|
182
|
+
if (isOA30NullableAndActive || isOA31NullableAndActive || ('enum' in schema && schema.enum)) {
|
|
183
|
+
return `(${getTypeFromSchemaResolved(schema, options)})`;
|
|
112
184
|
}
|
|
113
|
-
|
|
185
|
+
|
|
186
|
+
return getTypeFromSchemaResolved(schema, options);
|
|
114
187
|
}
|
|
115
188
|
|
|
116
189
|
/**
|
|
@@ -126,7 +199,7 @@ function getTypeFromObject(
|
|
|
126
199
|
if (schema.additionalProperties) {
|
|
127
200
|
const extraProps = schema.additionalProperties;
|
|
128
201
|
return `{ [key: string]: ${
|
|
129
|
-
extraProps === true ? 'any' :
|
|
202
|
+
extraProps === true ? 'any' : getTypeFromSchemaResolved(extraProps, options)
|
|
130
203
|
} }`;
|
|
131
204
|
}
|
|
132
205
|
|
|
@@ -140,7 +213,7 @@ function getTypeFromObject(
|
|
|
140
213
|
const isRequired = required.includes(prop);
|
|
141
214
|
const safePropName = _utils.escapePropName.call(void 0, prop);
|
|
142
215
|
result.push(
|
|
143
|
-
`${safePropName}${isRequired ? '' : '?'}: ${
|
|
216
|
+
`${safePropName}${isRequired ? '' : '?'}: ${getTypeFromSchemaResolved(propDefinition, options)};`
|
|
144
217
|
);
|
|
145
218
|
}
|
|
146
219
|
|
|
@@ -156,7 +229,9 @@ function getTypeFromObject(
|
|
|
156
229
|
function getTypeFromComposites(schema, options) {
|
|
157
230
|
const composite = schema.allOf || schema.oneOf || schema.anyOf;
|
|
158
231
|
|
|
159
|
-
return composite
|
|
232
|
+
return composite
|
|
233
|
+
.map((s) => getTypeFromSchemaResolved(s, options))
|
|
234
|
+
.join(schema.allOf ? ' & ' : ' | ');
|
|
160
235
|
}
|
|
161
236
|
|
|
162
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
|
**/
|