xpref 1.0.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/api-docs/body-schema.d.ts +1 -0
- package/api-docs/body-schema.js +31 -0
- package/api-docs/index.d.ts +3 -0
- package/api-docs/index.js +49 -0
- package/api-docs/parameter-schema.d.ts +1 -0
- package/api-docs/parameter-schema.js +57 -0
- package/api-docs/path-schema.d.ts +1 -0
- package/api-docs/path-schema.js +31 -0
- package/api-docs/path.d.ts +2 -0
- package/api-docs/path.js +79 -0
- package/api-docs/schema.d.ts +1 -0
- package/api-docs/schema.js +42 -0
- package/api-docs/security.d.ts +1 -0
- package/api-docs/security.js +48 -0
- package/api-docs/types.d.ts +27 -0
- package/api-docs/types.js +2 -0
- package/debug.d.ts +6 -0
- package/debug.js +26 -0
- package/i18n/index.d.ts +9 -0
- package/i18n/index.js +51 -0
- package/idempotency/index.d.ts +7 -0
- package/idempotency/index.js +130 -0
- package/idempotency/storage.d.ts +36 -0
- package/idempotency/storage.js +54 -0
- package/index.d.ts +7 -0
- package/index.js +126 -0
- package/package.json +36 -0
- package/request-forwarder/common.d.ts +11 -0
- package/request-forwarder/common.js +36 -0
- package/request-forwarder/forwarder.d.ts +2 -0
- package/request-forwarder/forwarder.js +81 -0
- package/request-forwarder/index.d.ts +2 -0
- package/request-forwarder/index.js +10 -0
- package/request-forwarder/pass-to-next.d.ts +4 -0
- package/request-forwarder/pass-to-next.js +48 -0
- package/request-forwarder/proxy.d.ts +8 -0
- package/request-forwarder/proxy.js +34 -0
- package/request-id.d.ts +7 -0
- package/request-id.js +19 -0
- package/request-log.d.ts +3 -0
- package/request-log.js +88 -0
- package/router.d.ts +13 -0
- package/router.js +65 -0
- package/setting/index.d.ts +1 -0
- package/setting/index.js +6 -0
- package/static.d.ts +2 -0
- package/static.js +12 -0
- package/types.d.ts +52 -0
- package/types.js +2 -0
- package/utils.d.ts +5 -0
- package/utils.js +22 -0
- package/validator/method-validator.d.ts +6 -0
- package/validator/method-validator.js +45 -0
- package/validator/route-schema.d.ts +2 -0
- package/validator/route-schema.js +71 -0
- package/validator/schema.d.ts +15 -0
- package/validator/schema.js +63 -0
- package/validator/validate.d.ts +8 -0
- package/validator/validate.js +94 -0
- package/validator/validator.test.d.ts +0 -0
- package/validator/validator.test.js +6 -0
package/router.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = registerRoutes;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const getMethodHandlers = (handlerOptions, options = {}) => {
|
|
6
|
+
if (Array.isArray(handlerOptions))
|
|
7
|
+
return handlerOptions;
|
|
8
|
+
if (typeof handlerOptions === 'function')
|
|
9
|
+
return [handlerOptions];
|
|
10
|
+
const { action, params } = handlerOptions;
|
|
11
|
+
if (!(params || false))
|
|
12
|
+
return Array.isArray(action) ? action : [action];
|
|
13
|
+
const { validator } = options;
|
|
14
|
+
const validatorMiddleware = validator({ params });
|
|
15
|
+
const methodHandlers = Array.isArray(action) ? action : [action];
|
|
16
|
+
return [validatorMiddleware, ...methodHandlers];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Registers the verb handlers to routes
|
|
20
|
+
* @property {any} handlers
|
|
21
|
+
* @property {any} router
|
|
22
|
+
*/
|
|
23
|
+
const registerHandler = ({ handlers, router }, options = {}) => {
|
|
24
|
+
const methods = Object.keys(handlers);
|
|
25
|
+
const path = '/';
|
|
26
|
+
methods.forEach((method) => {
|
|
27
|
+
const methodHandlers = handlers[method];
|
|
28
|
+
const callbacks = getMethodHandlers(methodHandlers, options);
|
|
29
|
+
router[method](path, ...callbacks);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Creates router for path information
|
|
34
|
+
* @param {PathDetail} pathDetail - The path default defined after uri
|
|
35
|
+
* @return router
|
|
36
|
+
*/
|
|
37
|
+
const createRouter = (pathHandler, options) => {
|
|
38
|
+
const router = (0, express_1.Router)({ mergeParams: true });
|
|
39
|
+
const [_name, middlewares, handlers, children = {}] = pathHandler;
|
|
40
|
+
if (middlewares.length > 0)
|
|
41
|
+
router.use(...middlewares);
|
|
42
|
+
registerHandler({ handlers, router }, options);
|
|
43
|
+
const childPaths = Object.keys(children);
|
|
44
|
+
if (childPaths.length === 0)
|
|
45
|
+
return router;
|
|
46
|
+
childPaths.forEach((childPath) => {
|
|
47
|
+
const childRouter = createRouter(children[childPath], options);
|
|
48
|
+
router.use(childPath, childRouter);
|
|
49
|
+
});
|
|
50
|
+
return router;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Registers routes configuration, the way to register routes
|
|
54
|
+
* is based on route base, not url base
|
|
55
|
+
* @param {Application} app - Express Application
|
|
56
|
+
* @param {Route} routes - Routes configuration
|
|
57
|
+
*/
|
|
58
|
+
function registerRoutes(app, routes, options) {
|
|
59
|
+
const paths = Object.keys(routes);
|
|
60
|
+
paths.forEach((path) => {
|
|
61
|
+
const pathDetail = routes[path];
|
|
62
|
+
const router = createRouter(pathDetail, options);
|
|
63
|
+
app.use(path, router);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function getSetting(): Date;
|
package/setting/index.js
ADDED
package/static.d.ts
ADDED
package/static.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = registerStatic;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const express_1 = require("express");
|
|
6
|
+
function registerStatic(app, staticRoutes = {}) {
|
|
7
|
+
const keys = Object.keys(staticRoutes);
|
|
8
|
+
keys.forEach((path) => {
|
|
9
|
+
const location = (0, path_1.resolve)(staticRoutes[path]);
|
|
10
|
+
app.use(path, (0, express_1.static)(location));
|
|
11
|
+
});
|
|
12
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Application } from 'express';
|
|
2
|
+
import type { IncomingMessage } from 'http';
|
|
3
|
+
export type { IncomingMessage } from 'http';
|
|
4
|
+
export type { Request, Response, NextFunction, Application } from 'express';
|
|
5
|
+
export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch';
|
|
6
|
+
type MethodHandlerAction = CallableFunction | CallableFunction[];
|
|
7
|
+
type Params = {
|
|
8
|
+
query?: any;
|
|
9
|
+
path?: any;
|
|
10
|
+
body?: any;
|
|
11
|
+
};
|
|
12
|
+
export type MethodOptions = MethodHandlerAction | {
|
|
13
|
+
action: MethodHandlerAction;
|
|
14
|
+
params?: Params;
|
|
15
|
+
description?: string | [string, string];
|
|
16
|
+
};
|
|
17
|
+
export type MethodHandler = {
|
|
18
|
+
get?: MethodOptions;
|
|
19
|
+
post?: MethodOptions;
|
|
20
|
+
put?: MethodOptions;
|
|
21
|
+
delete?: MethodOptions;
|
|
22
|
+
patch?: MethodOptions;
|
|
23
|
+
};
|
|
24
|
+
export type PathMiddleware = Array<any>;
|
|
25
|
+
export type PathDetail = [string, PathMiddleware, MethodHandler] | [string, PathMiddleware, MethodHandler, Record<string, PathDetail>];
|
|
26
|
+
export type Route = Record<any, PathDetail>;
|
|
27
|
+
type OnInit = (_app: Application) => void;
|
|
28
|
+
export type API = {
|
|
29
|
+
appName: string;
|
|
30
|
+
appEnv: string;
|
|
31
|
+
port?: number;
|
|
32
|
+
routes: Route;
|
|
33
|
+
logger?: any;
|
|
34
|
+
staticRoutes?: Record<string, string>;
|
|
35
|
+
interceptor?: any;
|
|
36
|
+
onInit?: OnInit;
|
|
37
|
+
schemas?: Record<string, any>;
|
|
38
|
+
manuallyStart?: any;
|
|
39
|
+
};
|
|
40
|
+
export type RequestForwarder = {
|
|
41
|
+
host: string;
|
|
42
|
+
proxyPrefix?: string;
|
|
43
|
+
withPrefix?: boolean;
|
|
44
|
+
headers?: Record<string, string | boolean | number>;
|
|
45
|
+
onUrlConstructed?: (url: string) => string;
|
|
46
|
+
passToNext?: boolean;
|
|
47
|
+
};
|
|
48
|
+
export type ProxyResult = {
|
|
49
|
+
statusCode: number;
|
|
50
|
+
headers: IncomingMessage['headers'];
|
|
51
|
+
body: Buffer;
|
|
52
|
+
};
|
package/types.js
ADDED
package/utils.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Response } from 'express';
|
|
2
|
+
export declare const responseError: (res: Response, message: any, statusCode?: number) => Response<any, Record<string, any>>;
|
|
3
|
+
type DecodedSchema = [string, boolean, string[]];
|
|
4
|
+
export declare const decodeSchemaName: (schemaName: string, accuRequired?: string[]) => DecodedSchema;
|
|
5
|
+
export {};
|
package/utils.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeSchemaName = exports.responseError = void 0;
|
|
4
|
+
const responseError = (res, message, statusCode = 400) => {
|
|
5
|
+
const objMsg = typeof message === 'string' ? { message } : message;
|
|
6
|
+
const errorResult = {
|
|
7
|
+
error: true,
|
|
8
|
+
status: statusCode,
|
|
9
|
+
...objMsg,
|
|
10
|
+
};
|
|
11
|
+
return res
|
|
12
|
+
.status(statusCode)
|
|
13
|
+
.send(errorResult);
|
|
14
|
+
};
|
|
15
|
+
exports.responseError = responseError;
|
|
16
|
+
const decodeSchemaName = (schemaName, accuRequired = []) => {
|
|
17
|
+
const [field, isRequired = false] = schemaName.split('*');
|
|
18
|
+
if (isRequired === false)
|
|
19
|
+
return [field, false, accuRequired];
|
|
20
|
+
return [field, true, [...accuRequired, field]];
|
|
21
|
+
};
|
|
22
|
+
exports.decodeSchemaName = decodeSchemaName;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction, MethodOptions } from '../types';
|
|
2
|
+
type SchemaOptions = {
|
|
3
|
+
domainName?: string;
|
|
4
|
+
};
|
|
5
|
+
export default function initMethodValidation(pSchemas: any, options?: SchemaOptions): (methodOptions: MethodOptions) => (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = initMethodValidation;
|
|
7
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
8
|
+
const ajvErrors = require('ajv-errors');
|
|
9
|
+
const schema_1 = require("./schema");
|
|
10
|
+
const validate_1 = require("./validate");
|
|
11
|
+
const ajvOptions = {
|
|
12
|
+
allErrors: true,
|
|
13
|
+
$data: true,
|
|
14
|
+
strict: true,
|
|
15
|
+
coerceTypes: true,
|
|
16
|
+
schemas: [],
|
|
17
|
+
};
|
|
18
|
+
const ajv = new ajv_1.default(ajvOptions);
|
|
19
|
+
ajvErrors(ajv);
|
|
20
|
+
function initMethodValidation(pSchemas, options = {}) {
|
|
21
|
+
const { domainName = 'common' } = options;
|
|
22
|
+
const schemas = (0, schema_1.getObjectSchema)({
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: pSchemas,
|
|
25
|
+
required: [],
|
|
26
|
+
}, domainName);
|
|
27
|
+
ajv.addSchema(schemas);
|
|
28
|
+
return (methodOptions) => {
|
|
29
|
+
const sources = Object.keys(methodOptions);
|
|
30
|
+
return (req, res, next) => {
|
|
31
|
+
if (sources.length === 0)
|
|
32
|
+
return next();
|
|
33
|
+
const errors = (0, validate_1.validate)(ajv, {
|
|
34
|
+
methodOptions,
|
|
35
|
+
request: req,
|
|
36
|
+
});
|
|
37
|
+
if (errors.length === 0)
|
|
38
|
+
return next();
|
|
39
|
+
return res.status(400).json({
|
|
40
|
+
error: true,
|
|
41
|
+
errors: (0, validate_1.getErrors)(errors),
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = getRouteSchema;
|
|
4
|
+
const utils_1 = require("../utils");
|
|
5
|
+
const schema_1 = require("./schema");
|
|
6
|
+
const getSchemaFromString = (accu, refName) => {
|
|
7
|
+
const [accuProps, accuRequired] = accu;
|
|
8
|
+
const [schemaName, _re, required] = (0, utils_1.decodeSchemaName)(refName, accuRequired);
|
|
9
|
+
return [
|
|
10
|
+
{ ...accuProps, [schemaName]: (0, schema_1.getRefSchema)(schemaName, 'common.js') },
|
|
11
|
+
required,
|
|
12
|
+
];
|
|
13
|
+
};
|
|
14
|
+
const getSchemasOfArrayProps = (properties, required = []) => {
|
|
15
|
+
const result = properties.reduce((accu, prop) => {
|
|
16
|
+
const isString = typeof prop === 'string';
|
|
17
|
+
if (isString)
|
|
18
|
+
return getSchemaFromString(accu, prop);
|
|
19
|
+
const [accuProps, accuRequired] = accu;
|
|
20
|
+
const [name, props] = prop;
|
|
21
|
+
const [schemaName, _req, nextRequired] = (0, utils_1.decodeSchemaName)(name, accuRequired);
|
|
22
|
+
return [
|
|
23
|
+
{ ...accuProps, [schemaName]: getObjectSchema(props) },
|
|
24
|
+
nextRequired,
|
|
25
|
+
];
|
|
26
|
+
}, [{}, required]);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
const getSchemasOfObjectProps = (properties, required = []) => {
|
|
30
|
+
const names = Object.keys(properties);
|
|
31
|
+
const result = names.reduce((accu) => accu, [{}, required]);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
const injectId = (props, id = '') => {
|
|
35
|
+
if (id === '')
|
|
36
|
+
return props;
|
|
37
|
+
return { ...props, $id: id };
|
|
38
|
+
};
|
|
39
|
+
function getObjectSchema(schemaProps, id = '') {
|
|
40
|
+
const { type = 'string' } = schemaProps;
|
|
41
|
+
if (type !== 'object') {
|
|
42
|
+
const res = (0, schema_1.senitizeSchema)(schemaProps);
|
|
43
|
+
return res;
|
|
44
|
+
}
|
|
45
|
+
;
|
|
46
|
+
const { properties = [], required = [] } = schemaProps;
|
|
47
|
+
const isArray = Array.isArray(properties);
|
|
48
|
+
const [nextProps, nextRequired] = (isArray)
|
|
49
|
+
? getSchemasOfArrayProps(properties, required)
|
|
50
|
+
: getSchemasOfObjectProps(properties, required);
|
|
51
|
+
const result = { properties: nextProps, required: nextRequired, type: 'object' };
|
|
52
|
+
return injectId(result, id);
|
|
53
|
+
}
|
|
54
|
+
;
|
|
55
|
+
function getRouteSchema(methodOptions) {
|
|
56
|
+
const { params = {} } = methodOptions;
|
|
57
|
+
return ['query', 'params', 'body'].reduce((accu, dataSlot) => {
|
|
58
|
+
const properties = params[dataSlot] || [];
|
|
59
|
+
const isArray = Array.isArray(properties);
|
|
60
|
+
const isEmpty = isArray && properties.length == 0;
|
|
61
|
+
if (isEmpty)
|
|
62
|
+
return accu;
|
|
63
|
+
const schemaProps = isArray
|
|
64
|
+
? { properties, type: 'object' }
|
|
65
|
+
: { type: 'object', ...properties };
|
|
66
|
+
const now = new Date().getTime();
|
|
67
|
+
const schema = getObjectSchema(schemaProps, `${schema_1.domain}/${dataSlot}-${now}.js`);
|
|
68
|
+
return { ...accu, [dataSlot]: schema };
|
|
69
|
+
}, {});
|
|
70
|
+
}
|
|
71
|
+
;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type ObjectSchema = {
|
|
2
|
+
type?: string;
|
|
3
|
+
properties: string[];
|
|
4
|
+
required?: string[];
|
|
5
|
+
$id?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const senitizeSchema: (schemaProps: Record<string, any>) => {
|
|
8
|
+
type: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const domain = "https://schemas.api.com";
|
|
11
|
+
export declare const getRefSchema: (name: string, ref: string) => {
|
|
12
|
+
$ref: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function getObjectSchema(schema: ObjectSchema, id?: string | false, ref?: string): ObjectSchema;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRefSchema = exports.domain = exports.senitizeSchema = void 0;
|
|
4
|
+
exports.getObjectSchema = getObjectSchema;
|
|
5
|
+
const senitizeSchema = (schemaProps) => {
|
|
6
|
+
const { example: _ex, ...senitizedSchema } = schemaProps;
|
|
7
|
+
return { type: 'string', ...senitizedSchema };
|
|
8
|
+
};
|
|
9
|
+
exports.senitizeSchema = senitizeSchema;
|
|
10
|
+
exports.domain = 'https://schemas.api.com';
|
|
11
|
+
const getRef = (refName, ref = '') => `${ref}#/properties/${refName}`;
|
|
12
|
+
const getRefSchema = (name, ref) => ({
|
|
13
|
+
$ref: getRef(name, ref),
|
|
14
|
+
});
|
|
15
|
+
exports.getRefSchema = getRefSchema;
|
|
16
|
+
const getArrayProperties = (properties, ref = '') => {
|
|
17
|
+
if (properties.length === 0)
|
|
18
|
+
return properties;
|
|
19
|
+
const touchedProperties = properties.reduce((accu, prop) => {
|
|
20
|
+
const isString = typeof prop === 'string';
|
|
21
|
+
if (isString)
|
|
22
|
+
return { ...accu, [prop]: (0, exports.getRefSchema)(prop, ref) };
|
|
23
|
+
const [schemaName, schemaProps] = prop;
|
|
24
|
+
const type = schemaProps.type || 'string';
|
|
25
|
+
if (type !== 'object')
|
|
26
|
+
return {
|
|
27
|
+
...accu,
|
|
28
|
+
[schemaName]: (0, exports.senitizeSchema)(schemaProps),
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
...accu,
|
|
32
|
+
[schemaName]: getObjectSchema(schemaProps),
|
|
33
|
+
};
|
|
34
|
+
}, {});
|
|
35
|
+
return touchedProperties;
|
|
36
|
+
};
|
|
37
|
+
const getObjectProperties = (properties) => {
|
|
38
|
+
const schemaNames = Object.keys(properties);
|
|
39
|
+
const nextProperties = schemaNames.reduce((accu, schemaName) => {
|
|
40
|
+
const schemaProps = properties[schemaName];
|
|
41
|
+
const type = schemaProps.type || 'string';
|
|
42
|
+
if (type !== 'object')
|
|
43
|
+
return { ...accu, [schemaName]: (0, exports.senitizeSchema)(schemaProps) };
|
|
44
|
+
return { ...accu, [schemaName]: getObjectSchema(schemaProps, false) };
|
|
45
|
+
}, {});
|
|
46
|
+
return nextProperties;
|
|
47
|
+
};
|
|
48
|
+
function getObjectSchema(schema, id = false, ref = '') {
|
|
49
|
+
const { properties, required = [] } = schema;
|
|
50
|
+
const isArray = Array.isArray(properties);
|
|
51
|
+
const nextProperties = isArray
|
|
52
|
+
? getArrayProperties(properties, ref)
|
|
53
|
+
: getObjectProperties(properties);
|
|
54
|
+
const result = {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: nextProperties,
|
|
57
|
+
required,
|
|
58
|
+
};
|
|
59
|
+
if (!id)
|
|
60
|
+
return result;
|
|
61
|
+
const refId = `${exports.domain}/${id}.js`;
|
|
62
|
+
return { ...result, $id: refId };
|
|
63
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Request, MethodOptions } from '../types';
|
|
2
|
+
type ValidationProps = {
|
|
3
|
+
request: Request;
|
|
4
|
+
methodOptions: MethodOptions;
|
|
5
|
+
};
|
|
6
|
+
export declare const getErrors: (errors: any) => any;
|
|
7
|
+
export declare const validate: (ajv: any, pProps: ValidationProps) => any;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validate = exports.getErrors = void 0;
|
|
7
|
+
const route_schema_1 = __importDefault(require("./route-schema"));
|
|
8
|
+
const anyOfRequiredField = [];
|
|
9
|
+
const caseToWords = (field) => field
|
|
10
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2') // split camelCase => camel Case
|
|
11
|
+
.replace(/[_-]/g, ' ')
|
|
12
|
+
.replace(/\s+/g, ' ') // replace multi space with single one
|
|
13
|
+
.replace(/\b[a-z]/g, (char) => char.toUpperCase()) // capitalize text => Text
|
|
14
|
+
.trim(); // remove start/end space
|
|
15
|
+
const getRequestData = (req) => {
|
|
16
|
+
const { query, params, body } = req;
|
|
17
|
+
return { query, params, body };
|
|
18
|
+
};
|
|
19
|
+
const splitField = (field, delimiter = '/') => {
|
|
20
|
+
const fields = field.split(delimiter);
|
|
21
|
+
return fields[fields.length - 1];
|
|
22
|
+
};
|
|
23
|
+
const customMsg = (params, keyword, message) => {
|
|
24
|
+
const { missingProperty = '' } = params;
|
|
25
|
+
let newMsg = message;
|
|
26
|
+
switch (keyword) {
|
|
27
|
+
case 'required':
|
|
28
|
+
anyOfRequiredField.push(missingProperty);
|
|
29
|
+
const words = caseToWords(missingProperty);
|
|
30
|
+
newMsg = `${words} field is required.`;
|
|
31
|
+
break;
|
|
32
|
+
case 'anyOf':
|
|
33
|
+
newMsg = `Must has anyOf the field ${anyOfRequiredField}`;
|
|
34
|
+
anyOfRequiredField.splice(0, anyOfRequiredField.length);
|
|
35
|
+
break;
|
|
36
|
+
case 'maximum':
|
|
37
|
+
newMsg = message.replace('<=', 'less than or equal to');
|
|
38
|
+
break;
|
|
39
|
+
case 'minimum':
|
|
40
|
+
newMsg = message.replace('>=', 'greater than or equal to');
|
|
41
|
+
break;
|
|
42
|
+
case 'minLength':
|
|
43
|
+
newMsg = message.replace('NOT have fewer than', 'be at least');
|
|
44
|
+
break;
|
|
45
|
+
case 'enum':
|
|
46
|
+
newMsg = `${message} ${JSON.stringify(params.allowedValues)}`;
|
|
47
|
+
break;
|
|
48
|
+
default: break;
|
|
49
|
+
}
|
|
50
|
+
return newMsg;
|
|
51
|
+
};
|
|
52
|
+
const getErrorMsg = (error) => {
|
|
53
|
+
const { instancePath = '', params = {}, keyword = '', message, } = error;
|
|
54
|
+
const newMessage = customMsg(params, keyword, message);
|
|
55
|
+
if (instancePath === '')
|
|
56
|
+
return newMessage;
|
|
57
|
+
const errorField = splitField(instancePath, '/');
|
|
58
|
+
return `${caseToWords(errorField)} ${newMessage}`;
|
|
59
|
+
};
|
|
60
|
+
const getErrorField = (error) => {
|
|
61
|
+
const { params, keyword } = error;
|
|
62
|
+
switch (keyword) {
|
|
63
|
+
case 'required':
|
|
64
|
+
return splitField(params.missingProperty, '.');
|
|
65
|
+
case 'anyOf':
|
|
66
|
+
return 'anyOf';
|
|
67
|
+
default:
|
|
68
|
+
return splitField(error.instancePath, '/');
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const getErrors = (errors) => (errors.reduce((acc, error) => {
|
|
72
|
+
const field = getErrorField(error);
|
|
73
|
+
const message = getErrorMsg(error);
|
|
74
|
+
return { ...acc, [field]: message };
|
|
75
|
+
}, {}));
|
|
76
|
+
exports.getErrors = getErrors;
|
|
77
|
+
const validate = (ajv, pProps) => {
|
|
78
|
+
const { methodOptions, request } = pProps;
|
|
79
|
+
const requestData = getRequestData(request);
|
|
80
|
+
const schemaData = (0, route_schema_1.default)(methodOptions);
|
|
81
|
+
const dataSlots = Object.keys(schemaData);
|
|
82
|
+
const validatedRequest = dataSlots.reduce((accu, dataSlot) => {
|
|
83
|
+
const schema = schemaData[dataSlot];
|
|
84
|
+
const data = requestData[dataSlot];
|
|
85
|
+
const ajvValidate = ajv.compile({ type: 'object', ...schema });
|
|
86
|
+
const valid = ajvValidate(data);
|
|
87
|
+
ajv.removeSchema(schema.$id);
|
|
88
|
+
if (valid)
|
|
89
|
+
return accu;
|
|
90
|
+
return [...accu, ...ajvValidate.errors];
|
|
91
|
+
}, []);
|
|
92
|
+
return validatedRequest;
|
|
93
|
+
};
|
|
94
|
+
exports.validate = validate;
|
|
File without changes
|