axe-api 0.22.0 → 0.30.0-rc10

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.
Files changed (73) hide show
  1. package/build/dev-kit.d.ts +1 -0
  2. package/build/dev-kit.js +16 -0
  3. package/build/index.d.ts +3 -3
  4. package/build/index.js +4 -1
  5. package/build/src/Builders/ModelTreeBuilder.d.ts +3 -0
  6. package/build/src/Builders/ModelTreeBuilder.js +21 -17
  7. package/build/src/Builders/RouterBuilder.d.ts +3 -0
  8. package/build/src/Builders/RouterBuilder.js +28 -27
  9. package/build/src/Enums.d.ts +98 -0
  10. package/build/src/Enums.js +103 -1
  11. package/build/src/Exceptions/ApiError.d.ts +1 -1
  12. package/build/src/Exceptions/ApiError.js +2 -2
  13. package/build/src/Exceptions/AxeError.d.ts +8 -0
  14. package/build/src/Exceptions/AxeError.js +11 -0
  15. package/build/src/Handlers/AllHandler.js +4 -5
  16. package/build/src/Handlers/DocsHandler.d.ts +3 -0
  17. package/build/src/Handlers/DocsHandler.js +22 -0
  18. package/build/src/Handlers/HandlerFactory.d.ts +1 -1
  19. package/build/src/Handlers/HandlerFactory.js +1 -1
  20. package/build/src/Handlers/Helpers.d.ts +5 -3
  21. package/build/src/Handlers/Helpers.js +29 -13
  22. package/build/src/Handlers/PaginateHandler.js +4 -5
  23. package/build/src/Handlers/PatchHandler.js +2 -2
  24. package/build/src/Handlers/RoutesHandler.d.ts +3 -0
  25. package/build/src/Handlers/RoutesHandler.js +16 -0
  26. package/build/src/Handlers/ShowHandler.js +4 -5
  27. package/build/src/Handlers/StoreHandler.js +2 -2
  28. package/build/src/Handlers/UpdateHandler.js +2 -2
  29. package/build/src/Helpers.d.ts +4 -0
  30. package/build/src/Helpers.js +78 -0
  31. package/build/src/Interfaces.d.ts +54 -14
  32. package/build/src/Middlewares/acceptLanguageMiddleware.js +3 -5
  33. package/build/src/Model.d.ts +2 -2
  34. package/build/src/Model.js +3 -4
  35. package/build/src/Resolvers/FileResolver.js +2 -2
  36. package/build/src/Resolvers/GeneralHookResolver.d.ts +4 -2
  37. package/build/src/Resolvers/GeneralHookResolver.js +5 -8
  38. package/build/src/Resolvers/ModelResolver.d.ts +7 -0
  39. package/build/src/Resolvers/ModelResolver.js +99 -19
  40. package/build/src/Resolvers/TransactionResolver.d.ts +4 -2
  41. package/build/src/Resolvers/TransactionResolver.js +5 -4
  42. package/build/src/Resolvers/VersionConfigResolver.d.ts +7 -0
  43. package/build/src/Resolvers/VersionConfigResolver.js +58 -0
  44. package/build/src/Resolvers/VersionResolver.d.ts +7 -0
  45. package/build/src/Resolvers/VersionResolver.js +65 -0
  46. package/build/src/Resolvers/index.d.ts +3 -2
  47. package/build/src/Resolvers/index.js +5 -3
  48. package/build/src/Server.d.ts +3 -2
  49. package/build/src/Server.js +73 -46
  50. package/build/src/Services/APIService.d.ts +16 -0
  51. package/build/src/Services/APIService.js +82 -0
  52. package/build/src/Services/DocumentationService.d.ts +3 -1
  53. package/build/src/Services/DocumentationService.js +6 -0
  54. package/build/src/Services/LimitService.d.ts +5 -0
  55. package/build/src/Services/LimitService.js +116 -0
  56. package/build/src/Services/LogService.d.ts +4 -1
  57. package/build/src/Services/LogService.js +6 -0
  58. package/build/src/Services/ModelService.d.ts +6 -1
  59. package/build/src/Services/ModelService.js +8 -0
  60. package/build/src/Services/QueryService.d.ts +3 -2
  61. package/build/src/Services/QueryService.js +32 -7
  62. package/build/src/Services/SchemaValidatorService.d.ts +7 -0
  63. package/build/src/Services/SchemaValidatorService.js +62 -8
  64. package/build/src/Services/index.d.ts +3 -1
  65. package/build/src/Services/index.js +6 -1
  66. package/build/src/Types.d.ts +2 -0
  67. package/build/src/Types.js +2 -0
  68. package/build/src/constants.d.ts +5 -1
  69. package/build/src/constants.js +43 -2
  70. package/package.json +26 -24
  71. package/CHANGELOG.md +0 -212
  72. package/build/src/Resolvers/FolderResolver.d.ts +0 -5
  73. package/build/src/Resolvers/FolderResolver.js +0 -19
@@ -1,8 +1,10 @@
1
1
  import { IModelService, IRouteDocumentation } from "../Interfaces";
2
2
  import { HttpMethods } from "../Enums";
3
3
  declare class DocumentationService {
4
- routes: IRouteDocumentation[];
4
+ private static instance;
5
+ private routes;
5
6
  constructor();
7
+ static getInstance(): DocumentationService;
6
8
  push(method: HttpMethods, url: string, model: IModelService): void;
7
9
  get(): IRouteDocumentation[];
8
10
  }
@@ -4,6 +4,12 @@ class DocumentationService {
4
4
  constructor() {
5
5
  this.routes = [];
6
6
  }
7
+ static getInstance() {
8
+ if (!DocumentationService.instance) {
9
+ DocumentationService.instance = new DocumentationService();
10
+ }
11
+ return DocumentationService.instance;
12
+ }
7
13
  push(method, url, model) {
8
14
  this.routes.push({
9
15
  model: model.name,
@@ -0,0 +1,5 @@
1
+ import { QueryFeature } from "../Enums";
2
+ import { IModelService, IQueryLimitConfig } from "../Interfaces";
3
+ export declare const allow: (feature: QueryFeature, keys?: string[]) => IQueryLimitConfig[];
4
+ export declare const deny: (feature: QueryFeature, keys?: string[]) => IQueryLimitConfig[];
5
+ export declare const valideteQueryFeature: (model: IModelService, feature: QueryFeature, key?: string | null, errorDescription?: string) => void;
@@ -0,0 +1,116 @@
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.valideteQueryFeature = exports.deny = exports.allow = void 0;
7
+ const Enums_1 = require("../Enums");
8
+ const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
9
+ const QueryFeatureMap = {
10
+ [Enums_1.QueryFeature.All]: [
11
+ Enums_1.QueryFeature.FieldsAll,
12
+ Enums_1.QueryFeature.Sorting,
13
+ Enums_1.QueryFeature.Limits,
14
+ Enums_1.QueryFeature.WhereEqual,
15
+ Enums_1.QueryFeature.WhereNotEqual,
16
+ Enums_1.QueryFeature.WhereGt,
17
+ Enums_1.QueryFeature.WhereGte,
18
+ Enums_1.QueryFeature.WhereLt,
19
+ Enums_1.QueryFeature.WhereLte,
20
+ Enums_1.QueryFeature.WhereLike,
21
+ Enums_1.QueryFeature.WhereNotLike,
22
+ Enums_1.QueryFeature.WhereIn,
23
+ Enums_1.QueryFeature.WhereNotIn,
24
+ Enums_1.QueryFeature.WhereBetween,
25
+ Enums_1.QueryFeature.WhereNotBetween,
26
+ Enums_1.QueryFeature.WhereNull,
27
+ Enums_1.QueryFeature.WhereNotNull,
28
+ Enums_1.QueryFeature.Trashed,
29
+ Enums_1.QueryFeature.WithHasOne,
30
+ Enums_1.QueryFeature.WithHasMany,
31
+ ],
32
+ [Enums_1.QueryFeature.FieldsAll]: [Enums_1.QueryFeature.FieldsAll],
33
+ [Enums_1.QueryFeature.Sorting]: [Enums_1.QueryFeature.Sorting],
34
+ [Enums_1.QueryFeature.Limits]: [Enums_1.QueryFeature.Limits],
35
+ [Enums_1.QueryFeature.WhereAll]: [
36
+ Enums_1.QueryFeature.WhereEqual,
37
+ Enums_1.QueryFeature.WhereNotEqual,
38
+ Enums_1.QueryFeature.WhereGt,
39
+ Enums_1.QueryFeature.WhereGte,
40
+ Enums_1.QueryFeature.WhereLt,
41
+ Enums_1.QueryFeature.WhereLte,
42
+ Enums_1.QueryFeature.WhereLike,
43
+ Enums_1.QueryFeature.WhereNotLike,
44
+ Enums_1.QueryFeature.WhereIn,
45
+ Enums_1.QueryFeature.WhereNotIn,
46
+ Enums_1.QueryFeature.WhereBetween,
47
+ Enums_1.QueryFeature.WhereNotBetween,
48
+ Enums_1.QueryFeature.WhereNull,
49
+ Enums_1.QueryFeature.WhereNotNull,
50
+ ],
51
+ [Enums_1.QueryFeature.WhereEqual]: [Enums_1.QueryFeature.WhereEqual],
52
+ [Enums_1.QueryFeature.WhereNotEqual]: [Enums_1.QueryFeature.WhereNotEqual],
53
+ [Enums_1.QueryFeature.WhereGt]: [Enums_1.QueryFeature.WhereGt],
54
+ [Enums_1.QueryFeature.WhereGte]: [Enums_1.QueryFeature.WhereGte],
55
+ [Enums_1.QueryFeature.WhereLt]: [Enums_1.QueryFeature.WhereLt],
56
+ [Enums_1.QueryFeature.WhereLte]: [Enums_1.QueryFeature.WhereLte],
57
+ [Enums_1.QueryFeature.WhereLike]: [Enums_1.QueryFeature.WhereLike],
58
+ [Enums_1.QueryFeature.WhereNotLike]: [Enums_1.QueryFeature.WhereNotLike],
59
+ [Enums_1.QueryFeature.WhereIn]: [Enums_1.QueryFeature.WhereIn],
60
+ [Enums_1.QueryFeature.WhereNotIn]: [Enums_1.QueryFeature.WhereNotIn],
61
+ [Enums_1.QueryFeature.WhereBetween]: [Enums_1.QueryFeature.WhereBetween],
62
+ [Enums_1.QueryFeature.WhereNotBetween]: [Enums_1.QueryFeature.WhereNotBetween],
63
+ [Enums_1.QueryFeature.WhereNull]: [Enums_1.QueryFeature.WhereNull],
64
+ [Enums_1.QueryFeature.WhereNotNull]: [Enums_1.QueryFeature.WhereNotNull],
65
+ [Enums_1.QueryFeature.Trashed]: [Enums_1.QueryFeature.Trashed],
66
+ [Enums_1.QueryFeature.WithAll]: [Enums_1.QueryFeature.WithHasOne, Enums_1.QueryFeature.WithHasMany],
67
+ [Enums_1.QueryFeature.WithHasOne]: [Enums_1.QueryFeature.WithHasOne],
68
+ [Enums_1.QueryFeature.WithHasMany]: [Enums_1.QueryFeature.WithHasMany],
69
+ };
70
+ const generatePermission = (type, feature, keys = []) => {
71
+ const features = QueryFeatureMap[feature];
72
+ if (keys.length === 0) {
73
+ keys = [null];
74
+ }
75
+ return features
76
+ .map((subFeature) => {
77
+ return keys.map((key) => {
78
+ return {
79
+ type,
80
+ feature: subFeature,
81
+ key,
82
+ };
83
+ });
84
+ })
85
+ .flat();
86
+ };
87
+ const allow = (feature, keys = []) => {
88
+ return generatePermission(Enums_1.QueryFeatureType.Allow, feature, keys);
89
+ };
90
+ exports.allow = allow;
91
+ const deny = (feature, keys = []) => {
92
+ return generatePermission(Enums_1.QueryFeatureType.Deny, feature, keys);
93
+ };
94
+ exports.deny = deny;
95
+ const valideteQueryFeature = (model, feature, key = null, errorDescription) => {
96
+ const errorDetail = errorDescription ? ` (${errorDescription})` : "";
97
+ const rules = model.queryLimits.filter((limit) => limit.feature === feature && limit.key === null);
98
+ if (key) {
99
+ const keyRules = model.queryLimits.filter((limit) => limit.feature === feature && limit.key === key);
100
+ if (keyRules.length > 0) {
101
+ const lastKeyRule = keyRules[keyRules.length - 1];
102
+ if ((lastKeyRule === null || lastKeyRule === void 0 ? void 0 : lastKeyRule.type) === Enums_1.QueryFeatureType.Deny) {
103
+ throw new ApiError_1.default(`Unsupported query feature${errorDetail}: ${feature.toString()} [${key}]`);
104
+ }
105
+ return;
106
+ }
107
+ }
108
+ if (rules.length === 0) {
109
+ throw new ApiError_1.default(`Unsupported query feature${errorDetail}: ${feature.toString()}`);
110
+ }
111
+ const lastRule = rules[rules.length - 1];
112
+ if ((lastRule === null || lastRule === void 0 ? void 0 : lastRule.type) === Enums_1.QueryFeatureType.Deny) {
113
+ throw new ApiError_1.default(`Unsupported query feature${errorDetail}: ${feature.toString()}`);
114
+ }
115
+ };
116
+ exports.valideteQueryFeature = valideteQueryFeature;
@@ -1,7 +1,10 @@
1
1
  import { LogLevels } from "../Enums";
2
2
  declare class LogService {
3
- level: LogLevels;
3
+ private static instance;
4
+ private level;
4
5
  constructor(level: LogLevels);
6
+ static setInstance(level: LogLevels): void;
7
+ static getInstance(): LogService;
5
8
  error(message: string): void;
6
9
  warn(message: string): void;
7
10
  info(message: string): void;
@@ -7,6 +7,12 @@ class LogService {
7
7
  constructor(level) {
8
8
  this.level = level;
9
9
  }
10
+ static setInstance(level) {
11
+ LogService.instance = new LogService(level);
12
+ }
13
+ static getInstance() {
14
+ return LogService.instance;
15
+ }
10
16
  error(message) {
11
17
  if (this.level >= Enums_1.LogLevels.ERROR) {
12
18
  console.error(fgRed, "[axe]", message, fgReset);
@@ -1,6 +1,7 @@
1
1
  import { HookFunctionTypes, Extensions } from "../Enums";
2
- import { IColumn, IHookParameter, IModelService, IRelation } from "../Interfaces";
2
+ import { IColumn, IHookParameter, IModelService, IQueryLimitConfig, IRelation } from "../Interfaces";
3
3
  import Model from "./../Model";
4
+ import { SerializationFunction } from "../Types";
4
5
  declare class ModelService implements IModelService {
5
6
  name: string;
6
7
  instance: Model;
@@ -11,9 +12,13 @@ declare class ModelService implements IModelService {
11
12
  events: Record<HookFunctionTypes, (params: IHookParameter) => void>;
12
13
  children: IModelService[];
13
14
  isRecursive: boolean;
15
+ queryLimits: IQueryLimitConfig[];
16
+ serialize: SerializationFunction | null;
14
17
  constructor(name: string, instance: Model);
15
18
  setColumns(columns: IColumn[]): void;
16
19
  setExtensions(type: Extensions, hookFunctionType: HookFunctionTypes, data: (params: IHookParameter) => void): void;
20
+ setQueryLimits(limits: IQueryLimitConfig[]): void;
21
+ setSerialization(callback: SerializationFunction): void;
17
22
  private setHooks;
18
23
  private setEvents;
19
24
  }
@@ -12,6 +12,8 @@ class ModelService {
12
12
  this.columnNames = [];
13
13
  this.children = [];
14
14
  this.isRecursive = false;
15
+ this.queryLimits = [];
16
+ this.serialize = null;
15
17
  }
16
18
  setColumns(columns) {
17
19
  this.columns = columns;
@@ -28,6 +30,12 @@ class ModelService {
28
30
  throw new Error("Undefined hook type.");
29
31
  }
30
32
  }
33
+ setQueryLimits(limits) {
34
+ this.queryLimits = limits;
35
+ }
36
+ setSerialization(callback) {
37
+ this.serialize = callback;
38
+ }
31
39
  setHooks(hookFunctionType, data) {
32
40
  this.hooks[hookFunctionType] = data;
33
41
  }
@@ -1,4 +1,4 @@
1
- import { IQuery, ISortField, NestedWhere, IWhere, IModelService } from "../Interfaces";
1
+ import { IQuery, ISortField, NestedWhere, IWhere, IModelService, IVersionConfig } from "../Interfaces";
2
2
  import { Knex } from "knex";
3
3
  declare class QueryService {
4
4
  model: IModelService;
@@ -6,7 +6,8 @@ declare class QueryService {
6
6
  usedConditionColumns: string[];
7
7
  relationColumns: string[];
8
8
  createdJoins: string[];
9
- constructor(model: IModelService, models: IModelService[]);
9
+ config: IVersionConfig;
10
+ constructor(model: IModelService, models: IModelService[], config: IVersionConfig);
10
11
  applyFields(query: Knex.QueryBuilder, fields: string[]): void;
11
12
  applySorting(query: Knex.QueryBuilder, sort: ISortField[]): void;
12
13
  applyWheresInsideGroup(sub: Knex.QueryBuilder, ruleSet: NestedWhere | IWhere): void;
@@ -6,10 +6,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const Enums_1 = require("../Enums");
7
7
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
8
8
  const Resolvers_1 = require("../Resolvers");
9
+ const constants_1 = require("../constants");
10
+ const LimitService_1 = require("./LimitService");
11
+ const Helpers_1 = require("../Handlers/Helpers");
9
12
  class QueryService {
10
- constructor(model, models) {
13
+ constructor(model, models, config) {
11
14
  this.model = model;
12
15
  this.models = models;
16
+ this.config = config;
13
17
  this.createdJoins = [];
14
18
  this.relationColumns = [];
15
19
  this.usedConditionColumns = [];
@@ -17,6 +21,7 @@ class QueryService {
17
21
  applyFields(query, fields) {
18
22
  // Users should be able to select some fields to show.
19
23
  if (fields.length === 0 || (fields.length === 1 && fields[0] === "*")) {
24
+ (0, LimitService_1.valideteQueryFeature)(this.model, Enums_1.QueryFeature.FieldsAll);
20
25
  query.select(`${this.model.instance.table}.*`);
21
26
  }
22
27
  else {
@@ -33,7 +38,9 @@ class QueryService {
33
38
  if (sort.length === 0) {
34
39
  return;
35
40
  }
41
+ (0, LimitService_1.valideteQueryFeature)(this.model, Enums_1.QueryFeature.Sorting);
36
42
  sort.forEach((item) => {
43
+ (0, LimitService_1.valideteQueryFeature)(this.model, Enums_1.QueryFeature.Sorting, `${this.model.instance.table}.${item.name}`);
37
44
  query.orderBy(item.name, item.type);
38
45
  });
39
46
  }
@@ -156,6 +163,7 @@ class QueryService {
156
163
  this.createdJoins.push(relation.name);
157
164
  }
158
165
  parseSections(sections) {
166
+ var _a, _b, _c, _d;
159
167
  if (sections.q) {
160
168
  const queryContent = sections.q.replace(/%20/g, "").replace(/ /g, "");
161
169
  // Users can send an unacceptable query string. We shouldn't allow them to
@@ -175,10 +183,14 @@ class QueryService {
175
183
  sort: this.parseSortingOptions(sections.sort),
176
184
  q: this.parseCondition(sections.q),
177
185
  with: withQueryResolver.resolve((sections === null || sections === void 0 ? void 0 : sections.with) || ""),
178
- trashed: (sections === null || sections === void 0 ? void 0 : sections.trashed)
179
- ? sections.trashed.trim() === "true" || sections.trashed.trim() === "1"
180
- : false,
186
+ trashed: (sections === null || sections === void 0 ? void 0 : sections.trashed) ? (0, Helpers_1.isBoolean)(sections.trashed) : false,
181
187
  };
188
+ const configPerPage = ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.query.defaults) === null || _b === void 0 ? void 0 : _b.perPage) ||
189
+ ((_d = (_c = constants_1.DEFAULT_VERSION_CONFIG.query) === null || _c === void 0 ? void 0 : _c.defaults) === null || _d === void 0 ? void 0 : _d.perPage) ||
190
+ 10;
191
+ if (query.per_page !== configPerPage) {
192
+ (0, LimitService_1.valideteQueryFeature)(this.model, Enums_1.QueryFeature.Limits);
193
+ }
182
194
  this.addRelationColumns(query.with);
183
195
  return query;
184
196
  }
@@ -193,9 +205,21 @@ class QueryService {
193
205
  return value;
194
206
  }
195
207
  parsePerPage(content) {
196
- const value = parseInt(content);
197
- if (isNaN(value) || value <= 1 || value > 10000) {
198
- return 10;
208
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
209
+ const value = parseInt(content ||
210
+ ((_b = (_a = this.config.query) === null || _a === void 0 ? void 0 : _a.defaults) === null || _b === void 0 ? void 0 : _b.perPage) ||
211
+ ((_c = constants_1.DEFAULT_VERSION_CONFIG.query.defaults) === null || _c === void 0 ? void 0 : _c.perPage) ||
212
+ 10);
213
+ const minPerPage = ((_e = (_d = this.config.query) === null || _d === void 0 ? void 0 : _d.defaults) === null || _e === void 0 ? void 0 : _e.minPerPage) ||
214
+ ((_f = constants_1.DEFAULT_VERSION_CONFIG.query.defaults) === null || _f === void 0 ? void 0 : _f.minPerPage) ||
215
+ 1;
216
+ const maxPerPage = ((_h = (_g = this.config.query) === null || _g === void 0 ? void 0 : _g.defaults) === null || _h === void 0 ? void 0 : _h.maxPerPage) ||
217
+ ((_j = constants_1.DEFAULT_VERSION_CONFIG.query.defaults) === null || _j === void 0 ? void 0 : _j.maxPerPage) ||
218
+ 100;
219
+ if (isNaN(value) || value <= minPerPage || value > maxPerPage) {
220
+ return (((_l = (_k = this.config.query) === null || _k === void 0 ? void 0 : _k.defaults) === null || _l === void 0 ? void 0 : _l.perPage) ||
221
+ ((_m = constants_1.DEFAULT_VERSION_CONFIG.query.defaults) === null || _m === void 0 ? void 0 : _m.perPage) ||
222
+ 10);
199
223
  }
200
224
  return value;
201
225
  }
@@ -332,6 +356,7 @@ class QueryService {
332
356
  where.relation = relation;
333
357
  where.field = field;
334
358
  }
359
+ (0, LimitService_1.valideteQueryFeature)(this.model, constants_1.ConditionQueryFeatureMap[where.condition], `${where.table}.${where.field}`);
335
360
  this.shouldBeAcceptableColumn(where.field);
336
361
  this.usedConditionColumns.push(`${where.table}.${where.field}`);
337
362
  return where;
@@ -1,6 +1,13 @@
1
+ import { IVersion } from "../Interfaces";
1
2
  declare class SchemaValidatorService {
3
+ private version;
4
+ constructor(version: IVersion);
2
5
  validate(): Promise<void>;
3
6
  private checkModelColumnsOrFail;
7
+ private checkRelationNamesOrFail;
8
+ private getQueryLimitRelations;
9
+ private getQueryLimitColumns;
10
+ private getQueryLimitKeyByFilter;
4
11
  private getModelFillableColumns;
5
12
  private getModelFormValidationColumns;
6
13
  private getModelHiddenColumns;
@@ -8,11 +8,55 @@ 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
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ const AxeError_1 = __importDefault(require("../Exceptions/AxeError"));
12
16
  const Enums_1 = require("../Enums");
13
17
  const Services_1 = require("../Services");
18
+ const COLUMN_BASED_QUERY_LIMITS = [
19
+ Enums_1.QueryFeature.Sorting,
20
+ Enums_1.QueryFeature.WhereEqual,
21
+ Enums_1.QueryFeature.WhereNotEqual,
22
+ Enums_1.QueryFeature.WhereGt,
23
+ Enums_1.QueryFeature.WhereGte,
24
+ Enums_1.QueryFeature.WhereLt,
25
+ Enums_1.QueryFeature.WhereLte,
26
+ Enums_1.QueryFeature.WhereLike,
27
+ Enums_1.QueryFeature.WhereNotLike,
28
+ Enums_1.QueryFeature.WhereIn,
29
+ Enums_1.QueryFeature.WhereNotIn,
30
+ Enums_1.QueryFeature.WhereBetween,
31
+ Enums_1.QueryFeature.WhereNotBetween,
32
+ Enums_1.QueryFeature.WhereNull,
33
+ Enums_1.QueryFeature.WhereNotNull,
34
+ ];
35
+ const RELATION_BASED_QUERY_LIMITS = [
36
+ Enums_1.QueryFeature.WithHasMany,
37
+ Enums_1.QueryFeature.WithHasOne,
38
+ ];
14
39
  class SchemaValidatorService {
15
- constructor() {
40
+ constructor(version) {
41
+ this.getQueryLimitRelations = (model) => {
42
+ return this.getQueryLimitKeyByFilter(model, RELATION_BASED_QUERY_LIMITS);
43
+ };
44
+ this.getQueryLimitColumns = (model) => {
45
+ return this.getQueryLimitKeyByFilter(model, COLUMN_BASED_QUERY_LIMITS);
46
+ };
47
+ this.getQueryLimitKeyByFilter = (model, filter) => {
48
+ const items = model.queryLimits
49
+ .filter((limit) => limit.key && filter.includes(limit.feature))
50
+ .map((limit) => limit.key)
51
+ .map((key) => {
52
+ if (!key) {
53
+ return "";
54
+ }
55
+ const [, field] = key === null || key === void 0 ? void 0 : key.split(".");
56
+ return field;
57
+ });
58
+ return items;
59
+ };
16
60
  this.getModelFillableColumns = (model) => {
17
61
  const fillable = model.instance.fillable;
18
62
  if (!fillable) {
@@ -66,30 +110,40 @@ class SchemaValidatorService {
66
110
  this.checkModelColumnsOrFail(model, [relation.primaryKey]);
67
111
  const relatedModel = modelList.find(relation.model);
68
112
  if (!relatedModel) {
69
- throw new Error(`Undefined related model: ${relation.model}`);
113
+ throw new AxeError_1.default(Enums_1.AxeErrorCode.UNDEFINED_RELATION_MODEL, `Undefined related model: ${relation.model} (${model.name}.${relation.name})`);
70
114
  }
71
115
  this.checkModelColumnsOrFail(relatedModel, [relation.foreignKey]);
72
116
  };
117
+ this.version = version;
73
118
  }
74
119
  validate() {
75
120
  return __awaiter(this, void 0, void 0, function* () {
76
- const logger = yield Services_1.IoCService.useByType("LogService");
77
- const modelList = yield Services_1.IoCService.useByType("ModelListService");
78
- modelList.get().forEach((model) => {
121
+ const logger = Services_1.LogService.getInstance();
122
+ this.version.modelList.get().forEach((model) => {
79
123
  this.checkModelColumnsOrFail(model, this.getModelFillableColumns(model));
80
124
  this.checkModelColumnsOrFail(model, this.getModelFormValidationColumns(model));
81
125
  this.checkModelColumnsOrFail(model, this.getModelHiddenColumns(model));
82
126
  this.checkModelColumnsOrFail(model, this.getTimestampsColumns(model));
127
+ this.checkModelColumnsOrFail(model, this.getQueryLimitColumns(model));
83
128
  this.checkModelColumnsOrFail(model, [model.instance.primaryKey]);
84
- this.checkRelationColumnsOrFail(modelList, model);
129
+ this.checkRelationNamesOrFail(model, this.getQueryLimitRelations(model));
130
+ this.checkRelationColumnsOrFail(this.version.modelList, model);
85
131
  });
86
- logger.info("Database schema has been validated.");
132
+ logger.info(`[${this.version.name}] Database schema has been validated.`);
87
133
  });
88
134
  }
89
135
  checkModelColumnsOrFail(model, modelColumns) {
90
136
  const undefinedColumns = modelColumns.filter((modelColumn) => !model.columnNames.includes(modelColumn));
91
137
  if (undefinedColumns.length > 0) {
92
- throw new Error(`${model.name} model doesn't have the following columns on the database; "${model.instance.table}.${undefinedColumns.join(",")}"`);
138
+ throw new AxeError_1.default(Enums_1.AxeErrorCode.UNDEFINED_COLUMN, `${model.name} model doesn't have the following columns on the database; "${model.instance.table}.${undefinedColumns.join(",")}"`);
139
+ }
140
+ }
141
+ checkRelationNamesOrFail(model, names) {
142
+ const undefinedRelationNames = names.filter((name) => {
143
+ return !model.relations.map((relation) => relation.name).includes(name);
144
+ });
145
+ if (undefinedRelationNames.length > 0) {
146
+ throw new AxeError_1.default(Enums_1.AxeErrorCode.UNDEFINED_RELATION_NAME, `${model.name} model doesn't have a valid relation name that is defined in query limits; "${undefinedRelationNames.join(",")}"`);
93
147
  }
94
148
  }
95
149
  checkRelationColumnsOrFail(modelList, model) {
@@ -1,8 +1,10 @@
1
+ import APIService from "./APIService";
1
2
  import DocumentationService from "./DocumentationService";
2
3
  import IoCService from "./IoCService";
4
+ import { allow, deny } from "./LimitService";
3
5
  import LogService from "./LogService";
4
6
  import ModelListService from "./ModelListService";
5
7
  import ModelService from "./ModelService";
6
8
  import QueryService from "./QueryService";
7
9
  import SchemaValidatorService from "./SchemaValidatorService";
8
- export { DocumentationService, IoCService, LogService, ModelListService, ModelService, QueryService, SchemaValidatorService, };
10
+ export { DocumentationService, APIService, IoCService, LogService, ModelListService, ModelService, QueryService, SchemaValidatorService, allow, deny, };
@@ -3,11 +3,16 @@ 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.SchemaValidatorService = exports.QueryService = exports.ModelService = exports.ModelListService = exports.LogService = exports.IoCService = exports.DocumentationService = void 0;
6
+ exports.deny = exports.allow = exports.SchemaValidatorService = exports.QueryService = exports.ModelService = exports.ModelListService = exports.LogService = exports.IoCService = exports.APIService = exports.DocumentationService = void 0;
7
+ const APIService_1 = __importDefault(require("./APIService"));
8
+ exports.APIService = APIService_1.default;
7
9
  const DocumentationService_1 = __importDefault(require("./DocumentationService"));
8
10
  exports.DocumentationService = DocumentationService_1.default;
9
11
  const IoCService_1 = __importDefault(require("./IoCService"));
10
12
  exports.IoCService = IoCService_1.default;
13
+ const LimitService_1 = require("./LimitService");
14
+ Object.defineProperty(exports, "allow", { enumerable: true, get: function () { return LimitService_1.allow; } });
15
+ Object.defineProperty(exports, "deny", { enumerable: true, get: function () { return LimitService_1.deny; } });
11
16
  const LogService_1 = __importDefault(require("./LogService"));
12
17
  exports.LogService = LogService_1.default;
13
18
  const ModelListService_1 = __importDefault(require("./ModelListService"));
@@ -0,0 +1,2 @@
1
+ import { Request } from "express";
2
+ export type SerializationFunction = (item: any, request: Request) => any;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,5 @@
1
- import { HandlerTypes } from "./Enums";
1
+ import { ConditionTypes, HandlerTypes, QueryFeature, Relationships } from "./Enums";
2
+ import { IVersionConfig } from "./Interfaces";
2
3
  export declare const LOG_COLORS: {
3
4
  fgBlack: string;
4
5
  fgRed: string;
@@ -22,3 +23,6 @@ export declare const API_ROUTE_TEMPLATES: {
22
23
  destroy: (prefix: string, parentUrl: string, resource: string, primaryKey: string) => string;
23
24
  force_delete: (prefix: string, parentUrl: string, resource: string, primaryKey: string) => string;
24
25
  };
26
+ export declare const ConditionQueryFeatureMap: Record<ConditionTypes, QueryFeature>;
27
+ export declare const RelationQueryFeatureMap: Record<Relationships, QueryFeature>;
28
+ export declare const DEFAULT_VERSION_CONFIG: IVersionConfig;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.API_ROUTE_TEMPLATES = exports.DEFAULT_METHODS_OF_MODELS = exports.DEFAULT_HANDLERS = exports.LOG_COLORS = void 0;
3
+ exports.DEFAULT_VERSION_CONFIG = exports.RelationQueryFeatureMap = exports.ConditionQueryFeatureMap = exports.API_ROUTE_TEMPLATES = exports.DEFAULT_METHODS_OF_MODELS = exports.DEFAULT_HANDLERS = exports.LOG_COLORS = void 0;
4
4
  const Enums_1 = require("./Enums");
5
+ const LimitService_1 = require("./Services/LimitService");
5
6
  exports.LOG_COLORS = {
6
7
  fgBlack: "\x1b[30m",
7
8
  fgRed: "\x1b[31m",
@@ -26,7 +27,6 @@ exports.DEFAULT_METHODS_OF_MODELS = [
26
27
  "hasMany",
27
28
  "hasOne",
28
29
  "belongsTo",
29
- "serialize",
30
30
  "__defineGetter__",
31
31
  "__defineSetter__",
32
32
  "hasOwnProperty",
@@ -49,6 +49,7 @@ exports.DEFAULT_METHODS_OF_MODELS = [
49
49
  "deletedAtColumn",
50
50
  "transaction",
51
51
  "ignore",
52
+ "limits",
52
53
  "getFillableFields",
53
54
  "getValidationRules",
54
55
  ];
@@ -62,3 +63,43 @@ exports.API_ROUTE_TEMPLATES = {
62
63
  [Enums_1.HandlerTypes.DELETE]: (prefix, parentUrl, resource, primaryKey) => `/${prefix}/${parentUrl}${resource}/:${primaryKey}`,
63
64
  [Enums_1.HandlerTypes.FORCE_DELETE]: (prefix, parentUrl, resource, primaryKey) => `/${prefix}/${parentUrl}${resource}/:${primaryKey}/force`,
64
65
  };
66
+ exports.ConditionQueryFeatureMap = {
67
+ [Enums_1.ConditionTypes.NotNull]: Enums_1.QueryFeature.WhereNotNull,
68
+ [Enums_1.ConditionTypes.Null]: Enums_1.QueryFeature.WhereNull,
69
+ [Enums_1.ConditionTypes["="]]: Enums_1.QueryFeature.WhereEqual,
70
+ [Enums_1.ConditionTypes["<>"]]: Enums_1.QueryFeature.WhereNotEqual,
71
+ [Enums_1.ConditionTypes[">"]]: Enums_1.QueryFeature.WhereGt,
72
+ [Enums_1.ConditionTypes[">="]]: Enums_1.QueryFeature.WhereGte,
73
+ [Enums_1.ConditionTypes["<"]]: Enums_1.QueryFeature.WhereLt,
74
+ [Enums_1.ConditionTypes["<="]]: Enums_1.QueryFeature.WhereLte,
75
+ [Enums_1.ConditionTypes["LIKE"]]: Enums_1.QueryFeature.WhereLike,
76
+ [Enums_1.ConditionTypes["NOT LIKE"]]: Enums_1.QueryFeature.WhereNotLike,
77
+ [Enums_1.ConditionTypes["In"]]: Enums_1.QueryFeature.WhereIn,
78
+ [Enums_1.ConditionTypes["NotIn"]]: Enums_1.QueryFeature.WhereNotIn,
79
+ [Enums_1.ConditionTypes["Between"]]: Enums_1.QueryFeature.WhereBetween,
80
+ [Enums_1.ConditionTypes["NotBetween"]]: Enums_1.QueryFeature.WhereNotBetween,
81
+ };
82
+ exports.RelationQueryFeatureMap = {
83
+ [Enums_1.Relationships.HAS_ONE]: Enums_1.QueryFeature.WithHasOne,
84
+ [Enums_1.Relationships.HAS_MANY]: Enums_1.QueryFeature.WithHasMany,
85
+ };
86
+ exports.DEFAULT_VERSION_CONFIG = {
87
+ transaction: false,
88
+ serializers: [],
89
+ supportedLanguages: ["en"],
90
+ defaultLanguage: "en",
91
+ query: {
92
+ limits: [
93
+ (0, LimitService_1.allow)(Enums_1.QueryFeature.All),
94
+ (0, LimitService_1.deny)(Enums_1.QueryFeature.WithHasMany),
95
+ (0, LimitService_1.deny)(Enums_1.QueryFeature.WhereLike),
96
+ (0, LimitService_1.deny)(Enums_1.QueryFeature.WhereNotLike),
97
+ (0, LimitService_1.deny)(Enums_1.QueryFeature.Trashed),
98
+ ],
99
+ defaults: {
100
+ perPage: 10,
101
+ minPerPage: 1,
102
+ maxPerPage: 100,
103
+ },
104
+ },
105
+ };