@kipicore/dbcore 1.1.660 → 1.1.662
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/commonValidator/commandValidator.d.ts +27 -0
- package/dist/commonValidator/commandValidator.js +225 -0
- package/dist/commonValidator/index.d.ts +2 -0
- package/dist/commonValidator/index.js +18 -0
- package/dist/commonValidator/joiCommonValidator.d.ts +12 -0
- package/dist/commonValidator/joiCommonValidator.js +47 -0
- package/dist/commonValidator/joiSchemaBuilder.d.ts +6 -0
- package/dist/commonValidator/joiSchemaBuilder.js +70 -0
- package/dist/helpers/utils.d.ts +2 -3
- package/dist/helpers/utils.js +46 -31
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/types/commonType.d.ts +19 -0
- package/package.json +5 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Joi from 'joi';
|
|
2
|
+
import { Request, Response, NextFunction } from 'express';
|
|
3
|
+
import BaseValidator from './joiSchemaBuilder';
|
|
4
|
+
import { CrudValidatorRules } from '../types/commonType';
|
|
5
|
+
export default class BaseCrudValidator<TModel extends Record<string, any>, TKeys extends Extract<keyof TModel, string> = Extract<keyof TModel, string>> extends BaseValidator {
|
|
6
|
+
protected baseSchema: Joi.ObjectSchema<any>;
|
|
7
|
+
protected rules: CrudValidatorRules<TKeys>;
|
|
8
|
+
constructor(baseSchema: Joi.ObjectSchema<any>, rules?: CrudValidatorRules<TKeys>);
|
|
9
|
+
/** MERGE RULES */
|
|
10
|
+
private mergeRules;
|
|
11
|
+
/** APPLY DEFAULT ID RULE */
|
|
12
|
+
private applyDefaultIdRule;
|
|
13
|
+
/** Nested Required for */
|
|
14
|
+
private applyNestedRequired;
|
|
15
|
+
/** CREATE */
|
|
16
|
+
createValidator: (req: Request, res: Response, next: NextFunction) => void;
|
|
17
|
+
/** UPDATE */
|
|
18
|
+
updateValidator: (req: Request, res: Response, next: NextFunction) => void;
|
|
19
|
+
/** DELETE */
|
|
20
|
+
deleteValidator: (req: Request, res: Response, next: NextFunction) => void;
|
|
21
|
+
/** GET BY ID */
|
|
22
|
+
getByIdValidator: (req: Request, res: Response, next: NextFunction) => void;
|
|
23
|
+
/** GET ALL */
|
|
24
|
+
getAllValidator: (req: Request, res: Response, next: NextFunction) => void;
|
|
25
|
+
/** GET ALL WITH PAGINATION */
|
|
26
|
+
getAllWithPaginationValidator: (req: Request, res: Response, next: NextFunction) => void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const joi_1 = __importDefault(require("joi"));
|
|
40
|
+
const joiSchemaBuilder_1 = __importStar(require("./joiSchemaBuilder"));
|
|
41
|
+
const joiCommonValidator_1 = require("./joiCommonValidator");
|
|
42
|
+
class BaseCrudValidator extends joiSchemaBuilder_1.default {
|
|
43
|
+
constructor(baseSchema, rules = {}) {
|
|
44
|
+
super();
|
|
45
|
+
/** CREATE */
|
|
46
|
+
this.createValidator = (req, res, next) => {
|
|
47
|
+
try {
|
|
48
|
+
const mergedRules = this.mergeRules({}, this.rules.create);
|
|
49
|
+
let schema = (0, joiSchemaBuilder_1.buildSchema)(this.baseSchema, mergedRules);
|
|
50
|
+
if (mergedRules.nestedRequired?.length) {
|
|
51
|
+
schema = this.applyNestedRequired(schema, mergedRules.nestedRequired);
|
|
52
|
+
}
|
|
53
|
+
this.validate(schema, req);
|
|
54
|
+
next();
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
next(err);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
/** UPDATE */
|
|
61
|
+
this.updateValidator = (req, res, next) => {
|
|
62
|
+
try {
|
|
63
|
+
const idRules = this.applyDefaultIdRule(this.rules.update);
|
|
64
|
+
const mergedRules = this.mergeRules({}, idRules);
|
|
65
|
+
let schema = (0, joiSchemaBuilder_1.buildSchema)(this.baseSchema, mergedRules);
|
|
66
|
+
if (mergedRules.nestedRequired?.length) {
|
|
67
|
+
schema = this.applyNestedRequired(schema, mergedRules.nestedRequired);
|
|
68
|
+
}
|
|
69
|
+
this.validate(schema, req);
|
|
70
|
+
next();
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
next(err);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/** DELETE */
|
|
77
|
+
this.deleteValidator = (req, res, next) => {
|
|
78
|
+
try {
|
|
79
|
+
const idRules = this.applyDefaultIdRule(this.rules.delete);
|
|
80
|
+
const mergedRules = this.mergeRules({}, idRules);
|
|
81
|
+
const schema = (0, joiSchemaBuilder_1.buildSchema)(this.baseSchema, mergedRules);
|
|
82
|
+
this.validate(schema, req);
|
|
83
|
+
next();
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
next(err);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
/** GET BY ID */
|
|
90
|
+
this.getByIdValidator = (req, res, next) => {
|
|
91
|
+
try {
|
|
92
|
+
const idRules = this.applyDefaultIdRule(this.rules.getById);
|
|
93
|
+
const mergedRules = this.mergeRules({}, idRules);
|
|
94
|
+
const schema = (0, joiSchemaBuilder_1.buildSchema)(this.baseSchema, mergedRules);
|
|
95
|
+
this.validate(schema, req);
|
|
96
|
+
next();
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
next(err);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/** GET ALL */
|
|
103
|
+
this.getAllValidator = (req, res, next) => {
|
|
104
|
+
try {
|
|
105
|
+
const mergedRules = this.mergeRules({}, this.rules.getAll);
|
|
106
|
+
const schema = (0, joiSchemaBuilder_1.buildSchema)(this.baseSchema, mergedRules);
|
|
107
|
+
this.validate(schema, req);
|
|
108
|
+
next();
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
next(err);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
/** GET ALL WITH PAGINATION */
|
|
115
|
+
this.getAllWithPaginationValidator = (req, res, next) => {
|
|
116
|
+
try {
|
|
117
|
+
const mergedRules = this.mergeRules({ customFields: joiCommonValidator_1.paginationValidators }, this.rules.getAllWithPagination ?? this.rules.getAll);
|
|
118
|
+
const schema = (0, joiSchemaBuilder_1.buildSchema)(this.baseSchema, mergedRules);
|
|
119
|
+
this.validate(schema, req);
|
|
120
|
+
next();
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
next(err);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
this.baseSchema = baseSchema;
|
|
127
|
+
this.rules = rules;
|
|
128
|
+
}
|
|
129
|
+
/** MERGE RULES */
|
|
130
|
+
mergeRules(defaultRules, overrideRules) {
|
|
131
|
+
const defaultCustomFields = {
|
|
132
|
+
search: joi_1.default.string().optional().allow(null),
|
|
133
|
+
};
|
|
134
|
+
return {
|
|
135
|
+
...defaultRules,
|
|
136
|
+
...overrideRules,
|
|
137
|
+
required: [...(defaultRules.required || []), ...(overrideRules?.required || [])],
|
|
138
|
+
optional: [...(defaultRules.optional || []), ...(overrideRules?.optional || [])],
|
|
139
|
+
allowNull: [...(defaultRules.allowNull || []), ...(overrideRules?.allowNull || [])],
|
|
140
|
+
forbidden: [...(defaultRules.forbidden || []), ...(overrideRules?.forbidden || [])],
|
|
141
|
+
singleOrArray: [...(defaultRules.singleOrArray || []), ...(overrideRules?.singleOrArray || [])],
|
|
142
|
+
singleOrArrayOrNull: [...(defaultRules.singleOrArrayOrNull || []), ...(overrideRules?.singleOrArrayOrNull || [])],
|
|
143
|
+
nestedRequired: [...(defaultRules.nestedRequired || []), ...(overrideRules?.nestedRequired || [])],
|
|
144
|
+
customFields: {
|
|
145
|
+
...defaultCustomFields,
|
|
146
|
+
...(defaultRules.customFields || {}),
|
|
147
|
+
...(overrideRules?.customFields || {}),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** APPLY DEFAULT ID RULE */
|
|
152
|
+
applyDefaultIdRule(override) {
|
|
153
|
+
const overrideHasId = override?.required?.includes('id') ||
|
|
154
|
+
override?.optional?.includes('id') ||
|
|
155
|
+
override?.forbidden?.includes('id');
|
|
156
|
+
if (override && overrideHasId)
|
|
157
|
+
return override;
|
|
158
|
+
if (override)
|
|
159
|
+
return override;
|
|
160
|
+
return { required: ['id'] };
|
|
161
|
+
}
|
|
162
|
+
/** Nested Required for */
|
|
163
|
+
// private applyNestedRequired(schema: Joi.ObjectSchema, paths: string[]): Joi.ObjectSchema {
|
|
164
|
+
// return schema.custom((value, helpers) => {
|
|
165
|
+
// for (const path of paths) {
|
|
166
|
+
// const keys = path.split('.');
|
|
167
|
+
// let current: any = value;
|
|
168
|
+
// let fullPath = '';
|
|
169
|
+
// for (const key of keys) {
|
|
170
|
+
// if (Array.isArray(current)) {
|
|
171
|
+
// if (!current.length) {
|
|
172
|
+
// return helpers.message(`"${fullPath || path}" is required`);
|
|
173
|
+
// }
|
|
174
|
+
// current = current[0];
|
|
175
|
+
// fullPath += '[0]';
|
|
176
|
+
// }
|
|
177
|
+
// fullPath = fullPath ? `${fullPath}.${key}` : key;
|
|
178
|
+
// if (current?.[key] === undefined) {
|
|
179
|
+
// return helpers.message(`"${fullPath}" is required`);
|
|
180
|
+
// }
|
|
181
|
+
// current = current[key];
|
|
182
|
+
// }
|
|
183
|
+
// }
|
|
184
|
+
// return value;
|
|
185
|
+
// });
|
|
186
|
+
// }
|
|
187
|
+
applyNestedRequired(schema, paths) {
|
|
188
|
+
return schema
|
|
189
|
+
.custom((value, helpers) => {
|
|
190
|
+
const checkPath = (current, keys, basePath = '') => {
|
|
191
|
+
if (!keys.length)
|
|
192
|
+
return null;
|
|
193
|
+
const [key, ...rest] = keys;
|
|
194
|
+
if (Array.isArray(current)) {
|
|
195
|
+
for (let i = 0; i < current.length; i++) {
|
|
196
|
+
const result = checkPath(current[i], keys, `${basePath}[${i}]`);
|
|
197
|
+
if (result)
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const nextValue = current?.[key];
|
|
203
|
+
const currentPath = basePath ? `${basePath}.${key}` : key;
|
|
204
|
+
if (nextValue === undefined) {
|
|
205
|
+
return currentPath;
|
|
206
|
+
}
|
|
207
|
+
return checkPath(nextValue, rest, currentPath);
|
|
208
|
+
};
|
|
209
|
+
for (const path of paths) {
|
|
210
|
+
const keys = path.split('.');
|
|
211
|
+
const missingPath = checkPath(value, keys);
|
|
212
|
+
if (missingPath) {
|
|
213
|
+
return helpers.error('any.custom', {
|
|
214
|
+
path: missingPath,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return value;
|
|
219
|
+
})
|
|
220
|
+
.messages({
|
|
221
|
+
'any.custom': '"{{#path}}" is required',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.default = BaseCrudValidator;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./joiSchemaBuilder"), exports);
|
|
18
|
+
__exportStar(require("./joiCommonValidator"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Joi from 'joi';
|
|
2
|
+
export declare const paginationValidators: {
|
|
3
|
+
page: Joi.NumberSchema<number>;
|
|
4
|
+
limit: Joi.NumberSchema<number>;
|
|
5
|
+
search: Joi.StringSchema<string>;
|
|
6
|
+
isPaginate: Joi.BooleanSchema<boolean>;
|
|
7
|
+
order: Joi.ArraySchema<string[][]>;
|
|
8
|
+
sort: Joi.StringSchema<string>;
|
|
9
|
+
};
|
|
10
|
+
export declare const enumAlternatives: (enumObj: Record<string, string>, isRequired?: boolean, allowArray?: boolean) => Joi.AlternativesSchema<any> | Joi.StringSchema<string>;
|
|
11
|
+
export declare const objectIdAlternatives: (isRequired?: boolean, allowArray?: boolean) => Joi.AlternativesSchema<any> | undefined;
|
|
12
|
+
export declare const uuidIdAlternatives: (isRequired?: boolean, allowArray?: boolean) => Joi.AlternativesSchema<any> | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
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.uuidIdAlternatives = exports.objectIdAlternatives = exports.enumAlternatives = exports.paginationValidators = void 0;
|
|
7
|
+
const joi_1 = __importDefault(require("joi"));
|
|
8
|
+
exports.paginationValidators = {
|
|
9
|
+
page: joi_1.default.number().integer().min(1).default(1),
|
|
10
|
+
limit: joi_1.default.number().integer().min(1).default(10),
|
|
11
|
+
search: joi_1.default.string().trim(),
|
|
12
|
+
isPaginate: joi_1.default.boolean().default(true),
|
|
13
|
+
order: joi_1.default.array().items(joi_1.default.array().items(joi_1.default.string().trim(), joi_1.default.string().trim())),
|
|
14
|
+
sort: joi_1.default.string()
|
|
15
|
+
.pattern(/^(-?\\w+(,-?\\w+)*)?$/)
|
|
16
|
+
.optional()
|
|
17
|
+
.messages({
|
|
18
|
+
'string.pattern.base': `"sort" must be a comma-separated list of field names, optionally prefixed with '-' for descending`,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
const enumAlternatives = (enumObj, isRequired = false, allowArray = true) => {
|
|
22
|
+
const base = joi_1.default.string().valid(...Object.values(enumObj));
|
|
23
|
+
if (allowArray) {
|
|
24
|
+
const alt = joi_1.default.alternatives().try(base, joi_1.default.array().items(base));
|
|
25
|
+
return isRequired ? alt.required() : alt.optional();
|
|
26
|
+
}
|
|
27
|
+
return isRequired ? base.required() : base.optional();
|
|
28
|
+
};
|
|
29
|
+
exports.enumAlternatives = enumAlternatives;
|
|
30
|
+
const objectIdAlternatives = (isRequired = false, allowArray = true) => {
|
|
31
|
+
const base = joi_1.default.string()
|
|
32
|
+
.pattern(/^[0-9a-fA-F]{24}$/)
|
|
33
|
+
.message('Invalid ObjectId format');
|
|
34
|
+
if (allowArray) {
|
|
35
|
+
const alt = joi_1.default.alternatives().try(base, joi_1.default.array().items(base));
|
|
36
|
+
return isRequired ? alt.required() : alt.optional();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
exports.objectIdAlternatives = objectIdAlternatives;
|
|
40
|
+
const uuidIdAlternatives = (isRequired = false, allowArray = true) => {
|
|
41
|
+
const base = joi_1.default.string().uuid().message('Invalid Uuid format');
|
|
42
|
+
if (allowArray) {
|
|
43
|
+
const alt = joi_1.default.alternatives().try(base, joi_1.default.array().items(base));
|
|
44
|
+
return isRequired ? alt.required() : alt.optional();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.uuidIdAlternatives = uuidIdAlternatives;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import Joi from 'joi';
|
|
2
|
+
import { SchemaRules } from '../types/commonType';
|
|
3
|
+
export declare const buildSchema: <TModel extends Record<string, any>, Keys extends keyof TModel & string = keyof TModel & string>(base: Joi.ObjectSchema<TModel>, rules?: SchemaRules<Keys>) => Joi.ObjectSchema<TModel>;
|
|
4
|
+
export default class BaseValidator {
|
|
5
|
+
protected validate(schema: Joi.ObjectSchema, req: any, options?: Joi.ValidationOptions): void;
|
|
6
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
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.buildSchema = void 0;
|
|
7
|
+
const joi_1 = __importDefault(require("joi"));
|
|
8
|
+
const httpStatusCode_1 = require("../constants/httpStatusCode");
|
|
9
|
+
class ApiError extends Error {
|
|
10
|
+
constructor(statusCode, message, isOperational = true, stack = '') {
|
|
11
|
+
super(message);
|
|
12
|
+
this.statusCode = statusCode;
|
|
13
|
+
this.isOperational = isOperational;
|
|
14
|
+
if (stack) {
|
|
15
|
+
this.stack = stack;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
Error.captureStackTrace(this, this.constructor);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// GENERIC BUILDER
|
|
23
|
+
const buildSchema = (base, rules = {}) => {
|
|
24
|
+
let schema = base;
|
|
25
|
+
// REQUIRED
|
|
26
|
+
if (rules.required) {
|
|
27
|
+
schema = schema.fork(rules.required, field => field.required());
|
|
28
|
+
}
|
|
29
|
+
// OPTIONAL
|
|
30
|
+
if (rules.optional) {
|
|
31
|
+
schema = schema.fork(rules.optional, field => field.optional());
|
|
32
|
+
}
|
|
33
|
+
// ALLOW NULL
|
|
34
|
+
if (rules.allowNull) {
|
|
35
|
+
schema = schema.fork(rules.allowNull, field => field.allow(null));
|
|
36
|
+
}
|
|
37
|
+
// FORBIDDEN
|
|
38
|
+
if (rules.forbidden) {
|
|
39
|
+
schema = schema.fork(rules.forbidden, field => field.forbidden());
|
|
40
|
+
}
|
|
41
|
+
// SINGLE OR ARRAY
|
|
42
|
+
if (rules.singleOrArray) {
|
|
43
|
+
schema = schema.fork(rules.singleOrArray, field => joi_1.default.alternatives().try(field, joi_1.default.array().items(field)));
|
|
44
|
+
}
|
|
45
|
+
// SINGLE OR ARRAY OR NULL
|
|
46
|
+
if (rules.singleOrArrayOrNull) {
|
|
47
|
+
schema = schema.fork(rules.singleOrArrayOrNull, field => joi_1.default.alternatives().try(field, joi_1.default.array().items(field), joi_1.default.valid(null)));
|
|
48
|
+
}
|
|
49
|
+
// CUSTOM FIELDS
|
|
50
|
+
if (rules.customFields) {
|
|
51
|
+
schema = schema.append(rules.customFields);
|
|
52
|
+
}
|
|
53
|
+
return schema;
|
|
54
|
+
};
|
|
55
|
+
exports.buildSchema = buildSchema;
|
|
56
|
+
const defaultOptions = {
|
|
57
|
+
abortEarly: false,
|
|
58
|
+
allowUnknown: false,
|
|
59
|
+
};
|
|
60
|
+
class BaseValidator {
|
|
61
|
+
validate(schema, req, options) {
|
|
62
|
+
const { error, value } = schema.validate({ ...req.body, ...req.query, ...req.params }, { ...defaultOptions, ...options });
|
|
63
|
+
if (error) {
|
|
64
|
+
const errorMessage = error.details.map(d => d.message).join(', ');
|
|
65
|
+
throw new ApiError(httpStatusCode_1.HTTP_STATUS_CODE.BAD_REQUEST, errorMessage);
|
|
66
|
+
}
|
|
67
|
+
req.body = value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.default = BaseValidator;
|
package/dist/helpers/utils.d.ts
CHANGED
|
@@ -156,9 +156,6 @@ export declare function extractFromObject(data: any[], config: {
|
|
|
156
156
|
userdata: any[];
|
|
157
157
|
columns: string[];
|
|
158
158
|
};
|
|
159
|
-
export declare const enumAlternatives: (enumObj: Record<string, string>, isRequired?: boolean, allowArray?: boolean) => Joi.StringSchema<string> | Joi.AlternativesSchema<any>;
|
|
160
|
-
export declare const objectIdAlternatives: (isRequired?: boolean, allowArray?: boolean) => Joi.AlternativesSchema<any> | undefined;
|
|
161
|
-
export declare const uuidIdAlternatives: (isRequired?: boolean, allowArray?: boolean) => Joi.AlternativesSchema<any> | undefined;
|
|
162
159
|
export declare const customPagination: <T>(data: T[], page: number, limit: number, totalRecords: number) => Promise<{
|
|
163
160
|
limit: number;
|
|
164
161
|
totalRecords: number;
|
|
@@ -179,4 +176,6 @@ export declare const calculateGrade: (subject: {
|
|
|
179
176
|
obtained: number;
|
|
180
177
|
}) => GRADE;
|
|
181
178
|
export declare const getOverallGrade: (subjects: Subject[]) => GRADE;
|
|
179
|
+
export declare const readEmailTemplate: (templateName: string) => Promise<string>;
|
|
180
|
+
export declare const readEmailTemplateWithOutGlobal: (data: any, templateName?: string) => Promise<string>;
|
|
182
181
|
export {};
|
package/dist/helpers/utils.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.readEmailTemplateWithOutGlobal = exports.readEmailTemplate = exports.getOverallGrade = exports.calculateGrade = exports.getNextLetter = exports.getCityAreas = exports.generateVoucherCode = exports.verifyHmacSHA256 = exports.generateHmacSHA256 = exports.customPagination = exports.fromSnakeCaseToNormalText = exports.normalizeToArray = exports.capitalizeFirst = exports.parseOrderOptions = exports.isValidUUID = exports.removeFalsyValues = exports.flattenNestedStructure = exports.buildNestedStructure = exports.getParentsByChildrenId = exports.getChildrenByParentId = exports.sortArray = exports.groupByFields = exports.endOfDay = exports.generateUuidToNumber = exports.startOfDay = exports.isDateWithinRange = exports.isTimeWithinRange = exports.keyByFieldOrFields = exports.getUniqueArrayByFields = exports.generateTempPassword = exports.generateAlphaNumericCode = exports.generateOtp = exports.ensureDirectoryExists = exports.omit = exports.isValidMongoDbId = exports.pick = void 0;
|
|
40
40
|
exports.groupByFieldOrFields = groupByFieldOrFields;
|
|
41
41
|
exports.slugify = slugify;
|
|
42
42
|
exports.assignNonNull = assignNonNull;
|
|
@@ -51,6 +51,8 @@ const uuid = require('uuid');
|
|
|
51
51
|
const crypto_1 = __importDefault(require("crypto"));
|
|
52
52
|
const sequelize_1 = require("sequelize");
|
|
53
53
|
const axios_1 = __importDefault(require("axios"));
|
|
54
|
+
const ejs_1 = __importDefault(require("ejs"));
|
|
55
|
+
const path_1 = __importDefault(require("path"));
|
|
54
56
|
const PASSWORD_REGEX = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!.@#$%^&*])(?=.{8,})');
|
|
55
57
|
const pick = (objOrArray, keys) => {
|
|
56
58
|
const pickObject = (obj) => keys.reduce((acc, key) => {
|
|
@@ -506,9 +508,10 @@ const parseOrderOptions = (inputOrder, defaultOrder = [['createdAt', 'DESC']]) =
|
|
|
506
508
|
return order;
|
|
507
509
|
};
|
|
508
510
|
exports.parseOrderOptions = parseOrderOptions;
|
|
511
|
+
const configs_1 = require("../configs");
|
|
509
512
|
const capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
510
513
|
exports.capitalizeFirst = capitalizeFirst;
|
|
511
|
-
const normalizeToArray = (value) => value ? (Array.isArray(value) ? value : [value]) : undefined;
|
|
514
|
+
const normalizeToArray = (value) => (value ? (Array.isArray(value) ? value : [value]) : undefined);
|
|
512
515
|
exports.normalizeToArray = normalizeToArray;
|
|
513
516
|
/**
|
|
514
517
|
* Converts a snake_case string to Normal Text
|
|
@@ -541,8 +544,7 @@ function assignNonNull(target, source) {
|
|
|
541
544
|
});
|
|
542
545
|
}
|
|
543
546
|
function isUserSchoolInfoUpdate(institute, reqUser) {
|
|
544
|
-
return
|
|
545
|
-
(reqUser.isAddDetails || reqUser.type === app_1.USER_TYPES.INSTITUTE_MASTER_ADMIN || reqUser.type === app_1.USER_TYPES.INSTITUTE_ADMIN));
|
|
547
|
+
return !!(institute.type || institute.subType) && (reqUser.isAddDetails || reqUser.type === app_1.USER_TYPES.INSTITUTE_MASTER_ADMIN || reqUser.type === app_1.USER_TYPES.INSTITUTE_ADMIN);
|
|
546
548
|
}
|
|
547
549
|
function chunkArray(array, size) {
|
|
548
550
|
const chunks = [];
|
|
@@ -614,33 +616,6 @@ function extractFromObject(data, config) {
|
|
|
614
616
|
});
|
|
615
617
|
return { tableTitle: config.tableTitle, userdata, columns };
|
|
616
618
|
}
|
|
617
|
-
const enumAlternatives = (enumObj, isRequired = false, allowArray = true) => {
|
|
618
|
-
const base = joi_1.default.string().valid(...Object.values(enumObj));
|
|
619
|
-
if (allowArray) {
|
|
620
|
-
const alt = joi_1.default.alternatives().try(base, joi_1.default.array().items(base));
|
|
621
|
-
return isRequired ? alt.required() : alt.optional();
|
|
622
|
-
}
|
|
623
|
-
return isRequired ? base.required() : base.optional();
|
|
624
|
-
};
|
|
625
|
-
exports.enumAlternatives = enumAlternatives;
|
|
626
|
-
const objectIdAlternatives = (isRequired = false, allowArray = true) => {
|
|
627
|
-
const base = joi_1.default.string()
|
|
628
|
-
.pattern(/^[0-9a-fA-F]{24}$/)
|
|
629
|
-
.message('Invalid ObjectId format');
|
|
630
|
-
if (allowArray) {
|
|
631
|
-
const alt = joi_1.default.alternatives().try(base, joi_1.default.array().items(base));
|
|
632
|
-
return isRequired ? alt.required() : alt.optional();
|
|
633
|
-
}
|
|
634
|
-
};
|
|
635
|
-
exports.objectIdAlternatives = objectIdAlternatives;
|
|
636
|
-
const uuidIdAlternatives = (isRequired = false, allowArray = true) => {
|
|
637
|
-
const base = joi_1.default.string().uuid().message('Invalid Uuid format');
|
|
638
|
-
if (allowArray) {
|
|
639
|
-
const alt = joi_1.default.alternatives().try(base, joi_1.default.array().items(base));
|
|
640
|
-
return isRequired ? alt.required() : alt.optional();
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
exports.uuidIdAlternatives = uuidIdAlternatives;
|
|
644
619
|
const customPagination = async (data, page, limit, totalRecords) => {
|
|
645
620
|
page = Math.max(1, page || app_1.PAGINATION.PAGE);
|
|
646
621
|
limit = Math.max(1, limit || app_1.PAGINATION.LIMIT);
|
|
@@ -761,3 +736,43 @@ const getOverallGrade = (subjects) => {
|
|
|
761
736
|
return worstGrade;
|
|
762
737
|
};
|
|
763
738
|
exports.getOverallGrade = getOverallGrade;
|
|
739
|
+
const readEmailTemplate = async (templateName) => {
|
|
740
|
+
const globalFilePath = path_1.default.join(process.cwd(), 'emailTemplates', `globalEmailTemplate.ejs`);
|
|
741
|
+
const filePath = path_1.default.join(process.cwd(), 'emailTemplates', `${templateName}.ejs`);
|
|
742
|
+
let globalEmailTemplate = await fs_1.default.readFileSync(globalFilePath, 'utf-8');
|
|
743
|
+
const html = ejs_1.default.render(globalEmailTemplate, {
|
|
744
|
+
data: {
|
|
745
|
+
kipiLogo: `${configs_1.ENV_VARIABLE.SERVER_URL}/public/kipilogo.png`,
|
|
746
|
+
googlePlayLogo: `${configs_1.ENV_VARIABLE.SERVER_URL}/public/googleplaylogo.png`,
|
|
747
|
+
applePlayLogo: `${configs_1.ENV_VARIABLE.SERVER_URL}/public/appleplaylogo.png`,
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
globalEmailTemplate = html.replace(/\r\n/g, '');
|
|
751
|
+
return new Promise((resolve, reject) => {
|
|
752
|
+
fs_1.default.readFile(filePath, 'utf-8', (err, content) => {
|
|
753
|
+
if (err) {
|
|
754
|
+
return reject(err);
|
|
755
|
+
}
|
|
756
|
+
resolve(globalEmailTemplate.replace(/{{content}}/g, content));
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
};
|
|
760
|
+
exports.readEmailTemplate = readEmailTemplate;
|
|
761
|
+
const readEmailTemplateWithOutGlobal = async (data, templateName) => {
|
|
762
|
+
return new Promise((resolve, reject) => {
|
|
763
|
+
const templatePath = path_1.default.join(process.cwd(), 'emailTemplates', `${templateName || app_1.EMAIL_TEMPLATES.COMMON_TEMPLATE}.ejs`);
|
|
764
|
+
fs_1.default.readFile(templatePath, 'utf-8', (err, templateContent) => {
|
|
765
|
+
if (err) {
|
|
766
|
+
return reject(err);
|
|
767
|
+
}
|
|
768
|
+
const html = ejs_1.default.render(templateContent, {
|
|
769
|
+
logoUrl: data.instituteLogo,
|
|
770
|
+
content: data.content,
|
|
771
|
+
googlePlayLogo: `${process.env.SERVER_URL}/public/googleplaylogo.png`,
|
|
772
|
+
appStoreLogo: `${process.env.SERVER_URL}/public/appleplaylogo.png`,
|
|
773
|
+
});
|
|
774
|
+
resolve(html);
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
};
|
|
778
|
+
exports.readEmailTemplateWithOutGlobal = readEmailTemplateWithOutGlobal;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -31,3 +31,5 @@ __exportStar(require("./models/mongodb/index"), exports);
|
|
|
31
31
|
__exportStar(require("./models/psql/index"), exports);
|
|
32
32
|
/************ types *************/
|
|
33
33
|
__exportStar(require("./types/index"), exports);
|
|
34
|
+
/************ validator ********** */
|
|
35
|
+
__exportStar(require("./commonValidator"), exports);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Joi from 'joi';
|
|
1
2
|
export type TPaginationOptions<T> = {
|
|
2
3
|
limit: number | undefined;
|
|
3
4
|
totalRecords: number;
|
|
@@ -7,3 +8,21 @@ export type TPaginationOptions<T> = {
|
|
|
7
8
|
currentPage: number;
|
|
8
9
|
recordList?: T[];
|
|
9
10
|
};
|
|
11
|
+
export type SchemaRules<TField> = {
|
|
12
|
+
required?: TField[];
|
|
13
|
+
optional?: TField[];
|
|
14
|
+
allowNull?: TField[];
|
|
15
|
+
forbidden?: TField[];
|
|
16
|
+
singleOrArray?: TField[];
|
|
17
|
+
singleOrArrayOrNull?: TField[];
|
|
18
|
+
customFields?: Record<string, Joi.Schema>;
|
|
19
|
+
nestedRequired?: string[];
|
|
20
|
+
};
|
|
21
|
+
export interface CrudValidatorRules<TField> {
|
|
22
|
+
create?: SchemaRules<TField>;
|
|
23
|
+
update?: SchemaRules<TField>;
|
|
24
|
+
getAll?: SchemaRules<TField>;
|
|
25
|
+
getAllWithPagination?: SchemaRules<TField>;
|
|
26
|
+
getById?: SchemaRules<TField>;
|
|
27
|
+
delete?: SchemaRules<TField>;
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kipicore/dbcore",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.662",
|
|
4
4
|
"description": "Reusable DB core package with Postgres, MongoDB, models, services, interfaces, and types",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -50,11 +50,14 @@
|
|
|
50
50
|
"mongoose": "^8.5.2",
|
|
51
51
|
"pg": "^8.12.0",
|
|
52
52
|
"sequelize": "^6.37.3",
|
|
53
|
+
"ejs": "^3.1.10",
|
|
53
54
|
"uuid": "^8.3.2"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"@eslint/js": "^9.17.0",
|
|
58
|
+
"@types/express": "^5.0.6",
|
|
57
59
|
"@types/mongoose": "^5.11.97",
|
|
60
|
+
"@types/ejs": "^3.1.5",
|
|
58
61
|
"@types/node": "^24.5.2",
|
|
59
62
|
"@types/sequelize": "^4.28.14",
|
|
60
63
|
"country-state-city": "^3.2.1",
|
|
@@ -72,4 +75,4 @@
|
|
|
72
75
|
"LICENSE",
|
|
73
76
|
".sequelizerc"
|
|
74
77
|
]
|
|
75
|
-
}
|
|
78
|
+
}
|