axe-api 1.0.11 → 1.2.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.
@@ -51,7 +51,7 @@ class ModelTreeBuilder {
51
51
  }
52
52
  getChildModelNames(model) {
53
53
  return model.relations
54
- .filter((item) => item.type === Enums_1.Relationships.HAS_MANY)
54
+ .filter((item) => item.type === Enums_1.Relationships.HAS_MANY && item.options.autoRouting)
55
55
  .map((item) => item.model);
56
56
  }
57
57
  addNestedRoutes(tree) {
@@ -21,6 +21,7 @@ const return404 = (response) => {
21
21
  response.end();
22
22
  };
23
23
  exports.default = (request, response, next) => __awaiter(void 0, void 0, void 0, function* () {
24
+ var _a, _b;
24
25
  const api = Services_1.APIService.getInstance();
25
26
  Services_1.LogService.debug(`šŸ“„ ${request.method} ${request.url}`);
26
27
  const { axeRequest, axeResponse } = (0, ConverterService_1.toAxeRequestResponsePair)(request, response);
@@ -29,6 +30,18 @@ exports.default = (request, response, next) => __awaiter(void 0, void 0, void 0,
29
30
  Services_1.LogService.warn(`The URL is not matched! ${request.method} ${request.url}`);
30
31
  return return404(response);
31
32
  }
33
+ // On custom routes, there is not any version config
34
+ if ((_b = (_a = match === null || match === void 0 ? void 0 : match.data) === null || _a === void 0 ? void 0 : _a.version) === null || _b === void 0 ? void 0 : _b.config) {
35
+ // If the requested language is not supported, the default language is used
36
+ const { supportedLanguages, defaultLanguage } = match.data.version.config;
37
+ if (!supportedLanguages.includes(axeRequest.currentLanguage.language)) {
38
+ axeRequest.currentLanguage = {
39
+ title: defaultLanguage,
40
+ language: defaultLanguage,
41
+ region: null,
42
+ };
43
+ }
44
+ }
32
45
  // We should set the params
33
46
  axeRequest.params = match.params;
34
47
  const database = yield Services_1.IoCService.use("Database");
@@ -38,7 +51,8 @@ exports.default = (request, response, next) => __awaiter(void 0, void 0, void 0,
38
51
  Services_1.LogService.info("\tšŸ›¢ DBTransaction:created()");
39
52
  trx = yield database.transaction();
40
53
  }
41
- const context = Object.assign(Object.assign({}, match.data), { params: match.params, api, req: axeRequest, res: axeResponse, isTransactionOpen: match.hasTransaction, database: match.hasTransaction && trx ? trx : database });
54
+ const validator = yield Services_1.IoCService.use("Validator");
55
+ const context = Object.assign(Object.assign({}, match.data), { params: match.params, api, req: axeRequest, res: axeResponse, isTransactionOpen: match.hasTransaction, database: match.hasTransaction && trx ? trx : database, validator });
42
56
  response.setHeader("Content-Type", "application/json");
43
57
  response.setHeader("x-powered-by", "Axe API");
44
58
  for (const phase of match.phases) {
@@ -5,7 +5,7 @@ import { Options as FormOptions } from "formidable";
5
5
  import { Column } from "knex-schema-inspector/lib/types/column";
6
6
  import { HandlerTypes, HttpMethods, HookFunctionTypes, Extensions, Relationships, SortTypes, ConditionTypes, DependencyTypes, QueryFeature, QueryFeatureType, CacheStrategies } from "./Enums";
7
7
  import Model from "./Model";
8
- import { AdaptorType, AxeFunction, GeneralFunction, HandlerFunction, ModelHooks, PhaseFunction, SerializationFunction } from "./Types";
8
+ import { AdaptorType, AxeFunction, FormValidatorLibrary, GeneralFunction, HandlerFunction, ModelHooks, PhaseFunction, SerializationFunction } from "./Types";
9
9
  import { ModelListService, QueryService } from "./Services";
10
10
  import AxeRequest from "./Services/AxeRequest";
11
11
  import AxeResponse from "./Services/AxeResponse";
@@ -91,6 +91,7 @@ export interface AxeConfig extends IConfig {
91
91
  cache: ICacheConfiguration;
92
92
  elasticSearch: ClientOptions;
93
93
  search: ISearchConfigutation;
94
+ validator: FormValidatorLibrary;
94
95
  }
95
96
  export type IApplicationConfig = Partial<AxeConfig>;
96
97
  export interface ILanguage {
@@ -163,6 +164,7 @@ export interface IRelation {
163
164
  model: string;
164
165
  primaryKey: string;
165
166
  foreignKey: string;
167
+ options: IHasManyOptions;
166
168
  }
167
169
  export interface IRouteData {
168
170
  version: IVersion;
@@ -177,14 +179,107 @@ export interface IContext extends IRouteData {
177
179
  res: AxeResponse;
178
180
  database: Knex | Knex.Transaction;
179
181
  isTransactionOpen: boolean;
182
+ validator: IValidator;
180
183
  queryParser?: QueryService;
184
+ params?: any;
185
+ /**
186
+ * @deprecated Use special hook type instead of IContext like IBeforeInsertContext
187
+ */
181
188
  conditions?: IQuery;
189
+ /**
190
+ * @deprecated Use special hook type instead of IContext like IBeforeInsertContext
191
+ */
182
192
  query?: Knex.QueryBuilder;
183
- params?: any;
193
+ /**
194
+ * @deprecated Use special hook type instead of IContext like IBeforeInsertContext
195
+ */
184
196
  result?: any;
197
+ /**
198
+ * @deprecated Use special hook type instead of IContext like IBeforeInsertContext
199
+ */
185
200
  item?: any;
201
+ /**
202
+ * @deprecated Use special hook type instead of IContext like IBeforeInsertContext
203
+ */
186
204
  formData?: any;
187
205
  }
206
+ export interface IBeforeInsertContext extends IContext {
207
+ formData: any;
208
+ }
209
+ export interface IBeforeUpdateQueryContext extends IContext {
210
+ query: Knex.QueryBuilder;
211
+ }
212
+ export interface IBeforeUpdateContext extends IContext {
213
+ query: Knex.QueryBuilder;
214
+ item: any;
215
+ formData: any;
216
+ }
217
+ export interface IBeforeDeleteQueryContext extends IContext {
218
+ query: Knex.QueryBuilder;
219
+ }
220
+ export interface IBeforeDeleteContext extends IContext {
221
+ query: Knex.QueryBuilder;
222
+ }
223
+ export interface IBeforeForceDeleteQueryContext extends IContext {
224
+ query: Knex.QueryBuilder;
225
+ }
226
+ export interface IBeforeForceDeleteContext extends IContext {
227
+ query: Knex.QueryBuilder;
228
+ }
229
+ export interface IBeforePaginateContext extends IContext {
230
+ query: Knex.QueryBuilder;
231
+ conditions: IQuery;
232
+ }
233
+ export interface IBeforeAllContext extends IContext {
234
+ query: Knex.QueryBuilder;
235
+ conditions: IQuery;
236
+ }
237
+ export interface IBeforeShowContext extends IContext {
238
+ query: Knex.QueryBuilder;
239
+ conditions: IQuery;
240
+ }
241
+ export interface IAfterInsertContext extends IContext {
242
+ item: any;
243
+ formData: any;
244
+ }
245
+ export interface IAfterUpdateQueryContext extends IContext {
246
+ query: Knex.QueryBuilder;
247
+ item: any;
248
+ }
249
+ export interface IAfterUpdateContext extends IContext {
250
+ query: Knex.QueryBuilder;
251
+ item: any;
252
+ formData: any;
253
+ }
254
+ export interface IAfterDeleteQueryContext extends IContext {
255
+ query: Knex.QueryBuilder;
256
+ item: any;
257
+ }
258
+ export interface IAfterDeleteContext extends IContext {
259
+ item: any;
260
+ }
261
+ export interface IAfterForceDeleteQueryContext extends IContext {
262
+ query: Knex.QueryBuilder;
263
+ item: any;
264
+ }
265
+ export interface IAfterForceDeleteContext extends IContext {
266
+ item: any;
267
+ }
268
+ export interface IAfterPaginateContext extends IContext {
269
+ query: Knex.QueryBuilder;
270
+ conditions: IQuery;
271
+ result: any;
272
+ }
273
+ export interface IAfterAllContext extends IContext {
274
+ query: Knex.QueryBuilder;
275
+ conditions: IQuery;
276
+ result: any;
277
+ }
278
+ export interface IAfterShowContext extends IContext {
279
+ query: Knex.QueryBuilder;
280
+ conditions: IQuery;
281
+ item: any;
282
+ }
188
283
  export interface IRouteDocumentation {
189
284
  version: string;
190
285
  handler: string;
@@ -307,4 +402,13 @@ export interface IElasticSearchParameters {
307
402
  parentModel: IModelService | null;
308
403
  text: string;
309
404
  }
405
+ export interface IHasManyOptions {
406
+ autoRouting: boolean;
407
+ }
408
+ export interface IValidator {
409
+ validate: (req: AxeRequest, model: IModelService, formData: any) => Promise<null | IValidationError>;
410
+ }
411
+ export interface IValidationError {
412
+ errors: Record<string, string[]>;
413
+ }
310
414
  export {};
@@ -1,4 +1,4 @@
1
- import { IRelation, IMethodBaseConfig, IQueryLimitConfig, IHandlerBasedTransactionConfig, ICacheConfiguration, IHandlerBasedCacheConfig, IElasticSearchParameters } from "./Interfaces";
1
+ import { IRelation, IMethodBaseConfig, IQueryLimitConfig, IHandlerBasedTransactionConfig, ICacheConfiguration, IHandlerBasedCacheConfig, IElasticSearchParameters, IHasManyOptions } from "./Interfaces";
2
2
  import { HandlerTypes, HttpMethods } from "./Enums";
3
3
  import { ModelMiddleware, AxeFunction, ModelValidation } from "./Types";
4
4
  declare class Model {
@@ -226,7 +226,7 @@ declare class Model {
226
226
  * @type {Array<IQueryLimitConfig[]>}
227
227
  * @tutorial https://axe-api.com/learn/routing.html#model-relations
228
228
  */
229
- hasMany(relatedModel: string, primaryKey?: string, foreignKey?: string): IRelation;
229
+ hasMany(relatedModel: string, primaryKey?: string, foreignKey?: string, options?: Partial<IHasManyOptions>): IRelation;
230
230
  /**
231
231
  * Model relationship definition.
232
232
  *
@@ -263,7 +263,7 @@ class Model {
263
263
  * @type {Array<IQueryLimitConfig[]>}
264
264
  * @tutorial https://axe-api.com/learn/routing.html#model-relations
265
265
  */
266
- hasMany(relatedModel, primaryKey = "id", foreignKey = "") {
266
+ hasMany(relatedModel, primaryKey = "id", foreignKey = "", options) {
267
267
  if (!foreignKey) {
268
268
  const currentModelName = pluralize_1.default.singular(this.constructor.name.toLowerCase());
269
269
  foreignKey = `${currentModelName}_id`;
@@ -274,6 +274,7 @@ class Model {
274
274
  model: relatedModel,
275
275
  primaryKey,
276
276
  foreignKey,
277
+ options: Object.assign(Object.assign({}, constants_1.DEFAULT_HASH_MANY_OPTIONS), options),
277
278
  };
278
279
  }
279
280
  /**
@@ -296,6 +297,7 @@ class Model {
296
297
  model: relatedModel,
297
298
  primaryKey,
298
299
  foreignKey,
300
+ options: constants_1.DEFAULT_HASH_MANY_OPTIONS,
299
301
  };
300
302
  }
301
303
  /**
@@ -8,27 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const validatorjs_1 = __importDefault(require("validatorjs"));
16
12
  const Enums_1 = require("../../Enums");
17
13
  const Helpers_1 = require("../../Handlers/Helpers");
18
14
  exports.default = (context) => __awaiter(void 0, void 0, void 0, function* () {
19
- const { req, res, model } = context;
15
+ const { req, res, model, validator } = context;
20
16
  const requestMethod = req.method;
21
17
  const fillables = model.instance.getFillableFields(requestMethod);
22
18
  context.formData = Object.assign(Object.assign({}, context.item), (0, Helpers_1.getMergedFormData)(req, fillables));
23
- const validationRules = model.instance.getValidationRules(requestMethod);
24
- if (validationRules) {
25
- // The validation language should be set
26
- validatorjs_1.default.useLang(req.currentLanguage.language);
27
- // Validate the data
28
- const validation = new validatorjs_1.default(context.formData, validationRules);
29
- if (validation.fails()) {
30
- return res.status(Enums_1.StatusCodes.BAD_REQUEST).json(validation.errors);
31
- }
19
+ // Form validation
20
+ const validatorErrors = yield validator.validate(req, model, context.formData);
21
+ if (validatorErrors) {
22
+ return res.status(Enums_1.StatusCodes.BAD_REQUEST).json(validatorErrors);
32
23
  }
33
24
  // Checking the foreign key values if there is any
34
25
  const errors = yield (0, Helpers_1.getForeignKeyValueErrors)(context);
@@ -8,28 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const validatorjs_1 = __importDefault(require("validatorjs"));
16
12
  const Helpers_1 = require("../../Handlers/Helpers");
17
13
  const Enums_1 = require("../../Enums");
18
14
  exports.default = (context) => __awaiter(void 0, void 0, void 0, function* () {
19
- const { req, res, model } = context;
15
+ const { req, res, model, validator } = context;
20
16
  const requestMethod = req.method;
21
17
  const fillables = model.instance.getFillableFields(requestMethod);
22
18
  context.formData = (0, Helpers_1.getMergedFormData)(req, fillables);
23
- const validationRules = model.instance.getValidationRules(requestMethod);
24
- if (validationRules) {
25
- // The validation language should be set
26
- validatorjs_1.default.useLang(req.currentLanguage.language);
27
- // Validate the data
28
- const validation = new validatorjs_1.default(context.formData, validationRules);
29
- if (validation.fails()) {
30
- res.status(Enums_1.StatusCodes.BAD_REQUEST).json(validation.errors);
31
- return;
32
- }
19
+ // Form validation
20
+ const validatorErrors = yield validator.validate(req, model, context.formData);
21
+ if (validatorErrors) {
22
+ return res.status(Enums_1.StatusCodes.BAD_REQUEST).json(validatorErrors);
33
23
  }
34
24
  if (context.relation && context.parentModel) {
35
25
  const parentColumn = (0, Helpers_1.getParentColumn)(context.parentModel, context.relation);
@@ -8,27 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const validatorjs_1 = __importDefault(require("validatorjs"));
16
12
  const Enums_1 = require("../../Enums");
17
13
  const Helpers_1 = require("../../Handlers/Helpers");
18
14
  exports.default = (context) => __awaiter(void 0, void 0, void 0, function* () {
19
- const { req, res, model } = context;
15
+ const { req, res, model, validator } = context;
20
16
  const requestMethod = req.method;
21
17
  const fillables = model.instance.getFillableFields(requestMethod);
22
18
  context.formData = (0, Helpers_1.getMergedFormData)(req, fillables);
23
- const validationRules = model.instance.getValidationRules(requestMethod);
24
- if (validationRules) {
25
- // The validation language should be set
26
- validatorjs_1.default.useLang(req.currentLanguage.language);
27
- // Validate the data
28
- const validation = new validatorjs_1.default(context.formData, validationRules);
29
- if (validation.fails()) {
30
- return res.status(Enums_1.StatusCodes.BAD_REQUEST).json(validation.errors);
31
- }
19
+ // Form validation
20
+ const validatorErrors = yield validator.validate(req, model, context.formData);
21
+ if (validatorErrors) {
22
+ return res.status(Enums_1.StatusCodes.BAD_REQUEST).json(validatorErrors);
32
23
  }
33
24
  // Checking the foreign key values if there is any
34
25
  const errors = yield (0, Helpers_1.getForeignKeyValueErrors)(context);
@@ -191,9 +191,22 @@ class ModelResolver {
191
191
  const fileResolver = new FileResolver_1.default();
192
192
  const serializations = yield fileResolver.resolveContent(this.version.folders.serialization);
193
193
  for (const model of modelList.get()) {
194
- const fileName = `${model.name}Serialization`;
195
- if (serializations[fileName]) {
196
- const file = serializations[fileName];
194
+ // Old serialization
195
+ const oldName = `${model.name}Serialization`;
196
+ let isOldNamingUsed = false;
197
+ if (serializations[oldName]) {
198
+ isOldNamingUsed = true;
199
+ const file = serializations[oldName];
200
+ model.setSerialization(file.default);
201
+ Services_1.LogService.warn(`'${oldName}.ts' naming is deprecated. You can use '${oldName.replace("Serialization", "")}.ts' instead.`);
202
+ }
203
+ // New
204
+ const newName = `${model.name}`;
205
+ if (serializations[newName]) {
206
+ if (isOldNamingUsed) {
207
+ throw new Error(`You cannot use '${oldName}.ts' and '${newName}.ts' at the same time.`);
208
+ }
209
+ const file = serializations[newName];
197
210
  model.setSerialization(file.default);
198
211
  }
199
212
  }
@@ -54,6 +54,7 @@ const RedisAdaptor_1 = __importDefault(require("./Middlewares/RateLimit/RedisAda
54
54
  const RateLimit_1 = __importDefault(require("./Middlewares/RateLimit"));
55
55
  const ElasticService_1 = __importDefault(require("./Services/ElasticService"));
56
56
  const IndexBuilder_1 = __importDefault(require("./Builders/IndexBuilder"));
57
+ const ValidatorFactory_1 = __importDefault(require("./Validators/ValidatorFactory"));
57
58
  class Server {
58
59
  /**
59
60
  * Start the application with the rootFolder.
@@ -114,6 +115,10 @@ class Server {
114
115
  yield new IndexBuilder_1.default(version).build();
115
116
  yield new Builders_1.RouterBuilder(version).build();
116
117
  }
118
+ // We should initialize the validator with the language support
119
+ Services_1.IoCService.fastSingleton("Validator", () => {
120
+ return ValidatorFactory_1.default.resolve(api.config);
121
+ });
117
122
  });
118
123
  }
119
124
  loadGeneralConfiguration() {
@@ -20,6 +20,16 @@ declare class IoCService {
20
20
  * IoCService.singleton("MySingleton", () => new MySingleton())
21
21
  */
22
22
  static singleton(name: string, callback: any): void;
23
+ /**
24
+ * Adding a singleton dependency and create the first instance immediately.
25
+ *
26
+ * @param name
27
+ * @param callback
28
+ * @example
29
+ *
30
+ * IoCService.singleton("MySingleton", () => new MySingleton())
31
+ */
32
+ static fastSingleton(name: string, callback: any): void;
23
33
  /**
24
34
  * Getting the service by the name.
25
35
  *
@@ -35,6 +35,19 @@ class IoCService {
35
35
  static singleton(name, callback) {
36
36
  this._add(Enums_1.DependencyTypes.SINGLETON, name, callback);
37
37
  }
38
+ /**
39
+ * Adding a singleton dependency and create the first instance immediately.
40
+ *
41
+ * @param name
42
+ * @param callback
43
+ * @example
44
+ *
45
+ * IoCService.singleton("MySingleton", () => new MySingleton())
46
+ */
47
+ static fastSingleton(name, callback) {
48
+ this._add(Enums_1.DependencyTypes.SINGLETON, name, callback);
49
+ this.use(name);
50
+ }
38
51
  /**
39
52
  * Getting the service by the name.
40
53
  *
@@ -11,6 +11,7 @@ export type ModelValidation = Record<string, string>;
11
11
  export type ModelHooks = Record<HookFunctionTypes, PhaseFunction>;
12
12
  export type ModelMiddleware = Array<AxeFunction | IHandlerBaseMiddleware>;
13
13
  export type AdaptorType = "redis" | "memory";
14
+ export type FormValidatorLibrary = "validatorjs" | "robust-validator";
14
15
  export type DefaultResponse = Promise<void> | void | undefined;
15
16
  export type NextFunction = (error?: any) => void;
16
17
  export type SchemaInspectorFunction = (database: Knex) => SchemaInspector;
@@ -0,0 +1,9 @@
1
+ import { IModelService, IValidator } from "../Interfaces";
2
+ import { AxeRequest } from "../Services";
3
+ declare class RobustValidator implements IValidator {
4
+ constructor(supportedLanguages: string[]);
5
+ validate(req: AxeRequest, model: IModelService, formData: any): Promise<{
6
+ errors: Record<string, string[]>;
7
+ } | null>;
8
+ }
9
+ export default RobustValidator;
@@ -0,0 +1,77 @@
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 (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ const Services_1 = require("../Services");
36
+ const robust_validator_1 = require("robust-validator");
37
+ class RobustValidator {
38
+ constructor(supportedLanguages) {
39
+ Promise.resolve().then(() => __importStar(require("robust-validator"))).then((pkg) => {
40
+ for (const language of supportedLanguages) {
41
+ const languagePack = pkg[language];
42
+ if (!languagePack) {
43
+ throw new Error(`The language is not supported by robust-validator: ${language}`);
44
+ }
45
+ (0, robust_validator_1.setLocales)(languagePack);
46
+ Services_1.LogService.debug(`Robust-validator language pack has been imported: ${language}`);
47
+ }
48
+ });
49
+ }
50
+ validate(req, model, formData) {
51
+ return __awaiter(this, void 0, void 0, function* () {
52
+ // Getting the validation rules
53
+ const requestMethod = req.method;
54
+ const validationRules = model.instance.getValidationRules(requestMethod);
55
+ // Validating the data if there is any
56
+ if (validationRules) {
57
+ const result = yield (0, robust_validator_1.validate)(formData, validationRules, {
58
+ language: req.currentLanguage.language,
59
+ });
60
+ if (result.isInvalid) {
61
+ const errors = {};
62
+ Object.keys(result.errors).forEach((field) => {
63
+ if (!errors[field]) {
64
+ errors[field] = [];
65
+ }
66
+ errors[field].push(...result.errors[field].map((item) => item.message));
67
+ });
68
+ return {
69
+ errors,
70
+ };
71
+ }
72
+ }
73
+ return null;
74
+ });
75
+ }
76
+ }
77
+ exports.default = RobustValidator;
@@ -0,0 +1,5 @@
1
+ import { AxeConfig, IValidator } from "../Interfaces";
2
+ declare class ValidatorFactory {
3
+ static resolve(config: AxeConfig): IValidator;
4
+ }
5
+ export default ValidatorFactory;
@@ -0,0 +1,25 @@
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
+ const Validatorjs_1 = __importDefault(require("./Validatorjs"));
7
+ const RobustValidator_1 = __importDefault(require("./RobustValidator"));
8
+ const Services_1 = require("../Services");
9
+ class ValidatorFactory {
10
+ static resolve(config) {
11
+ const api = Services_1.APIService.getInstance();
12
+ const supportedLanguages = [
13
+ ...new Set(api.versions.map((version) => version.config.supportedLanguages).flat()),
14
+ ];
15
+ switch (config.validator) {
16
+ case "validatorjs":
17
+ return new Validatorjs_1.default(supportedLanguages);
18
+ case "robust-validator":
19
+ return new RobustValidator_1.default(supportedLanguages);
20
+ default:
21
+ throw new Error(`Undefined validator library: ${config.validator}`);
22
+ }
23
+ }
24
+ }
25
+ exports.default = ValidatorFactory;
@@ -0,0 +1,8 @@
1
+ import Validator from "validatorjs";
2
+ import { AxeRequest } from "../Services";
3
+ import { IModelService, IValidator } from "../Interfaces";
4
+ declare class Validatorjs implements IValidator {
5
+ constructor(supportedLanguages: string[]);
6
+ validate(req: AxeRequest, model: IModelService, formData: any): Promise<Validator.Errors | null>;
7
+ }
8
+ export default Validatorjs;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const validatorjs_1 = __importDefault(require("validatorjs"));
16
+ const Services_1 = require("../Services");
17
+ class Validatorjs {
18
+ constructor(supportedLanguages) {
19
+ supportedLanguages.forEach((language) => {
20
+ validatorjs_1.default.useLang(language);
21
+ Services_1.LogService.debug(`Validatorjs language pack has been imported: ${language}`);
22
+ });
23
+ }
24
+ validate(req, model, formData) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ // Setting the language
27
+ validatorjs_1.default.useLang(req.currentLanguage.language);
28
+ // Getting the validation rules
29
+ const requestMethod = req.method;
30
+ const validationRules = model.instance.getValidationRules(requestMethod);
31
+ // Validating the data if there is any
32
+ if (validationRules) {
33
+ const validation = new validatorjs_1.default(formData, validationRules);
34
+ // Return the validation errors
35
+ if (validation.fails()) {
36
+ return validation.errors;
37
+ }
38
+ }
39
+ return null;
40
+ });
41
+ }
42
+ }
43
+ exports.default = Validatorjs;
@@ -1,5 +1,5 @@
1
1
  import { ConditionTypes, HandlerTypes, HttpMethods, QueryFeature, Relationships } from "./Enums";
2
- import { AxeConfig, AxeVersionConfig, ICacheConfiguration, IStepDefinition } from "./Interfaces";
2
+ import { AxeConfig, AxeVersionConfig, ICacheConfiguration, IHasManyOptions, IStepDefinition } from "./Interfaces";
3
3
  export declare const RESERVED_KEYWORDS: string[];
4
4
  export declare const DEFAULT_HANDLERS: HandlerTypes[];
5
5
  export declare const DEFAULT_METHODS_OF_MODELS: string[];
@@ -24,3 +24,4 @@ export declare const DEFAULT_CACHE_CONFIGURATION: ICacheConfiguration;
24
24
  export declare const DEFAULT_APP_CONFIG: AxeConfig;
25
25
  export declare const DEFAULT_VERSION_CONFIG: AxeVersionConfig;
26
26
  export declare const ALL_HANDLERS: HandlerTypes[];
27
+ export declare const DEFAULT_HASH_MANY_OPTIONS: IHasManyOptions;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ALL_HANDLERS = exports.DEFAULT_VERSION_CONFIG = exports.DEFAULT_APP_CONFIG = exports.DEFAULT_CACHE_CONFIGURATION = exports.HANDLER_CYLES = exports.HANDLER_METHOD_MAP = exports.STRING_COLUMN_TYPES = exports.NUMERIC_PRIMARY_KEY_TYPES = exports.RelationQueryFeatureMap = exports.ConditionQueryFeatureMap = exports.API_ROUTE_TEMPLATES = exports.DEFAULT_METHODS_OF_MODELS = exports.DEFAULT_HANDLERS = exports.RESERVED_KEYWORDS = void 0;
6
+ exports.DEFAULT_HASH_MANY_OPTIONS = exports.ALL_HANDLERS = exports.DEFAULT_VERSION_CONFIG = exports.DEFAULT_APP_CONFIG = exports.DEFAULT_CACHE_CONFIGURATION = exports.HANDLER_CYLES = exports.HANDLER_METHOD_MAP = exports.STRING_COLUMN_TYPES = exports.NUMERIC_PRIMARY_KEY_TYPES = exports.RelationQueryFeatureMap = exports.ConditionQueryFeatureMap = exports.API_ROUTE_TEMPLATES = exports.DEFAULT_METHODS_OF_MODELS = exports.DEFAULT_HANDLERS = exports.RESERVED_KEYWORDS = void 0;
7
7
  const Enums_1 = require("./Enums");
8
8
  const LimitService_1 = require("./Services/LimitService");
9
9
  const Single_1 = __importDefault(require("./Phases/Single"));
@@ -314,6 +314,7 @@ exports.DEFAULT_APP_CONFIG = {
314
314
  search: {
315
315
  indexPrefix: "axe",
316
316
  },
317
+ validator: "validatorjs",
317
318
  };
318
319
  exports.DEFAULT_VERSION_CONFIG = {
319
320
  transaction: false,
@@ -347,3 +348,6 @@ exports.ALL_HANDLERS = [
347
348
  Enums_1.HandlerTypes.SHOW,
348
349
  Enums_1.HandlerTypes.UPDATE,
349
350
  ];
351
+ exports.DEFAULT_HASH_MANY_OPTIONS = {
352
+ autoRouting: true,
353
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axe-api",
3
- "version": "1.0.11",
3
+ "version": "1.2.0",
4
4
  "description": "AXE API is a simple tool to create Rest APIs quickly.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -29,8 +29,7 @@
29
29
  "scripts": {
30
30
  "build": "rm -rf build && tsc && rm -rf build/dev-kit",
31
31
  "build:watch": "tsc -w",
32
- "dev": "ts-node-dev --files --respawn --clear index.ts",
33
- "dev-kit": "ts-node-dev --respawn --clear dev-kit.ts",
32
+ "dev-kit": "tsx watch dev-kit.ts",
34
33
  "dev-kit:install": "node ./scripts/dev-kit-install.js",
35
34
  "dev-kit:remove": "node ./scripts/dev-kit-remove.js",
36
35
  "test": "jest --runInBand",
@@ -51,7 +50,7 @@
51
50
  "test:sqlite": "sh ./scripts/test-sqlite.sh",
52
51
  "prettier:check": "prettier --check .",
53
52
  "prettier:write": "prettier --write .",
54
- "prepare": "husky install",
53
+ "prepare": "husky",
55
54
  "benchmark": "k6 run benchmark/run.js"
56
55
  },
57
56
  "engines": {
@@ -61,57 +60,58 @@
61
60
  "body-parser": "^1.20.2",
62
61
  "change-case": "^4.1.2",
63
62
  "connect": "^3.7.0",
64
- "dotenv": "^16.3.1",
63
+ "dotenv": "^16.4.4",
65
64
  "formidable": "^3.5.1",
66
65
  "knex": "^3.1.0",
67
66
  "knex-paginate": "^3.1.1",
68
67
  "knex-schema-inspector": "^3.1.0",
69
68
  "nanoid": "^3.3.7",
70
- "pino": "^8.16.2",
71
- "pino-pretty": "^10.2.3",
69
+ "pino": "^8.18.0",
70
+ "pino-pretty": "^10.3.1",
72
71
  "pluralize": "^8.0.0",
73
72
  "validatorjs": "^3.22.1"
74
73
  },
75
74
  "devDependencies": {
76
- "@babel/core": "^7.23.5",
77
- "@babel/preset-env": "^7.23.5",
75
+ "@babel/core": "^7.23.9",
76
+ "@babel/preset-env": "^7.23.9",
78
77
  "@babel/preset-typescript": "^7.23.3",
79
- "@elastic/elasticsearch": "^8.10.0",
78
+ "@elastic/elasticsearch": "^8.12.1",
80
79
  "@types/accept-language-parser": "^1.5.6",
81
- "@types/aws-lambda": "^8.10.130",
80
+ "@types/aws-lambda": "^8.10.133",
82
81
  "@types/cors": "^2.8.17",
83
82
  "@types/formidable": "^3.4.5",
84
83
  "@types/multer": "^1.4.11",
85
84
  "@types/pluralize": "^0.0.33",
86
85
  "@types/validatorjs": "^3.15.5",
87
- "@typescript-eslint/eslint-plugin": "^6.13.2",
88
- "@typescript-eslint/parser": "^6.13.2",
86
+ "@typescript-eslint/eslint-plugin": "^7.0.1",
87
+ "@typescript-eslint/parser": "^7.0.1",
89
88
  "babel-jest": "^29.7.0",
90
89
  "cors": "^2.8.5",
91
90
  "eslint": "^8.56.0",
92
91
  "eslint-config-standard": "^17.1.0",
93
- "eslint-plugin-import": "^2.29.0",
92
+ "eslint-plugin-import": "^2.29.1",
94
93
  "eslint-plugin-node": "^11.1.0",
95
94
  "eslint-plugin-promise": "^6.1.1",
96
- "eslint-plugin-unicorn": "^50.0.1",
95
+ "eslint-plugin-unicorn": "^51.0.1",
97
96
  "eslint-watch": "^8.0.0",
98
97
  "glob": "^10.3.10",
99
- "husky": "^8.0.3",
98
+ "husky": "^9.0.11",
100
99
  "jest": "^29.7.0",
101
- "lint-staged": "^15.2.0",
100
+ "lint-staged": "^15.2.2",
102
101
  "multer": "^1.4.5-lts.1",
103
102
  "mysql": "^2.18.1",
104
103
  "node-cache": "^5.1.2",
105
- "node-color-log": "^11.0.0",
106
- "nodemon": "^3.0.2",
104
+ "node-color-log": "^11.0.2",
105
+ "nodemon": "^3.0.3",
107
106
  "pg": "^8.11.3",
108
- "prettier": "^3.1.1",
109
- "redis": "^4.6.11",
107
+ "prettier": "^3.2.5",
108
+ "redis": "^4.6.13",
109
+ "robust-validator": "^1.1.0",
110
110
  "serve-static": "^1.15.0",
111
111
  "set-value": ">=4.1.0",
112
- "sqlite3": "^5.1.6",
112
+ "sqlite3": "^5.1.7",
113
113
  "ts-node": "^10.9.2",
114
- "ts-node-dev": "^2.0.0",
114
+ "tsx": "^4.7.1",
115
115
  "typescript": "^5.3.3"
116
116
  },
117
117
  "lint-staged": {