swaggie 1.8.5 → 1.8.7
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 +28 -11
- package/dist/browser.js +10 -0
- package/dist/cli.js +5 -0
- package/dist/gen/genTypes.js +36 -3
- package/dist/index.js +13 -1
- package/dist/swagger/typesExtractor.js +2 -0
- package/dist/types.d.ts +12 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
Swaggie generates TypeScript client code from an OpenAPI 3 specification. Instead of writing API-fetching code by hand, you point Swaggie at your API spec and it outputs a fully typed, ready-to-use client — helping you catch errors at compile time rather than at runtime.
|
|
14
14
|
|
|
15
|
-
See the [Example section](#example) for a quick demo.
|
|
15
|
+
See the [Example section](#example) for a quick demo, or visit the full documentation at **[yhnavein.github.io/swaggie](https://yhnavein.github.io/swaggie/)** for guides, configuration reference, and an interactive playground.
|
|
16
16
|
|
|
17
17
|
> Inspired by [OpenApi Client](https://github.com/mikestead/openapi-client).
|
|
18
18
|
|
|
@@ -81,6 +81,7 @@ swaggie -s https://petstore3.swagger.io/api/v3/openapi.json -o ./client/petstore
|
|
|
81
81
|
-m, --mode <mode> Generation mode: "full" or "schemas" (default: "full")
|
|
82
82
|
-d, --schemaStyle <style> Schema object style: "interface" or "type" (default: "interface")
|
|
83
83
|
--enumStyle <style> Enum style for plain string enums: "union" or "enum" (default: "union")
|
|
84
|
+
--enumNamesStyle <s> Enum member name casing: "original" or "PascalCase" (default: "original")
|
|
84
85
|
--dateFormat <format> Date handling in schemas: "Date" or "string"
|
|
85
86
|
--nullables <strategy> Nullable handling: "include", "nullableAsOptional", or "ignore"
|
|
86
87
|
--preferAny Use "any" instead of "unknown" for untyped values (default: false)
|
|
@@ -127,6 +128,7 @@ swaggie -c swaggie.config.json
|
|
|
127
128
|
"generationMode": "full",
|
|
128
129
|
"schemaDeclarationStyle": "interface",
|
|
129
130
|
"enumDeclarationStyle": "union",
|
|
131
|
+
"enumNamesStyle": "original",
|
|
130
132
|
"queryParamsSerialization": {
|
|
131
133
|
"arrayFormat": "repeat",
|
|
132
134
|
"allowDots": true
|
|
@@ -291,6 +293,30 @@ Use `enumDeclarationStyle` (or CLI `--enumStyle`) for plain string enums:
|
|
|
291
293
|
|
|
292
294
|
Note: this applies only to plain string enums. Non-string enums are still emitted as union types.
|
|
293
295
|
|
|
296
|
+
### Enum Names Style
|
|
297
|
+
|
|
298
|
+
Use `enumNamesStyle` (or CLI `--enumNamesStyle`) to control the casing of enum member names when `enumDeclarationStyle` is `"enum"`:
|
|
299
|
+
- `"original"` (default): member names are used exactly as they appear in the spec
|
|
300
|
+
- `"PascalCase"`: member names are converted to PascalCase
|
|
301
|
+
|
|
302
|
+
### `x-ts-type` Extension
|
|
303
|
+
|
|
304
|
+
Add `x-ts-type` to any schema in your spec to emit a verbatim TypeScript type string instead of deriving it from the schema definition. This is useful for intersection types, complex mapped types, or any TypeScript construct that cannot be expressed in OpenAPI's type system:
|
|
305
|
+
|
|
306
|
+
```yaml
|
|
307
|
+
ResourceAccess:
|
|
308
|
+
x-ts-type: >-
|
|
309
|
+
{ items?: { [key: string]: Entry } } & { [key: string]: boolean | Entry | undefined }
|
|
310
|
+
type: object # kept for doc/validation purposes
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Swaggie emits exactly:
|
|
314
|
+
```typescript
|
|
315
|
+
export type ResourceAccess = { items?: { [key: string]: Entry } } & { [key: string]: boolean | Entry | undefined };
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
`x-ts-type` takes precedence over all other schema fields, including `$ref`. See the [full documentation](https://yhnavein.github.io/swaggie/guide/advanced#x-ts-type-extension) for more detail.
|
|
319
|
+
|
|
294
320
|
### Parameter Modifiers
|
|
295
321
|
|
|
296
322
|
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.
|
|
@@ -358,15 +384,6 @@ function error(e) {
|
|
|
358
384
|
|
|
359
385
|
---
|
|
360
386
|
|
|
361
|
-
## Server Setup Samples
|
|
362
|
-
|
|
363
|
-
Swaggie only needs a JSON or YAML OpenAPI spec file — it does not require a running server. However, if you want to see how to configure your backend to expose an OpenAPI spec automatically, check out the sample configurations in the `samples/` folder:
|
|
364
|
-
|
|
365
|
-
- [ASP.NET Core + NSwag](./samples/dotnetcore/nswag/README.md)
|
|
366
|
-
- [ASP.NET Core + Swashbuckle](./samples/dotnetcore/swashbuckle/README.md)
|
|
367
|
-
|
|
368
|
-
---
|
|
369
|
-
|
|
370
387
|
## What's Supported
|
|
371
388
|
|
|
372
389
|
| Supported | Not Supported |
|
|
@@ -374,7 +391,7 @@ Swaggie only needs a JSON or YAML OpenAPI spec file — it does not require a ru
|
|
|
374
391
|
| OpenAPI 3.0, 3.1, 3.2 | Swagger / OpenAPI 2.0 |
|
|
375
392
|
| `allOf`, `oneOf`, `anyOf`, `$ref`, external $refs | `not` keyword |
|
|
376
393
|
| Spec formats: JSON, YAML | Very complex query parameter structures |
|
|
377
|
-
| Extensions: `x-position`, `x-name`, `x-enumNames`, `x-enum-varnames`
|
|
394
|
+
| Extensions: `x-position`, `x-name`, `x-enumNames`, `x-enum-varnames`, `x-ts-type` | Multiple response types (only the first is used) |
|
|
378
395
|
| Content types: JSON, plain text, multipart/form-data | Multiple request body types (only the first is used) |
|
|
379
396
|
| Content types: `application/x-www-form-urlencoded`, `application/octet-stream` | OpenAPI callbacks and webhooks |
|
|
380
397
|
| Various enum definition styles, support for additionalProperties | |
|
package/dist/browser.js
CHANGED
|
@@ -72,6 +72,7 @@ async function generateCode(spec, options) {
|
|
|
72
72
|
mode,
|
|
73
73
|
schemaStyle,
|
|
74
74
|
enumStyle,
|
|
75
|
+
enumNamesStyle,
|
|
75
76
|
nullables,
|
|
76
77
|
template,
|
|
77
78
|
queryParamsSerialization = {},
|
|
@@ -96,6 +97,15 @@ async function generateCode(spec, options) {
|
|
|
96
97
|
_nullishCoalesce(_nullishCoalesce(schemaStyle, () => ( rest.schemaDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.schemaDeclarationStyle)),
|
|
97
98
|
enumDeclarationStyle:
|
|
98
99
|
_nullishCoalesce(_nullishCoalesce(enumStyle, () => ( rest.enumDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.enumDeclarationStyle)),
|
|
100
|
+
enumNamesStyle: normalizeEnumNamesStyle(enumNamesStyle),
|
|
99
101
|
queryParamsSerialization: mergedQueryParamsSerialization,
|
|
100
102
|
};
|
|
101
103
|
} exports.prepareAppOptions = prepareAppOptions;
|
|
104
|
+
|
|
105
|
+
function normalizeEnumNamesStyle(value) {
|
|
106
|
+
if (!value) return _swagger.APP_DEFAULTS.enumNamesStyle;
|
|
107
|
+
const lower = value.toLowerCase();
|
|
108
|
+
if (lower === 'pascal' || lower === 'pascalcase') return 'PascalCase';
|
|
109
|
+
if (lower === 'original') return 'original';
|
|
110
|
+
return _swagger.APP_DEFAULTS.enumNamesStyle;
|
|
111
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -27,6 +27,10 @@ const enumStyleOption = new (0, _commander.Option)(
|
|
|
27
27
|
'--enumStyle <style>',
|
|
28
28
|
'Enum declaration style for plain string enums'
|
|
29
29
|
).choices(['union', 'enum']);
|
|
30
|
+
const enumNamesStyleOption = new (0, _commander.Option)(
|
|
31
|
+
'--enumNamesStyle <style>',
|
|
32
|
+
'Controls how enum member names are formatted (only with --enumStyle enum)'
|
|
33
|
+
).choices(['original', 'PascalCase', 'pascal']);
|
|
30
34
|
const dateFormatOption = new (0, _commander.Option)(
|
|
31
35
|
'--dateFormat <format>',
|
|
32
36
|
'How date fields are emitted in generated types'
|
|
@@ -78,6 +82,7 @@ program
|
|
|
78
82
|
.addOption(modeOption)
|
|
79
83
|
.addOption(schemaStyleOption)
|
|
80
84
|
.addOption(enumStyleOption)
|
|
85
|
+
.addOption(enumNamesStyleOption)
|
|
81
86
|
.addOption(dateFormatOption)
|
|
82
87
|
.addOption(nullableStrategyOption);
|
|
83
88
|
|
package/dist/gen/genTypes.js
CHANGED
|
@@ -53,6 +53,18 @@ function renderSchema(
|
|
|
53
53
|
return '';
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// x-ts-type takes precedence over everything, including $ref.
|
|
57
|
+
// When present, emit the literal TypeScript type string verbatim.
|
|
58
|
+
if ('x-ts-type' in schema) {
|
|
59
|
+
const result = [];
|
|
60
|
+
const s = schema ;
|
|
61
|
+
if (_nullishCoalesce(s.description, () => ( s.title))) {
|
|
62
|
+
result.push(_jsDocs.renderComment.call(void 0, _nullishCoalesce(s.description, () => ( s.title))));
|
|
63
|
+
}
|
|
64
|
+
result.push(`export type ${safeName} = ${schema['x-ts-type']};`);
|
|
65
|
+
return result.join('\n');
|
|
66
|
+
}
|
|
67
|
+
|
|
56
68
|
// This is an interesting case, because it is allowed but not likely to be used
|
|
57
69
|
// as it is just a reference to another schema object
|
|
58
70
|
if ('$ref' in schema) {
|
|
@@ -201,7 +213,7 @@ function renderExtendedEnumType(name, def) {
|
|
|
201
213
|
*/
|
|
202
214
|
function renderEnumType(name, def, options) {
|
|
203
215
|
if (options.enumDeclarationStyle === 'enum' && shouldRenderStringEnumDeclaration(def)) {
|
|
204
|
-
return renderStringEnumDeclaration(name, def);
|
|
216
|
+
return renderStringEnumDeclaration(name, def, options);
|
|
205
217
|
}
|
|
206
218
|
|
|
207
219
|
const values = def.enum.map((v) => (typeof v === 'number' ? v : `"${v}"`)).join(' | ');
|
|
@@ -218,17 +230,38 @@ function shouldRenderStringEnumDeclaration(def)
|
|
|
218
230
|
);
|
|
219
231
|
}
|
|
220
232
|
|
|
221
|
-
function renderStringEnumDeclaration(
|
|
233
|
+
function renderStringEnumDeclaration(
|
|
234
|
+
name,
|
|
235
|
+
def,
|
|
236
|
+
options
|
|
237
|
+
) {
|
|
238
|
+
const usePascalCase = options.enumNamesStyle === 'PascalCase';
|
|
222
239
|
let res = `export enum ${name} {\n`;
|
|
223
240
|
for (let index = 0; index < def.enum.length; index++) {
|
|
224
241
|
const value = def.enum[index];
|
|
225
|
-
const
|
|
242
|
+
const rawName = usePascalCase ? toPascalCase(value) : value;
|
|
243
|
+
const memberName = _nullishCoalesce(_utils.escapePropName.call(void 0, rawName), () => ( `VALUE_${index}`));
|
|
226
244
|
res += ` ${memberName} = ${JSON.stringify(value)},\n`;
|
|
227
245
|
}
|
|
228
246
|
|
|
229
247
|
return `${res}}\n`;
|
|
230
248
|
}
|
|
231
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Converts a string to PascalCase.
|
|
252
|
+
* Splits on non-alphanumeric characters (spaces, hyphens, dots, underscores, etc.)
|
|
253
|
+
* and capitalizes the first letter of each segment.
|
|
254
|
+
*
|
|
255
|
+
* Examples: "org name" → "OrgName", "my-value" → "MyValue", "some.thing" → "SomeThing"
|
|
256
|
+
*/
|
|
257
|
+
function toPascalCase(value) {
|
|
258
|
+
return value
|
|
259
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
260
|
+
.filter(Boolean)
|
|
261
|
+
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
262
|
+
.join('');
|
|
263
|
+
}
|
|
264
|
+
|
|
232
265
|
/**
|
|
233
266
|
* OpenApi 3.1 introduced a new way to define enums that we support here.
|
|
234
267
|
*/
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,9 @@ function gen(spec, options) {
|
|
|
41
41
|
return _gen2.default.call(void 0, spec, options);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
async function applyConfigFile(
|
|
44
|
+
async function applyConfigFile(
|
|
45
|
+
options
|
|
46
|
+
) {
|
|
45
47
|
try {
|
|
46
48
|
if (!options.config) {
|
|
47
49
|
return prepareAppOptions(options );
|
|
@@ -84,6 +86,7 @@ function readFile(filePath) {
|
|
|
84
86
|
mode,
|
|
85
87
|
schemaStyle,
|
|
86
88
|
enumStyle,
|
|
89
|
+
enumNamesStyle,
|
|
87
90
|
nullables,
|
|
88
91
|
template,
|
|
89
92
|
queryParamsSerialization = {},
|
|
@@ -108,6 +111,15 @@ function readFile(filePath) {
|
|
|
108
111
|
_nullishCoalesce(_nullishCoalesce(schemaStyle, () => ( rest.schemaDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.schemaDeclarationStyle)),
|
|
109
112
|
enumDeclarationStyle:
|
|
110
113
|
_nullishCoalesce(_nullishCoalesce(enumStyle, () => ( rest.enumDeclarationStyle)), () => ( _swagger.APP_DEFAULTS.enumDeclarationStyle)),
|
|
114
|
+
enumNamesStyle: normalizeEnumNamesStyle(enumNamesStyle),
|
|
111
115
|
queryParamsSerialization: mergedQueryParamsSerialization,
|
|
112
116
|
};
|
|
113
117
|
} exports.prepareAppOptions = prepareAppOptions;
|
|
118
|
+
|
|
119
|
+
function normalizeEnumNamesStyle(value) {
|
|
120
|
+
if (!value) return _swagger.APP_DEFAULTS.enumNamesStyle;
|
|
121
|
+
const lower = value.toLowerCase();
|
|
122
|
+
if (lower === 'pascal' || lower === 'pascalcase') return 'PascalCase';
|
|
123
|
+
if (lower === 'original') return 'original';
|
|
124
|
+
return _swagger.APP_DEFAULTS.enumNamesStyle;
|
|
125
|
+
}
|
|
@@ -375,6 +375,7 @@ function isRequiredOnlyCompositeBranch(schema) {
|
|
|
375
375
|
generationMode: 'full',
|
|
376
376
|
schemaDeclarationStyle: 'interface',
|
|
377
377
|
enumDeclarationStyle: 'union',
|
|
378
|
+
enumNamesStyle: 'original',
|
|
378
379
|
queryParamsSerialization: {
|
|
379
380
|
allowDots: true,
|
|
380
381
|
arrayFormat: 'repeat',
|
|
@@ -395,6 +396,7 @@ function isRequiredOnlyCompositeBranch(schema) {
|
|
|
395
396
|
generationMode: _nullishCoalesce(opts.generationMode, () => ( exports.APP_DEFAULTS.generationMode)),
|
|
396
397
|
schemaDeclarationStyle: _nullishCoalesce(opts.schemaDeclarationStyle, () => ( exports.APP_DEFAULTS.schemaDeclarationStyle)),
|
|
397
398
|
enumDeclarationStyle: _nullishCoalesce(opts.enumDeclarationStyle, () => ( exports.APP_DEFAULTS.enumDeclarationStyle)),
|
|
399
|
+
enumNamesStyle: _nullishCoalesce(opts.enumNamesStyle, () => ( exports.APP_DEFAULTS.enumNamesStyle)),
|
|
398
400
|
queryParamsSerialization: {
|
|
399
401
|
...exports.APP_DEFAULTS.queryParamsSerialization,
|
|
400
402
|
...opts.queryParamsSerialization,
|
package/dist/types.d.ts
CHANGED
|
@@ -35,6 +35,13 @@ export interface ClientOptions {
|
|
|
35
35
|
schemaDeclarationStyle?: SchemaDeclarationStyle;
|
|
36
36
|
/** Controls whether plain string enums are emitted as unions or TypeScript enums */
|
|
37
37
|
enumDeclarationStyle?: EnumDeclarationStyle;
|
|
38
|
+
/**
|
|
39
|
+
* Controls how enum member names are formatted when generating TypeScript `enum` declarations.
|
|
40
|
+
* Only applies when `enumDeclarationStyle` is set to `'enum'`.
|
|
41
|
+
* - `'original'` — use the raw enum value as the member name (e.g. `org name = "org name"`)
|
|
42
|
+
* - `'PascalCase'` — convert values to PascalCase (e.g. `OrgName = "org name"`)
|
|
43
|
+
*/
|
|
44
|
+
enumNamesStyle?: EnumNamesStyle;
|
|
38
45
|
/** Offers ability to adjust the OpenAPI spec before it is processed */
|
|
39
46
|
modifiers?: {
|
|
40
47
|
/** Global-level modifiers for parameter with a given name */
|
|
@@ -43,12 +50,14 @@ export interface ClientOptions {
|
|
|
43
50
|
};
|
|
44
51
|
};
|
|
45
52
|
}
|
|
46
|
-
export interface CliOptions extends FullAppOptions {
|
|
53
|
+
export interface CliOptions extends Omit<FullAppOptions, 'enumNamesStyle'> {
|
|
47
54
|
allowDots?: boolean;
|
|
48
55
|
arrayFormat?: ArrayFormat;
|
|
49
56
|
mode?: GenerationMode;
|
|
50
57
|
schemaStyle?: SchemaDeclarationStyle;
|
|
51
58
|
enumStyle?: EnumDeclarationStyle;
|
|
59
|
+
/** Accepts 'original', 'PascalCase', or 'pascal' (normalized to 'PascalCase') */
|
|
60
|
+
enumNamesStyle?: string;
|
|
52
61
|
nullables?: NullableStrategy;
|
|
53
62
|
}
|
|
54
63
|
export interface FullAppOptions extends ClientOptions {
|
|
@@ -63,6 +72,7 @@ export type NullableStrategy = 'include' | 'nullableAsOptional' | 'ignore';
|
|
|
63
72
|
export type GenerationMode = 'full' | 'schemas';
|
|
64
73
|
export type SchemaDeclarationStyle = 'interface' | 'type';
|
|
65
74
|
export type EnumDeclarationStyle = 'union' | 'enum';
|
|
75
|
+
export type EnumNamesStyle = 'original' | 'PascalCase';
|
|
66
76
|
/**
|
|
67
77
|
* Internal options type used throughout the app after `prepareAppOptions` has run.
|
|
68
78
|
* All fields that have defaults are required here so the rest of the codebase never
|
|
@@ -75,6 +85,7 @@ export interface AppOptions extends ClientOptions {
|
|
|
75
85
|
generationMode: GenerationMode;
|
|
76
86
|
schemaDeclarationStyle: SchemaDeclarationStyle;
|
|
77
87
|
enumDeclarationStyle: EnumDeclarationStyle;
|
|
88
|
+
enumNamesStyle: EnumNamesStyle;
|
|
78
89
|
queryParamsSerialization: {
|
|
79
90
|
allowDots: boolean;
|
|
80
91
|
arrayFormat: ArrayFormat;
|