axe-api 0.20.1 → 0.20.2

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 (69) hide show
  1. package/build/index.d.ts +8 -0
  2. package/build/index.js +32 -0
  3. package/build/src/Builders/ModelTreeBuilder.d.ts +9 -0
  4. package/build/src/Builders/ModelTreeBuilder.js +64 -0
  5. package/build/src/Builders/RouterBuilder.d.ts +15 -0
  6. package/build/src/Builders/RouterBuilder.js +219 -0
  7. package/build/src/Builders/index.d.ts +3 -0
  8. package/build/src/Builders/index.js +10 -0
  9. package/build/src/Enums.d.ts +77 -0
  10. package/build/src/Enums.js +90 -0
  11. package/build/src/Exceptions/ApiError.d.ts +8 -0
  12. package/build/src/Exceptions/ApiError.js +12 -0
  13. package/build/src/Handlers/AllHandler.d.ts +4 -0
  14. package/build/src/Handlers/AllHandler.js +44 -0
  15. package/build/src/Handlers/DestroyHandler.d.ts +4 -0
  16. package/build/src/Handlers/DestroyHandler.js +37 -0
  17. package/build/src/Handlers/HandlerFactory.d.ts +6 -0
  18. package/build/src/Handlers/HandlerFactory.js +36 -0
  19. package/build/src/Handlers/Helpers.d.ts +14 -0
  20. package/build/src/Handlers/Helpers.js +217 -0
  21. package/build/src/Handlers/PaginateHandler.d.ts +4 -0
  22. package/build/src/Handlers/PaginateHandler.js +48 -0
  23. package/build/src/Handlers/PatchHandler.d.ts +4 -0
  24. package/build/src/Handlers/PatchHandler.js +62 -0
  25. package/build/src/Handlers/ShowHandler.d.ts +4 -0
  26. package/build/src/Handlers/ShowHandler.js +51 -0
  27. package/build/src/Handlers/StoreHandler.d.ts +4 -0
  28. package/build/src/Handlers/StoreHandler.js +59 -0
  29. package/build/src/Handlers/UpdateHandler.d.ts +4 -0
  30. package/build/src/Handlers/UpdateHandler.js +62 -0
  31. package/build/src/Interfaces.d.ts +146 -0
  32. package/build/src/Interfaces.js +3 -0
  33. package/build/src/Model.d.ts +25 -0
  34. package/build/src/Model.js +145 -0
  35. package/build/src/Resolvers/FileResolver.d.ts +5 -0
  36. package/build/src/Resolvers/FileResolver.js +85 -0
  37. package/build/src/Resolvers/FolderResolver.d.ts +5 -0
  38. package/build/src/Resolvers/FolderResolver.js +19 -0
  39. package/build/src/Resolvers/GeneralHookResolver.d.ts +5 -0
  40. package/build/src/Resolvers/GeneralHookResolver.js +35 -0
  41. package/build/src/Resolvers/ModelResolver.d.ts +9 -0
  42. package/build/src/Resolvers/ModelResolver.js +107 -0
  43. package/build/src/Resolvers/TransactionResolver.d.ts +8 -0
  44. package/build/src/Resolvers/TransactionResolver.js +75 -0
  45. package/build/src/Resolvers/WithQueryResolver.d.ts +13 -0
  46. package/build/src/Resolvers/WithQueryResolver.js +116 -0
  47. package/build/src/Resolvers/index.d.ts +7 -0
  48. package/build/src/Resolvers/index.js +18 -0
  49. package/build/src/Server.d.ts +8 -0
  50. package/build/src/Server.js +103 -0
  51. package/build/src/Services/DocumentationService.d.ts +9 -0
  52. package/build/src/Services/DocumentationService.js +22 -0
  53. package/build/src/Services/IoCService.d.ts +9 -0
  54. package/build/src/Services/IoCService.js +51 -0
  55. package/build/src/Services/LogService.d.ts +12 -0
  56. package/build/src/Services/LogService.js +41 -0
  57. package/build/src/Services/ModelListService.d.ts +8 -0
  58. package/build/src/Services/ModelListService.js +18 -0
  59. package/build/src/Services/ModelService.d.ts +20 -0
  60. package/build/src/Services/ModelService.js +38 -0
  61. package/build/src/Services/QueryService.d.ts +34 -0
  62. package/build/src/Services/QueryService.js +377 -0
  63. package/build/src/Services/SchemaValidatorService.d.ts +12 -0
  64. package/build/src/Services/SchemaValidatorService.js +114 -0
  65. package/build/src/Services/index.d.ts +8 -0
  66. package/build/src/Services/index.js +20 -0
  67. package/build/src/constants.d.ts +23 -0
  68. package/build/src/constants.js +62 -0
  69. package/package.json +1 -1
@@ -0,0 +1,377 @@
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 Enums_1 = require("../Enums");
7
+ const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
8
+ const Resolvers_1 = require("../Resolvers");
9
+ class QueryService {
10
+ constructor(model, models) {
11
+ this.model = model;
12
+ this.models = models;
13
+ this.createdJoins = [];
14
+ this.relationColumns = [];
15
+ this.usedConditionColumns = [];
16
+ }
17
+ applyFields(query, fields) {
18
+ // Users should be able to select some fields to show.
19
+ if (fields.length === 0 || (fields.length === 1 && fields[0] === "*")) {
20
+ query.select(`${this.model.instance.table}.*`);
21
+ }
22
+ else {
23
+ const fullPathFields = fields.map((field) => {
24
+ if (field.includes(".") === false) {
25
+ return `${this.model.instance.table}.${field}`;
26
+ }
27
+ return field;
28
+ });
29
+ query.select([...fullPathFields, ...this.relationColumns]);
30
+ }
31
+ }
32
+ applySorting(query, sort) {
33
+ if (sort.length === 0) {
34
+ return;
35
+ }
36
+ sort.forEach((item) => {
37
+ query.orderBy(item.name, item.type);
38
+ });
39
+ }
40
+ applyWheresInsideGroup(sub, ruleSet) {
41
+ // If there is not any query, we don't have to filter the data.
42
+ if (!ruleSet) {
43
+ return;
44
+ }
45
+ if (Array.isArray(ruleSet)) {
46
+ for (const item of ruleSet) {
47
+ // If the item is not an array, it means that it is a standard condition
48
+ if (Array.isArray(item) === false) {
49
+ const condition = item;
50
+ this.applyConditionRule(sub, condition);
51
+ }
52
+ else {
53
+ // If the item is an array, we should create the query recursively.
54
+ const firstItem = item[0];
55
+ if (firstItem.prefix === "or") {
56
+ sub.orWhere((sub) => {
57
+ this.applyWheresInsideGroup(sub, item);
58
+ });
59
+ }
60
+ else {
61
+ sub.where((sub) => {
62
+ this.applyWheresInsideGroup(sub, item);
63
+ });
64
+ }
65
+ }
66
+ }
67
+ }
68
+ else {
69
+ const condition = ruleSet;
70
+ this.applyConditionRule(sub, condition);
71
+ }
72
+ }
73
+ applyWheres(query, ruleSet) {
74
+ query.where((sub) => {
75
+ this.applyWheresInsideGroup(sub, ruleSet);
76
+ });
77
+ this.applyRelatedQueryJoins(query, ruleSet);
78
+ }
79
+ get(query) {
80
+ const conditions = this.parseSections(query);
81
+ const usedColumns = this.getUsedColumns(conditions);
82
+ const undefinedColumns = usedColumns.filter((columnName) => {
83
+ let currentModel = this.model;
84
+ let realColumName = columnName;
85
+ if (columnName.includes(".")) {
86
+ const [table, splittedColumnName] = columnName.split(".");
87
+ currentModel = this.models.find((model) => model.instance.table === table);
88
+ realColumName = splittedColumnName;
89
+ }
90
+ return !currentModel || !currentModel.columnNames.includes(realColumName);
91
+ });
92
+ if (undefinedColumns.length > 0) {
93
+ throw new ApiError_1.default(`Undefined column names: ${undefinedColumns.join(",")}`);
94
+ }
95
+ return conditions;
96
+ }
97
+ getUsedColumns(conditions) {
98
+ return [
99
+ ...conditions.fields,
100
+ ...conditions.sort.map((item) => item.name),
101
+ ...Array.from(this.usedConditionColumns),
102
+ ];
103
+ }
104
+ applyConditionRule(sub, ruleSet) {
105
+ const method = this.getConditionMethodName(ruleSet);
106
+ const zeroArguments = ["Null", "NotNull"];
107
+ const oneArguments = ["In", "NotIn", "Between", "NotBetween"];
108
+ const fullFieldPath = `${ruleSet.table}.${ruleSet.field}`;
109
+ if (zeroArguments.indexOf(ruleSet.condition) > -1) {
110
+ const methodName = `${method}${ruleSet.condition}`;
111
+ return sub[methodName](fullFieldPath);
112
+ }
113
+ if (oneArguments.indexOf(ruleSet.condition) > -1) {
114
+ const methodName = `${method}${ruleSet.condition}`;
115
+ return sub[methodName](fullFieldPath, ruleSet.value);
116
+ }
117
+ return sub[method](fullFieldPath, ruleSet.condition, ruleSet.value);
118
+ }
119
+ applyRelatedQueryJoins(query, ruleSet) {
120
+ if (!ruleSet) {
121
+ return;
122
+ }
123
+ if (Array.isArray(ruleSet)) {
124
+ for (const item of ruleSet) {
125
+ // If the item is not an array, it means that it is a standard condition
126
+ if (Array.isArray(item) === false) {
127
+ const condition = item;
128
+ this.applyJoinIfNecessary(query, condition);
129
+ }
130
+ else {
131
+ this.applyRelatedQueryJoins(query, item);
132
+ }
133
+ }
134
+ }
135
+ else {
136
+ this.applyJoinIfNecessary(query, ruleSet);
137
+ }
138
+ }
139
+ applyJoinIfNecessary(query, ruleSet) {
140
+ if (ruleSet.table !== this.model.instance.table) {
141
+ this.addJoinOnce(query, ruleSet);
142
+ }
143
+ }
144
+ addJoinOnce(query, ruleSet) {
145
+ const { model, relation } = ruleSet;
146
+ if (!relation) {
147
+ return;
148
+ }
149
+ if (this.createdJoins.includes(relation.name)) {
150
+ return;
151
+ }
152
+ const tableName = model.instance.table;
153
+ const primaryKey = `${model.instance.table}.${relation.primaryKey}`;
154
+ const foreignKey = `${this.model.instance.table}.${relation.foreignKey}`;
155
+ query.leftJoin(tableName, primaryKey, foreignKey);
156
+ this.createdJoins.push(relation.name);
157
+ }
158
+ parseSections(sections) {
159
+ if (sections.q) {
160
+ const queryContent = sections.q.replace(/%20/g, "").replace(/ /g, "");
161
+ // Users can send an unacceptable query string. We shouldn't allow them to
162
+ // send unacceptable structure because of security reasons.
163
+ try {
164
+ sections.q = JSON.parse(queryContent);
165
+ }
166
+ catch (err) {
167
+ throw new ApiError_1.default(`Unacceptable query string: ${queryContent}`);
168
+ }
169
+ }
170
+ const withQueryResolver = new Resolvers_1.WithQueryResolver(this.model, this.models);
171
+ const query = {
172
+ page: this.parsePage(sections.page),
173
+ per_page: this.parsePerPage(sections.per_page),
174
+ fields: this.parseFields(sections.fields),
175
+ sort: this.parseSortingOptions(sections.sort),
176
+ q: this.parseCondition(sections.q),
177
+ with: withQueryResolver.resolve((sections === null || sections === void 0 ? void 0 : sections.with) || ""),
178
+ };
179
+ this.addRelationColumns(query.with);
180
+ return query;
181
+ }
182
+ parsePage(content) {
183
+ const value = parseInt(content);
184
+ if (isNaN(value)) {
185
+ return 1;
186
+ }
187
+ if (value <= 0) {
188
+ return 1;
189
+ }
190
+ return value;
191
+ }
192
+ parsePerPage(content) {
193
+ const value = parseInt(content);
194
+ if (isNaN(value) || value <= 1 || value > 10000) {
195
+ return 10;
196
+ }
197
+ return value;
198
+ }
199
+ parseFields(content) {
200
+ if (!content) {
201
+ return [];
202
+ }
203
+ const strContent = content;
204
+ // User should be able to select "all" fields.
205
+ if (strContent.trim() === "*") {
206
+ return ["*"];
207
+ }
208
+ const fields = strContent.split(",");
209
+ fields.forEach((field) => {
210
+ this.shouldBeAcceptableColumn(field);
211
+ });
212
+ return fields;
213
+ }
214
+ parseSortingOptions(content) {
215
+ // If there is not any sorting options, we don't have to return any value
216
+ if (!content) {
217
+ return [];
218
+ }
219
+ const result = [];
220
+ const strContent = content;
221
+ for (let field of strContent.split(",")) {
222
+ let type = Enums_1.SortTypes.ASC;
223
+ if (field.indexOf("-") === 0) {
224
+ type = Enums_1.SortTypes.DESC;
225
+ field = field.substr(1);
226
+ }
227
+ if (field.indexOf("+") === 0) {
228
+ field = field.substr(1);
229
+ }
230
+ this.shouldBeAcceptableColumn(field);
231
+ result.push({
232
+ name: field,
233
+ type,
234
+ });
235
+ }
236
+ return result;
237
+ }
238
+ parseConditions(conditions) {
239
+ if (!Array.isArray(conditions)) {
240
+ throw new Error("An array should be sent to parseConditions() method.");
241
+ }
242
+ return conditions.map((condition) => {
243
+ return this.parseCondition(condition);
244
+ });
245
+ }
246
+ parseCondition(content) {
247
+ if (Array.isArray(content)) {
248
+ return this.parseConditions(content);
249
+ }
250
+ if (!content) {
251
+ return [];
252
+ }
253
+ const wheres = [];
254
+ for (const key in content) {
255
+ wheres.push(this.parseConditionObject(content, key));
256
+ }
257
+ return wheres;
258
+ }
259
+ parseConditionObject(content, key) {
260
+ const where = {
261
+ prefix: null,
262
+ model: this.model,
263
+ table: this.model.instance.table,
264
+ field: key,
265
+ condition: Enums_1.ConditionTypes["="],
266
+ value: content[key],
267
+ relation: null,
268
+ };
269
+ // Sometimes we can have basic OR operations for queries
270
+ if (where.field.indexOf("$or.") === 0) {
271
+ where.prefix = "or";
272
+ where.field = where.field.replace("$or.", "");
273
+ }
274
+ if (where.field.indexOf("$and.") === 0) {
275
+ where.prefix = "and";
276
+ where.field = where.field.replace("$and.", "");
277
+ }
278
+ // If there is not any value, it means that we should check nullable values
279
+ if (where.value === null) {
280
+ // If the client wants to see not nullable values
281
+ if (this.hasSpecialStructure(where.field, ".$not")) {
282
+ where.field = where.field.replace(".$not", "");
283
+ where.condition = Enums_1.ConditionTypes.NotNull;
284
+ }
285
+ else {
286
+ // So, it means that the clients wants to see null valus
287
+ where.condition = Enums_1.ConditionTypes.Null;
288
+ }
289
+ }
290
+ else {
291
+ // If there is value, we should check it
292
+ this.applySpecialCondition(where, "$not", Enums_1.ConditionTypes["<>"]);
293
+ this.applySpecialCondition(where, "$gt", Enums_1.ConditionTypes[">"]);
294
+ this.applySpecialCondition(where, "$gte", Enums_1.ConditionTypes[">="]);
295
+ this.applySpecialCondition(where, "$lt", Enums_1.ConditionTypes["<"]);
296
+ this.applySpecialCondition(where, "$lte", Enums_1.ConditionTypes["<="]);
297
+ this.applySpecialCondition(where, "$like", Enums_1.ConditionTypes.LIKE);
298
+ this.applySpecialCondition(where, "$notLike", Enums_1.ConditionTypes["NOT LIKE"]);
299
+ this.applySpecialCondition(where, "$in", Enums_1.ConditionTypes.In);
300
+ this.applySpecialCondition(where, "$notIn", Enums_1.ConditionTypes.NotIn);
301
+ this.applySpecialCondition(where, "$between", Enums_1.ConditionTypes.Between);
302
+ this.applySpecialCondition(where, "$notBetween", Enums_1.ConditionTypes.NotBetween);
303
+ }
304
+ if (where.condition === Enums_1.ConditionTypes.In ||
305
+ where.condition === Enums_1.ConditionTypes.NotIn) {
306
+ where.value = where.value.split(",");
307
+ }
308
+ if (where.condition === Enums_1.ConditionTypes.Between ||
309
+ where.condition === Enums_1.ConditionTypes.NotBetween) {
310
+ where.value = where.value.split(":");
311
+ }
312
+ if (where.condition === Enums_1.ConditionTypes.LIKE ||
313
+ where.condition === Enums_1.ConditionTypes["NOT LIKE"]) {
314
+ where.value = where.value.replace(/\*/g, "%");
315
+ }
316
+ // This means that the condition is related with another table
317
+ if (where.field.includes(".")) {
318
+ const [relationName, field] = where.field.split(".");
319
+ const relation = this.model.relations.find((item) => item.name === relationName && item.type === Enums_1.Relationships.HAS_ONE);
320
+ if (!relation) {
321
+ throw new ApiError_1.default(`Unacceptable query field: ${relationName}.${field}`);
322
+ }
323
+ const relatedModel = this.models.find((item) => item.name === relation.model);
324
+ if (!relatedModel) {
325
+ throw new ApiError_1.default(`Undefined model name: ${relation.model}`);
326
+ }
327
+ where.model = relatedModel;
328
+ where.table = relatedModel.instance.table;
329
+ where.relation = relation;
330
+ where.field = field;
331
+ }
332
+ this.shouldBeAcceptableColumn(where.field);
333
+ this.usedConditionColumns.push(`${where.table}.${where.field}`);
334
+ return where;
335
+ }
336
+ applySpecialCondition(where, structure, condition) {
337
+ structure = `.${structure}`;
338
+ if (this.hasSpecialStructure(where.field, structure)) {
339
+ where.field = where.field.replace(structure, "");
340
+ where.condition = condition;
341
+ }
342
+ }
343
+ addRelationColumns(withs) {
344
+ withs.forEach((item) => {
345
+ const relation = this.model.relations.find((i) => i.name === item.relationship);
346
+ if (!relation) {
347
+ throw new ApiError_1.default(`Undefined relation: ${item.relationship}`);
348
+ }
349
+ this.relationColumns.push(`${this.model.instance.table}.${relation.foreignKey}`);
350
+ });
351
+ }
352
+ getConditionMethodName(ruleSet) {
353
+ if (ruleSet.prefix === "or") {
354
+ return "orWhere";
355
+ }
356
+ return "where";
357
+ }
358
+ hasSpecialStructure(field, structure) {
359
+ if (field.indexOf(structure) === -1) {
360
+ return false;
361
+ }
362
+ if (field.indexOf(structure) === field.length - structure.length) {
363
+ return true;
364
+ }
365
+ return false;
366
+ }
367
+ shouldBeAcceptableColumn(field) {
368
+ const regex = /^[0-9,a-z,A-Z_.]+$/;
369
+ if (!field.match(regex)) {
370
+ throw new ApiError_1.default(`Unacceptable field name: ${field}`);
371
+ }
372
+ if (field.indexOf(".") === 0 || field.indexOf(".") === field.length - 1) {
373
+ throw new ApiError_1.default(`You have to define the column specefically: ${field}`);
374
+ }
375
+ }
376
+ }
377
+ exports.default = QueryService;
@@ -0,0 +1,12 @@
1
+ declare class SchemaValidatorService {
2
+ validate(): Promise<void>;
3
+ private checkModelColumnsOrFail;
4
+ private getModelFillableColumns;
5
+ private getModelFormValidationColumns;
6
+ private getModelHiddenColumns;
7
+ private getTimestampsColumns;
8
+ private checkRelationColumnsOrFail;
9
+ private checkHasManyRelation;
10
+ private checkHasOneRelation;
11
+ }
12
+ export default SchemaValidatorService;
@@ -0,0 +1,114 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const Enums_1 = require("../Enums");
13
+ const Services_1 = require("../Services");
14
+ class SchemaValidatorService {
15
+ constructor() {
16
+ this.getModelFillableColumns = (model) => {
17
+ const fillable = model.instance.fillable;
18
+ if (!fillable) {
19
+ return [];
20
+ }
21
+ if (Array.isArray(fillable)) {
22
+ return fillable;
23
+ }
24
+ const config = fillable;
25
+ return [
26
+ ...(config.POST || []),
27
+ ...(config.PUT || []),
28
+ ...(config.PATCH || []),
29
+ ];
30
+ };
31
+ this.getModelFormValidationColumns = (model) => {
32
+ const validations = model.instance.validations;
33
+ if (!validations) {
34
+ return [];
35
+ }
36
+ const objValidations = validations;
37
+ if (!objValidations.POST && !objValidations.PUT) {
38
+ return Object.keys(objValidations);
39
+ }
40
+ const config = validations;
41
+ return [
42
+ ...Object.keys(config.POST ? config.POST : {}),
43
+ ...Object.keys(config.PUT ? config.PUT : {}),
44
+ ];
45
+ };
46
+ this.getModelHiddenColumns = (model) => {
47
+ if (!model.instance.hiddens) {
48
+ return [];
49
+ }
50
+ return model.instance.hiddens;
51
+ };
52
+ this.getTimestampsColumns = (model) => {
53
+ const columns = [];
54
+ if (model.instance.createdAtColumn) {
55
+ columns.push(model.instance.createdAtColumn);
56
+ }
57
+ if (model.instance.updatedAtColumn) {
58
+ columns.push(model.instance.updatedAtColumn);
59
+ }
60
+ return columns;
61
+ };
62
+ this.checkHasManyRelation = (modelList, model, relation) => {
63
+ this.checkModelColumnsOrFail(model, [relation.primaryKey]);
64
+ const relatedModel = modelList.find(relation.model);
65
+ if (!relatedModel) {
66
+ throw new Error(`Undefined related model: ${relation.model}`);
67
+ }
68
+ this.checkModelColumnsOrFail(relatedModel, [relation.foreignKey]);
69
+ };
70
+ }
71
+ validate() {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ const logger = yield Services_1.IoCService.useByType("LogService");
74
+ const modelList = yield Services_1.IoCService.useByType("ModelListService");
75
+ modelList.get().forEach((model) => {
76
+ this.checkModelColumnsOrFail(model, this.getModelFillableColumns(model));
77
+ this.checkModelColumnsOrFail(model, this.getModelFormValidationColumns(model));
78
+ this.checkModelColumnsOrFail(model, this.getModelHiddenColumns(model));
79
+ this.checkModelColumnsOrFail(model, this.getTimestampsColumns(model));
80
+ this.checkModelColumnsOrFail(model, [model.instance.primaryKey]);
81
+ this.checkRelationColumnsOrFail(modelList, model);
82
+ });
83
+ logger.info("Database schema has been validated.");
84
+ });
85
+ }
86
+ checkModelColumnsOrFail(model, modelColumns) {
87
+ const undefinedColumns = modelColumns.filter((modelColumn) => !model.columnNames.includes(modelColumn));
88
+ if (undefinedColumns.length > 0) {
89
+ throw new Error(`${model.name} model doesn't have the following columns on the database; "${model.instance.table}.${undefinedColumns.join(",")}"`);
90
+ }
91
+ }
92
+ checkRelationColumnsOrFail(modelList, model) {
93
+ for (const relation of model.relations) {
94
+ if (relation.type === Enums_1.Relationships.HAS_MANY) {
95
+ this.checkHasManyRelation(modelList, model, relation);
96
+ }
97
+ else if (relation.type === Enums_1.Relationships.HAS_ONE) {
98
+ this.checkHasOneRelation(modelList, model, relation);
99
+ }
100
+ else {
101
+ throw new Error(`Undefined relation type: ${relation.type}`);
102
+ }
103
+ }
104
+ }
105
+ checkHasOneRelation(modelList, model, relation) {
106
+ this.checkModelColumnsOrFail(model, [relation.foreignKey]);
107
+ const relatedModel = modelList.find(relation.model);
108
+ if (!relatedModel) {
109
+ throw new Error(`Undefined related model: ${relation.model}`);
110
+ }
111
+ this.checkModelColumnsOrFail(relatedModel, [relation.primaryKey]);
112
+ }
113
+ }
114
+ exports.default = SchemaValidatorService;
@@ -0,0 +1,8 @@
1
+ import DocumentationService from "./DocumentationService";
2
+ import IoCService from "./IoCService";
3
+ import LogService from "./LogService";
4
+ import ModelListService from "./ModelListService";
5
+ import ModelService from "./ModelService";
6
+ import QueryService from "./QueryService";
7
+ import SchemaValidatorService from "./SchemaValidatorService";
8
+ export { DocumentationService, IoCService, LogService, ModelListService, ModelService, QueryService, SchemaValidatorService, };
@@ -0,0 +1,20 @@
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.SchemaValidatorService = exports.QueryService = exports.ModelService = exports.ModelListService = exports.LogService = exports.IoCService = exports.DocumentationService = void 0;
7
+ const DocumentationService_1 = __importDefault(require("./DocumentationService"));
8
+ exports.DocumentationService = DocumentationService_1.default;
9
+ const IoCService_1 = __importDefault(require("./IoCService"));
10
+ exports.IoCService = IoCService_1.default;
11
+ const LogService_1 = __importDefault(require("./LogService"));
12
+ exports.LogService = LogService_1.default;
13
+ const ModelListService_1 = __importDefault(require("./ModelListService"));
14
+ exports.ModelListService = ModelListService_1.default;
15
+ const ModelService_1 = __importDefault(require("./ModelService"));
16
+ exports.ModelService = ModelService_1.default;
17
+ const QueryService_1 = __importDefault(require("./QueryService"));
18
+ exports.QueryService = QueryService_1.default;
19
+ const SchemaValidatorService_1 = __importDefault(require("./SchemaValidatorService"));
20
+ exports.SchemaValidatorService = SchemaValidatorService_1.default;
@@ -0,0 +1,23 @@
1
+ import { HandlerTypes } from "./Enums";
2
+ export declare const LOG_COLORS: {
3
+ fgBlack: string;
4
+ fgRed: string;
5
+ fgGreen: string;
6
+ fgYellow: string;
7
+ fgBlue: string;
8
+ fgMagenta: string;
9
+ fgCyan: string;
10
+ fgWhite: string;
11
+ fgReset: string;
12
+ };
13
+ export declare const DEFAULT_HANDLERS: HandlerTypes[];
14
+ export declare const DEFAULT_METHODS_OF_MODELS: string[];
15
+ export declare const API_ROUTE_TEMPLATES: {
16
+ store: (prefix: string, parentUrl: string, resource: string) => string;
17
+ paginate: (prefix: string, parentUrl: string, resource: string) => string;
18
+ all: (prefix: string, parentUrl: string, resource: string) => string;
19
+ show: (prefix: string, parentUrl: string, resource: string, primaryKey: string) => string;
20
+ update: (prefix: string, parentUrl: string, resource: string, primaryKey: string) => string;
21
+ patch: (prefix: string, parentUrl: string, resource: string, primaryKey: string) => string;
22
+ destroy: (prefix: string, parentUrl: string, resource: string, primaryKey: string) => string;
23
+ };
@@ -0,0 +1,62 @@
1
+ "use strict";
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;
4
+ const Enums_1 = require("./Enums");
5
+ exports.LOG_COLORS = {
6
+ fgBlack: "\x1b[30m",
7
+ fgRed: "\x1b[31m",
8
+ fgGreen: "\x1b[32m",
9
+ fgYellow: "\x1b[33m",
10
+ fgBlue: "\x1b[34m",
11
+ fgMagenta: "\x1b[35m",
12
+ fgCyan: "\x1b[36m",
13
+ fgWhite: "\x1b[37m",
14
+ fgReset: "\x1b[0m",
15
+ };
16
+ exports.DEFAULT_HANDLERS = [
17
+ Enums_1.HandlerTypes.INSERT,
18
+ Enums_1.HandlerTypes.PAGINATE,
19
+ Enums_1.HandlerTypes.SHOW,
20
+ Enums_1.HandlerTypes.UPDATE,
21
+ Enums_1.HandlerTypes.PATCH,
22
+ Enums_1.HandlerTypes.DELETE,
23
+ ];
24
+ exports.DEFAULT_METHODS_OF_MODELS = [
25
+ "constructor",
26
+ "hasMany",
27
+ "hasOne",
28
+ "belongsTo",
29
+ "serialize",
30
+ "__defineGetter__",
31
+ "__defineSetter__",
32
+ "hasOwnProperty",
33
+ "__lookupGetter__",
34
+ "__lookupSetter__",
35
+ "isPrototypeOf",
36
+ "propertyIsEnumerable",
37
+ "toString",
38
+ "valueOf",
39
+ "toLocaleString",
40
+ "primaryKey",
41
+ "table",
42
+ "fillable",
43
+ "validations",
44
+ "handlers",
45
+ "middlewares",
46
+ "hiddens",
47
+ "createdAtColumn",
48
+ "updatedAtColumn",
49
+ "transaction",
50
+ "ignore",
51
+ "getFillableFields",
52
+ "getValidationRules",
53
+ ];
54
+ exports.API_ROUTE_TEMPLATES = {
55
+ [Enums_1.HandlerTypes.INSERT]: (prefix, parentUrl, resource) => `/${prefix}/${parentUrl}${resource}`,
56
+ [Enums_1.HandlerTypes.PAGINATE]: (prefix, parentUrl, resource) => `/${prefix}/${parentUrl}${resource}`,
57
+ [Enums_1.HandlerTypes.ALL]: (prefix, parentUrl, resource) => `/${prefix}/${parentUrl}${resource}/all`,
58
+ [Enums_1.HandlerTypes.SHOW]: (prefix, parentUrl, resource, primaryKey) => `/${prefix}/${parentUrl}${resource}/:${primaryKey}`,
59
+ [Enums_1.HandlerTypes.UPDATE]: (prefix, parentUrl, resource, primaryKey) => `/${prefix}/${parentUrl}${resource}/:${primaryKey}`,
60
+ [Enums_1.HandlerTypes.PATCH]: (prefix, parentUrl, resource, primaryKey) => `/${prefix}/${parentUrl}${resource}/:${primaryKey}`,
61
+ [Enums_1.HandlerTypes.DELETE]: (prefix, parentUrl, resource, primaryKey) => `/${prefix}/${parentUrl}${resource}/:${primaryKey}`,
62
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axe-api",
3
- "version": "0.20.1",
3
+ "version": "0.20.2",
4
4
  "description": "AXE API is a simple tool which has been created based on Express and Knex.js to create Rest APIs quickly.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",