axe-api 0.20.0-rc2 → 0.20.0-rc21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import Server from "./src/Server";
2
2
  import Model from "./src/Model";
3
3
  import ApiError from "./src/Exceptions/ApiError";
4
4
  import { DEFAULT_HANDLERS } from "./src/constants";
5
+ import { IoCService } from "./src/Services";
5
6
  export * from "./src/Enums";
6
7
  export * from "./src/Interfaces";
7
- export { Server, Model, ApiError, DEFAULT_HANDLERS };
8
+ export { Server, Model, ApiError, DEFAULT_HANDLERS, IoCService };
package/build/index.js CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.DEFAULT_HANDLERS = exports.ApiError = exports.Model = exports.Server = void 0;
20
+ exports.IoCService = exports.DEFAULT_HANDLERS = exports.ApiError = exports.Model = exports.Server = void 0;
21
21
  const Server_1 = __importDefault(require("./src/Server"));
22
22
  exports.Server = Server_1.default;
23
23
  const Model_1 = __importDefault(require("./src/Model"));
@@ -26,5 +26,7 @@ const ApiError_1 = __importDefault(require("./src/Exceptions/ApiError"));
26
26
  exports.ApiError = ApiError_1.default;
27
27
  const constants_1 = require("./src/constants");
28
28
  Object.defineProperty(exports, "DEFAULT_HANDLERS", { enumerable: true, get: function () { return constants_1.DEFAULT_HANDLERS; } });
29
+ const Services_1 = require("./src/Services");
30
+ Object.defineProperty(exports, "IoCService", { enumerable: true, get: function () { return Services_1.IoCService; } });
29
31
  __exportStar(require("./src/Enums"), exports);
30
32
  __exportStar(require("./src/Interfaces"), exports);
@@ -1,6 +1,5 @@
1
1
  declare class RouterBuilder {
2
2
  build(): Promise<void>;
3
- private getGeneralHooks;
4
3
  private createRoutesByModelTree;
5
4
  private createRouteByModel;
6
5
  private createNestedRoutes;
@@ -12,6 +11,5 @@ declare class RouterBuilder {
12
11
  private sendErrorAsResponse;
13
12
  private getResourcePath;
14
13
  private getRootPrefix;
15
- private getModelMiddlewares;
16
14
  }
17
15
  export default RouterBuilder;
@@ -12,7 +12,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const path_1 = __importDefault(require("path"));
16
15
  const pluralize_1 = __importDefault(require("pluralize"));
17
16
  const http_status_codes_1 = require("http-status-codes");
18
17
  const change_case_1 = require("change-case");
@@ -44,35 +43,21 @@ class RouterBuilder {
44
43
  }
45
44
  build() {
46
45
  return __awaiter(this, void 0, void 0, function* () {
46
+ const app = yield Services_1.IoCService.useByType("App");
47
47
  const logger = yield Services_1.IoCService.useByType("LogService");
48
48
  const modelTree = yield Services_1.IoCService.useByType("ModelTree");
49
49
  const modelList = yield Services_1.IoCService.useByType("ModelListService");
50
- const generalHooks = yield this.getGeneralHooks();
50
+ const generalHooks = yield Resolvers_1.GeneralHookResolver.resolve();
51
51
  if (generalHooks.onBeforeInit) {
52
- generalHooks.onBeforeInit();
52
+ generalHooks.onBeforeInit(app);
53
53
  }
54
54
  yield this.createRoutesByModelTree(modelTree, modelList);
55
55
  if (generalHooks.onAfterInit) {
56
- generalHooks.onAfterInit();
56
+ generalHooks.onAfterInit(app);
57
57
  }
58
58
  logger.info("Express routes have been created.");
59
59
  });
60
60
  }
61
- getGeneralHooks() {
62
- return __awaiter(this, void 0, void 0, function* () {
63
- const folders = (yield Services_1.IoCService.use("Folders"));
64
- const fileResolver = new Resolvers_1.FileResolver();
65
- const content = yield fileResolver.resolveContent(path_1.default.join(folders.App, "app"));
66
- if (content && content.init) {
67
- const { onBeforeInit = null, onAfterInit = null } = content.init;
68
- return { onBeforeInit, onAfterInit };
69
- }
70
- return {
71
- onBeforeInit: null,
72
- onAfterInit: null,
73
- };
74
- });
75
- }
76
61
  createRoutesByModelTree(modelTree, modelList) {
77
62
  return __awaiter(this, void 0, void 0, function* () {
78
63
  for (const model of modelTree) {
@@ -95,7 +80,7 @@ class RouterBuilder {
95
80
  const urlCreator = constants_1.API_ROUTE_TEMPLATES[handlerType];
96
81
  const url = urlCreator(yield this.getRootPrefix(), urlPrefix, resource, model.instance.primaryKey);
97
82
  // Detecting filters
98
- const middlewares = this.getModelMiddlewares(model, handlerType);
83
+ const middlewares = Resolvers_1.ModelMiddlewareResolver.resolve(model, handlerType);
99
84
  // Adding the route to the express
100
85
  yield this.addExpressRoute(handlerType, url, middlewares, model, parentModel, relation);
101
86
  }
@@ -176,9 +161,15 @@ class RouterBuilder {
176
161
  }
177
162
  requestHandler(handlerType, req, res, model, parentModel, relation) {
178
163
  return __awaiter(this, void 0, void 0, function* () {
164
+ let trx = null;
165
+ let hasTransaction = false;
179
166
  try {
180
167
  const factory = yield Services_1.IoCService.useByType("HandlerFactory");
181
168
  const database = (yield Services_1.IoCService.use("Database"));
169
+ hasTransaction = yield Resolvers_1.TransactionResolver.resolve(model, handlerType);
170
+ if (hasTransaction) {
171
+ trx = yield database.transaction();
172
+ }
182
173
  const handler = factory.get(handlerType);
183
174
  const pack = {
184
175
  req,
@@ -187,11 +178,17 @@ class RouterBuilder {
187
178
  model,
188
179
  parentModel,
189
180
  relation,
190
- database,
181
+ database: hasTransaction && trx ? trx : database,
191
182
  };
192
183
  yield handler(pack);
184
+ if (hasTransaction && trx) {
185
+ trx.commit();
186
+ }
193
187
  }
194
188
  catch (error) {
189
+ if (hasTransaction && trx) {
190
+ trx.rollback();
191
+ }
195
192
  this.sendErrorAsResponse(res, error);
196
193
  }
197
194
  });
@@ -213,35 +210,11 @@ class RouterBuilder {
213
210
  }
214
211
  }
215
212
  getResourcePath(model, relation) {
216
- // TODO: Fixe
213
+ // TODO: Fix
217
214
  return (0, change_case_1.paramCase)(pluralize_1.default.plural(model.name)).toLowerCase();
218
215
  // return relation
219
216
  // ? relation.resource
220
217
  // : paramCase(pluralize.plural(model.name)).toLowerCase();
221
218
  }
222
- getModelMiddlewares(model, handlerType) {
223
- const results = [];
224
- const middlewares = model.instance.middlewares;
225
- if (Array.isArray(middlewares)) {
226
- middlewares.forEach((item) => {
227
- if (item === null || item === void 0 ? void 0 : item.handler) {
228
- const methodBasedMiddlewares = item;
229
- if (methodBasedMiddlewares.handler.includes(handlerType)) {
230
- results.push(methodBasedMiddlewares.middleware);
231
- }
232
- }
233
- else {
234
- results.push(item);
235
- }
236
- });
237
- }
238
- else {
239
- const methodBasedMiddlewares = middlewares;
240
- if (methodBasedMiddlewares.handler.includes(handlerType)) {
241
- results.push(methodBasedMiddlewares.middleware);
242
- }
243
- }
244
- return results;
245
- }
246
219
  }
247
220
  exports.default = RouterBuilder;
@@ -11,4 +11,4 @@ export declare const getParentColumn: (relation: IRelation | null) => string | n
11
11
  export declare const addForeignKeyQuery: (request: Request, query: Knex.QueryBuilder, relation: IRelation | null, parentModel: IModelService | null) => void;
12
12
  export declare const serializeData: (itemArray: any[] | any, modelSerializer: (data: any, request: Request) => void, handler: HandlerTypes, request: Request) => Promise<any[]>;
13
13
  export declare const filterHiddenFields: (itemArray: any[], hiddens: string[] | null) => void;
14
- export declare const getRelatedData: (data: any[], withArray: IWith[], model: IModelService, modelList: ModelListService, database: Knex, handler: HandlerTypes, request: Request) => Promise<void>;
14
+ export declare const getRelatedData: (data: any[], withArray: IWith[], model: IModelService, modelList: ModelListService, database: Knex | Knex.Transaction, handler: HandlerTypes, request: Request) => Promise<void>;
@@ -43,16 +43,13 @@ const callHooks = (model, type, params) => __awaiter(void 0, void 0, void 0, fun
43
43
  yield model.hooks[type](params);
44
44
  }
45
45
  if (model.events[type]) {
46
- // const context = {
47
- // ...data,
48
- // };
49
- // // Developers shouldn't be able to access transaction in events. Because
50
- // // we don't await for the events. If the developer uses the transaction and
51
- // // try to commit something, it would be lost cause the transaction could be
52
- // // already completed.
53
- // if (context.trx) {
54
- // delete context.trx;
55
- // }
46
+ // Developers shouldn't be able to access transaction in events. Because
47
+ // we don't await for the events. If the developer uses the transaction and
48
+ // try to commit something, it would be lost cause the transaction could be
49
+ // already completed.
50
+ const database = (yield Services_1.IoCService.use("Database"));
51
+ params.database = database;
52
+ // Calling the events
56
53
  model.events[type](params);
57
54
  }
58
55
  });
@@ -149,7 +146,7 @@ const getRelatedData = (data, withArray, model, modelList, database, handler, re
149
146
  for (const clientQuery of withArray) {
150
147
  // Find the relation of the model. If the model doesn't have any relationship like the
151
148
  // user wants, we can't show anything.
152
- const definedRelation = model.relations.find((relation) => relation.model === clientQuery.relationModel.name);
149
+ const definedRelation = model.relations.find((relation) => relation.name === clientQuery.relationship);
153
150
  if (!definedRelation) {
154
151
  throw new ApiError_1.default(`Undefined relation: ${clientQuery.relationship}`);
155
152
  }
@@ -194,6 +191,15 @@ const getRelatedData = (data, withArray, model, modelList, database, handler, re
194
191
  // };
195
192
  // }),
196
193
  // ];
194
+ console.log([
195
+ ...workList.map((relationship) => {
196
+ return {
197
+ relationship,
198
+ fields: [],
199
+ children: [],
200
+ };
201
+ }),
202
+ ]);
197
203
  // We should check if the column is defined on the table.
198
204
  const undefinedColumns = selectColumns.filter((column) => !foreignModel.columnNames.includes(column));
199
205
  if (undefinedColumns.length > 0) {
@@ -1,5 +1,5 @@
1
1
  import { Knex } from "knex";
2
- import { Request, Response, NextFunction } from "express";
2
+ import { Express, Request, Response, NextFunction } from "express";
3
3
  import { Column } from "knex-schema-inspector/lib/types/column";
4
4
  import { HandlerTypes, LogLevels, HttpMethods, HookFunctionTypes, Extensions, Relationships, SortTypes, ConditionTypes, DependencyTypes } from "./Enums";
5
5
  import Model from "./Model";
@@ -21,7 +21,7 @@ interface IPoolConfig {
21
21
  interface IMigrationConfig {
22
22
  tableName: "knex_migrations";
23
23
  }
24
- interface IHandlerBasedTransactionConfig {
24
+ export interface IHandlerBasedTransactionConfig {
25
25
  handler: HandlerTypes | HandlerTypes[];
26
26
  transaction: boolean;
27
27
  }
@@ -33,6 +33,7 @@ export interface IApplicationConfig extends IConfig {
33
33
  env: string;
34
34
  port: number;
35
35
  logLevel: LogLevels;
36
+ prefix: string;
36
37
  transaction: boolean | IHandlerBasedTransactionConfig | IHandlerBasedTransactionConfig[];
37
38
  serializers: ((data: any, request: Request) => void)[] | IHandlerBasedSerializer[];
38
39
  }
@@ -51,12 +52,12 @@ export interface IFolders {
51
52
  Models: string;
52
53
  }
53
54
  export interface IGeneralHooks {
54
- onBeforeInit: () => void | null;
55
- onAfterInit: () => void | null;
55
+ onBeforeInit: (app: Express) => void | null;
56
+ onAfterInit: (app: Express) => void | null;
56
57
  }
57
58
  export interface IHandlerBaseMiddleware {
58
59
  handler: HandlerTypes[];
59
- middleware: (req: Request, res: Response, next: NextFunction) => void;
60
+ middleware: (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
60
61
  }
61
62
  export interface IHookParameter {
62
63
  req: Request;
@@ -65,7 +66,7 @@ export interface IHookParameter {
65
66
  model: IModelService;
66
67
  parentModel: IModelService | null;
67
68
  relation: IRelation | null;
68
- database: Knex;
69
+ database: Knex | Knex.Transaction;
69
70
  conditions: IQuery | null;
70
71
  query: Knex.QueryBuilder | null;
71
72
  result: any | null;
@@ -108,7 +109,7 @@ export interface IRequestPack {
108
109
  model: IModelService;
109
110
  parentModel: IModelService | null;
110
111
  relation: IRelation | null;
111
- database: Knex;
112
+ database: Knex | Knex.Transaction;
112
113
  }
113
114
  export interface IRouteDocumentation {
114
115
  model: string;
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, NextFunction } from "express";
2
- import { IRelation, IMethodBaseConfig, IMethodBaseValidations, IHandlerBaseMiddleware } from "./Interfaces";
2
+ import { IRelation, IMethodBaseConfig, IMethodBaseValidations, IHandlerBaseMiddleware, IHandlerBasedTransactionConfig } from "./Interfaces";
3
3
  import { HandlerTypes, HttpMethods } from "./Enums";
4
4
  declare class Model {
5
5
  constructor();
@@ -12,7 +12,7 @@ declare class Model {
12
12
  get hiddens(): string[];
13
13
  get createdAtColumn(): string | null;
14
14
  get updatedAtColumn(): string | null;
15
- get transaction(): any;
15
+ get transaction(): boolean | IHandlerBasedTransactionConfig | IHandlerBasedTransactionConfig[] | null;
16
16
  get ignore(): boolean;
17
17
  getFillableFields(methodType: HttpMethods): string[];
18
18
  getValidationRules(methodType: HttpMethods): Record<string, string> | null;
@@ -1,4 +1,27 @@
1
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
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -18,10 +41,14 @@ class FileResolver {
18
41
  resolve(directory) {
19
42
  return __awaiter(this, void 0, void 0, function* () {
20
43
  const results = {};
21
- const files = yield fs_1.default.readdirSync(directory);
44
+ const files = (yield fs_1.default.readdirSync(directory, { withFileTypes: true }))
45
+ .filter((item) => !item.isDirectory())
46
+ .filter((filename) => filename.name.includes(".ts"))
47
+ .filter((filename) => filename.name.includes(".ts"))
48
+ .map((item) => item.name);
22
49
  for (const file of files) {
23
50
  const configFile = path_1.default.join(directory, file);
24
- const { default: content } = require(configFile);
51
+ const { default: content } = yield Promise.resolve().then(() => __importStar(require(configFile)));
25
52
  const key = file.replace(".ts", "");
26
53
  if (content === null || content === void 0 ? void 0 : content.prototype) {
27
54
  results[key] = new content();
@@ -42,7 +69,7 @@ class FileResolver {
42
69
  .map((item) => item.name);
43
70
  for (const file of files) {
44
71
  const configFile = path_1.default.join(directory, file);
45
- const content = require(configFile);
72
+ const content = yield Promise.resolve().then(() => __importStar(require(configFile)));
46
73
  const key = file.replace(".ts", "");
47
74
  results[key] = content;
48
75
  }
@@ -0,0 +1,5 @@
1
+ import { IGeneralHooks } from "../Interfaces";
2
+ declare class GeneralHookResolver {
3
+ static resolve(): Promise<IGeneralHooks>;
4
+ }
5
+ export default GeneralHookResolver;
@@ -0,0 +1,35 @@
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 path_1 = __importDefault(require("path"));
16
+ const Services_1 = require("../Services");
17
+ const _1 = require(".");
18
+ class GeneralHookResolver {
19
+ static resolve() {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ const folders = (yield Services_1.IoCService.use("Folders"));
22
+ const fileResolver = new _1.FileResolver();
23
+ const content = yield fileResolver.resolveContent(path_1.default.join(folders.App, "app"));
24
+ if (content && content.init) {
25
+ const { onBeforeInit = null, onAfterInit = null } = content.init;
26
+ return { onBeforeInit, onAfterInit };
27
+ }
28
+ return {
29
+ onBeforeInit: null,
30
+ onAfterInit: null,
31
+ };
32
+ });
33
+ }
34
+ }
35
+ exports.default = GeneralHookResolver;
@@ -0,0 +1,7 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { IModelService } from "../Interfaces";
3
+ import { HandlerTypes } from "../Enums";
4
+ declare class ModelMiddlewareResolver {
5
+ static resolve(model: IModelService, handlerType: HandlerTypes): ((req: Request, res: Response, next: NextFunction) => void)[];
6
+ }
7
+ export default ModelMiddlewareResolver;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class ModelMiddlewareResolver {
4
+ static resolve(model, handlerType) {
5
+ const results = [];
6
+ const middlewares = model.instance.middlewares;
7
+ if (Array.isArray(middlewares)) {
8
+ middlewares.forEach((item) => {
9
+ if (item === null || item === void 0 ? void 0 : item.handler) {
10
+ const methodBasedMiddlewares = item;
11
+ if (methodBasedMiddlewares.handler.includes(handlerType)) {
12
+ results.push(methodBasedMiddlewares.middleware);
13
+ }
14
+ }
15
+ else {
16
+ results.push(item);
17
+ }
18
+ });
19
+ }
20
+ else {
21
+ const methodBasedMiddlewares = middlewares;
22
+ if (methodBasedMiddlewares.handler.includes(handlerType)) {
23
+ results.push(methodBasedMiddlewares.middleware);
24
+ }
25
+ }
26
+ return results;
27
+ }
28
+ }
29
+ exports.default = ModelMiddlewareResolver;
@@ -35,7 +35,13 @@ class ModelResolver {
35
35
  for (const model of modelList.get()) {
36
36
  const relationMethods = this.getInstanceMethods(model);
37
37
  for (const relationMethod of relationMethods) {
38
- model.relations.push(model.instance[relationMethod]());
38
+ const relationFunction = model.instance[relationMethod];
39
+ if (typeof relationFunction !== "function") {
40
+ throw new Error(`Model relation definition should be a function: ${model.name}.${relationMethod}`);
41
+ }
42
+ const definition = relationFunction.call(model.instance);
43
+ definition.name = relationMethod;
44
+ model.relations.push(definition);
39
45
  }
40
46
  }
41
47
  });
@@ -0,0 +1,8 @@
1
+ import { IModelService } from "../Interfaces";
2
+ import { HandlerTypes } from "../Enums";
3
+ declare class TransactionResolver {
4
+ static resolve(model: IModelService, handlerType: HandlerTypes): Promise<boolean>;
5
+ private static resolveTransactionOption;
6
+ private static getTransactionConfiguration;
7
+ }
8
+ export default TransactionResolver;
@@ -0,0 +1,75 @@
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 Services_1 = require("../Services");
13
+ class TransactionResolver {
14
+ static resolve(model, handlerType) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const config = yield Services_1.IoCService.use("Config");
17
+ const global = config.Application.transaction;
18
+ const local = model.instance.transaction;
19
+ let privilegedOption = false;
20
+ if (global) {
21
+ privilegedOption = TransactionResolver.resolveTransactionOption(global, handlerType, privilegedOption);
22
+ }
23
+ if (local !== null) {
24
+ privilegedOption = TransactionResolver.resolveTransactionOption(local, handlerType, privilegedOption);
25
+ }
26
+ return privilegedOption;
27
+ });
28
+ }
29
+ static getTransactionConfiguration(configItem, handlerType) {
30
+ // An item definitions might have handler array such as;
31
+ //
32
+ // handler: [HandlerTypes.ALL, HandlerTypes.INSERT]
33
+ if (Array.isArray(configItem.handler)) {
34
+ // If this is an array, we should find the matched handler type
35
+ const found = configItem.handler.find((item) => item === handlerType);
36
+ // If there is, this is the our transaction choice
37
+ if (found) {
38
+ return configItem.transaction;
39
+ }
40
+ }
41
+ else if (configItem.handler === handlerType) {
42
+ // If the "configItem.handler" is not an array, should be matched
43
+ // with the handlerType. If it matches, it means that this is our
44
+ // transaction configuration
45
+ return configItem.transaction;
46
+ }
47
+ return null;
48
+ }
49
+ }
50
+ TransactionResolver.resolveTransactionOption = (option, handlerType, defaultValue) => {
51
+ if (Array.isArray(option)) {
52
+ // If this is an array, we should treat it like an array.
53
+ const configs = option;
54
+ // We should check every item of the array
55
+ for (const configItem of configs) {
56
+ const value = TransactionResolver.getTransactionConfiguration(configItem, handlerType);
57
+ if (value) {
58
+ defaultValue = configItem.transaction;
59
+ }
60
+ }
61
+ }
62
+ else if (typeof option === "boolean") {
63
+ // Developer should be able to select a boolean value for all kind of routes
64
+ defaultValue = option;
65
+ }
66
+ else {
67
+ const configItem = option;
68
+ const value = TransactionResolver.getTransactionConfiguration(configItem, handlerType);
69
+ if (value) {
70
+ defaultValue = configItem.transaction;
71
+ }
72
+ }
73
+ return defaultValue;
74
+ };
75
+ exports.default = TransactionResolver;
@@ -0,0 +1,13 @@
1
+ import { IModelService, IWith } from "../Interfaces";
2
+ declare class WithQueryResolver {
3
+ model: IModelService;
4
+ models: IModelService[];
5
+ constructor(model: IModelService, models: IModelService[]);
6
+ resolve(expression: string): IWith[];
7
+ private resolveRelationsByKey;
8
+ private toNestedArray;
9
+ private getKey;
10
+ private getGroupValue;
11
+ private splitByGroups;
12
+ }
13
+ export default WithQueryResolver;
@@ -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
+ const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
7
+ class WithQueryResolver {
8
+ constructor(model, models) {
9
+ this.getKey = (group) => {
10
+ const firstIndex = group.indexOf("{");
11
+ if (firstIndex > -1) {
12
+ return group.substring(0, firstIndex);
13
+ }
14
+ return null;
15
+ };
16
+ this.getGroupValue = (group) => {
17
+ const firstIndex = group.indexOf("{");
18
+ if (firstIndex > -1) {
19
+ return group.substring(firstIndex + 1, group.length - 1);
20
+ }
21
+ return group;
22
+ };
23
+ this.model = model;
24
+ this.models = models;
25
+ }
26
+ resolve(expression) {
27
+ const result = [];
28
+ const root = {
29
+ key: "root",
30
+ children: [],
31
+ };
32
+ const currentModel = this.model;
33
+ this.toNestedArray(root, expression);
34
+ this.resolveRelationsByKey(result, null, root.children, currentModel);
35
+ return result;
36
+ }
37
+ resolveRelationsByKey(result, fields, expressions, model) {
38
+ for (const expression of expressions) {
39
+ if (expression.key.trim().length === 0) {
40
+ continue;
41
+ }
42
+ const relationFunction = model.instance[expression.key];
43
+ if (typeof relationFunction === "function") {
44
+ const definition = relationFunction.call(model.instance);
45
+ const relationModel = this.models.find((item) => item.name === definition.model);
46
+ if (relationModel === undefined) {
47
+ throw new ApiError_1.default(`Undefined relation model: ${definition.model} (${expression.key})`);
48
+ }
49
+ const data = {
50
+ relationship: expression.key,
51
+ relationModel,
52
+ fields: [],
53
+ children: [],
54
+ };
55
+ if (expression.children.length > 0) {
56
+ this.resolveRelationsByKey(data.children, data.fields, expression.children, relationModel);
57
+ }
58
+ result.push(data);
59
+ }
60
+ else if (fields !== null) {
61
+ if (model.columnNames.includes(expression.key)) {
62
+ fields.push(expression.key);
63
+ }
64
+ else {
65
+ throw new ApiError_1.default(`It is not a field or a relation: ${expression.key}`);
66
+ }
67
+ }
68
+ else {
69
+ throw new ApiError_1.default(`Unknown expression: ${expression.key}`);
70
+ }
71
+ }
72
+ }
73
+ toNestedArray(root, expression) {
74
+ const groups = this.splitByGroups(expression);
75
+ for (const group of groups) {
76
+ const key = this.getKey(group);
77
+ if (key) {
78
+ const child = {
79
+ key,
80
+ children: [],
81
+ };
82
+ this.toNestedArray(child, this.getGroupValue(group));
83
+ root.children.push(child);
84
+ }
85
+ else {
86
+ root.children.push(...group.split("|").map((field) => {
87
+ return {
88
+ key: field,
89
+ children: [],
90
+ };
91
+ }));
92
+ }
93
+ }
94
+ }
95
+ splitByGroups(expression) {
96
+ const result = [];
97
+ let bracket = 0;
98
+ let startedAt = 0;
99
+ for (let index = 0; index < expression.length; index++) {
100
+ const char = expression[index];
101
+ if (char === "{") {
102
+ bracket++;
103
+ }
104
+ else if (char === "}") {
105
+ bracket--;
106
+ }
107
+ if (bracket === 0 && char === ",") {
108
+ result.push(expression.substring(startedAt, index));
109
+ startedAt = index + 1;
110
+ }
111
+ }
112
+ result.push(expression.substring(startedAt, expression.length));
113
+ return result;
114
+ }
115
+ }
116
+ exports.default = WithQueryResolver;
@@ -1,4 +1,8 @@
1
1
  import FileResolver from "./FileResolver";
2
2
  import FolderResolver from "./FolderResolver";
3
+ import GeneralHookResolver from "./GeneralHookResolver";
4
+ import ModelMiddlewareResolver from "./ModelMiddlewareResolver";
3
5
  import ModelResolver from "./ModelResolver";
4
- export { FileResolver, FolderResolver, ModelResolver };
6
+ import TransactionResolver from "./TransactionResolver";
7
+ import WithQueryResolver from "./WithQueryResolver";
8
+ export { FileResolver, FolderResolver, GeneralHookResolver, ModelMiddlewareResolver, ModelResolver, TransactionResolver, WithQueryResolver, };
@@ -3,10 +3,18 @@ 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.ModelResolver = exports.FolderResolver = exports.FileResolver = void 0;
6
+ exports.WithQueryResolver = exports.TransactionResolver = exports.ModelResolver = exports.ModelMiddlewareResolver = exports.GeneralHookResolver = exports.FolderResolver = exports.FileResolver = void 0;
7
7
  const FileResolver_1 = __importDefault(require("./FileResolver"));
8
8
  exports.FileResolver = FileResolver_1.default;
9
9
  const FolderResolver_1 = __importDefault(require("./FolderResolver"));
10
10
  exports.FolderResolver = FolderResolver_1.default;
11
+ const GeneralHookResolver_1 = __importDefault(require("./GeneralHookResolver"));
12
+ exports.GeneralHookResolver = GeneralHookResolver_1.default;
13
+ const ModelMiddlewareResolver_1 = __importDefault(require("./ModelMiddlewareResolver"));
14
+ exports.ModelMiddlewareResolver = ModelMiddlewareResolver_1.default;
11
15
  const ModelResolver_1 = __importDefault(require("./ModelResolver"));
12
16
  exports.ModelResolver = ModelResolver_1.default;
17
+ const TransactionResolver_1 = __importDefault(require("./TransactionResolver"));
18
+ exports.TransactionResolver = TransactionResolver_1.default;
19
+ const WithQueryResolver_1 = __importDefault(require("./WithQueryResolver"));
20
+ exports.WithQueryResolver = WithQueryResolver_1.default;
@@ -1,5 +1,4 @@
1
- import { ConditionTypes } from "../Enums";
2
- import { IRawQuery, IQuery, ISortField, NestedWhere, IWhere, IWith, IModelService } from "../Interfaces";
1
+ import { IQuery, ISortField, NestedWhere, IWhere, IModelService } from "../Interfaces";
3
2
  import { Knex } from "knex";
4
3
  declare class QueryService {
5
4
  model: IModelService;
@@ -13,27 +12,23 @@ declare class QueryService {
13
12
  applyWheresInsideGroup(sub: Knex.QueryBuilder, ruleSet: NestedWhere | IWhere): void;
14
13
  applyWheres(query: Knex.QueryBuilder, ruleSet: NestedWhere): void;
15
14
  get(query: any): IQuery;
16
- _getUsedColumns(conditions: IQuery): string[];
17
- _applyConditionRule(sub: Knex.QueryBuilder, ruleSet: IWhere): Knex.QueryBuilder;
18
- _applyRelatedQueryJoins(query: Knex.QueryBuilder, ruleSet: NestedWhere): void;
19
- _applyJoinIfNecessary(query: Knex.QueryBuilder, ruleSet: IWhere): void;
20
- _addJoinOnce(query: Knex.QueryBuilder, ruleSet: IWhere): void;
21
- _getSections(query: any): IRawQuery;
22
- _parseSections(sections: IRawQuery): IQuery;
23
- _parsePage(content: any): number;
24
- _parsePerPage(content: any): number;
25
- _parseFields(content: any): string[];
26
- _parseSortingOptions(content: any): ISortField[];
27
- _parseConditions(conditions: any): NestedWhere;
28
- _parseCondition(content: any): NestedWhere;
29
- _parseConditionObject(content: any, key: string): IWhere;
30
- _parseWithSections(content: any): string[];
31
- _parseWith(items: string[]): IWith[];
32
- _splitWithRecursive(content: string): string[];
33
- _applySpecialCondition(where: IWhere, structure: string, condition: ConditionTypes): void;
34
- _addRelationColumns(withs: IWith[]): void;
35
- _getConditionMethodName(ruleSet: IWhere): "orWhere" | "where";
36
- _hasSpecialStructure(field: string, structure: string): boolean;
37
- _shouldBeAcceptableColumn(field: string): void;
15
+ private getUsedColumns;
16
+ private applyConditionRule;
17
+ private applyRelatedQueryJoins;
18
+ private applyJoinIfNecessary;
19
+ private addJoinOnce;
20
+ private parseSections;
21
+ private parsePage;
22
+ private parsePerPage;
23
+ private parseFields;
24
+ private parseSortingOptions;
25
+ private parseConditions;
26
+ private parseCondition;
27
+ private parseConditionObject;
28
+ private applySpecialCondition;
29
+ private addRelationColumns;
30
+ private getConditionMethodName;
31
+ private hasSpecialStructure;
32
+ private shouldBeAcceptableColumn;
38
33
  }
39
34
  export default QueryService;
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const Enums_1 = require("../Enums");
7
7
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
8
+ const Resolvers_1 = require("../Resolvers");
8
9
  class QueryService {
9
10
  constructor(model, models) {
10
11
  this.model = model;
@@ -15,7 +16,7 @@ class QueryService {
15
16
  }
16
17
  applyFields(query, fields) {
17
18
  // Users should be able to select some fields to show.
18
- if (fields.length === 1 && fields[0] === "*") {
19
+ if (fields.length === 0 || (fields.length === 1 && fields[0] === "*")) {
19
20
  query.select(`${this.model.instance.table}.*`);
20
21
  }
21
22
  else {
@@ -46,7 +47,7 @@ class QueryService {
46
47
  // If the item is not an array, it means that it is a standard condition
47
48
  if (Array.isArray(item) === false) {
48
49
  const condition = item;
49
- this._applyConditionRule(sub, condition);
50
+ this.applyConditionRule(sub, condition);
50
51
  }
51
52
  else {
52
53
  // If the item is an array, we should create the query recursively.
@@ -66,18 +67,18 @@ class QueryService {
66
67
  }
67
68
  else {
68
69
  const condition = ruleSet;
69
- this._applyConditionRule(sub, condition);
70
+ this.applyConditionRule(sub, condition);
70
71
  }
71
72
  }
72
73
  applyWheres(query, ruleSet) {
73
74
  query.where((sub) => {
74
75
  this.applyWheresInsideGroup(sub, ruleSet);
75
76
  });
76
- this._applyRelatedQueryJoins(query, ruleSet);
77
+ this.applyRelatedQueryJoins(query, ruleSet);
77
78
  }
78
79
  get(query) {
79
- const conditions = this._parseSections(query);
80
- const usedColumns = this._getUsedColumns(conditions);
80
+ const conditions = this.parseSections(query);
81
+ const usedColumns = this.getUsedColumns(conditions);
81
82
  const undefinedColumns = usedColumns.filter((columnName) => {
82
83
  let currentModel = this.model;
83
84
  let realColumName = columnName;
@@ -93,15 +94,15 @@ class QueryService {
93
94
  }
94
95
  return conditions;
95
96
  }
96
- _getUsedColumns(conditions) {
97
+ getUsedColumns(conditions) {
97
98
  return [
98
99
  ...conditions.fields,
99
100
  ...conditions.sort.map((item) => item.name),
100
101
  ...Array.from(this.usedConditionColumns),
101
102
  ];
102
103
  }
103
- _applyConditionRule(sub, ruleSet) {
104
- const method = this._getConditionMethodName(ruleSet);
104
+ applyConditionRule(sub, ruleSet) {
105
+ const method = this.getConditionMethodName(ruleSet);
105
106
  const zeroArguments = ["Null", "NotNull"];
106
107
  const oneArguments = ["In", "NotIn", "Between", "NotBetween"];
107
108
  const fullFieldPath = `${ruleSet.table}.${ruleSet.field}`;
@@ -115,7 +116,7 @@ class QueryService {
115
116
  }
116
117
  return sub[method](fullFieldPath, ruleSet.condition, ruleSet.value);
117
118
  }
118
- _applyRelatedQueryJoins(query, ruleSet) {
119
+ applyRelatedQueryJoins(query, ruleSet) {
119
120
  if (!ruleSet) {
120
121
  return;
121
122
  }
@@ -124,23 +125,23 @@ class QueryService {
124
125
  // If the item is not an array, it means that it is a standard condition
125
126
  if (Array.isArray(item) === false) {
126
127
  const condition = item;
127
- this._applyJoinIfNecessary(query, condition);
128
+ this.applyJoinIfNecessary(query, condition);
128
129
  }
129
130
  else {
130
- this._applyRelatedQueryJoins(query, item);
131
+ this.applyRelatedQueryJoins(query, item);
131
132
  }
132
133
  }
133
134
  }
134
135
  else {
135
- this._applyJoinIfNecessary(query, ruleSet);
136
+ this.applyJoinIfNecessary(query, ruleSet);
136
137
  }
137
138
  }
138
- _applyJoinIfNecessary(query, ruleSet) {
139
+ applyJoinIfNecessary(query, ruleSet) {
139
140
  if (ruleSet.table !== this.model.instance.table) {
140
- this._addJoinOnce(query, ruleSet);
141
+ this.addJoinOnce(query, ruleSet);
141
142
  }
142
143
  }
143
- _addJoinOnce(query, ruleSet) {
144
+ addJoinOnce(query, ruleSet) {
144
145
  const { model, relation } = ruleSet;
145
146
  if (!relation) {
146
147
  return;
@@ -154,21 +155,7 @@ class QueryService {
154
155
  query.leftJoin(tableName, primaryKey, foreignKey);
155
156
  this.createdJoins.push(relation.name);
156
157
  }
157
- _getSections(query) {
158
- if (typeof query !== "object") {
159
- throw new ApiError_1.default("You have to send an object to get sections.");
160
- }
161
- const sections = {
162
- q: query.q || null,
163
- page: query.page || 1,
164
- per_page: query.per_page || 10,
165
- sort: query.sory || null,
166
- fields: query.fields || null,
167
- with: query.with || null,
168
- };
169
- return sections;
170
- }
171
- _parseSections(sections) {
158
+ parseSections(sections) {
172
159
  if (sections.q) {
173
160
  const queryContent = sections.q.replace(/%20/g, "").replace(/ /g, "");
174
161
  // Users can send an unacceptable query string. We shouldn't allow them to
@@ -180,18 +167,19 @@ class QueryService {
180
167
  throw new ApiError_1.default(`Unacceptable query string: ${queryContent}`);
181
168
  }
182
169
  }
170
+ const withQueryResolver = new Resolvers_1.WithQueryResolver(this.model, this.models);
183
171
  const query = {
184
- page: this._parsePage(sections.page),
185
- per_page: this._parsePerPage(sections.per_page),
186
- fields: this._parseFields(sections.fields),
187
- sort: this._parseSortingOptions(sections.sort),
188
- q: this._parseCondition(sections.q),
189
- with: this._parseWith(this._parseWithSections(sections.with)),
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) || ""),
190
178
  };
191
- this._addRelationColumns(query.with);
179
+ this.addRelationColumns(query.with);
192
180
  return query;
193
181
  }
194
- _parsePage(content) {
182
+ parsePage(content) {
195
183
  const value = parseInt(content);
196
184
  if (isNaN(value)) {
197
185
  return 1;
@@ -201,14 +189,14 @@ class QueryService {
201
189
  }
202
190
  return value;
203
191
  }
204
- _parsePerPage(content) {
192
+ parsePerPage(content) {
205
193
  const value = parseInt(content);
206
194
  if (isNaN(value) || value <= 1 || value > 10000) {
207
195
  return 10;
208
196
  }
209
197
  return value;
210
198
  }
211
- _parseFields(content) {
199
+ parseFields(content) {
212
200
  if (!content) {
213
201
  return [];
214
202
  }
@@ -219,11 +207,11 @@ class QueryService {
219
207
  }
220
208
  const fields = strContent.split(",");
221
209
  fields.forEach((field) => {
222
- this._shouldBeAcceptableColumn(field);
210
+ this.shouldBeAcceptableColumn(field);
223
211
  });
224
212
  return fields;
225
213
  }
226
- _parseSortingOptions(content) {
214
+ parseSortingOptions(content) {
227
215
  // If there is not any sorting options, we don't have to return any value
228
216
  if (!content) {
229
217
  return [];
@@ -239,7 +227,7 @@ class QueryService {
239
227
  if (field.indexOf("+") === 0) {
240
228
  field = field.substr(1);
241
229
  }
242
- this._shouldBeAcceptableColumn(field);
230
+ this.shouldBeAcceptableColumn(field);
243
231
  result.push({
244
232
  name: field,
245
233
  type,
@@ -247,28 +235,28 @@ class QueryService {
247
235
  }
248
236
  return result;
249
237
  }
250
- _parseConditions(conditions) {
238
+ parseConditions(conditions) {
251
239
  if (!Array.isArray(conditions)) {
252
240
  throw new Error("An array should be sent to parseConditions() method.");
253
241
  }
254
242
  return conditions.map((condition) => {
255
- return this._parseCondition(condition);
243
+ return this.parseCondition(condition);
256
244
  });
257
245
  }
258
- _parseCondition(content) {
246
+ parseCondition(content) {
259
247
  if (Array.isArray(content)) {
260
- return this._parseConditions(content);
248
+ return this.parseConditions(content);
261
249
  }
262
250
  if (!content) {
263
251
  return [];
264
252
  }
265
253
  const wheres = [];
266
254
  for (const key in content) {
267
- wheres.push(this._parseConditionObject(content, key));
255
+ wheres.push(this.parseConditionObject(content, key));
268
256
  }
269
257
  return wheres;
270
258
  }
271
- _parseConditionObject(content, key) {
259
+ parseConditionObject(content, key) {
272
260
  const where = {
273
261
  prefix: null,
274
262
  model: this.model,
@@ -290,7 +278,7 @@ class QueryService {
290
278
  // If there is not any value, it means that we should check nullable values
291
279
  if (where.value === null) {
292
280
  // If the client wants to see not nullable values
293
- if (this._hasSpecialStructure(where.field, ".$not")) {
281
+ if (this.hasSpecialStructure(where.field, ".$not")) {
294
282
  where.field = where.field.replace(".$not", "");
295
283
  where.condition = Enums_1.ConditionTypes.NotNull;
296
284
  }
@@ -301,17 +289,17 @@ class QueryService {
301
289
  }
302
290
  else {
303
291
  // If there is value, we should check it
304
- this._applySpecialCondition(where, "$not", Enums_1.ConditionTypes["<>"]);
305
- this._applySpecialCondition(where, "$gt", Enums_1.ConditionTypes[">"]);
306
- this._applySpecialCondition(where, "$gte", Enums_1.ConditionTypes[">="]);
307
- this._applySpecialCondition(where, "$lt", Enums_1.ConditionTypes["<"]);
308
- this._applySpecialCondition(where, "$lte", Enums_1.ConditionTypes["<="]);
309
- this._applySpecialCondition(where, "$like", Enums_1.ConditionTypes.LIKE);
310
- this._applySpecialCondition(where, "$notLike", Enums_1.ConditionTypes["NOT LIKE"]);
311
- this._applySpecialCondition(where, "$in", Enums_1.ConditionTypes.In);
312
- this._applySpecialCondition(where, "$notIn", Enums_1.ConditionTypes.NotIn);
313
- this._applySpecialCondition(where, "$between", Enums_1.ConditionTypes.Between);
314
- this._applySpecialCondition(where, "$notBetween", Enums_1.ConditionTypes.NotBetween);
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);
315
303
  }
316
304
  if (where.condition === "In" || where.condition === "NotIn") {
317
305
  where.value = where.value.split(",");
@@ -338,94 +326,33 @@ class QueryService {
338
326
  where.relation = relation;
339
327
  where.field = field;
340
328
  }
341
- this._shouldBeAcceptableColumn(where.field);
329
+ this.shouldBeAcceptableColumn(where.field);
342
330
  this.usedConditionColumns.push(`${where.table}.${where.field}`);
343
331
  return where;
344
332
  }
345
- _parseWithSections(content) {
346
- if (!content) {
347
- return [];
348
- }
349
- const stringContent = content;
350
- return stringContent.split(",");
351
- }
352
- _parseWith(items) {
353
- const result = [];
354
- for (const item of items) {
355
- let relationship = item;
356
- let fields = [];
357
- let children = [];
358
- const columnIndex = relationship.indexOf("{");
359
- if (columnIndex > -1) {
360
- fields = this._splitWithRecursive(relationship.substr(columnIndex + 1, relationship.length - columnIndex - 2));
361
- relationship = relationship.substr(0, columnIndex);
362
- }
363
- // We are checking there is any children
364
- children = fields.filter((field) => field.indexOf("{") > -1 || field.indexOf(".") > -1);
365
- // Field list shouldn't have any related table
366
- fields = fields.filter((field) => field.indexOf("{") === -1 && field.indexOf(".") === -1);
367
- // We should validate fields are correct.
368
- fields.forEach((field) => {
369
- this._shouldBeAcceptableColumn(field);
370
- });
371
- // We should calculate recursivly all of childre
372
- children = this._parseWith(children);
373
- const relationModel = this.models.find((item) => item.name.toLowerCase() === relationship.toLowerCase());
374
- if (!relationModel) {
375
- throw new ApiError_1.default(`Undefined relationship: ${relationship}`);
376
- }
377
- result.push({
378
- relationship,
379
- relationModel,
380
- fields,
381
- children,
382
- });
383
- }
384
- return result;
385
- }
386
- _splitWithRecursive(content) {
387
- const result = [];
388
- let startAt = 0;
389
- let subcounter = 0;
390
- for (let position = 0; position < content.length; position++) {
391
- const current = content[position];
392
- if (current === "{") {
393
- subcounter++;
394
- }
395
- if (current === "}") {
396
- subcounter--;
397
- }
398
- if (current === "|" && subcounter === 0) {
399
- result.push(content.substr(startAt, position - startAt));
400
- startAt = position + 1;
401
- }
402
- }
403
- result.push(content.substr(startAt));
404
- return result;
405
- }
406
- _applySpecialCondition(where, structure, condition) {
333
+ applySpecialCondition(where, structure, condition) {
407
334
  structure = `.${structure}`;
408
- if (this._hasSpecialStructure(where.field, structure)) {
335
+ if (this.hasSpecialStructure(where.field, structure)) {
409
336
  where.field = where.field.replace(structure, "");
410
337
  where.condition = condition;
411
338
  }
412
339
  }
413
- _addRelationColumns(withs) {
340
+ addRelationColumns(withs) {
414
341
  withs.forEach((item) => {
415
- const relation = this.model.relations.find((i) => i.model.toLowerCase() === item.relationship.toLowerCase());
342
+ const relation = this.model.relations.find((i) => i.name === item.relationship);
416
343
  if (!relation) {
417
344
  throw new ApiError_1.default(`Undefined relation: ${item.relationship}`);
418
345
  }
419
346
  this.relationColumns.push(`${this.model.instance.table}.${relation.foreignKey}`);
420
347
  });
421
348
  }
422
- _getConditionMethodName(ruleSet) {
349
+ getConditionMethodName(ruleSet) {
423
350
  if (ruleSet.prefix === "or") {
424
351
  return "orWhere";
425
352
  }
426
353
  return "where";
427
354
  }
428
- _hasSpecialStructure(field, structure) {
355
+ hasSpecialStructure(field, structure) {
429
356
  if (field.indexOf(structure) === -1) {
430
357
  return false;
431
358
  }
@@ -434,7 +361,7 @@ class QueryService {
434
361
  }
435
362
  return false;
436
363
  }
437
- _shouldBeAcceptableColumn(field) {
364
+ shouldBeAcceptableColumn(field) {
438
365
  const regex = /^[0-9,a-z,A-Z_.]+$/;
439
366
  if (!field.match(regex)) {
440
367
  throw new ApiError_1.default(`Unacceptable field name: ${field}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axe-api",
3
- "version": "0.20.0-rc2",
3
+ "version": "0.20.0-rc21",
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",
@@ -25,9 +25,11 @@
25
25
  "test:integration:postgres": "cd ./tests/integrations && node index.js postgres"
26
26
  },
27
27
  "dependencies": {
28
+ "@types/express": "^4.17.13",
28
29
  "change-case": "^4.1.2",
29
30
  "dotenv": "^14.2.0",
30
31
  "express": "^4.17.2",
32
+ "http-status-codes": "^2.2.0",
31
33
  "knex": "^1.0.1",
32
34
  "knex-paginate": "^3.0.0",
33
35
  "knex-schema-inspector": "^1.7.1",
@@ -39,8 +41,10 @@
39
41
  "@babel/core": "^7.16.10",
40
42
  "@babel/node": "^7.16.8",
41
43
  "@babel/preset-env": "^7.16.11",
44
+ "@babel/preset-typescript": "^7.18.6",
42
45
  "@babel/runtime": "^7.16.7",
43
- "babel-jest": "^27.4.6",
46
+ "@types/pluralize": "^0.0.29",
47
+ "babel-jest": "^29.0.3",
44
48
  "babel-loader": "^8.2.3",
45
49
  "babel-plugin-module-resolver": "^4.1.0",
46
50
  "babel-preset-minify": "^0.5.1",
@@ -52,11 +56,11 @@
52
56
  "eslint-plugin-standard": "^5.0.0",
53
57
  "eslint-plugin-unicorn": "^33.0.1",
54
58
  "eslint-watch": "^7.0.0",
55
- "jest": "^27.4.7",
56
59
  "mysql": "^2.18.1",
57
60
  "nodemon": "^2.0.15",
58
61
  "pg": "^8.7.1",
59
62
  "set-value": ">=4.1.0",
60
- "sqlite3": "^5.0.2"
63
+ "sqlite3": "^5.0.2",
64
+ "ts-jest": "^29.0.1"
61
65
  }
62
66
  }