@extk/expressive 0.7.1 → 0.8.0
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 +104 -0
- package/dist/index.d.mts +49 -21
- package/dist/index.d.ts +49 -21
- package/dist/index.js +19 -2
- package/dist/index.mjs +19 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,29 @@
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Table of Contents
|
|
20
|
+
|
|
21
|
+
- [What is this?](#what-is-this)
|
|
22
|
+
- [Install](#install)
|
|
23
|
+
- [Quick Start](#quick-start)
|
|
24
|
+
- [Error Handling](#error-handling)
|
|
25
|
+
- [OpenAPI / Swagger](#openapi--swagger)
|
|
26
|
+
- [File uploads](#file-uploads)
|
|
27
|
+
- [Using Zod schemas for OpenAPI](#using-zod-schemas-for-openapi)
|
|
28
|
+
- [Middleware](#middleware)
|
|
29
|
+
- [getApiErrorHandlerMiddleware](#getapierrorhandlermiddleware)
|
|
30
|
+
- [getApiNotFoundMiddleware](#getapinotfoundmiddleware)
|
|
31
|
+
- [getGlobalNotFoundMiddleware](#getglobalnotfoundmiddleware)
|
|
32
|
+
- [getGlobalErrorHandlerMiddleware](#getglobalerrorhandlermiddleware)
|
|
33
|
+
- [getBasicAuthMiddleware](#getbasicauthmiddleware)
|
|
34
|
+
- [silently](#silently)
|
|
35
|
+
- [Logging](#logging)
|
|
36
|
+
- [Utilities](#utilities)
|
|
37
|
+
- [API Response Format](#api-response-format)
|
|
38
|
+
- [License](#license)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
19
42
|
## What is this?
|
|
20
43
|
|
|
21
44
|
`@extk/expressive` is an opinionated toolkit for Express 5 that wires up the things every API needs but nobody wants to set up from scratch:
|
|
@@ -171,6 +194,38 @@ addRoute(
|
|
|
171
194
|
);
|
|
172
195
|
```
|
|
173
196
|
|
|
197
|
+
### File uploads
|
|
198
|
+
|
|
199
|
+
Use `SWG.singleFileSchema` for a single file field, or `SWG.formDataSchema` for a custom multipart body:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// single file — field name defaults to 'file', required defaults to true
|
|
203
|
+
addRoute({
|
|
204
|
+
method: 'post',
|
|
205
|
+
path: '/upload',
|
|
206
|
+
oapi: {
|
|
207
|
+
requestBody: SWG.singleFileSchema(),
|
|
208
|
+
// requestBody: SWG.singleFileSchema('avatar', true),
|
|
209
|
+
},
|
|
210
|
+
}, handler);
|
|
211
|
+
|
|
212
|
+
// custom multipart schema with multiple fields
|
|
213
|
+
addRoute({
|
|
214
|
+
method: 'post',
|
|
215
|
+
path: '/upload/rich',
|
|
216
|
+
oapi: {
|
|
217
|
+
requestBody: SWG.formDataSchema({
|
|
218
|
+
type: 'object',
|
|
219
|
+
properties: {
|
|
220
|
+
file: { type: 'string', format: 'binary' },
|
|
221
|
+
title: { type: 'string' },
|
|
222
|
+
},
|
|
223
|
+
required: ['file'],
|
|
224
|
+
}),
|
|
225
|
+
},
|
|
226
|
+
}, handler);
|
|
227
|
+
```
|
|
228
|
+
|
|
174
229
|
Configure security schemes via the swagger builder:
|
|
175
230
|
|
|
176
231
|
```ts
|
|
@@ -261,6 +316,55 @@ addRoute({
|
|
|
261
316
|
|
|
262
317
|
This way your Zod schemas serve as the single source of truth for both runtime validation and API documentation.
|
|
263
318
|
|
|
319
|
+
## Middleware
|
|
320
|
+
|
|
321
|
+
All middleware factories are returned from `bootstrap()`.
|
|
322
|
+
|
|
323
|
+
### `getApiErrorHandlerMiddleware(errorMapper?)`
|
|
324
|
+
|
|
325
|
+
Express error handler for API routes. Catches `ApiError` subclasses, handles malformed JSON, and falls back to `InternalError` for unknown errors. Pass an optional `errorMapper` to map third-party errors (e.g. Zod, Multer) to typed `ApiError` instances.
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
app.use(getApiErrorHandlerMiddleware((err) => {
|
|
329
|
+
if (err.name === 'ZodError') return new SchemaValidationError('Validation failed').setData(err.issues);
|
|
330
|
+
return null;
|
|
331
|
+
}));
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### `getApiNotFoundMiddleware()`
|
|
335
|
+
|
|
336
|
+
Returns a JSON `404` response for unmatched API routes.
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
app.use(getApiNotFoundMiddleware());
|
|
340
|
+
// { status: 'error', message: 'GET /unknown not found', errorCode: 'NOT_FOUND' }
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### `getGlobalNotFoundMiddleware(content?)`
|
|
344
|
+
|
|
345
|
+
Returns a plain-text `404`. Useful as the last catch-all for non-API routes. Defaults to `¯\_(ツ)_/¯`.
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
app.use(getGlobalNotFoundMiddleware());
|
|
349
|
+
app.use(getGlobalNotFoundMiddleware('Not found'));
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### `getGlobalErrorHandlerMiddleware()`
|
|
353
|
+
|
|
354
|
+
Minimal error handler that logs and responds with a plain-text `500`. Use this outside of API route groups where JSON responses aren't expected.
|
|
355
|
+
|
|
356
|
+
### `getBasicAuthMiddleware(basicAuthBase64, realm?)`
|
|
357
|
+
|
|
358
|
+
Protects a route or the Swagger UI with HTTP Basic auth. Accepts a pre-encoded base64 `user:password` string.
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
expressiveServer()
|
|
362
|
+
.withSwagger(
|
|
363
|
+
{ config: swaggerDoc },
|
|
364
|
+
getBasicAuthMiddleware(process.env.SWAGGER_AUTH!, 'API Docs'),
|
|
365
|
+
)
|
|
366
|
+
```
|
|
367
|
+
|
|
264
368
|
## silently
|
|
265
369
|
|
|
266
370
|
`silently` runs a function — sync or async — and suppresses any errors it throws. Errors are forwarded to `alertHandler` (if configured) or logged via the container logger.
|
package/dist/index.d.mts
CHANGED
|
@@ -33,61 +33,85 @@ type Container = {
|
|
|
33
33
|
alertHandler?: AlertHandler;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
type Nullable<T extends string> = T | [T, 'null'] | ['null', T];
|
|
36
37
|
type NumericConfigs = {
|
|
37
38
|
minimum?: number;
|
|
38
39
|
maximum?: number;
|
|
39
|
-
exclusiveMinimum?:
|
|
40
|
-
exclusiveMaximum?:
|
|
40
|
+
exclusiveMinimum?: number;
|
|
41
|
+
exclusiveMaximum?: number;
|
|
41
42
|
multipleOf?: number;
|
|
42
43
|
};
|
|
43
44
|
type NumberSchema = {
|
|
44
|
-
type: 'number'
|
|
45
|
+
type: Nullable<'number'>;
|
|
45
46
|
format?: 'float' | 'double';
|
|
46
47
|
} & NumericConfigs;
|
|
47
48
|
type IntegerSchema = {
|
|
48
|
-
type: 'integer'
|
|
49
|
+
type: Nullable<'integer'>;
|
|
49
50
|
format?: 'int32' | 'int64';
|
|
50
51
|
} & NumericConfigs;
|
|
51
52
|
type StringSchema = {
|
|
52
|
-
type: 'string'
|
|
53
|
+
type: Nullable<'string'>;
|
|
53
54
|
minLength?: number;
|
|
54
55
|
maxLength?: number;
|
|
55
56
|
format?: 'date' | 'date-time' | 'password' | 'byte' | 'binary' | 'email' | 'uuid' | 'uri' | 'hostname' | 'ipv4' | 'ipv6' | OtherString;
|
|
56
57
|
pattern?: string;
|
|
57
58
|
};
|
|
58
59
|
type BooleanSchema = {
|
|
59
|
-
type: 'boolean'
|
|
60
|
+
type: Nullable<'boolean'>;
|
|
61
|
+
};
|
|
62
|
+
type NullSchema = {
|
|
63
|
+
type: 'null';
|
|
60
64
|
};
|
|
61
65
|
type ArraySchema = {
|
|
62
|
-
type: 'array'
|
|
63
|
-
items
|
|
66
|
+
type: Nullable<'array'>;
|
|
67
|
+
items?: Schema;
|
|
64
68
|
minItems?: number;
|
|
65
69
|
maxItems?: number;
|
|
66
70
|
uniqueItems?: boolean;
|
|
67
71
|
};
|
|
68
72
|
type ObjectSchema = {
|
|
69
|
-
type: 'object'
|
|
73
|
+
type: Nullable<'object'>;
|
|
70
74
|
properties?: Record<string, Schema>;
|
|
71
75
|
required?: string[];
|
|
72
76
|
additionalProperties?: boolean | Schema;
|
|
73
77
|
minProperties?: number;
|
|
74
78
|
maxProperties?: number;
|
|
75
79
|
};
|
|
76
|
-
type
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
type Discriminator = {
|
|
81
|
+
propertyName: string;
|
|
82
|
+
mapping?: Record<string, string>;
|
|
83
|
+
};
|
|
84
|
+
type CommonSchemaProps = {
|
|
85
|
+
title?: string;
|
|
79
86
|
description?: string;
|
|
87
|
+
example?: unknown;
|
|
80
88
|
default?: unknown;
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
enum?: unknown[];
|
|
90
|
+
const?: unknown;
|
|
91
|
+
readOnly?: boolean;
|
|
92
|
+
writeOnly?: boolean;
|
|
93
|
+
deprecated?: boolean;
|
|
83
94
|
};
|
|
84
|
-
type
|
|
95
|
+
type BaseSchema = CommonSchemaProps & (StringSchema | NumberSchema | IntegerSchema | BooleanSchema | NullSchema | ArraySchema | ObjectSchema | {
|
|
96
|
+
$ref: string;
|
|
97
|
+
});
|
|
98
|
+
type Schema = // circular
|
|
99
|
+
BaseSchema | (CommonSchemaProps & {
|
|
85
100
|
allOf: Schema[];
|
|
86
|
-
|
|
101
|
+
discriminator?: Discriminator;
|
|
102
|
+
}) | (CommonSchemaProps & {
|
|
87
103
|
anyOf: Schema[];
|
|
88
|
-
|
|
104
|
+
discriminator?: Discriminator;
|
|
105
|
+
}) | (CommonSchemaProps & {
|
|
89
106
|
oneOf: Schema[];
|
|
90
|
-
|
|
107
|
+
discriminator?: Discriminator;
|
|
108
|
+
}) | (CommonSchemaProps & {
|
|
109
|
+
not: Schema;
|
|
110
|
+
}) | (CommonSchemaProps & {
|
|
111
|
+
if: Schema;
|
|
112
|
+
then?: Schema;
|
|
113
|
+
else?: Schema;
|
|
114
|
+
}) | OtherUnknown;
|
|
91
115
|
type Content = {
|
|
92
116
|
description?: string;
|
|
93
117
|
content?: Partial<Record<ContentType, {
|
|
@@ -95,7 +119,7 @@ type Content = {
|
|
|
95
119
|
}>>;
|
|
96
120
|
};
|
|
97
121
|
type Param = {
|
|
98
|
-
in: 'path' | 'query' | '
|
|
122
|
+
in: 'path' | 'query' | 'header' | 'cookie';
|
|
99
123
|
name: string;
|
|
100
124
|
description: string;
|
|
101
125
|
required: boolean;
|
|
@@ -107,6 +131,7 @@ type Servers = {
|
|
|
107
131
|
}[];
|
|
108
132
|
type PathItem = {
|
|
109
133
|
summary?: string;
|
|
134
|
+
description?: string;
|
|
110
135
|
requestBody?: Content;
|
|
111
136
|
parameters?: Param[];
|
|
112
137
|
servers?: Servers;
|
|
@@ -116,13 +141,14 @@ type PathItem = {
|
|
|
116
141
|
deprecated?: boolean;
|
|
117
142
|
security?: AuthMethod[];
|
|
118
143
|
};
|
|
144
|
+
/** { BearerAuth: [] } | { OAuth2: ['read', 'write'] } */
|
|
119
145
|
type AuthMethod = Record<string, string[]>;
|
|
120
146
|
type SecurityScheme = {
|
|
121
147
|
type: 'http';
|
|
122
148
|
scheme: 'basic' | 'bearer';
|
|
123
149
|
} | {
|
|
124
150
|
type: 'apiKey';
|
|
125
|
-
in: 'header';
|
|
151
|
+
in: 'header' | 'query' | 'cookie';
|
|
126
152
|
name: string;
|
|
127
153
|
} | {
|
|
128
154
|
type: 'openIdConnect';
|
|
@@ -234,8 +260,9 @@ declare class SwaggerBuilder {
|
|
|
234
260
|
withSecuritySchemes(schemes: Record<string, SecurityScheme>): this;
|
|
235
261
|
withSchemas(schemas: Record<string, Schema>): this;
|
|
236
262
|
withDefaultSecurity(globalAuthMethods: AuthMethod[]): this;
|
|
237
|
-
|
|
263
|
+
build(): SwaggerConfig;
|
|
238
264
|
}
|
|
265
|
+
declare function singleFileSchema(field?: string, required?: boolean): Content;
|
|
239
266
|
declare function formDataSchema(schema: Schema): Content;
|
|
240
267
|
declare function jsonSchema(schema: Schema): Content;
|
|
241
268
|
declare function jsonSchemaRef(name: string): Content;
|
|
@@ -251,6 +278,7 @@ declare const SWG: {
|
|
|
251
278
|
formDataSchema: typeof formDataSchema;
|
|
252
279
|
jsonSchema: typeof jsonSchema;
|
|
253
280
|
jsonSchemaRef: typeof jsonSchemaRef;
|
|
281
|
+
singleFileSchema: typeof singleFileSchema;
|
|
254
282
|
security: (name: string) => AuthMethod;
|
|
255
283
|
securitySchemes: {
|
|
256
284
|
readonly BasicAuth: () => SecurityScheme;
|
package/dist/index.d.ts
CHANGED
|
@@ -33,61 +33,85 @@ type Container = {
|
|
|
33
33
|
alertHandler?: AlertHandler;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
type Nullable<T extends string> = T | [T, 'null'] | ['null', T];
|
|
36
37
|
type NumericConfigs = {
|
|
37
38
|
minimum?: number;
|
|
38
39
|
maximum?: number;
|
|
39
|
-
exclusiveMinimum?:
|
|
40
|
-
exclusiveMaximum?:
|
|
40
|
+
exclusiveMinimum?: number;
|
|
41
|
+
exclusiveMaximum?: number;
|
|
41
42
|
multipleOf?: number;
|
|
42
43
|
};
|
|
43
44
|
type NumberSchema = {
|
|
44
|
-
type: 'number'
|
|
45
|
+
type: Nullable<'number'>;
|
|
45
46
|
format?: 'float' | 'double';
|
|
46
47
|
} & NumericConfigs;
|
|
47
48
|
type IntegerSchema = {
|
|
48
|
-
type: 'integer'
|
|
49
|
+
type: Nullable<'integer'>;
|
|
49
50
|
format?: 'int32' | 'int64';
|
|
50
51
|
} & NumericConfigs;
|
|
51
52
|
type StringSchema = {
|
|
52
|
-
type: 'string'
|
|
53
|
+
type: Nullable<'string'>;
|
|
53
54
|
minLength?: number;
|
|
54
55
|
maxLength?: number;
|
|
55
56
|
format?: 'date' | 'date-time' | 'password' | 'byte' | 'binary' | 'email' | 'uuid' | 'uri' | 'hostname' | 'ipv4' | 'ipv6' | OtherString;
|
|
56
57
|
pattern?: string;
|
|
57
58
|
};
|
|
58
59
|
type BooleanSchema = {
|
|
59
|
-
type: 'boolean'
|
|
60
|
+
type: Nullable<'boolean'>;
|
|
61
|
+
};
|
|
62
|
+
type NullSchema = {
|
|
63
|
+
type: 'null';
|
|
60
64
|
};
|
|
61
65
|
type ArraySchema = {
|
|
62
|
-
type: 'array'
|
|
63
|
-
items
|
|
66
|
+
type: Nullable<'array'>;
|
|
67
|
+
items?: Schema;
|
|
64
68
|
minItems?: number;
|
|
65
69
|
maxItems?: number;
|
|
66
70
|
uniqueItems?: boolean;
|
|
67
71
|
};
|
|
68
72
|
type ObjectSchema = {
|
|
69
|
-
type: 'object'
|
|
73
|
+
type: Nullable<'object'>;
|
|
70
74
|
properties?: Record<string, Schema>;
|
|
71
75
|
required?: string[];
|
|
72
76
|
additionalProperties?: boolean | Schema;
|
|
73
77
|
minProperties?: number;
|
|
74
78
|
maxProperties?: number;
|
|
75
79
|
};
|
|
76
|
-
type
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
type Discriminator = {
|
|
81
|
+
propertyName: string;
|
|
82
|
+
mapping?: Record<string, string>;
|
|
83
|
+
};
|
|
84
|
+
type CommonSchemaProps = {
|
|
85
|
+
title?: string;
|
|
79
86
|
description?: string;
|
|
87
|
+
example?: unknown;
|
|
80
88
|
default?: unknown;
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
enum?: unknown[];
|
|
90
|
+
const?: unknown;
|
|
91
|
+
readOnly?: boolean;
|
|
92
|
+
writeOnly?: boolean;
|
|
93
|
+
deprecated?: boolean;
|
|
83
94
|
};
|
|
84
|
-
type
|
|
95
|
+
type BaseSchema = CommonSchemaProps & (StringSchema | NumberSchema | IntegerSchema | BooleanSchema | NullSchema | ArraySchema | ObjectSchema | {
|
|
96
|
+
$ref: string;
|
|
97
|
+
});
|
|
98
|
+
type Schema = // circular
|
|
99
|
+
BaseSchema | (CommonSchemaProps & {
|
|
85
100
|
allOf: Schema[];
|
|
86
|
-
|
|
101
|
+
discriminator?: Discriminator;
|
|
102
|
+
}) | (CommonSchemaProps & {
|
|
87
103
|
anyOf: Schema[];
|
|
88
|
-
|
|
104
|
+
discriminator?: Discriminator;
|
|
105
|
+
}) | (CommonSchemaProps & {
|
|
89
106
|
oneOf: Schema[];
|
|
90
|
-
|
|
107
|
+
discriminator?: Discriminator;
|
|
108
|
+
}) | (CommonSchemaProps & {
|
|
109
|
+
not: Schema;
|
|
110
|
+
}) | (CommonSchemaProps & {
|
|
111
|
+
if: Schema;
|
|
112
|
+
then?: Schema;
|
|
113
|
+
else?: Schema;
|
|
114
|
+
}) | OtherUnknown;
|
|
91
115
|
type Content = {
|
|
92
116
|
description?: string;
|
|
93
117
|
content?: Partial<Record<ContentType, {
|
|
@@ -95,7 +119,7 @@ type Content = {
|
|
|
95
119
|
}>>;
|
|
96
120
|
};
|
|
97
121
|
type Param = {
|
|
98
|
-
in: 'path' | 'query' | '
|
|
122
|
+
in: 'path' | 'query' | 'header' | 'cookie';
|
|
99
123
|
name: string;
|
|
100
124
|
description: string;
|
|
101
125
|
required: boolean;
|
|
@@ -107,6 +131,7 @@ type Servers = {
|
|
|
107
131
|
}[];
|
|
108
132
|
type PathItem = {
|
|
109
133
|
summary?: string;
|
|
134
|
+
description?: string;
|
|
110
135
|
requestBody?: Content;
|
|
111
136
|
parameters?: Param[];
|
|
112
137
|
servers?: Servers;
|
|
@@ -116,13 +141,14 @@ type PathItem = {
|
|
|
116
141
|
deprecated?: boolean;
|
|
117
142
|
security?: AuthMethod[];
|
|
118
143
|
};
|
|
144
|
+
/** { BearerAuth: [] } | { OAuth2: ['read', 'write'] } */
|
|
119
145
|
type AuthMethod = Record<string, string[]>;
|
|
120
146
|
type SecurityScheme = {
|
|
121
147
|
type: 'http';
|
|
122
148
|
scheme: 'basic' | 'bearer';
|
|
123
149
|
} | {
|
|
124
150
|
type: 'apiKey';
|
|
125
|
-
in: 'header';
|
|
151
|
+
in: 'header' | 'query' | 'cookie';
|
|
126
152
|
name: string;
|
|
127
153
|
} | {
|
|
128
154
|
type: 'openIdConnect';
|
|
@@ -234,8 +260,9 @@ declare class SwaggerBuilder {
|
|
|
234
260
|
withSecuritySchemes(schemes: Record<string, SecurityScheme>): this;
|
|
235
261
|
withSchemas(schemas: Record<string, Schema>): this;
|
|
236
262
|
withDefaultSecurity(globalAuthMethods: AuthMethod[]): this;
|
|
237
|
-
|
|
263
|
+
build(): SwaggerConfig;
|
|
238
264
|
}
|
|
265
|
+
declare function singleFileSchema(field?: string, required?: boolean): Content;
|
|
239
266
|
declare function formDataSchema(schema: Schema): Content;
|
|
240
267
|
declare function jsonSchema(schema: Schema): Content;
|
|
241
268
|
declare function jsonSchemaRef(name: string): Content;
|
|
@@ -251,6 +278,7 @@ declare const SWG: {
|
|
|
251
278
|
formDataSchema: typeof formDataSchema;
|
|
252
279
|
jsonSchema: typeof jsonSchema;
|
|
253
280
|
jsonSchemaRef: typeof jsonSchemaRef;
|
|
281
|
+
singleFileSchema: typeof singleFileSchema;
|
|
254
282
|
security: (name: string) => AuthMethod;
|
|
255
283
|
securitySchemes: {
|
|
256
284
|
readonly BasicAuth: () => SecurityScheme;
|
package/dist/index.js
CHANGED
|
@@ -91,7 +91,7 @@ var SwaggerBuilder = class {
|
|
|
91
91
|
this.swaggerDoc.security = globalAuthMethods;
|
|
92
92
|
return this;
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
build() {
|
|
95
95
|
return this.swaggerDoc;
|
|
96
96
|
}
|
|
97
97
|
};
|
|
@@ -131,6 +131,22 @@ var security = (name) => {
|
|
|
131
131
|
}
|
|
132
132
|
return securityRegistry[name];
|
|
133
133
|
};
|
|
134
|
+
function singleFileSchema(field = "file", required = true) {
|
|
135
|
+
const schema = {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
[field]: { type: "string", format: "binary" }
|
|
139
|
+
},
|
|
140
|
+
...required && { required: [field] }
|
|
141
|
+
};
|
|
142
|
+
return {
|
|
143
|
+
content: {
|
|
144
|
+
"multipart/form-data": {
|
|
145
|
+
schema
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
134
150
|
function formDataSchema(schema) {
|
|
135
151
|
return {
|
|
136
152
|
content: {
|
|
@@ -168,7 +184,7 @@ function queryParam(id, schema, required = true, description = "", name) {
|
|
|
168
184
|
return param("query", id, schema, required, description, name);
|
|
169
185
|
}
|
|
170
186
|
function headerParam(id, schema, required = true, description = "", name) {
|
|
171
|
-
return param("
|
|
187
|
+
return param("header", id, schema, required, description, name);
|
|
172
188
|
}
|
|
173
189
|
function convertExpressPath(path2) {
|
|
174
190
|
return path2.replace(/:([a-zA-Z0-9_*]+)/g, "{$1}");
|
|
@@ -188,6 +204,7 @@ var SWG = {
|
|
|
188
204
|
formDataSchema,
|
|
189
205
|
jsonSchema,
|
|
190
206
|
jsonSchemaRef,
|
|
207
|
+
singleFileSchema,
|
|
191
208
|
security,
|
|
192
209
|
securitySchemes
|
|
193
210
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -30,7 +30,7 @@ var SwaggerBuilder = class {
|
|
|
30
30
|
this.swaggerDoc.security = globalAuthMethods;
|
|
31
31
|
return this;
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
build() {
|
|
34
34
|
return this.swaggerDoc;
|
|
35
35
|
}
|
|
36
36
|
};
|
|
@@ -70,6 +70,22 @@ var security = (name) => {
|
|
|
70
70
|
}
|
|
71
71
|
return securityRegistry[name];
|
|
72
72
|
};
|
|
73
|
+
function singleFileSchema(field = "file", required = true) {
|
|
74
|
+
const schema = {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: {
|
|
77
|
+
[field]: { type: "string", format: "binary" }
|
|
78
|
+
},
|
|
79
|
+
...required && { required: [field] }
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
content: {
|
|
83
|
+
"multipart/form-data": {
|
|
84
|
+
schema
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
73
89
|
function formDataSchema(schema) {
|
|
74
90
|
return {
|
|
75
91
|
content: {
|
|
@@ -107,7 +123,7 @@ function queryParam(id, schema, required = true, description = "", name) {
|
|
|
107
123
|
return param("query", id, schema, required, description, name);
|
|
108
124
|
}
|
|
109
125
|
function headerParam(id, schema, required = true, description = "", name) {
|
|
110
|
-
return param("
|
|
126
|
+
return param("header", id, schema, required, description, name);
|
|
111
127
|
}
|
|
112
128
|
function convertExpressPath(path2) {
|
|
113
129
|
return path2.replace(/:([a-zA-Z0-9_*]+)/g, "{$1}");
|
|
@@ -127,6 +143,7 @@ var SWG = {
|
|
|
127
143
|
formDataSchema,
|
|
128
144
|
jsonSchema,
|
|
129
145
|
jsonSchemaRef,
|
|
146
|
+
singleFileSchema,
|
|
130
147
|
security,
|
|
131
148
|
securitySchemes
|
|
132
149
|
};
|