@naturalcycles/backend-lib 5.2.0 → 5.4.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/dist/admin/secureHeaderMiddleware.js +2 -1
- package/dist/db/httpDBRequestHandler.js +10 -10
- package/dist/deploy/deployGae.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/server/basicAuthMiddleware.js +1 -1
- package/dist/server/serverStatsMiddleware.js +1 -1
- package/dist/server/startServer.js +1 -1
- package/dist/server/validation/validateMiddleware.d.ts +1 -1
- package/dist/server/validation/{reqValidationMiddleware.d.ts → validateRequest.d.ts} +1 -2
- package/dist/server/validation/{reqValidationMiddleware.js → validateRequest.js} +1 -24
- package/dist/server/validation/zodValidateMiddleware.d.ts +1 -1
- package/package.json +2 -2
- package/src/admin/secureHeaderMiddleware.ts +3 -1
- package/src/db/httpDBRequestHandler.ts +11 -11
- package/src/index.ts +1 -1
- package/src/server/basicAuthMiddleware.ts +2 -2
- package/src/server/validation/validateMiddleware.ts +1 -1
- package/src/server/validation/{reqValidationMiddleware.ts → validateRequest.ts} +1 -35
- package/src/server/validation/zodValidateMiddleware.ts +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createSecureHeaderMiddleware = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
6
|
const adminMiddleware_1 = require("./adminMiddleware");
|
|
6
7
|
/**
|
|
7
8
|
* Secures the endpoint by requiring a secret header to be present.
|
|
@@ -21,7 +22,7 @@ function requireSecureHeaderOrAdmin(cfg, reqPermissions) {
|
|
|
21
22
|
return next();
|
|
22
23
|
// Header provided - don't check for Admin
|
|
23
24
|
if (providedHeader) {
|
|
24
|
-
if (!secureHeaderValue || providedHeader
|
|
25
|
+
if (!secureHeaderValue || (0, nodejs_lib_1.timingSafeStringEqual)(providedHeader, secureHeaderValue))
|
|
25
26
|
return next();
|
|
26
27
|
return next(new js_lib_1.AppError('secureHeader or adminToken is required', {
|
|
27
28
|
backendResponseStatusCode: 401,
|
|
@@ -49,25 +49,25 @@ function httpDBRequestHandler(db) {
|
|
|
49
49
|
//
|
|
50
50
|
// })
|
|
51
51
|
// getByIds
|
|
52
|
-
router.put('/getByIds',
|
|
53
|
-
const { table, ids, opt } =
|
|
52
|
+
router.put('/getByIds', async (req, res) => {
|
|
53
|
+
const { table, ids, opt } = __1.validateRequest.body(req, getByIdsInputSchema);
|
|
54
54
|
res.json(await db.getByIds(table, ids, opt));
|
|
55
55
|
});
|
|
56
56
|
// runQuery
|
|
57
|
-
router.put('/runQuery',
|
|
58
|
-
const { query, opt } =
|
|
57
|
+
router.put('/runQuery', async (req, res) => {
|
|
58
|
+
const { query, opt } = __1.validateRequest.body(req, runQueryInputSchema);
|
|
59
59
|
const q = db_lib_1.DBQuery.fromPlainObject(query);
|
|
60
60
|
res.json(await db.runQuery(q, opt));
|
|
61
61
|
});
|
|
62
62
|
// runQueryCount
|
|
63
|
-
router.put('/runQueryCount',
|
|
64
|
-
const { query, opt } =
|
|
63
|
+
router.put('/runQueryCount', async (req, res) => {
|
|
64
|
+
const { query, opt } = __1.validateRequest.body(req, runQueryInputSchema);
|
|
65
65
|
const q = db_lib_1.DBQuery.fromPlainObject(query);
|
|
66
66
|
res.json(await db.runQueryCount(q, opt));
|
|
67
67
|
});
|
|
68
68
|
// saveBatch
|
|
69
|
-
router.put('/saveBatch',
|
|
70
|
-
const { table, rows, opt } =
|
|
69
|
+
router.put('/saveBatch', async (req, res) => {
|
|
70
|
+
const { table, rows, opt } = __1.validateRequest.body(req, saveBatchInputSchema);
|
|
71
71
|
await db.saveBatch(table, rows, opt);
|
|
72
72
|
res.end();
|
|
73
73
|
});
|
|
@@ -77,8 +77,8 @@ function httpDBRequestHandler(db) {
|
|
|
77
77
|
// res.json(await db.deleteByIds(table, ids, opt))
|
|
78
78
|
// })
|
|
79
79
|
// deleteByQuery
|
|
80
|
-
router.put('/deleteByQuery',
|
|
81
|
-
const { query, opt } =
|
|
80
|
+
router.put('/deleteByQuery', async (req, res) => {
|
|
81
|
+
const { query, opt } = __1.validateRequest.body(req, runQueryInputSchema);
|
|
82
82
|
const q = db_lib_1.DBQuery.fromPlainObject(query);
|
|
83
83
|
res.json(await db.deleteByQuery(q, opt));
|
|
84
84
|
});
|
package/dist/deploy/deployGae.js
CHANGED
|
@@ -35,7 +35,7 @@ async function deployGae(opt = {}) {
|
|
|
35
35
|
}, {
|
|
36
36
|
name: 'deploy',
|
|
37
37
|
maxAttempts: 2,
|
|
38
|
-
delay:
|
|
38
|
+
delay: 30_000,
|
|
39
39
|
// todo: this doesn't work, as the error is different from what is logged.
|
|
40
40
|
// We shoud somehow capture the logged text
|
|
41
41
|
predicate: err => (0, js_lib_1._anyToError)(err).message.includes('operation is already in progress'),
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export * from './server/notFoundMiddleware';
|
|
|
20
20
|
export * from './server/okMiddleware';
|
|
21
21
|
export * from './server/basicAuthMiddleware';
|
|
22
22
|
export * from './server/requestTimeoutMiddleware';
|
|
23
|
-
export * from './server/validation/
|
|
23
|
+
export * from './server/validation/validateRequest';
|
|
24
24
|
export * from './server/simpleRequestLoggerMiddleware';
|
|
25
25
|
export * from './server/serverStatusMiddleware';
|
|
26
26
|
export * from './server/validation/validateMiddleware';
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ tslib_1.__exportStar(require("./server/notFoundMiddleware"), exports);
|
|
|
25
25
|
tslib_1.__exportStar(require("./server/okMiddleware"), exports);
|
|
26
26
|
tslib_1.__exportStar(require("./server/basicAuthMiddleware"), exports);
|
|
27
27
|
tslib_1.__exportStar(require("./server/requestTimeoutMiddleware"), exports);
|
|
28
|
-
tslib_1.__exportStar(require("./server/validation/
|
|
28
|
+
tslib_1.__exportStar(require("./server/validation/validateRequest"), exports);
|
|
29
29
|
tslib_1.__exportStar(require("./server/simpleRequestLoggerMiddleware"), exports);
|
|
30
30
|
tslib_1.__exportStar(require("./server/serverStatusMiddleware"), exports);
|
|
31
31
|
tslib_1.__exportStar(require("./server/validation/validateMiddleware"), exports);
|
|
@@ -9,7 +9,7 @@ function basicAuthMiddleware(cfg) {
|
|
|
9
9
|
const hash = (req.headers.authorization || '').split(' ')[1];
|
|
10
10
|
if (hash) {
|
|
11
11
|
const [login, password] = (0, js_lib_1._split)((0, nodejs_lib_1.base64ToString)(hash), ':', 2);
|
|
12
|
-
if (login && password && cfg.loginPasswordMap[login]
|
|
12
|
+
if (login && password && (0, nodejs_lib_1.timingSafeStringEqual)(cfg.loginPasswordMap[login], password)) {
|
|
13
13
|
return next();
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -62,7 +62,7 @@ class BackendServer {
|
|
|
62
62
|
const shutdownTimeout = setTimeout(() => {
|
|
63
63
|
console.log((0, nodejs_lib_1.boldGrey)('Forceful shutdown after timeout'));
|
|
64
64
|
process.exit(0);
|
|
65
|
-
}, this.cfg.forceShutdownTimeout ??
|
|
65
|
+
}, this.cfg.forceShutdownTimeout ?? 10_000);
|
|
66
66
|
try {
|
|
67
67
|
await Promise.all([
|
|
68
68
|
this.server && new Promise(r => this.server.close(r)),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JsonSchema, JsonSchemaBuilder } from '@naturalcycles/js-lib';
|
|
2
2
|
import { AjvSchema, AjvValidationError } from '@naturalcycles/nodejs-lib';
|
|
3
3
|
import { BackendRequestHandler } from '../server.model';
|
|
4
|
-
import { ReqValidationOptions } from './
|
|
4
|
+
import { ReqValidationOptions } from './validateRequest';
|
|
5
5
|
export declare function validateBody(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>): BackendRequestHandler;
|
|
6
6
|
export declare function validateParams(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>): BackendRequestHandler;
|
|
7
7
|
export declare function validateQuery(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>): BackendRequestHandler;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AnySchema, JoiValidationError } from '@naturalcycles/nodejs-lib';
|
|
2
|
-
import { BackendRequest
|
|
2
|
+
import { BackendRequest } from '../server.model';
|
|
3
3
|
export interface ReqValidationOptions<ERR extends Error> {
|
|
4
4
|
/**
|
|
5
5
|
* Pass a 'dot-paths' (e.g `pw`, or `input.pw`) that needs to be redacted from the output, in case of error.
|
|
@@ -12,7 +12,6 @@ export interface ReqValidationOptions<ERR extends Error> {
|
|
|
12
12
|
*/
|
|
13
13
|
report?: boolean | ((err: ERR) => boolean);
|
|
14
14
|
}
|
|
15
|
-
export declare function reqValidation(reqProperty: 'body' | 'params' | 'query', schema: AnySchema, opt?: ReqValidationOptions<JoiValidationError>): BackendRequestHandler;
|
|
16
15
|
declare class ValidateRequest {
|
|
17
16
|
body<T>(req: BackendRequest, schema: AnySchema<T>, opt?: ReqValidationOptions<JoiValidationError>): T;
|
|
18
17
|
query<T>(req: BackendRequest, schema: AnySchema<T>, opt?: ReqValidationOptions<JoiValidationError>): T;
|
|
@@ -1,32 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateRequest =
|
|
3
|
+
exports.validateRequest = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const REDACTED = 'REDACTED';
|
|
7
|
-
function reqValidation(reqProperty, schema, opt = {}) {
|
|
8
|
-
const reportPredicate = typeof opt.report === 'function' ? opt.report : () => opt.report;
|
|
9
|
-
return (req, res, next) => {
|
|
10
|
-
const { value, error } = (0, nodejs_lib_1.getValidationResult)(req[reqProperty], schema, `request ${reqProperty}`);
|
|
11
|
-
if (error) {
|
|
12
|
-
const report = reportPredicate(error);
|
|
13
|
-
if (opt.redactPaths) {
|
|
14
|
-
redact(opt.redactPaths, req[reqProperty], error);
|
|
15
|
-
error.data.joiValidationErrorItems.length = 0; // clears the array
|
|
16
|
-
delete error.data.annotation;
|
|
17
|
-
}
|
|
18
|
-
return next(new js_lib_1.AppError(error.message, {
|
|
19
|
-
backendResponseStatusCode: 400,
|
|
20
|
-
report,
|
|
21
|
-
...error.data,
|
|
22
|
-
}));
|
|
23
|
-
}
|
|
24
|
-
// mutate req to replace the property with the value, converted by Joi
|
|
25
|
-
req[reqProperty] = value;
|
|
26
|
-
next();
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
exports.reqValidation = reqValidation;
|
|
30
7
|
/**
|
|
31
8
|
* Mutates error
|
|
32
9
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ZodSchema, ZodValidationError } from '@naturalcycles/js-lib';
|
|
2
2
|
import { BackendRequestHandler } from '../server.model';
|
|
3
|
-
import { ReqValidationOptions } from './
|
|
3
|
+
import { ReqValidationOptions } from './validateRequest';
|
|
4
4
|
/**
|
|
5
5
|
* Validates req property (body, params or query).
|
|
6
6
|
* Supports Joi schema or AjvSchema (from nodejs-lib).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky",
|
|
6
6
|
"dev": "APP_ENV=dev nodemon",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"yargs": "^17.0.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@naturalcycles/bench-lib": "^
|
|
39
|
+
"@naturalcycles/bench-lib": "^2.0.0",
|
|
40
40
|
"@naturalcycles/dev-lib": "^13.0.0",
|
|
41
41
|
"@sentry/node": "^7.0.0",
|
|
42
42
|
"@types/ejs": "^3.0.0",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppError } from '@naturalcycles/js-lib'
|
|
2
|
+
import { timingSafeStringEqual } from '@naturalcycles/nodejs-lib'
|
|
2
3
|
import { BackendRequestHandler } from '../server/server.model'
|
|
3
4
|
import { AdminMiddleware, RequireAdminCfg, requireAdminPermissions } from './adminMiddleware'
|
|
4
5
|
import { BaseAdminService } from './base.admin.service'
|
|
@@ -41,7 +42,8 @@ function requireSecureHeaderOrAdmin(
|
|
|
41
42
|
|
|
42
43
|
// Header provided - don't check for Admin
|
|
43
44
|
if (providedHeader) {
|
|
44
|
-
if (!secureHeaderValue || providedHeader
|
|
45
|
+
if (!secureHeaderValue || timingSafeStringEqual(providedHeader, secureHeaderValue))
|
|
46
|
+
return next()
|
|
45
47
|
|
|
46
48
|
return next(
|
|
47
49
|
new AppError('secureHeader or adminToken is required', {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from '@naturalcycles/db-lib/dist/validation'
|
|
13
13
|
import { ObjectWithId } from '@naturalcycles/js-lib'
|
|
14
14
|
import { anyObjectSchema, arraySchema, objectSchema, stringSchema } from '@naturalcycles/nodejs-lib'
|
|
15
|
-
import { BackendRouter, getDefaultRouter,
|
|
15
|
+
import { BackendRouter, getDefaultRouter, validateRequest } from '..'
|
|
16
16
|
|
|
17
17
|
export interface GetByIdsInput {
|
|
18
18
|
table: string
|
|
@@ -84,28 +84,28 @@ export function httpDBRequestHandler(db: CommonDB): BackendRouter {
|
|
|
84
84
|
// })
|
|
85
85
|
|
|
86
86
|
// getByIds
|
|
87
|
-
router.put('/getByIds',
|
|
88
|
-
const { table, ids, opt } =
|
|
87
|
+
router.put('/getByIds', async (req, res) => {
|
|
88
|
+
const { table, ids, opt } = validateRequest.body(req, getByIdsInputSchema)
|
|
89
89
|
res.json(await db.getByIds(table, ids, opt))
|
|
90
90
|
})
|
|
91
91
|
|
|
92
92
|
// runQuery
|
|
93
|
-
router.put('/runQuery',
|
|
94
|
-
const { query, opt } =
|
|
93
|
+
router.put('/runQuery', async (req, res) => {
|
|
94
|
+
const { query, opt } = validateRequest.body(req, runQueryInputSchema)
|
|
95
95
|
const q = DBQuery.fromPlainObject(query)
|
|
96
96
|
res.json(await db.runQuery(q, opt))
|
|
97
97
|
})
|
|
98
98
|
|
|
99
99
|
// runQueryCount
|
|
100
|
-
router.put('/runQueryCount',
|
|
101
|
-
const { query, opt } =
|
|
100
|
+
router.put('/runQueryCount', async (req, res) => {
|
|
101
|
+
const { query, opt } = validateRequest.body(req, runQueryInputSchema)
|
|
102
102
|
const q = DBQuery.fromPlainObject(query)
|
|
103
103
|
res.json(await db.runQueryCount(q, opt))
|
|
104
104
|
})
|
|
105
105
|
|
|
106
106
|
// saveBatch
|
|
107
|
-
router.put('/saveBatch',
|
|
108
|
-
const { table, rows, opt } =
|
|
107
|
+
router.put('/saveBatch', async (req, res) => {
|
|
108
|
+
const { table, rows, opt } = validateRequest.body(req, saveBatchInputSchema)
|
|
109
109
|
await db.saveBatch(table, rows, opt)
|
|
110
110
|
res.end()
|
|
111
111
|
})
|
|
@@ -117,8 +117,8 @@ export function httpDBRequestHandler(db: CommonDB): BackendRouter {
|
|
|
117
117
|
// })
|
|
118
118
|
|
|
119
119
|
// deleteByQuery
|
|
120
|
-
router.put('/deleteByQuery',
|
|
121
|
-
const { query, opt } =
|
|
120
|
+
router.put('/deleteByQuery', async (req, res) => {
|
|
121
|
+
const { query, opt } = validateRequest.body(req, runQueryInputSchema)
|
|
122
122
|
const q = DBQuery.fromPlainObject(query)
|
|
123
123
|
res.json(await db.deleteByQuery(q, opt))
|
|
124
124
|
})
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ export * from './server/notFoundMiddleware'
|
|
|
20
20
|
export * from './server/okMiddleware'
|
|
21
21
|
export * from './server/basicAuthMiddleware'
|
|
22
22
|
export * from './server/requestTimeoutMiddleware'
|
|
23
|
-
export * from './server/validation/
|
|
23
|
+
export * from './server/validation/validateRequest'
|
|
24
24
|
export * from './server/simpleRequestLoggerMiddleware'
|
|
25
25
|
export * from './server/serverStatusMiddleware'
|
|
26
26
|
export * from './server/validation/validateMiddleware'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _split, StringMap } from '@naturalcycles/js-lib'
|
|
2
|
-
import { base64ToString } from '@naturalcycles/nodejs-lib'
|
|
2
|
+
import { base64ToString, timingSafeStringEqual } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { BackendRequestHandler } from './server.model'
|
|
4
4
|
|
|
5
5
|
export interface BasicAuthMiddlewareCfg {
|
|
@@ -21,7 +21,7 @@ export function basicAuthMiddleware(cfg: BasicAuthMiddlewareCfg): BackendRequest
|
|
|
21
21
|
const hash = (req.headers.authorization || '').split(' ')[1]
|
|
22
22
|
if (hash) {
|
|
23
23
|
const [login, password] = _split(base64ToString(hash), ':', 2)
|
|
24
|
-
if (login && password && cfg.loginPasswordMap[login]
|
|
24
|
+
if (login && password && timingSafeStringEqual(cfg.loginPasswordMap[login], password)) {
|
|
25
25
|
return next()
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JsonSchema, JsonSchemaBuilder, _get, AppError } from '@naturalcycles/js-lib'
|
|
2
2
|
import { AjvSchema, AjvValidationError } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { BackendRequestHandler } from '../server.model'
|
|
4
|
-
import { ReqValidationOptions } from './
|
|
4
|
+
import { ReqValidationOptions } from './validateRequest'
|
|
5
5
|
|
|
6
6
|
const REDACTED = 'REDACTED'
|
|
7
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _get, AppError } from '@naturalcycles/js-lib'
|
|
2
2
|
import { AnySchema, getValidationResult, JoiValidationError } from '@naturalcycles/nodejs-lib'
|
|
3
|
-
import { BackendRequest
|
|
3
|
+
import { BackendRequest } from '../server.model'
|
|
4
4
|
|
|
5
5
|
const REDACTED = 'REDACTED'
|
|
6
6
|
|
|
@@ -18,40 +18,6 @@ export interface ReqValidationOptions<ERR extends Error> {
|
|
|
18
18
|
report?: boolean | ((err: ERR) => boolean)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function reqValidation(
|
|
22
|
-
reqProperty: 'body' | 'params' | 'query',
|
|
23
|
-
schema: AnySchema,
|
|
24
|
-
opt: ReqValidationOptions<JoiValidationError> = {},
|
|
25
|
-
): BackendRequestHandler {
|
|
26
|
-
const reportPredicate =
|
|
27
|
-
typeof opt.report === 'function' ? opt.report : () => opt.report as boolean | undefined
|
|
28
|
-
|
|
29
|
-
return (req, res, next) => {
|
|
30
|
-
const { value, error } = getValidationResult(req[reqProperty], schema, `request ${reqProperty}`)
|
|
31
|
-
if (error) {
|
|
32
|
-
const report = reportPredicate(error)
|
|
33
|
-
|
|
34
|
-
if (opt.redactPaths) {
|
|
35
|
-
redact(opt.redactPaths, req[reqProperty], error)
|
|
36
|
-
error.data.joiValidationErrorItems.length = 0 // clears the array
|
|
37
|
-
delete error.data.annotation
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return next(
|
|
41
|
-
new AppError(error.message, {
|
|
42
|
-
backendResponseStatusCode: 400,
|
|
43
|
-
report,
|
|
44
|
-
...error.data,
|
|
45
|
-
}),
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// mutate req to replace the property with the value, converted by Joi
|
|
50
|
-
req[reqProperty] = value
|
|
51
|
-
next()
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
21
|
/**
|
|
56
22
|
* Mutates error
|
|
57
23
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _get, AppError, ZodSchema, ZodValidationError, zSafeValidate } from '@naturalcycles/js-lib'
|
|
2
2
|
import { BackendRequestHandler } from '../server.model'
|
|
3
|
-
import { ReqValidationOptions } from './
|
|
3
|
+
import { ReqValidationOptions } from './validateRequest'
|
|
4
4
|
|
|
5
5
|
const REDACTED = 'REDACTED'
|
|
6
6
|
|