swaggie 1.7.1 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -4
- package/dist/cli.js +17 -1
- package/dist/gen/genTypes.js +75 -24
- package/dist/gen/index.js +8 -2
- package/dist/index.js +18 -2
- package/dist/swagger/typesExtractor.js +84 -10
- package/dist/types.d.ts +15 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,7 +78,10 @@ swaggie -s https://petstore3.swagger.io/api/v3/openapi.json -o ./client/petstore
|
|
|
78
78
|
-o, --out <filePath> Output file path (omit to print to stdout)
|
|
79
79
|
-b, --baseUrl <string> Default base URL for the generated client (default: "")
|
|
80
80
|
-t, --template <string> Template to use for code generation (default: "axios")
|
|
81
|
-
|
|
81
|
+
-m, --mode <mode> Generation mode: "full" or "schemas" (default: "full")
|
|
82
|
+
-d, --schemaStyle <style> Schema object style: "interface" or "type" (default: "interface")
|
|
83
|
+
--enumStyle <style> Enum style for plain string enums: "union" or "enum" (default: "union")
|
|
84
|
+
--preferAny Use "any" instead of "unknown" for untyped values (default: false)
|
|
82
85
|
--skipDeprecated Exclude deprecated operations from the output (default: false)
|
|
83
86
|
--servicePrefix Prefix for service names — useful when generating multiple APIs
|
|
84
87
|
--allowDots Use dot notation to serialize nested object query params
|
|
@@ -119,6 +122,9 @@ swaggie -c swaggie.config.json
|
|
|
119
122
|
"servicePrefix": "",
|
|
120
123
|
"dateFormat": "Date",
|
|
121
124
|
"nullableStrategy": "ignore",
|
|
125
|
+
"generationMode": "full",
|
|
126
|
+
"schemaDeclarationStyle": "interface",
|
|
127
|
+
"enumDeclarationStyle": "union",
|
|
122
128
|
"queryParamsSerialization": {
|
|
123
129
|
"arrayFormat": "repeat",
|
|
124
130
|
"allowDots": true
|
|
@@ -255,6 +261,34 @@ OpenAPI 3.0 allows fields to be marked as `nullable: true`. Swaggie gives you th
|
|
|
255
261
|
// nullableStrategy: "nullableAsOptional" → tenant?: string;
|
|
256
262
|
```
|
|
257
263
|
|
|
264
|
+
### Generation Mode
|
|
265
|
+
|
|
266
|
+
Use `generationMode` (or CLI `--mode`) to control what gets generated:
|
|
267
|
+
|
|
268
|
+
| Value | Behavior |
|
|
269
|
+
| ----------- | ------------------------------------------------------------------------------ |
|
|
270
|
+
| `"full"` | Generates full client code + used schemas (default, existing behavior) |
|
|
271
|
+
| `"schemas"`| Generates only schemas and includes all component schemas by default |
|
|
272
|
+
|
|
273
|
+
`"schemas"` mode intentionally does not run the used-schema heuristic.
|
|
274
|
+
|
|
275
|
+
### Schema Declaration Style
|
|
276
|
+
|
|
277
|
+
Use `schemaDeclarationStyle` (or CLI `--schemaStyle`) to control object schema output:
|
|
278
|
+
|
|
279
|
+
| Value | Behavior |
|
|
280
|
+
| ------------- | ------------------------------------------------------------------------ |
|
|
281
|
+
| `"interface"`| `export interface Tag { ... }` (default) |
|
|
282
|
+
| `"type"` | `export type Tag = { ... };` |
|
|
283
|
+
|
|
284
|
+
### Enum Declaration Style
|
|
285
|
+
|
|
286
|
+
Use `enumDeclarationStyle` (or CLI `--enumStyle`) for plain string enums:
|
|
287
|
+
- `"union"` (default): `export type Status = "active" | "disabled";`
|
|
288
|
+
- `"enum"`: `export enum Status { active = "active", disabled = "disabled" }`
|
|
289
|
+
|
|
290
|
+
Note: this applies only to plain string enums. Non-string enums are still emitted as union types.
|
|
291
|
+
|
|
258
292
|
### Parameter Modifiers
|
|
259
293
|
|
|
260
294
|
Sometimes an API spec marks a parameter as required, but your client handles it in an interceptor and you don't want it cluttering every method signature. Parameter modifiers let you override this globally without touching the spec.
|
|
@@ -336,12 +370,12 @@ Swaggie only needs a JSON or YAML OpenAPI spec file — it does not require a ru
|
|
|
336
370
|
| Supported | Not Supported |
|
|
337
371
|
| ------------------------------------------------------------------------------ | ---------------------------------------------------- |
|
|
338
372
|
| OpenAPI 3.0, 3.1, 3.2 | Swagger / OpenAPI 2.0 |
|
|
339
|
-
| `allOf`, `oneOf`, `anyOf`, `$ref
|
|
373
|
+
| `allOf`, `oneOf`, `anyOf`, `$ref`, external $refs | `not` keyword |
|
|
340
374
|
| Spec formats: JSON, YAML | Very complex query parameter structures |
|
|
341
375
|
| Extensions: `x-position`, `x-name`, `x-enumNames`, `x-enum-varnames` | Multiple response types (only the first is used) |
|
|
342
376
|
| Content types: JSON, plain text, multipart/form-data | Multiple request body types (only the first is used) |
|
|
343
|
-
| Content types: `application/x-www-form-urlencoded`, `application/octet-stream` |
|
|
344
|
-
| Various enum definition styles
|
|
377
|
+
| Content types: `application/x-www-form-urlencoded`, `application/octet-stream` | OpenAPI callbacks and webhooks |
|
|
378
|
+
| Various enum definition styles, support for additionalProperties | |
|
|
345
379
|
| Nullable types, path inheritance, JSDoc descriptions | |
|
|
346
380
|
| Remote URLs and local file paths as spec source | |
|
|
347
381
|
| Grouping by tags, graceful handling of duplicate operation IDs | |
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,19 @@ const arrayFormatOption = new (0, _commander.Option)(
|
|
|
15
15
|
|
|
16
16
|
const packageJson = readPackageJson();
|
|
17
17
|
|
|
18
|
+
const modeOption = new (0, _commander.Option)('-m, --mode <mode>', 'Generation mode').choices([
|
|
19
|
+
'full',
|
|
20
|
+
'schemas',
|
|
21
|
+
]);
|
|
22
|
+
const schemaStyleOption = new (0, _commander.Option)(
|
|
23
|
+
'-d, --schemaStyle <style>',
|
|
24
|
+
'Schema object declaration style'
|
|
25
|
+
).choices(['interface', 'type']);
|
|
26
|
+
const enumStyleOption = new (0, _commander.Option)(
|
|
27
|
+
'--enumStyle <style>',
|
|
28
|
+
'Enum declaration style for plain string enums'
|
|
29
|
+
).choices(['union', 'enum']);
|
|
30
|
+
|
|
18
31
|
const program = new (0, _commander.Command)();
|
|
19
32
|
program
|
|
20
33
|
.version(packageJson.version)
|
|
@@ -53,7 +66,10 @@ program
|
|
|
53
66
|
'--allowDots <bool>',
|
|
54
67
|
'Determines if dots should be used for serialization object properties'
|
|
55
68
|
)
|
|
56
|
-
.addOption(arrayFormatOption)
|
|
69
|
+
.addOption(arrayFormatOption)
|
|
70
|
+
.addOption(modeOption)
|
|
71
|
+
.addOption(schemaStyleOption)
|
|
72
|
+
.addOption(enumStyleOption);
|
|
57
73
|
|
|
58
74
|
program.parse(process.argv);
|
|
59
75
|
|
package/dist/gen/genTypes.js
CHANGED
|
@@ -46,6 +46,7 @@ function renderSchema(
|
|
|
46
46
|
schema,
|
|
47
47
|
options
|
|
48
48
|
) {
|
|
49
|
+
const useTypeAliases = options.schemaDeclarationStyle === 'type';
|
|
49
50
|
const safeName = _swagger.getSafeIdentifier.call(void 0, name);
|
|
50
51
|
if (!safeName) {
|
|
51
52
|
console.warn(`Skipping schema ${name} because it is not a valid identifier`);
|
|
@@ -69,7 +70,7 @@ function renderSchema(
|
|
|
69
70
|
return result.join('\n');
|
|
70
71
|
}
|
|
71
72
|
if ('enum' in schema) {
|
|
72
|
-
result.push(renderEnumType(safeName, schema));
|
|
73
|
+
result.push(renderEnumType(safeName, schema, options));
|
|
73
74
|
return result.join('\n');
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -81,13 +82,28 @@ function renderSchema(
|
|
|
81
82
|
|
|
82
83
|
if ('allOf' in schema) {
|
|
83
84
|
const types = _swagger.getRefCompositeTypes.call(void 0, schema);
|
|
85
|
+
const mergedSchema = getMergedCompositeObjects(schema);
|
|
86
|
+
const objectType = _swagger.getTypeFromSchema.call(void 0, mergedSchema, options);
|
|
87
|
+
const objectContents = generateObjectTypeContents(mergedSchema, options);
|
|
88
|
+
const hasAdditionalProperties = !!mergedSchema.additionalProperties;
|
|
89
|
+
|
|
90
|
+
if (hasAdditionalProperties) {
|
|
91
|
+
const compositeTypes = [...types, objectType].join(' & ');
|
|
92
|
+
result.push(`export type ${safeName} = ${compositeTypes};`);
|
|
93
|
+
return `${result.join('\n')}\n`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (useTypeAliases) {
|
|
97
|
+
const compositeTypes = [...types, `{${objectContents ? `\n${objectContents}\n` : ''}}`].join(' & ');
|
|
98
|
+
result.push(`export type ${safeName} = ${compositeTypes};`);
|
|
99
|
+
return `${result.join('\n')}\n`;
|
|
100
|
+
}
|
|
101
|
+
|
|
84
102
|
const extensions = types ? `extends ${types.join(', ')} ` : '';
|
|
85
103
|
result.push(`export interface ${safeName} ${extensions}{`);
|
|
86
|
-
|
|
87
|
-
const mergedSchema = getMergedCompositeObjects(schema);
|
|
88
|
-
result.push(generateObjectTypeContents(mergedSchema, options));
|
|
104
|
+
result.push(objectContents);
|
|
89
105
|
} else if ('oneOf' in schema || 'anyOf' in schema) {
|
|
90
|
-
const typeDefinition =
|
|
106
|
+
const typeDefinition = _swagger.getTypeFromSchema.call(void 0, schema, options);
|
|
91
107
|
result.push(`export type ${safeName} = ${typeDefinition};`);
|
|
92
108
|
|
|
93
109
|
return `${result.join('\n')}\n`;
|
|
@@ -97,26 +113,26 @@ function renderSchema(
|
|
|
97
113
|
result.push(`export type ${safeName} = ${generateItemsType(schema.items, options)}[];`);
|
|
98
114
|
return result.join('\n');
|
|
99
115
|
} else {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
116
|
+
const objectType = _swagger.getTypeFromSchema.call(void 0, schema, options);
|
|
117
|
+
const hasAdditionalProperties = !!schema.additionalProperties;
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
119
|
+
const objectContents = generateObjectTypeContents(schema, options);
|
|
120
|
+
if (hasAdditionalProperties) {
|
|
121
|
+
result.push(`export type ${safeName} = ${objectType};`);
|
|
122
|
+
return `${result.join('\n')}\n`;
|
|
123
|
+
}
|
|
106
124
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!composite) {
|
|
116
|
-
return '';
|
|
125
|
+
if (useTypeAliases) {
|
|
126
|
+
result.push(`export type ${safeName} = {`);
|
|
127
|
+
result.push(objectContents);
|
|
128
|
+
return `${result.join('\n')}\n};\n`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
result.push(`export interface ${safeName} {`);
|
|
132
|
+
result.push(objectContents);
|
|
117
133
|
}
|
|
118
134
|
|
|
119
|
-
return
|
|
135
|
+
return `${result.join('\n')}\n}\n`;
|
|
120
136
|
}
|
|
121
137
|
|
|
122
138
|
/**
|
|
@@ -167,11 +183,36 @@ function renderExtendedEnumType(name, def) {
|
|
|
167
183
|
/**
|
|
168
184
|
* Render simple enum types (just a union of values)
|
|
169
185
|
*/
|
|
170
|
-
function renderEnumType(name, def) {
|
|
186
|
+
function renderEnumType(name, def, options) {
|
|
187
|
+
if (options.enumDeclarationStyle === 'enum' && shouldRenderStringEnumDeclaration(def)) {
|
|
188
|
+
return renderStringEnumDeclaration(name, def);
|
|
189
|
+
}
|
|
190
|
+
|
|
171
191
|
const values = def.enum.map((v) => (typeof v === 'number' ? v : `"${v}"`)).join(' | ');
|
|
172
192
|
return `export type ${name} = ${values};\n`;
|
|
173
193
|
}
|
|
174
194
|
|
|
195
|
+
function shouldRenderStringEnumDeclaration(def)
|
|
196
|
+
|
|
197
|
+
{
|
|
198
|
+
return (
|
|
199
|
+
def.type === 'string' &&
|
|
200
|
+
Array.isArray(def.enum) &&
|
|
201
|
+
def.enum.every((value) => typeof value === 'string')
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function renderStringEnumDeclaration(name, def) {
|
|
206
|
+
let res = `export enum ${name} {\n`;
|
|
207
|
+
for (let index = 0; index < def.enum.length; index++) {
|
|
208
|
+
const value = def.enum[index];
|
|
209
|
+
const memberName = _nullishCoalesce(_utils.escapePropName.call(void 0, value), () => ( `VALUE_${index}`));
|
|
210
|
+
res += ` ${memberName} = ${JSON.stringify(value)},\n`;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return `${res}}\n`;
|
|
214
|
+
}
|
|
215
|
+
|
|
175
216
|
/**
|
|
176
217
|
* OpenApi 3.1 introduced a new way to define enums that we support here.
|
|
177
218
|
*/
|
|
@@ -198,7 +239,10 @@ function renderTypeProp(
|
|
|
198
239
|
const type = _swagger.getTypeFromSchema.call(void 0, definition, options);
|
|
199
240
|
|
|
200
241
|
if ('description' in definition || 'title' in definition) {
|
|
201
|
-
|
|
242
|
+
const renderedComment = _jsDocs.renderComment.call(void 0, _nullishCoalesce(definition.description, () => ( definition.title)));
|
|
243
|
+
if (renderedComment) {
|
|
244
|
+
lines.push(indentComment(renderedComment, ' '));
|
|
245
|
+
}
|
|
202
246
|
}
|
|
203
247
|
|
|
204
248
|
const isOptional = !required || isNullableAsOptional(definition, options);
|
|
@@ -211,6 +255,13 @@ function renderTypeProp(
|
|
|
211
255
|
return lines.join('\n');
|
|
212
256
|
}
|
|
213
257
|
|
|
258
|
+
function indentComment(comment, indent) {
|
|
259
|
+
return comment
|
|
260
|
+
.split('\n')
|
|
261
|
+
.map((line) => `${indent}${line}`)
|
|
262
|
+
.join('\n');
|
|
263
|
+
}
|
|
264
|
+
|
|
214
265
|
/**
|
|
215
266
|
* When nullableAsOptional strategy is set, nullable properties are treated as optional.
|
|
216
267
|
* Supports both OA3.0 (nullable: true) and OA3.1 (type: ["string", "null"]).
|
|
@@ -242,7 +293,7 @@ function getMergedCompositeObjects(schema) {
|
|
|
242
293
|
subSchemas.push(safeSchema);
|
|
243
294
|
}
|
|
244
295
|
|
|
245
|
-
return deepMerge({}, ...subSchemas);
|
|
296
|
+
return deepMerge({}, ...subSchemas) ;
|
|
246
297
|
}
|
|
247
298
|
|
|
248
299
|
function isObject(item) {
|
package/dist/gen/index.js
CHANGED
|
@@ -9,8 +9,14 @@ var _utils = require('../utils');
|
|
|
9
9
|
spec,
|
|
10
10
|
options
|
|
11
11
|
) {
|
|
12
|
-
let fileContents =
|
|
13
|
-
|
|
12
|
+
let fileContents = '';
|
|
13
|
+
|
|
14
|
+
if (options.generationMode === 'schemas') {
|
|
15
|
+
fileContents = _genTypes2.default.call(void 0, spec, options, false);
|
|
16
|
+
} else {
|
|
17
|
+
fileContents = await _genOperations2.default.call(void 0, spec, options);
|
|
18
|
+
fileContents += _genTypes2.default.call(void 0, spec, options);
|
|
19
|
+
}
|
|
14
20
|
|
|
15
21
|
if (options.out) {
|
|
16
22
|
const destFile = _utils.prepareOutputFilename.call(void 0, options.out);
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,9 @@ function verifyOptions(options) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function gen(spec, options) {
|
|
37
|
-
|
|
37
|
+
if (options.generationMode === 'full') {
|
|
38
|
+
_utils.loadAllTemplateFiles.call(void 0, options.template);
|
|
39
|
+
}
|
|
38
40
|
|
|
39
41
|
return _gen2.default.call(void 0, spec, options);
|
|
40
42
|
}
|
|
@@ -76,7 +78,16 @@ function readFile(filePath) {
|
|
|
76
78
|
* object where every defaultable field is guaranteed to be present.
|
|
77
79
|
*/
|
|
78
80
|
function prepareAppOptions(cliOpts) {
|
|
79
|
-
const {
|
|
81
|
+
const {
|
|
82
|
+
allowDots,
|
|
83
|
+
arrayFormat,
|
|
84
|
+
mode,
|
|
85
|
+
schemaStyle,
|
|
86
|
+
enumStyle,
|
|
87
|
+
template,
|
|
88
|
+
queryParamsSerialization = {},
|
|
89
|
+
...rest
|
|
90
|
+
} = cliOpts;
|
|
80
91
|
const mergedQueryParamsSerialization = {
|
|
81
92
|
..._swagger.APP_DEFAULTS.queryParamsSerialization,
|
|
82
93
|
...Object.fromEntries(
|
|
@@ -91,6 +102,11 @@ function readFile(filePath) {
|
|
|
91
102
|
template: _nullishCoalesce(template, () => ( _swagger.APP_DEFAULTS.template)),
|
|
92
103
|
servicePrefix: _nullishCoalesce(rest.servicePrefix, () => ( _swagger.APP_DEFAULTS.servicePrefix)),
|
|
93
104
|
nullableStrategy: _nullishCoalesce(rest.nullableStrategy, () => ( _swagger.APP_DEFAULTS.nullableStrategy)),
|
|
105
|
+
generationMode: _nullishCoalesce(_nullishCoalesce(mode, () => ( rest.generationMode)), () => ( _swagger.APP_DEFAULTS.generationMode)),
|
|
106
|
+
schemaDeclarationStyle:
|
|
107
|
+
_nullishCoalesce(_nullishCoalesce(schemaStyle, () => ( rest.schemaDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.schemaDeclarationStyle)),
|
|
108
|
+
enumDeclarationStyle:
|
|
109
|
+
_nullishCoalesce(_nullishCoalesce(enumStyle, () => ( rest.enumDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.enumDeclarationStyle)),
|
|
94
110
|
queryParamsSerialization: mergedQueryParamsSerialization,
|
|
95
111
|
};
|
|
96
112
|
} exports.prepareAppOptions = prepareAppOptions;
|
|
@@ -192,20 +192,16 @@ function getNestedTypeFromSchema(
|
|
|
192
192
|
*/
|
|
193
193
|
function getTypeFromObject(
|
|
194
194
|
schema,
|
|
195
|
-
options
|
|
195
|
+
options,
|
|
196
|
+
requiredOverride
|
|
196
197
|
) {
|
|
197
198
|
const unknownType = options.preferAny ? 'any' : 'unknown';
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const extraProps = schema.additionalProperties;
|
|
201
|
-
return `{ [key: string]: ${
|
|
202
|
-
extraProps === true ? 'any' : getTypeFromSchemaResolved(extraProps, options)
|
|
203
|
-
} }`;
|
|
204
|
-
}
|
|
199
|
+
let objectWithNamedPropsType = '';
|
|
200
|
+
let objectWithIndexSignatureType = '';
|
|
205
201
|
|
|
206
202
|
if (schema.properties) {
|
|
207
203
|
const props = Object.keys(schema.properties);
|
|
208
|
-
const required = schema.required
|
|
204
|
+
const required = _nullishCoalesce(_nullishCoalesce(requiredOverride, () => ( schema.required)), () => ( []));
|
|
209
205
|
const result = [];
|
|
210
206
|
|
|
211
207
|
for (const prop of props) {
|
|
@@ -217,7 +213,26 @@ function getTypeFromObject(
|
|
|
217
213
|
);
|
|
218
214
|
}
|
|
219
215
|
|
|
220
|
-
|
|
216
|
+
objectWithNamedPropsType = `{ ${result.join('\n')} }`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (schema.additionalProperties) {
|
|
220
|
+
const extraProps = schema.additionalProperties;
|
|
221
|
+
objectWithIndexSignatureType = `{ [key: string]: ${
|
|
222
|
+
extraProps === true ? 'any' : getTypeFromSchemaResolved(extraProps, options)
|
|
223
|
+
} }`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (objectWithNamedPropsType && objectWithIndexSignatureType) {
|
|
227
|
+
return `${objectWithNamedPropsType} & ${objectWithIndexSignatureType}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (objectWithNamedPropsType) {
|
|
231
|
+
return objectWithNamedPropsType;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (objectWithIndexSignatureType) {
|
|
235
|
+
return objectWithIndexSignatureType;
|
|
221
236
|
}
|
|
222
237
|
|
|
223
238
|
return unknownType;
|
|
@@ -229,11 +244,64 @@ function getTypeFromObject(
|
|
|
229
244
|
function getTypeFromComposites(schema, options) {
|
|
230
245
|
const composite = schema.allOf || schema.oneOf || schema.anyOf;
|
|
231
246
|
|
|
247
|
+
if (!composite) {
|
|
248
|
+
return options.preferAny ? 'any' : 'unknown';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const isUnionComposite = !!schema.oneOf || !!schema.anyOf;
|
|
252
|
+
const hasParentObjectShape = !!schema.properties || !!schema.additionalProperties;
|
|
253
|
+
|
|
254
|
+
if (isUnionComposite && hasParentObjectShape) {
|
|
255
|
+
const fallbackType = options.preferAny ? 'any' : 'unknown';
|
|
256
|
+
const parentObjectType = getTypeFromObject(schema, options);
|
|
257
|
+
const parentRequired = schema.required || [];
|
|
258
|
+
const parentPropSet = new Set(Object.keys(schema.properties || {}));
|
|
259
|
+
|
|
260
|
+
return composite
|
|
261
|
+
.map((subSchema) => {
|
|
262
|
+
if (!('$ref' in subSchema) && isRequiredOnlyCompositeBranch(subSchema)) {
|
|
263
|
+
const branchRequired = subSchema.required || [];
|
|
264
|
+
const validRequired = branchRequired.filter((name) => {
|
|
265
|
+
const isKnown = parentPropSet.has(name);
|
|
266
|
+
if (!isKnown) {
|
|
267
|
+
console.warn(
|
|
268
|
+
`Composite required key '${name}' is not present in schema properties and will be ignored.`
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
return isKnown;
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
return getTypeFromObject(schema, options, Array.from(new Set([...parentRequired, ...validRequired])));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const subType = getTypeFromSchemaResolved(subSchema, options);
|
|
278
|
+
if (subType === fallbackType) {
|
|
279
|
+
return parentObjectType;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return `${parentObjectType} & ${subType}`;
|
|
283
|
+
})
|
|
284
|
+
.join(' | ');
|
|
285
|
+
}
|
|
286
|
+
|
|
232
287
|
return composite
|
|
233
288
|
.map((s) => getTypeFromSchemaResolved(s, options))
|
|
234
289
|
.join(schema.allOf ? ' & ' : ' | ');
|
|
235
290
|
}
|
|
236
291
|
|
|
292
|
+
function isRequiredOnlyCompositeBranch(schema) {
|
|
293
|
+
return (
|
|
294
|
+
Array.isArray(schema.required) &&
|
|
295
|
+
!schema.type &&
|
|
296
|
+
!schema.properties &&
|
|
297
|
+
!schema.additionalProperties &&
|
|
298
|
+
!schema.allOf &&
|
|
299
|
+
!schema.oneOf &&
|
|
300
|
+
!schema.anyOf &&
|
|
301
|
+
!schema.enum
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
237
305
|
/**
|
|
238
306
|
* Escapes name so it can be used as a valid identifier in the generated code.
|
|
239
307
|
* Component names can contain certain characters that are not allowed in identifiers.
|
|
@@ -262,6 +330,9 @@ function getTypeFromComposites(schema, options) {
|
|
|
262
330
|
template: 'axios',
|
|
263
331
|
servicePrefix: '',
|
|
264
332
|
nullableStrategy: 'ignore',
|
|
333
|
+
generationMode: 'full',
|
|
334
|
+
schemaDeclarationStyle: 'interface',
|
|
335
|
+
enumDeclarationStyle: 'union',
|
|
265
336
|
queryParamsSerialization: {
|
|
266
337
|
allowDots: true,
|
|
267
338
|
arrayFormat: 'repeat',
|
|
@@ -279,6 +350,9 @@ function getTypeFromComposites(schema, options) {
|
|
|
279
350
|
template: _nullishCoalesce(opts.template, () => ( exports.APP_DEFAULTS.template)),
|
|
280
351
|
servicePrefix: _nullishCoalesce(opts.servicePrefix, () => ( exports.APP_DEFAULTS.servicePrefix)),
|
|
281
352
|
nullableStrategy: _nullishCoalesce(opts.nullableStrategy, () => ( exports.APP_DEFAULTS.nullableStrategy)),
|
|
353
|
+
generationMode: _nullishCoalesce(opts.generationMode, () => ( exports.APP_DEFAULTS.generationMode)),
|
|
354
|
+
schemaDeclarationStyle: _nullishCoalesce(opts.schemaDeclarationStyle, () => ( exports.APP_DEFAULTS.schemaDeclarationStyle)),
|
|
355
|
+
enumDeclarationStyle: _nullishCoalesce(opts.enumDeclarationStyle, () => ( exports.APP_DEFAULTS.enumDeclarationStyle)),
|
|
282
356
|
queryParamsSerialization: {
|
|
283
357
|
...exports.APP_DEFAULTS.queryParamsSerialization,
|
|
284
358
|
...opts.queryParamsSerialization,
|
package/dist/types.d.ts
CHANGED
|
@@ -29,6 +29,12 @@ export interface ClientOptions {
|
|
|
29
29
|
nullableStrategy?: NullableStrategy;
|
|
30
30
|
/** Options for query parameters serialization */
|
|
31
31
|
queryParamsSerialization: QueryParamsSerializationOptions;
|
|
32
|
+
/** Controls whether to generate full client code or only component schemas */
|
|
33
|
+
generationMode?: GenerationMode;
|
|
34
|
+
/** Controls whether object schemas are emitted as interfaces or type aliases */
|
|
35
|
+
schemaDeclarationStyle?: SchemaDeclarationStyle;
|
|
36
|
+
/** Controls whether plain string enums are emitted as unions or TypeScript enums */
|
|
37
|
+
enumDeclarationStyle?: EnumDeclarationStyle;
|
|
32
38
|
/** Offers ability to adjust the OpenAPI spec before it is processed */
|
|
33
39
|
modifiers?: {
|
|
34
40
|
/** Global-level modifiers for parameter with a given name */
|
|
@@ -40,6 +46,9 @@ export interface ClientOptions {
|
|
|
40
46
|
export interface CliOptions extends FullAppOptions {
|
|
41
47
|
allowDots?: boolean;
|
|
42
48
|
arrayFormat?: ArrayFormat;
|
|
49
|
+
mode?: GenerationMode;
|
|
50
|
+
schemaStyle?: SchemaDeclarationStyle;
|
|
51
|
+
enumStyle?: EnumDeclarationStyle;
|
|
43
52
|
}
|
|
44
53
|
export interface FullAppOptions extends ClientOptions {
|
|
45
54
|
/** Path to the configuration file that contains actual config to be used */
|
|
@@ -50,6 +59,9 @@ export type HttpMethod = 'get' | 'put' | 'post' | 'delete' | 'options' | 'head'
|
|
|
50
59
|
export type DateSupport = 'string' | 'Date';
|
|
51
60
|
export type ArrayFormat = 'indices' | 'repeat' | 'brackets';
|
|
52
61
|
export type NullableStrategy = 'include' | 'nullableAsOptional' | 'ignore';
|
|
62
|
+
export type GenerationMode = 'full' | 'schemas';
|
|
63
|
+
export type SchemaDeclarationStyle = 'interface' | 'type';
|
|
64
|
+
export type EnumDeclarationStyle = 'union' | 'enum';
|
|
53
65
|
/**
|
|
54
66
|
* Internal options type used throughout the app after `prepareAppOptions` has run.
|
|
55
67
|
* All fields that have defaults are required here so the rest of the codebase never
|
|
@@ -59,6 +71,9 @@ export interface AppOptions extends ClientOptions {
|
|
|
59
71
|
template: Template;
|
|
60
72
|
servicePrefix: string;
|
|
61
73
|
nullableStrategy: NullableStrategy;
|
|
74
|
+
generationMode: GenerationMode;
|
|
75
|
+
schemaDeclarationStyle: SchemaDeclarationStyle;
|
|
76
|
+
enumDeclarationStyle: EnumDeclarationStyle;
|
|
62
77
|
queryParamsSerialization: {
|
|
63
78
|
allowDots: boolean;
|
|
64
79
|
arrayFormat: ArrayFormat;
|