@extk/expressive 0.7.1 → 0.9.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 +456 -349
- package/dist/index.d.mts +98 -62
- package/dist/index.d.ts +98 -62
- package/dist/index.js +61 -23
- package/dist/index.mjs +61 -23
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -91,9 +91,6 @@ var SwaggerBuilder = class {
|
|
|
91
91
|
this.swaggerDoc.security = globalAuthMethods;
|
|
92
92
|
return this;
|
|
93
93
|
}
|
|
94
|
-
get() {
|
|
95
|
-
return this.swaggerDoc;
|
|
96
|
-
}
|
|
97
94
|
};
|
|
98
95
|
var securitySchemes = {
|
|
99
96
|
BasicAuth: () => ({
|
|
@@ -131,6 +128,22 @@ var security = (name) => {
|
|
|
131
128
|
}
|
|
132
129
|
return securityRegistry[name];
|
|
133
130
|
};
|
|
131
|
+
function singleFileSchema(field = "file", required = true) {
|
|
132
|
+
const schema = {
|
|
133
|
+
type: "object",
|
|
134
|
+
properties: {
|
|
135
|
+
[field]: { type: "string", format: "binary" }
|
|
136
|
+
},
|
|
137
|
+
...required && { required: [field] }
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
content: {
|
|
141
|
+
"multipart/form-data": {
|
|
142
|
+
schema
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
134
147
|
function formDataSchema(schema) {
|
|
135
148
|
return {
|
|
136
149
|
content: {
|
|
@@ -168,7 +181,7 @@ function queryParam(id, schema, required = true, description = "", name) {
|
|
|
168
181
|
return param("query", id, schema, required, description, name);
|
|
169
182
|
}
|
|
170
183
|
function headerParam(id, schema, required = true, description = "", name) {
|
|
171
|
-
return param("
|
|
184
|
+
return param("header", id, schema, required, description, name);
|
|
172
185
|
}
|
|
173
186
|
function convertExpressPath(path2) {
|
|
174
187
|
return path2.replace(/:([a-zA-Z0-9_*]+)/g, "{$1}");
|
|
@@ -188,17 +201,20 @@ var SWG = {
|
|
|
188
201
|
formDataSchema,
|
|
189
202
|
jsonSchema,
|
|
190
203
|
jsonSchemaRef,
|
|
204
|
+
singleFileSchema,
|
|
191
205
|
security,
|
|
192
206
|
securitySchemes
|
|
193
207
|
};
|
|
194
208
|
|
|
195
209
|
// src/expressive.ts
|
|
196
210
|
var ServerBuilder = class {
|
|
197
|
-
constructor(app, container) {
|
|
211
|
+
constructor(app, container, swaggerRef) {
|
|
198
212
|
this.app = app;
|
|
199
213
|
this.container = container;
|
|
214
|
+
this.swaggerRef = swaggerRef;
|
|
200
215
|
}
|
|
201
216
|
build() {
|
|
217
|
+
this.swaggerRef.doc = null;
|
|
202
218
|
return this.app;
|
|
203
219
|
}
|
|
204
220
|
withHelmet(options) {
|
|
@@ -216,6 +232,7 @@ var ServerBuilder = class {
|
|
|
216
232
|
withMorgan(format, options) {
|
|
217
233
|
this.app.use((0, import_morgan.default)(
|
|
218
234
|
format ?? ":req[x-real-ip] :method :url :status :res[content-length] - :response-time ms",
|
|
235
|
+
// TODO: ip or x-real-ip; also, default to json?
|
|
219
236
|
options ?? { stream: { write: (message) => {
|
|
220
237
|
this.container.logger.info(message.trim());
|
|
221
238
|
} } }
|
|
@@ -233,18 +250,45 @@ var ServerBuilder = class {
|
|
|
233
250
|
fn(this.app, this.container);
|
|
234
251
|
return this;
|
|
235
252
|
}
|
|
236
|
-
withSwagger(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
253
|
+
withSwagger(configure, opts, ...handlers) {
|
|
254
|
+
const config = this.swaggerRef.doc;
|
|
255
|
+
if (!config) throw new Error("withSwagger must be called before build()");
|
|
256
|
+
configure(new SwaggerBuilder(config));
|
|
257
|
+
const { path: path2, uiOpts, options, customCss, customfavIcon, swaggerUrl, customSiteTitle } = opts;
|
|
258
|
+
const uiOptsWithDefaults = {
|
|
259
|
+
customSiteTitle: config.info?.title,
|
|
260
|
+
...uiOpts
|
|
261
|
+
};
|
|
262
|
+
this.app.use(
|
|
263
|
+
path2,
|
|
264
|
+
...handlers,
|
|
265
|
+
import_swagger_ui_express.default.serve,
|
|
266
|
+
import_swagger_ui_express.default.setup(
|
|
267
|
+
config,
|
|
268
|
+
uiOptsWithDefaults,
|
|
269
|
+
options,
|
|
270
|
+
customCss,
|
|
271
|
+
customfavIcon,
|
|
272
|
+
swaggerUrl,
|
|
273
|
+
customSiteTitle
|
|
274
|
+
)
|
|
275
|
+
);
|
|
240
276
|
return this;
|
|
241
277
|
}
|
|
242
278
|
};
|
|
243
|
-
function buildExpressive(container
|
|
279
|
+
function buildExpressive(container) {
|
|
280
|
+
const swaggerRef = {
|
|
281
|
+
doc: {
|
|
282
|
+
openapi: "3.1.0",
|
|
283
|
+
info: {},
|
|
284
|
+
paths: {},
|
|
285
|
+
components: {}
|
|
286
|
+
}
|
|
287
|
+
};
|
|
244
288
|
return {
|
|
245
289
|
expressiveServer(configs) {
|
|
246
290
|
const app = configs?.app ?? (0, import_express.default)();
|
|
247
|
-
return new ServerBuilder(app, container);
|
|
291
|
+
return new ServerBuilder(app, container, swaggerRef);
|
|
248
292
|
},
|
|
249
293
|
expressiveRouter(configs) {
|
|
250
294
|
const router = import_express.default.Router();
|
|
@@ -287,10 +331,12 @@ function buildExpressive(container, swaggerDoc) {
|
|
|
287
331
|
} else {
|
|
288
332
|
pathItem.parameters.push(...tryParsePathParameters(route));
|
|
289
333
|
}
|
|
290
|
-
if (
|
|
291
|
-
|
|
334
|
+
if (swaggerRef.doc) {
|
|
335
|
+
if (!swaggerRef.doc.paths[route]) {
|
|
336
|
+
swaggerRef.doc.paths[route] = {};
|
|
337
|
+
}
|
|
338
|
+
swaggerRef.doc.paths[route][context.method] = pathItem;
|
|
292
339
|
}
|
|
293
|
-
swaggerDoc.paths[route][context.method] = pathItem;
|
|
294
340
|
return router;
|
|
295
341
|
}
|
|
296
342
|
};
|
|
@@ -528,17 +574,9 @@ var ApiResponse = class {
|
|
|
528
574
|
|
|
529
575
|
// src/index.ts
|
|
530
576
|
function bootstrap(container) {
|
|
531
|
-
const swaggerDoc = {
|
|
532
|
-
openapi: "3.1.0",
|
|
533
|
-
// TODO
|
|
534
|
-
info: {},
|
|
535
|
-
paths: {},
|
|
536
|
-
components: {}
|
|
537
|
-
};
|
|
538
577
|
return {
|
|
539
|
-
...buildExpressive(container
|
|
578
|
+
...buildExpressive(container),
|
|
540
579
|
...buildMiddleware(container),
|
|
541
|
-
swaggerBuilder: () => new SwaggerBuilder(swaggerDoc),
|
|
542
580
|
silently: async (fn) => {
|
|
543
581
|
try {
|
|
544
582
|
await fn();
|
package/dist/index.mjs
CHANGED
|
@@ -30,9 +30,6 @@ var SwaggerBuilder = class {
|
|
|
30
30
|
this.swaggerDoc.security = globalAuthMethods;
|
|
31
31
|
return this;
|
|
32
32
|
}
|
|
33
|
-
get() {
|
|
34
|
-
return this.swaggerDoc;
|
|
35
|
-
}
|
|
36
33
|
};
|
|
37
34
|
var securitySchemes = {
|
|
38
35
|
BasicAuth: () => ({
|
|
@@ -70,6 +67,22 @@ var security = (name) => {
|
|
|
70
67
|
}
|
|
71
68
|
return securityRegistry[name];
|
|
72
69
|
};
|
|
70
|
+
function singleFileSchema(field = "file", required = true) {
|
|
71
|
+
const schema = {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: {
|
|
74
|
+
[field]: { type: "string", format: "binary" }
|
|
75
|
+
},
|
|
76
|
+
...required && { required: [field] }
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
content: {
|
|
80
|
+
"multipart/form-data": {
|
|
81
|
+
schema
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
73
86
|
function formDataSchema(schema) {
|
|
74
87
|
return {
|
|
75
88
|
content: {
|
|
@@ -107,7 +120,7 @@ function queryParam(id, schema, required = true, description = "", name) {
|
|
|
107
120
|
return param("query", id, schema, required, description, name);
|
|
108
121
|
}
|
|
109
122
|
function headerParam(id, schema, required = true, description = "", name) {
|
|
110
|
-
return param("
|
|
123
|
+
return param("header", id, schema, required, description, name);
|
|
111
124
|
}
|
|
112
125
|
function convertExpressPath(path2) {
|
|
113
126
|
return path2.replace(/:([a-zA-Z0-9_*]+)/g, "{$1}");
|
|
@@ -127,17 +140,20 @@ var SWG = {
|
|
|
127
140
|
formDataSchema,
|
|
128
141
|
jsonSchema,
|
|
129
142
|
jsonSchemaRef,
|
|
143
|
+
singleFileSchema,
|
|
130
144
|
security,
|
|
131
145
|
securitySchemes
|
|
132
146
|
};
|
|
133
147
|
|
|
134
148
|
// src/expressive.ts
|
|
135
149
|
var ServerBuilder = class {
|
|
136
|
-
constructor(app, container) {
|
|
150
|
+
constructor(app, container, swaggerRef) {
|
|
137
151
|
this.app = app;
|
|
138
152
|
this.container = container;
|
|
153
|
+
this.swaggerRef = swaggerRef;
|
|
139
154
|
}
|
|
140
155
|
build() {
|
|
156
|
+
this.swaggerRef.doc = null;
|
|
141
157
|
return this.app;
|
|
142
158
|
}
|
|
143
159
|
withHelmet(options) {
|
|
@@ -155,6 +171,7 @@ var ServerBuilder = class {
|
|
|
155
171
|
withMorgan(format, options) {
|
|
156
172
|
this.app.use(morgan(
|
|
157
173
|
format ?? ":req[x-real-ip] :method :url :status :res[content-length] - :response-time ms",
|
|
174
|
+
// TODO: ip or x-real-ip; also, default to json?
|
|
158
175
|
options ?? { stream: { write: (message) => {
|
|
159
176
|
this.container.logger.info(message.trim());
|
|
160
177
|
} } }
|
|
@@ -172,18 +189,45 @@ var ServerBuilder = class {
|
|
|
172
189
|
fn(this.app, this.container);
|
|
173
190
|
return this;
|
|
174
191
|
}
|
|
175
|
-
withSwagger(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
withSwagger(configure, opts, ...handlers) {
|
|
193
|
+
const config = this.swaggerRef.doc;
|
|
194
|
+
if (!config) throw new Error("withSwagger must be called before build()");
|
|
195
|
+
configure(new SwaggerBuilder(config));
|
|
196
|
+
const { path: path2, uiOpts, options, customCss, customfavIcon, swaggerUrl, customSiteTitle } = opts;
|
|
197
|
+
const uiOptsWithDefaults = {
|
|
198
|
+
customSiteTitle: config.info?.title,
|
|
199
|
+
...uiOpts
|
|
200
|
+
};
|
|
201
|
+
this.app.use(
|
|
202
|
+
path2,
|
|
203
|
+
...handlers,
|
|
204
|
+
swaggerUi.serve,
|
|
205
|
+
swaggerUi.setup(
|
|
206
|
+
config,
|
|
207
|
+
uiOptsWithDefaults,
|
|
208
|
+
options,
|
|
209
|
+
customCss,
|
|
210
|
+
customfavIcon,
|
|
211
|
+
swaggerUrl,
|
|
212
|
+
customSiteTitle
|
|
213
|
+
)
|
|
214
|
+
);
|
|
179
215
|
return this;
|
|
180
216
|
}
|
|
181
217
|
};
|
|
182
|
-
function buildExpressive(container
|
|
218
|
+
function buildExpressive(container) {
|
|
219
|
+
const swaggerRef = {
|
|
220
|
+
doc: {
|
|
221
|
+
openapi: "3.1.0",
|
|
222
|
+
info: {},
|
|
223
|
+
paths: {},
|
|
224
|
+
components: {}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
183
227
|
return {
|
|
184
228
|
expressiveServer(configs) {
|
|
185
229
|
const app = configs?.app ?? express();
|
|
186
|
-
return new ServerBuilder(app, container);
|
|
230
|
+
return new ServerBuilder(app, container, swaggerRef);
|
|
187
231
|
},
|
|
188
232
|
expressiveRouter(configs) {
|
|
189
233
|
const router = express.Router();
|
|
@@ -226,10 +270,12 @@ function buildExpressive(container, swaggerDoc) {
|
|
|
226
270
|
} else {
|
|
227
271
|
pathItem.parameters.push(...tryParsePathParameters(route));
|
|
228
272
|
}
|
|
229
|
-
if (
|
|
230
|
-
|
|
273
|
+
if (swaggerRef.doc) {
|
|
274
|
+
if (!swaggerRef.doc.paths[route]) {
|
|
275
|
+
swaggerRef.doc.paths[route] = {};
|
|
276
|
+
}
|
|
277
|
+
swaggerRef.doc.paths[route][context.method] = pathItem;
|
|
231
278
|
}
|
|
232
|
-
swaggerDoc.paths[route][context.method] = pathItem;
|
|
233
279
|
return router;
|
|
234
280
|
}
|
|
235
281
|
};
|
|
@@ -467,17 +513,9 @@ var ApiResponse = class {
|
|
|
467
513
|
|
|
468
514
|
// src/index.ts
|
|
469
515
|
function bootstrap(container) {
|
|
470
|
-
const swaggerDoc = {
|
|
471
|
-
openapi: "3.1.0",
|
|
472
|
-
// TODO
|
|
473
|
-
info: {},
|
|
474
|
-
paths: {},
|
|
475
|
-
components: {}
|
|
476
|
-
};
|
|
477
516
|
return {
|
|
478
|
-
...buildExpressive(container
|
|
517
|
+
...buildExpressive(container),
|
|
479
518
|
...buildMiddleware(container),
|
|
480
|
-
swaggerBuilder: () => new SwaggerBuilder(swaggerDoc),
|
|
481
519
|
silently: async (fn) => {
|
|
482
520
|
try {
|
|
483
521
|
await fn();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@extk/expressive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"lint": "eslint ./"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@extk/eslint-config": "^0.
|
|
28
|
+
"@extk/eslint-config": "^0.3.0",
|
|
29
29
|
"@extk/tsconfig": "0.1.1",
|
|
30
30
|
"@types/chance": "^1.1.7",
|
|
31
31
|
"@types/express": "^5.0.1",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@types/node": "^20.9.3",
|
|
34
34
|
"@types/swagger-ui-express": "^4.1.8",
|
|
35
35
|
"chance": "^1.1.13",
|
|
36
|
-
"eslint": "^
|
|
36
|
+
"eslint": "^10.0.3",
|
|
37
37
|
"tsup": "^8.5.0",
|
|
38
38
|
"tsx": "^4.20.3",
|
|
39
39
|
"typescript": "^5.9.2"
|