@terreno/api 0.0.18 → 0.1.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/.claude/CLAUDE.local.md +204 -0
- package/.cursor/rules/00-root.mdc +338 -0
- package/.github/copilot-instructions.md +333 -0
- package/AGENTS.md +23 -3
- package/README.md +73 -3
- package/dist/api.d.ts +68 -1
- package/dist/api.js +139 -4
- package/dist/api.test.js +906 -2
- package/dist/auth.js +3 -1
- package/dist/errors.js +14 -11
- package/dist/example.js +7 -7
- package/dist/githubAuth.test.js +3 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/openApi.test.js +8 -5
- package/dist/openApiBuilder.d.ts +69 -1
- package/dist/openApiBuilder.js +109 -5
- package/dist/openApiValidator.d.ts +296 -0
- package/dist/openApiValidator.js +698 -0
- package/dist/openApiValidator.test.d.ts +1 -0
- package/dist/openApiValidator.test.js +346 -0
- package/dist/plugins.test.js +3 -3
- package/dist/terrenoPlugin.d.ts +4 -0
- package/dist/terrenoPlugin.js +2 -0
- package/dist/tests.js +34 -24
- package/package.json +4 -1
- package/src/__snapshots__/openApi.test.ts.snap +399 -0
- package/src/__snapshots__/openApiBuilder.test.ts.snap +108 -0
- package/src/api.test.ts +743 -2
- package/src/api.ts +209 -3
- package/src/auth.ts +3 -1
- package/src/errors.ts +14 -11
- package/src/example.ts +7 -7
- package/src/githubAuth.test.ts +3 -3
- package/src/index.ts +2 -0
- package/src/openApi.test.ts +8 -5
- package/src/openApiBuilder.ts +188 -15
- package/src/openApiValidator.test.ts +241 -0
- package/src/openApiValidator.ts +860 -0
- package/src/plugins.test.ts +3 -3
- package/src/terrenoPlugin.ts +5 -0
- package/src/tests.ts +34 -24
- package/.cursorrules +0 -107
- package/.windsurfrules +0 -107
- package/dist/response.d.ts +0 -0
- package/dist/response.js +0 -1
- package/index.ts +0 -1
- package/src/response.ts +0 -0
package/dist/auth.js
CHANGED
|
@@ -377,7 +377,9 @@ function addAuthRoutes(app, userModel, authOptions) {
|
|
|
377
377
|
logger_1.logger.warn("Invalid login: ".concat(info));
|
|
378
378
|
return [2 /*return*/, res.status(401).json({ message: info === null || info === void 0 ? void 0 : info.message })];
|
|
379
379
|
}
|
|
380
|
-
|
|
380
|
+
if (process.env.NODE_ENV !== "test") {
|
|
381
|
+
logger_1.logger.info("User logged in: ".concat(user._id, ", type: ").concat(user.type || "N/A"));
|
|
382
|
+
}
|
|
381
383
|
return [4 /*yield*/, (0, exports.generateTokens)(user, authOptions)];
|
|
382
384
|
case 1:
|
|
383
385
|
tokens = _a.sent();
|
package/dist/errors.js
CHANGED
|
@@ -125,21 +125,24 @@ exports.APIError = APIError;
|
|
|
125
125
|
// model.
|
|
126
126
|
function errorsPlugin(schema) {
|
|
127
127
|
var errorSchema = new mongoose_1.Schema({
|
|
128
|
-
code: String,
|
|
129
|
-
detail: String,
|
|
130
|
-
id: String,
|
|
128
|
+
code: { description: "Application-specific error code", type: String },
|
|
129
|
+
detail: { description: "Human-readable explanation of the error", type: String },
|
|
130
|
+
id: { description: "Unique identifier for this error occurrence", type: String },
|
|
131
131
|
links: {
|
|
132
|
-
about: String,
|
|
133
|
-
type: String,
|
|
132
|
+
about: { description: "Link to documentation about this error", type: String },
|
|
133
|
+
type: { description: "Link describing the error type", type: String },
|
|
134
134
|
},
|
|
135
|
-
meta: mongoose_1.Schema.Types.Mixed,
|
|
135
|
+
meta: { description: "Non-standard meta information about the error", type: mongoose_1.Schema.Types.Mixed },
|
|
136
136
|
source: {
|
|
137
|
-
header: String,
|
|
138
|
-
parameter: String,
|
|
139
|
-
pointer:
|
|
137
|
+
header: { description: "HTTP header that caused the error", type: String },
|
|
138
|
+
parameter: { description: "Query parameter that caused the error", type: String },
|
|
139
|
+
pointer: {
|
|
140
|
+
description: "JSON pointer to the request field that caused the error",
|
|
141
|
+
type: String,
|
|
142
|
+
},
|
|
140
143
|
},
|
|
141
|
-
status: Number,
|
|
142
|
-
title: { required: true, type: String },
|
|
144
|
+
status: { description: "HTTP status code for this error", type: Number },
|
|
145
|
+
title: { description: "Short summary of the error", required: true, type: String },
|
|
143
146
|
});
|
|
144
147
|
schema.add({ apiErrors: errorSchema });
|
|
145
148
|
}
|
package/dist/example.js
CHANGED
|
@@ -65,19 +65,19 @@ mongoose_1.default
|
|
|
65
65
|
logger_1.logger.error("Error connecting to mongo ".concat(err));
|
|
66
66
|
});
|
|
67
67
|
var userSchema = new mongoose_1.Schema({
|
|
68
|
-
admin: { default: false, type: Boolean },
|
|
69
|
-
username: String,
|
|
68
|
+
admin: { default: false, description: "Whether the user has admin privileges", type: Boolean },
|
|
69
|
+
username: { description: "The user's username", type: String },
|
|
70
70
|
});
|
|
71
71
|
userSchema.plugin(passport_local_mongoose_1.default, { usernameField: "email" });
|
|
72
72
|
userSchema.plugin(plugins_1.createdUpdatedPlugin);
|
|
73
73
|
userSchema.plugin(plugins_1.baseUserPlugin);
|
|
74
74
|
var UserModel = (0, mongoose_1.model)("User", userSchema);
|
|
75
75
|
var schema = new mongoose_1.Schema({
|
|
76
|
-
calories: Number,
|
|
77
|
-
created: Date,
|
|
78
|
-
hidden: { default: false, type: Boolean },
|
|
79
|
-
name: String,
|
|
80
|
-
ownerId: { ref: "User", type: "ObjectId" },
|
|
76
|
+
calories: { description: "Number of calories in the food", type: Number },
|
|
77
|
+
created: { description: "When this food was created", type: Date },
|
|
78
|
+
hidden: { default: false, description: "Whether this food is hidden from listings", type: Boolean },
|
|
79
|
+
name: { description: "The name of the food", type: String },
|
|
80
|
+
ownerId: { description: "The user who owns this food entry", ref: "User", type: "ObjectId" },
|
|
81
81
|
});
|
|
82
82
|
var FoodModel = (0, mongoose_1.model)("Food", schema);
|
|
83
83
|
function getBaseServer() {
|
package/dist/githubAuth.test.js
CHANGED
|
@@ -82,9 +82,9 @@ var logger_1 = require("./logger");
|
|
|
82
82
|
var plugins_1 = require("./plugins");
|
|
83
83
|
// Create schema for GitHub-enabled user
|
|
84
84
|
var testUserSchema = new mongoose_1.Schema({
|
|
85
|
-
admin: { default: false, type: Boolean },
|
|
86
|
-
name: String,
|
|
87
|
-
username: String,
|
|
85
|
+
admin: { default: false, description: "Whether the user has admin privileges", type: Boolean },
|
|
86
|
+
name: { description: "The user's display name", type: String },
|
|
87
|
+
username: { description: "The user's username", type: String },
|
|
88
88
|
});
|
|
89
89
|
testUserSchema.plugin(passport_local_mongoose_1.default, {
|
|
90
90
|
attemptsField: "attempts",
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ export * from "./middleware";
|
|
|
8
8
|
export * from "./notifiers";
|
|
9
9
|
export * from "./openApiBuilder";
|
|
10
10
|
export * from "./openApiEtag";
|
|
11
|
+
export * from "./openApiValidator";
|
|
11
12
|
export * from "./permissions";
|
|
12
13
|
export * from "./plugins";
|
|
13
14
|
export * from "./populate";
|
|
15
|
+
export * from "./terrenoPlugin";
|
|
14
16
|
export * from "./transformers";
|
|
15
17
|
export * from "./utils";
|
package/dist/index.js
CHANGED
|
@@ -24,8 +24,10 @@ __exportStar(require("./middleware"), exports);
|
|
|
24
24
|
__exportStar(require("./notifiers"), exports);
|
|
25
25
|
__exportStar(require("./openApiBuilder"), exports);
|
|
26
26
|
__exportStar(require("./openApiEtag"), exports);
|
|
27
|
+
__exportStar(require("./openApiValidator"), exports);
|
|
27
28
|
__exportStar(require("./permissions"), exports);
|
|
28
29
|
__exportStar(require("./plugins"), exports);
|
|
29
30
|
__exportStar(require("./populate"), exports);
|
|
31
|
+
__exportStar(require("./terrenoPlugin"), exports);
|
|
30
32
|
__exportStar(require("./transformers"), exports);
|
|
31
33
|
__exportStar(require("./utils"), exports);
|
package/dist/openApi.test.js
CHANGED
|
@@ -273,13 +273,13 @@ function addRoutes(router, options) {
|
|
|
273
273
|
// Ensure that a Number query field supports gt/gte/lt/lte and just a Number
|
|
274
274
|
(0, bun_test_1.expect)(foodQuery.schema).toEqual({
|
|
275
275
|
oneOf: [
|
|
276
|
-
{ type: "number" },
|
|
276
|
+
{ description: "Number of calories in the food", type: "number" },
|
|
277
277
|
{
|
|
278
278
|
properties: {
|
|
279
|
-
$gt: { type: "number" },
|
|
280
|
-
$gte: { type: "number" },
|
|
281
|
-
$lt: { type: "number" },
|
|
282
|
-
$lte: { type: "number" },
|
|
279
|
+
$gt: { description: "Number of calories in the food", type: "number" },
|
|
280
|
+
$gte: { description: "Number of calories in the food", type: "number" },
|
|
281
|
+
$lt: { description: "Number of calories in the food", type: "number" },
|
|
282
|
+
$lte: { description: "Number of calories in the food", type: "number" },
|
|
283
283
|
},
|
|
284
284
|
type: "object",
|
|
285
285
|
},
|
|
@@ -393,6 +393,7 @@ function addRoutesPopulate(router, options) {
|
|
|
393
393
|
type: "string",
|
|
394
394
|
},
|
|
395
395
|
name: {
|
|
396
|
+
description: "The user's display name",
|
|
396
397
|
type: "string",
|
|
397
398
|
},
|
|
398
399
|
},
|
|
@@ -406,12 +407,14 @@ function addRoutesPopulate(router, options) {
|
|
|
406
407
|
type: "array",
|
|
407
408
|
});
|
|
408
409
|
(0, bun_test_1.expect)(properties.likesIds).toEqual({
|
|
410
|
+
description: "User likes for this food",
|
|
409
411
|
items: {
|
|
410
412
|
properties: {
|
|
411
413
|
_id: {
|
|
412
414
|
type: "string",
|
|
413
415
|
},
|
|
414
416
|
likes: {
|
|
417
|
+
description: "Whether the user liked the item",
|
|
415
418
|
type: "boolean",
|
|
416
419
|
},
|
|
417
420
|
userId: {
|
package/dist/openApiBuilder.d.ts
CHANGED
|
@@ -153,6 +153,20 @@ export type OpenApiResponse = {
|
|
|
153
153
|
};
|
|
154
154
|
};
|
|
155
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* Result from building OpenAPI middleware with schemas exposed.
|
|
158
|
+
* Useful when you want to use the schemas with asyncHandler's validation.
|
|
159
|
+
*/
|
|
160
|
+
export interface OpenApiBuildResult {
|
|
161
|
+
/** The OpenAPI documentation middleware */
|
|
162
|
+
middleware: any;
|
|
163
|
+
/** Request body schema if defined */
|
|
164
|
+
bodySchema?: Record<string, OpenApiSchemaProperty>;
|
|
165
|
+
/** Query parameter schemas if defined */
|
|
166
|
+
querySchema?: Record<string, OpenApiSchemaProperty>;
|
|
167
|
+
/** Whether validation was enabled on this builder */
|
|
168
|
+
validationEnabled: boolean;
|
|
169
|
+
}
|
|
156
170
|
/**
|
|
157
171
|
* A fluent builder for constructing OpenAPI middleware.
|
|
158
172
|
*
|
|
@@ -184,6 +198,12 @@ export declare class OpenApiMiddlewareBuilder {
|
|
|
184
198
|
private options;
|
|
185
199
|
/** Accumulated OpenAPI configuration from builder methods */
|
|
186
200
|
private config;
|
|
201
|
+
/** Validation configuration */
|
|
202
|
+
private validationConfig;
|
|
203
|
+
/** Store the raw request body schema for validation */
|
|
204
|
+
private requestBodySchema?;
|
|
205
|
+
/** Store the raw query parameter schemas for validation */
|
|
206
|
+
private queryParamSchemas;
|
|
187
207
|
/**
|
|
188
208
|
* Creates a new OpenApiMiddlewareBuilder instance.
|
|
189
209
|
*
|
|
@@ -365,6 +385,51 @@ export declare class OpenApiMiddlewareBuilder {
|
|
|
365
385
|
withPathParameter(name: string, schema: OpenApiSchemaProperty, options?: {
|
|
366
386
|
description?: string;
|
|
367
387
|
}): this;
|
|
388
|
+
/**
|
|
389
|
+
* Enables runtime validation for this route.
|
|
390
|
+
*
|
|
391
|
+
* When enabled, the built middleware will validate incoming requests
|
|
392
|
+
* against the documented schema before the handler runs.
|
|
393
|
+
*
|
|
394
|
+
* @param options - Optional configuration for validation
|
|
395
|
+
* @param options.body - Enable body validation (default: true if request body is defined)
|
|
396
|
+
* @param options.query - Enable query parameter validation (default: true if query params are defined)
|
|
397
|
+
* @param options.enabled - Override the global validation enabled setting
|
|
398
|
+
* @returns The builder instance for chaining
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```typescript
|
|
402
|
+
* createOpenApiBuilder(options)
|
|
403
|
+
* .withRequestBody<{name: string}>({name: {type: "string", required: true}})
|
|
404
|
+
* .withValidation() // Enable validation
|
|
405
|
+
* .build();
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
withValidation(options?: {
|
|
409
|
+
body?: boolean;
|
|
410
|
+
query?: boolean;
|
|
411
|
+
enabled?: boolean;
|
|
412
|
+
}): this;
|
|
413
|
+
/**
|
|
414
|
+
* Builds and returns the OpenAPI middleware along with schemas.
|
|
415
|
+
*
|
|
416
|
+
* This method is useful when you want to use asyncHandler's integrated
|
|
417
|
+
* validation instead of separate validation middleware.
|
|
418
|
+
*
|
|
419
|
+
* @returns Object containing middleware and schemas
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* ```typescript
|
|
423
|
+
* const {middleware, bodySchema} = createOpenApiBuilder(options)
|
|
424
|
+
* .withRequestBody<{name: string}>({name: {type: "string", required: true}})
|
|
425
|
+
* .buildWithSchemas();
|
|
426
|
+
*
|
|
427
|
+
* router.post("/users", middleware, asyncHandler(async (req, res) => {
|
|
428
|
+
* // handler code
|
|
429
|
+
* }, {bodySchema, validate: true}));
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
buildWithSchemas(): OpenApiBuildResult;
|
|
368
433
|
/**
|
|
369
434
|
* Builds and returns the OpenAPI middleware.
|
|
370
435
|
*
|
|
@@ -372,10 +437,13 @@ export declare class OpenApiMiddlewareBuilder {
|
|
|
372
437
|
* that integrates with the OpenAPI documentation system. If no OpenAPI
|
|
373
438
|
* path is configured in options, returns a no-op middleware.
|
|
374
439
|
*
|
|
440
|
+
* If validation was enabled via `withValidation()`, returns an array
|
|
441
|
+
* of middleware: [openApiDocMiddleware, validationMiddleware].
|
|
442
|
+
*
|
|
375
443
|
* Default error responses (400, 401, 403, 404, 405) are automatically
|
|
376
444
|
* merged with the configured responses.
|
|
377
445
|
*
|
|
378
|
-
* @returns Express middleware function for OpenAPI documentation
|
|
446
|
+
* @returns Express middleware function(s) for OpenAPI documentation and optional validation
|
|
379
447
|
*
|
|
380
448
|
* @example
|
|
381
449
|
* ```typescript
|
package/dist/openApiBuilder.js
CHANGED
|
@@ -66,6 +66,7 @@ exports.createOpenApiBuilder = createOpenApiBuilder;
|
|
|
66
66
|
var merge_1 = __importDefault(require("lodash/merge"));
|
|
67
67
|
var logger_1 = require("./logger");
|
|
68
68
|
var openApi_1 = require("./openApi");
|
|
69
|
+
var openApiValidator_1 = require("./openApiValidator");
|
|
69
70
|
/**
|
|
70
71
|
* A fluent builder for constructing OpenAPI middleware.
|
|
71
72
|
*
|
|
@@ -99,10 +100,13 @@ var OpenApiMiddlewareBuilder = /** @class */ (function () {
|
|
|
99
100
|
* @param options - Router options containing the OpenAPI path configuration
|
|
100
101
|
*/
|
|
101
102
|
function OpenApiMiddlewareBuilder(options) {
|
|
103
|
+
/** Store the raw query parameter schemas for validation */
|
|
104
|
+
this.queryParamSchemas = {};
|
|
102
105
|
this.options = options;
|
|
103
106
|
this.config = {
|
|
104
107
|
responses: {},
|
|
105
108
|
};
|
|
109
|
+
this.validationConfig = {};
|
|
106
110
|
}
|
|
107
111
|
/**
|
|
108
112
|
* Sets the tags for the OpenAPI operation.
|
|
@@ -201,6 +205,8 @@ var OpenApiMiddlewareBuilder = /** @class */ (function () {
|
|
|
201
205
|
_c),
|
|
202
206
|
required: (_e = options === null || options === void 0 ? void 0 : options.required) !== null && _e !== void 0 ? _e : true,
|
|
203
207
|
};
|
|
208
|
+
// Store the schema for validation
|
|
209
|
+
this.requestBodySchema = schema;
|
|
204
210
|
return this;
|
|
205
211
|
};
|
|
206
212
|
/**
|
|
@@ -324,6 +330,8 @@ var OpenApiMiddlewareBuilder = /** @class */ (function () {
|
|
|
324
330
|
required: (_c = options === null || options === void 0 ? void 0 : options.required) !== null && _c !== void 0 ? _c : false,
|
|
325
331
|
schema: schema,
|
|
326
332
|
});
|
|
333
|
+
// Store for validation
|
|
334
|
+
this.queryParamSchemas[name] = __assign(__assign({}, schema), { required: options === null || options === void 0 ? void 0 : options.required });
|
|
327
335
|
return this;
|
|
328
336
|
};
|
|
329
337
|
/**
|
|
@@ -358,6 +366,74 @@ var OpenApiMiddlewareBuilder = /** @class */ (function () {
|
|
|
358
366
|
});
|
|
359
367
|
return this;
|
|
360
368
|
};
|
|
369
|
+
/**
|
|
370
|
+
* Enables runtime validation for this route.
|
|
371
|
+
*
|
|
372
|
+
* When enabled, the built middleware will validate incoming requests
|
|
373
|
+
* against the documented schema before the handler runs.
|
|
374
|
+
*
|
|
375
|
+
* @param options - Optional configuration for validation
|
|
376
|
+
* @param options.body - Enable body validation (default: true if request body is defined)
|
|
377
|
+
* @param options.query - Enable query parameter validation (default: true if query params are defined)
|
|
378
|
+
* @param options.enabled - Override the global validation enabled setting
|
|
379
|
+
* @returns The builder instance for chaining
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```typescript
|
|
383
|
+
* createOpenApiBuilder(options)
|
|
384
|
+
* .withRequestBody<{name: string}>({name: {type: "string", required: true}})
|
|
385
|
+
* .withValidation() // Enable validation
|
|
386
|
+
* .build();
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
OpenApiMiddlewareBuilder.prototype.withValidation = function (options) {
|
|
390
|
+
var _c, _d, _e;
|
|
391
|
+
this.validationConfig = {
|
|
392
|
+
enabled: (_c = options === null || options === void 0 ? void 0 : options.enabled) !== null && _c !== void 0 ? _c : true,
|
|
393
|
+
validateBody: (_d = options === null || options === void 0 ? void 0 : options.body) !== null && _d !== void 0 ? _d : true,
|
|
394
|
+
validateQuery: (_e = options === null || options === void 0 ? void 0 : options.query) !== null && _e !== void 0 ? _e : true,
|
|
395
|
+
};
|
|
396
|
+
return this;
|
|
397
|
+
};
|
|
398
|
+
/**
|
|
399
|
+
* Builds and returns the OpenAPI middleware along with schemas.
|
|
400
|
+
*
|
|
401
|
+
* This method is useful when you want to use asyncHandler's integrated
|
|
402
|
+
* validation instead of separate validation middleware.
|
|
403
|
+
*
|
|
404
|
+
* @returns Object containing middleware and schemas
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* const {middleware, bodySchema} = createOpenApiBuilder(options)
|
|
409
|
+
* .withRequestBody<{name: string}>({name: {type: "string", required: true}})
|
|
410
|
+
* .buildWithSchemas();
|
|
411
|
+
*
|
|
412
|
+
* router.post("/users", middleware, asyncHandler(async (req, res) => {
|
|
413
|
+
* // handler code
|
|
414
|
+
* }, {bodySchema, validate: true}));
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
OpenApiMiddlewareBuilder.prototype.buildWithSchemas = function () {
|
|
418
|
+
var _c, _d, _e, _f, _g;
|
|
419
|
+
var noop = function (_a, _b, next) { return next(); };
|
|
420
|
+
// Build the OpenAPI documentation middleware only (no validation middleware)
|
|
421
|
+
var openApiMiddleware = noop;
|
|
422
|
+
if ((_c = this.options.openApi) === null || _c === void 0 ? void 0 : _c.path) {
|
|
423
|
+
openApiMiddleware = this.options.openApi.path((0, merge_1.default)(__assign(__assign({}, this.config), { responses: __assign(__assign({}, this.config.responses), openApi_1.defaultOpenApiErrorResponses) }), (_e = (_d = this.options.openApiOverwrite) === null || _d === void 0 ? void 0 : _d.get) !== null && _e !== void 0 ? _e : {}));
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
logger_1.logger.debug("No options.openApi provided, skipping OpenApiMiddleware");
|
|
427
|
+
}
|
|
428
|
+
var globalConfig = (0, openApiValidator_1.getOpenApiValidatorConfig)();
|
|
429
|
+
var validationEnabled = (_f = this.validationConfig.enabled) !== null && _f !== void 0 ? _f : ((0, openApiValidator_1.isOpenApiValidatorConfigured)() && ((_g = globalConfig.validateRequests) !== null && _g !== void 0 ? _g : false));
|
|
430
|
+
return {
|
|
431
|
+
bodySchema: this.requestBodySchema,
|
|
432
|
+
middleware: openApiMiddleware,
|
|
433
|
+
querySchema: Object.keys(this.queryParamSchemas).length > 0 ? this.queryParamSchemas : undefined,
|
|
434
|
+
validationEnabled: validationEnabled,
|
|
435
|
+
};
|
|
436
|
+
};
|
|
361
437
|
/**
|
|
362
438
|
* Builds and returns the OpenAPI middleware.
|
|
363
439
|
*
|
|
@@ -365,10 +441,13 @@ var OpenApiMiddlewareBuilder = /** @class */ (function () {
|
|
|
365
441
|
* that integrates with the OpenAPI documentation system. If no OpenAPI
|
|
366
442
|
* path is configured in options, returns a no-op middleware.
|
|
367
443
|
*
|
|
444
|
+
* If validation was enabled via `withValidation()`, returns an array
|
|
445
|
+
* of middleware: [openApiDocMiddleware, validationMiddleware].
|
|
446
|
+
*
|
|
368
447
|
* Default error responses (400, 401, 403, 404, 405) are automatically
|
|
369
448
|
* merged with the configured responses.
|
|
370
449
|
*
|
|
371
|
-
* @returns Express middleware function for OpenAPI documentation
|
|
450
|
+
* @returns Express middleware function(s) for OpenAPI documentation and optional validation
|
|
372
451
|
*
|
|
373
452
|
* @example
|
|
374
453
|
* ```typescript
|
|
@@ -381,13 +460,38 @@ var OpenApiMiddlewareBuilder = /** @class */ (function () {
|
|
|
381
460
|
* ```
|
|
382
461
|
*/
|
|
383
462
|
OpenApiMiddlewareBuilder.prototype.build = function () {
|
|
384
|
-
var _c, _d, _e;
|
|
463
|
+
var _c, _d, _e, _f, _g;
|
|
385
464
|
var noop = function (_a, _b, next) { return next(); };
|
|
386
|
-
|
|
465
|
+
// Build the OpenAPI documentation middleware
|
|
466
|
+
var openApiMiddleware = noop;
|
|
467
|
+
if ((_c = this.options.openApi) === null || _c === void 0 ? void 0 : _c.path) {
|
|
468
|
+
openApiMiddleware = this.options.openApi.path((0, merge_1.default)(__assign(__assign({}, this.config), { responses: __assign(__assign({}, this.config.responses), openApi_1.defaultOpenApiErrorResponses) }), (_e = (_d = this.options.openApiOverwrite) === null || _d === void 0 ? void 0 : _d.get) !== null && _e !== void 0 ? _e : {}));
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
387
471
|
logger_1.logger.debug("No options.openApi provided, skipping OpenApiMiddleware");
|
|
388
|
-
return noop;
|
|
389
472
|
}
|
|
390
|
-
|
|
473
|
+
// Check if validation should be enabled
|
|
474
|
+
var globalConfig = (0, openApiValidator_1.getOpenApiValidatorConfig)();
|
|
475
|
+
var shouldValidate = (_f = this.validationConfig.enabled) !== null && _f !== void 0 ? _f : ((0, openApiValidator_1.isOpenApiValidatorConfigured)() && ((_g = globalConfig.validateRequests) !== null && _g !== void 0 ? _g : false));
|
|
476
|
+
if (!shouldValidate) {
|
|
477
|
+
return openApiMiddleware;
|
|
478
|
+
}
|
|
479
|
+
// Build validation middleware
|
|
480
|
+
var validators = [openApiMiddleware];
|
|
481
|
+
// Add body validation if we have a request body schema
|
|
482
|
+
if (this.validationConfig.validateBody && this.requestBodySchema) {
|
|
483
|
+
validators.push((0, openApiValidator_1.validateRequestBody)(this.requestBodySchema, { enabled: true }));
|
|
484
|
+
}
|
|
485
|
+
// Add query validation if we have query parameter schemas
|
|
486
|
+
if (this.validationConfig.validateQuery && Object.keys(this.queryParamSchemas).length > 0) {
|
|
487
|
+
validators.push((0, openApiValidator_1.validateQueryParams)(this.queryParamSchemas, { enabled: true }));
|
|
488
|
+
}
|
|
489
|
+
// If only one middleware (the openApi one), return it directly
|
|
490
|
+
if (validators.length === 1) {
|
|
491
|
+
return openApiMiddleware;
|
|
492
|
+
}
|
|
493
|
+
// Return array of middleware to be spread in route definition
|
|
494
|
+
return validators;
|
|
391
495
|
};
|
|
392
496
|
return OpenApiMiddlewareBuilder;
|
|
393
497
|
}());
|