axe-api 0.31.3 → 0.31.5

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.
@@ -101,7 +101,8 @@ class RouterBuilder {
101
101
  const relation = model.relations.find((relation) => relation.model === model.name &&
102
102
  relation.type === Enums_1.Relationships.HAS_MANY);
103
103
  if (relation) {
104
- yield this.createRouteByModel(model, `${urlPrefix}${resource}/:${(0, change_case_1.camelCase)(relation.foreignKey)}/`, model, relation, false);
104
+ const paramName = (0, change_case_1.camelCase)(`${model.name}-${relation.primaryKey}`);
105
+ yield this.createRouteByModel(model, `${urlPrefix}${resource}/:${paramName}/`, model, relation, false);
105
106
  }
106
107
  });
107
108
  }
@@ -116,7 +117,8 @@ class RouterBuilder {
116
117
  const child = model.children.find((item) => item.name === relation.model);
117
118
  // It should be recursive
118
119
  if (child) {
119
- yield this.createRouteByModel(child, `${urlPrefix}${resource}/:${(0, change_case_1.camelCase)(relation.foreignKey)}/`, model, relation);
120
+ const paramName = (0, change_case_1.camelCase)(`${model.name}-${relation.primaryKey}`);
121
+ yield this.createRouteByModel(child, `${urlPrefix}${resource}/:${paramName}/`, model, relation);
120
122
  }
121
123
  }
122
124
  });
@@ -24,7 +24,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  // Users should be able to select some fields to show.
25
25
  queryParser.applyFields(query, conditions.fields);
26
26
  // Binding parent id if there is.
27
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
27
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
28
28
  // Users should be able to filter records
29
29
  queryParser.applyWheres(query, conditions.q);
30
30
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeAll, Object.assign(Object.assign({}, pack), { conditions,
@@ -27,7 +27,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
27
27
  // If there is a deletedAtColumn, it means that this table support soft-delete
28
28
  (0, Helpers_1.addSoftDeleteQuery)(model, null, query);
29
29
  // If there is a relation, we should bind it
30
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
30
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
31
31
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeDeleteQuery, Object.assign(Object.assign({}, pack), { query }));
32
32
  const item = yield query.first();
33
33
  if (!item) {
@@ -47,5 +47,5 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
47
47
  yield query.delete();
48
48
  }
49
49
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterDelete, Object.assign(Object.assign({}, pack), { item }));
50
- return res.json();
50
+ return res.status(204).json();
51
51
  });
@@ -29,7 +29,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
29
29
  throw new ApiError_1.default("You can use force delete only soft-delete supported models.", Enums_1.StatusCodes.NOT_FOUND);
30
30
  }
31
31
  // If there is a relation, we should bind it
32
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
32
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
33
33
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeForceDeleteQuery, Object.assign(Object.assign({}, pack), { query }));
34
34
  const item = yield query.first();
35
35
  if (!item) {
@@ -41,5 +41,5 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
41
41
  item }));
42
42
  yield query.delete();
43
43
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterForceDelete, Object.assign(Object.assign({}, pack), { item }));
44
- return res.json();
44
+ return res.status(204).json();
45
45
  });
@@ -7,9 +7,9 @@ import { SerializationFunction } from "../Types";
7
7
  export declare const bindTimestampValues: (formData: Record<string, any>, model: IModelService, columnTypes?: TimestampColumns[]) => void;
8
8
  export declare const getMergedFormData: (req: Request, fillables: string[]) => Record<string, any>;
9
9
  export declare const callHooks: (model: IModelService, type: HookFunctionTypes, params: IHookParameter) => Promise<void>;
10
- export declare const getParentColumn: (relation: IRelation | null) => string | null;
10
+ export declare const getParentColumn: (model: IModelService, relation: IRelation | null) => string | null;
11
11
  export declare const checkPrimaryKeyValueType: (model: IModelService, value: any) => void;
12
- export declare const addForeignKeyQuery: (request: Request, query: Knex.QueryBuilder, relation: IRelation | null, parentModel: IModelService | null) => void;
12
+ export declare const addForeignKeyQuery: (request: Request, query: Knex.QueryBuilder, model: IModelService, relation: IRelation | null, parentModel: IModelService | null) => void;
13
13
  export declare const serializeData: (version: IVersion, itemArray: any, modelSerializer: SerializationFunction | null, handler: HandlerTypes, request: Request) => Promise<any[]>;
14
14
  export declare const filterHiddenFields: (itemArray: any[], hiddens: string[] | null) => void;
15
15
  export declare const addSoftDeleteQuery: (model: IModelService, conditions: IQuery | null, query: Knex.QueryBuilder) => void;
@@ -57,24 +57,25 @@ const callHooks = (model, type, params) => __awaiter(void 0, void 0, void 0, fun
57
57
  }
58
58
  });
59
59
  exports.callHooks = callHooks;
60
- const getParentColumn = (relation) => {
60
+ const getParentColumn = (model, relation) => {
61
61
  if (!relation) {
62
62
  return null;
63
63
  }
64
- return (0, change_case_1.camelCase)(relation.foreignKey);
64
+ return (0, change_case_1.camelCase)(`${model.name}-${relation.primaryKey}`);
65
65
  };
66
66
  exports.getParentColumn = getParentColumn;
67
67
  const checkPrimaryKeyValueType = (model, value) => {
68
68
  // We should check the parameter type
69
69
  const primaryColumn = model.columns.find((column) => column.name === model.instance.primaryKey);
70
- if ((primaryColumn === null || primaryColumn === void 0 ? void 0 : primaryColumn.data_type) === "integer" && isNaN(parseInt(value))) {
70
+ if (constants_1.NUMERIC_PRIMARY_KEY_TYPES.includes((primaryColumn === null || primaryColumn === void 0 ? void 0 : primaryColumn.data_type) || "") &&
71
+ isNaN(parseInt(value))) {
71
72
  throw new ApiError_1.default(`Unacceptable parameter: ${value}`);
72
73
  }
73
74
  };
74
75
  exports.checkPrimaryKeyValueType = checkPrimaryKeyValueType;
75
- const addForeignKeyQuery = (request, query, relation, parentModel) => {
76
+ const addForeignKeyQuery = (request, query, model, relation, parentModel) => {
76
77
  if (relation && parentModel) {
77
- const parentColumn = (0, exports.getParentColumn)(relation);
78
+ const parentColumn = (0, exports.getParentColumn)(parentModel, relation);
78
79
  if (parentColumn) {
79
80
  query.where(relation.foreignKey, request.params[parentColumn]);
80
81
  }
@@ -24,7 +24,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  // Users should be able to select some fields to show.
25
25
  queryParser.applyFields(query, conditions.fields);
26
26
  // Binding parent id if there is.
27
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
27
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
28
28
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforePaginate, Object.assign(Object.assign({}, pack), { conditions,
29
29
  query }));
30
30
  // Users should be able to filter records
@@ -20,7 +20,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
20
20
  const { version, model, req, res, database, relation, parentModel } = pack;
21
21
  const query = database.from(model.instance.table);
22
22
  // If there is a relation, we should bind it
23
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
23
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
24
24
  // If there is a deletedAtColumn, it means that this table support soft-delete
25
25
  (0, Helpers_1.addSoftDeleteQuery)(model, null, query);
26
26
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeUpdateQuery, Object.assign(Object.assign({}, pack), { query }));
@@ -28,7 +28,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
28
28
  // Users should be able to select some fields to show.
29
29
  queryParser.applyFields(query, conditions.fields);
30
30
  // If there is a relation, we should bind it
31
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
31
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
32
32
  // We should check the parameter type
33
33
  const value = req.params[model.instance.primaryKey];
34
34
  (0, Helpers_1.checkPrimaryKeyValueType)(model, value);
@@ -31,7 +31,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
31
31
  }
32
32
  }
33
33
  if (relation && parentModel) {
34
- const parentColumn = (0, Helpers_1.getParentColumn)(relation);
34
+ const parentColumn = (0, Helpers_1.getParentColumn)(parentModel, relation);
35
35
  if (parentColumn) {
36
36
  formData[relation.foreignKey] = req.params[parentColumn];
37
37
  }
@@ -20,7 +20,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
20
20
  const { version, model, req, res, database, relation, parentModel } = pack;
21
21
  const query = database.from(model.instance.table);
22
22
  // If there is a relation, we should bind it
23
- (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
23
+ (0, Helpers_1.addForeignKeyQuery)(req, query, model, relation, parentModel);
24
24
  // If there is a deletedAtColumn, it means that this table support soft-delete
25
25
  (0, Helpers_1.addSoftDeleteQuery)(model, null, query);
26
26
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeUpdateQuery, Object.assign(Object.assign({}, pack), { query }));
@@ -326,16 +326,13 @@ class QueryService {
326
326
  this.applySpecialCondition(where, "$between", Enums_1.ConditionTypes.Between);
327
327
  this.applySpecialCondition(where, "$notBetween", Enums_1.ConditionTypes.NotBetween);
328
328
  }
329
- if (where.condition === Enums_1.ConditionTypes.In ||
330
- where.condition === Enums_1.ConditionTypes.NotIn) {
331
- where.value = where.value.split(",");
332
- }
333
- if (where.condition === Enums_1.ConditionTypes.Between ||
334
- where.condition === Enums_1.ConditionTypes.NotBetween) {
335
- where.value = where.value.split(":");
336
- }
337
329
  if (where.condition === Enums_1.ConditionTypes.LIKE ||
338
330
  where.condition === Enums_1.ConditionTypes["NOT LIKE"]) {
331
+ const queryColumn = where.model.columns.find((column) => column.name === where.field);
332
+ if (queryColumn &&
333
+ !constants_1.STRING_COLUMN_TYPES.includes(queryColumn.data_type.toLowerCase())) {
334
+ throw new ApiError_1.default(`Query field need to be string. Unacceptable query field: ${where.field}`);
335
+ }
339
336
  where.value = where.value.replace(/\*/g, "%");
340
337
  }
341
338
  // This means that the condition is related with another table
@@ -27,3 +27,5 @@ export declare const API_ROUTE_TEMPLATES: {
27
27
  export declare const ConditionQueryFeatureMap: Record<ConditionTypes, QueryFeature>;
28
28
  export declare const RelationQueryFeatureMap: Record<Relationships, QueryFeature>;
29
29
  export declare const DEFAULT_VERSION_CONFIG: IVersionConfig;
30
+ export declare const NUMERIC_PRIMARY_KEY_TYPES: string[];
31
+ export declare const STRING_COLUMN_TYPES: string[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_VERSION_CONFIG = exports.RelationQueryFeatureMap = exports.ConditionQueryFeatureMap = exports.API_ROUTE_TEMPLATES = exports.DEFAULT_METHODS_OF_MODELS = exports.DEFAULT_HANDLERS = exports.RESERVED_KEYWORDS = exports.LOG_COLORS = void 0;
3
+ exports.STRING_COLUMN_TYPES = exports.NUMERIC_PRIMARY_KEY_TYPES = exports.DEFAULT_VERSION_CONFIG = exports.RelationQueryFeatureMap = exports.ConditionQueryFeatureMap = exports.API_ROUTE_TEMPLATES = exports.DEFAULT_METHODS_OF_MODELS = exports.DEFAULT_HANDLERS = exports.RESERVED_KEYWORDS = exports.LOG_COLORS = void 0;
4
4
  const Enums_1 = require("./Enums");
5
5
  const LimitService_1 = require("./Services/LimitService");
6
6
  exports.LOG_COLORS = {
@@ -115,3 +115,14 @@ exports.DEFAULT_VERSION_CONFIG = {
115
115
  },
116
116
  },
117
117
  };
118
+ exports.NUMERIC_PRIMARY_KEY_TYPES = ["integer", "bigint"];
119
+ exports.STRING_COLUMN_TYPES = [
120
+ "CHAR",
121
+ "VARCHAR",
122
+ "BINARY",
123
+ "VARBINARY",
124
+ "BLOB",
125
+ "TEXT",
126
+ "ENUM",
127
+ "SET",
128
+ ].map((item) => item.toLowerCase());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axe-api",
3
- "version": "0.31.3",
3
+ "version": "0.31.5",
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",
@@ -39,8 +39,11 @@
39
39
  "lint:watch": "esw --watch --color",
40
40
  "prepare:integration": "nodemon --ignore \"./tests/**\" ./scripts/run-integration-test.js",
41
41
  "test:postgres": "sh ./scripts/test-postgres.sh",
42
+ "test:cockroach": "sh ./scripts/test-cockroach.sh",
42
43
  "test:mysql57": "sh ./scripts/test-mysql57.sh",
43
44
  "test:mysql8": "sh ./scripts/test-mysql8.sh",
45
+ "test:mariadb": "sh ./scripts/test-mariadb.sh",
46
+ "test:sqlite": "sh ./scripts/test-sqlite.sh",
44
47
  "prettier:check": "prettier --check .",
45
48
  "prepare": "husky install"
46
49
  },