axe-api 0.31.2 → 0.31.4

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.
@@ -32,11 +32,11 @@ class RouterBuilder {
32
32
  this.getRootPrefix = () => __awaiter(this, void 0, void 0, function* () {
33
33
  const api = Services_1.APIService.getInstance();
34
34
  let prefix = api.config.prefix || "api";
35
- if (prefix.substr(0, 1) === "/") {
36
- prefix = prefix.substr(1);
35
+ if (prefix.startsWith("/")) {
36
+ prefix = prefix.substring(1);
37
37
  }
38
- if (prefix.substr(prefix.length - 1) === "/") {
39
- prefix = prefix.substr(0, prefix.length - 1);
38
+ if (prefix.endsWith("/")) {
39
+ prefix = prefix.substring(0, prefix.length - 1);
40
40
  }
41
41
  return prefix;
42
42
  });
@@ -210,19 +210,17 @@ class RouterBuilder {
210
210
  }
211
211
  sendErrorAsResponse(res, error) {
212
212
  const type = error.type;
213
- switch (type) {
214
- case "ApiError":
215
- // eslint-disable-next-line no-case-declarations
216
- const apiError = error;
217
- res.status(apiError.status).json({
218
- error: apiError.message,
219
- });
220
- break;
221
- default:
222
- // We should log error and send general error response
223
- Services_1.LogService.getInstance().error(`SERVER ERROR: ${JSON.stringify(Object.assign(Object.assign({}, error), { message: error.message }), null, " ")}`);
224
- throw error;
213
+ if (type === "ApiError") {
214
+ // eslint-disable-next-line no-case-declarations
215
+ const apiError = error;
216
+ res.status(apiError.status).json({
217
+ error: apiError.message,
218
+ });
219
+ return;
225
220
  }
221
+ // We should log error and send general error response
222
+ Services_1.LogService.getInstance().error(`SERVER ERROR: ${JSON.stringify(Object.assign(Object.assign({}, error), { message: error.message }), null, " ")}`);
223
+ throw error;
226
224
  }
227
225
  getResourcePath(model, relation) {
228
226
  return relation
@@ -15,7 +15,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const Helpers_1 = require("./Helpers");
16
16
  const Enums_1 = require("../Enums");
17
17
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
18
- const Enums_2 = require("../Enums");
19
18
  exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
20
19
  const { model, req, res, database, relation, parentModel } = pack;
21
20
  // We should check the parameter type
@@ -32,7 +31,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
32
31
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeDeleteQuery, Object.assign(Object.assign({}, pack), { query }));
33
32
  const item = yield query.first();
34
33
  if (!item) {
35
- throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_2.StatusCodes.NOT_FOUND);
34
+ throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_1.StatusCodes.NOT_FOUND);
36
35
  }
37
36
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterDeleteQuery, Object.assign(Object.assign({}, pack), { query,
38
37
  item }));
@@ -48,5 +47,5 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
48
47
  yield query.delete();
49
48
  }
50
49
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterDelete, Object.assign(Object.assign({}, pack), { item }));
51
- return res.json();
50
+ return res.status(204).json();
52
51
  });
@@ -15,7 +15,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const Helpers_1 = require("./Helpers");
16
16
  const Enums_1 = require("../Enums");
17
17
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
18
- const Enums_2 = require("../Enums");
19
18
  exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
20
19
  const { model, req, res, database, relation, parentModel } = pack;
21
20
  // We should check the parameter type
@@ -27,7 +26,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
27
26
  .where(model.instance.primaryKey, value);
28
27
  // If there is a deletedAtColumn, it means that this table support soft-delete
29
28
  if (model.instance.deletedAtColumn === null) {
30
- throw new ApiError_1.default("You can use force delete only soft-delete supported models.", Enums_2.StatusCodes.NOT_FOUND);
29
+ throw new ApiError_1.default("You can use force delete only soft-delete supported models.", Enums_1.StatusCodes.NOT_FOUND);
31
30
  }
32
31
  // If there is a relation, we should bind it
33
32
  (0, Helpers_1.addForeignKeyQuery)(req, query, relation, parentModel);
@@ -42,5 +41,5 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
42
41
  item }));
43
42
  yield query.delete();
44
43
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterForceDelete, Object.assign(Object.assign({}, pack), { item }));
45
- return res.json();
44
+ return res.status(204).json();
46
45
  });
@@ -1,6 +1,6 @@
1
- import { IRequestPack } from "../Interfaces";
2
1
  import { HandlerTypes } from "../Enums";
2
+ import { HandlerFunction } from "../Types";
3
3
  declare class HandlerFactory {
4
- static get(handleType: HandlerTypes): (pack: IRequestPack) => void;
4
+ static get(handleType: HandlerTypes): HandlerFunction;
5
5
  }
6
6
  export default HandlerFactory;
@@ -1,17 +1,16 @@
1
1
  import { Request } from "express";
2
- import { IModelService, IRelation, IHookParameter, IQuery, IVersion } from "../Interfaces";
2
+ import { IModelService, IRelation, IHookParameter, IQuery, IVersion, IWith } from "../Interfaces";
3
3
  import { Knex } from "knex";
4
- import { IWith } from "../Interfaces";
5
4
  import { HandlerTypes, HookFunctionTypes, TimestampColumns } from "../Enums";
6
5
  import { ModelListService } from "../Services";
7
6
  import { SerializationFunction } from "../Types";
8
- export declare const bindTimestampValues: (formData: Record<string, any>, columnTypes: TimestampColumns[] | undefined, model: IModelService) => void;
7
+ export declare const bindTimestampValues: (formData: Record<string, any>, model: IModelService, columnTypes?: TimestampColumns[]) => void;
9
8
  export declare const getMergedFormData: (req: Request, fillables: string[]) => Record<string, any>;
10
9
  export declare const callHooks: (model: IModelService, type: HookFunctionTypes, params: IHookParameter) => Promise<void>;
11
10
  export declare const getParentColumn: (relation: IRelation | null) => string | null;
12
11
  export declare const checkPrimaryKeyValueType: (model: IModelService, value: any) => void;
13
12
  export declare const addForeignKeyQuery: (request: Request, query: Knex.QueryBuilder, relation: IRelation | null, parentModel: IModelService | null) => void;
14
- export declare const serializeData: (version: IVersion, itemArray: any[] | any, modelSerializer: SerializationFunction | null, handler: HandlerTypes, request: Request) => Promise<any[]>;
13
+ export declare const serializeData: (version: IVersion, itemArray: any, modelSerializer: SerializationFunction | null, handler: HandlerTypes, request: Request) => Promise<any[]>;
15
14
  export declare const filterHiddenFields: (itemArray: any[], hiddens: string[] | null) => void;
16
15
  export declare const addSoftDeleteQuery: (model: IModelService, conditions: IQuery | null, query: Knex.QueryBuilder) => void;
17
16
  export declare const getRelatedData: (version: IVersion, data: any[], withArray: IWith[], model: IModelService, modelList: ModelListService, database: Knex | Knex.Transaction, handler: HandlerTypes, request: Request) => Promise<void>;
@@ -19,7 +19,7 @@ const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
19
19
  const Services_1 = require("../Services");
20
20
  const LimitService_1 = require("../Services/LimitService");
21
21
  const constants_1 = require("../constants");
22
- const bindTimestampValues = (formData, columnTypes = [], model) => {
22
+ const bindTimestampValues = (formData, model, columnTypes = []) => {
23
23
  if (columnTypes.includes(Enums_1.TimestampColumns.CREATED_AT) &&
24
24
  model.instance.createdAtColumn) {
25
25
  formData[model.instance.createdAtColumn] = new Date();
@@ -42,7 +42,8 @@ const getMergedFormData = (req, fillables) => {
42
42
  exports.getMergedFormData = getMergedFormData;
43
43
  const callHooks = (model, type, params) => __awaiter(void 0, void 0, void 0, function* () {
44
44
  if (model.hooks[type]) {
45
- yield model.hooks[type](params);
45
+ const hookFunction = model.hooks[type];
46
+ yield hookFunction(params);
46
47
  }
47
48
  if (model.events[type]) {
48
49
  // Developers shouldn't be able to access transaction in events. Because
@@ -66,7 +67,8 @@ exports.getParentColumn = getParentColumn;
66
67
  const checkPrimaryKeyValueType = (model, value) => {
67
68
  // We should check the parameter type
68
69
  const primaryColumn = model.columns.find((column) => column.name === model.instance.primaryKey);
69
- 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))) {
70
72
  throw new ApiError_1.default(`Unacceptable parameter: ${value}`);
71
73
  }
72
74
  };
@@ -117,7 +119,6 @@ const globalSerializer = (version, itemArray, handler, request) => __awaiter(voi
117
119
  // Serialize data with specific handler like "PAGINATE" or "SHOW".
118
120
  if (configSerializer.handler.includes(handler)) {
119
121
  callbacks.push(...configSerializer.serializer);
120
- return;
121
122
  }
122
123
  });
123
124
  callbacks.forEach((callback) => {
@@ -16,7 +16,6 @@ const validatorjs_1 = __importDefault(require("validatorjs"));
16
16
  const Helpers_1 = require("./Helpers");
17
17
  const Enums_1 = require("../Enums");
18
18
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
19
- const Enums_2 = require("../Enums");
20
19
  exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
21
20
  const { version, model, req, res, database, relation, parentModel } = pack;
22
21
  const query = database.from(model.instance.table);
@@ -31,7 +30,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
31
30
  // Adding the main query
32
31
  let item = yield query.where(model.instance.primaryKey, value).first();
33
32
  if (!item) {
34
- throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_2.StatusCodes.NOT_FOUND);
33
+ throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_1.StatusCodes.NOT_FOUND);
35
34
  }
36
35
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterUpdateQuery, Object.assign(Object.assign({}, pack), { item,
37
36
  query }));
@@ -49,7 +48,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
49
48
  }
50
49
  }
51
50
  // We should bind the timestamp values
52
- (0, Helpers_1.bindTimestampValues)(formData, [Enums_1.TimestampColumns.UPDATED_AT], model);
51
+ (0, Helpers_1.bindTimestampValues)(formData, model, [Enums_1.TimestampColumns.UPDATED_AT]);
53
52
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeUpdate, Object.assign(Object.assign({}, pack), { item,
54
53
  formData,
55
54
  query }));
@@ -16,7 +16,6 @@ const Helpers_1 = require("./Helpers");
16
16
  const Enums_1 = require("../Enums");
17
17
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
18
18
  const Services_1 = require("../Services");
19
- const Enums_2 = require("../Enums");
20
19
  exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
21
20
  const { version, model, req, res, database, relation, parentModel } = pack;
22
21
  const queryParser = new Services_1.QueryService(model, version.modelList.get(), version.config);
@@ -41,7 +40,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
41
40
  queryParser.applyWheres(query, conditions.q);
42
41
  let item = yield query.first();
43
42
  if (!item) {
44
- throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_2.StatusCodes.NOT_FOUND);
43
+ throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_1.StatusCodes.NOT_FOUND);
45
44
  }
46
45
  // We should try to get related data if there is any
47
46
  yield (0, Helpers_1.getRelatedData)(version, [item], conditions.with, model, version.modelList, database, Enums_1.HandlerTypes.ALL, req);
@@ -37,7 +37,10 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
37
37
  }
38
38
  }
39
39
  // We should bind the timestamp values
40
- (0, Helpers_1.bindTimestampValues)(formData, [Enums_1.TimestampColumns.CREATED_AT, Enums_1.TimestampColumns.UPDATED_AT], model);
40
+ (0, Helpers_1.bindTimestampValues)(formData, model, [
41
+ Enums_1.TimestampColumns.CREATED_AT,
42
+ Enums_1.TimestampColumns.UPDATED_AT,
43
+ ]);
41
44
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeInsert, Object.assign(Object.assign({}, pack), { formData }));
42
45
  const [returningResult] = yield database(model.instance.table)
43
46
  .insert(formData)
@@ -16,7 +16,6 @@ const validatorjs_1 = __importDefault(require("validatorjs"));
16
16
  const Helpers_1 = require("./Helpers");
17
17
  const Enums_1 = require("../Enums");
18
18
  const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
19
- const Enums_2 = require("../Enums");
20
19
  exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
21
20
  const { version, model, req, res, database, relation, parentModel } = pack;
22
21
  const query = database.from(model.instance.table);
@@ -31,7 +30,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
31
30
  // Adding the main query
32
31
  let item = yield query.where(model.instance.primaryKey, value).first();
33
32
  if (!item) {
34
- throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_2.StatusCodes.NOT_FOUND);
33
+ throw new ApiError_1.default(`The item is not found on ${model.name}.`, Enums_1.StatusCodes.NOT_FOUND);
35
34
  }
36
35
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onAfterUpdateQuery, Object.assign(Object.assign({}, pack), { item,
37
36
  query }));
@@ -49,7 +48,7 @@ exports.default = (pack) => __awaiter(void 0, void 0, void 0, function* () {
49
48
  }
50
49
  }
51
50
  // We should bind the timestamp values
52
- (0, Helpers_1.bindTimestampValues)(formData, [Enums_1.TimestampColumns.UPDATED_AT], model);
51
+ (0, Helpers_1.bindTimestampValues)(formData, model, [Enums_1.TimestampColumns.UPDATED_AT]);
53
52
  yield (0, Helpers_1.callHooks)(model, Enums_1.HookFunctionTypes.onBeforeUpdate, Object.assign(Object.assign({}, pack), { item,
54
53
  formData,
55
54
  query }));
@@ -3,7 +3,7 @@ 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, QueryFeature, QueryFeatureType } from "./Enums";
5
5
  import Model from "./Model";
6
- import { SerializationFunction } from "./Types";
6
+ import { HookFunction, SerializationFunction } from "./Types";
7
7
  import { ModelListService } from "./Services";
8
8
  export interface IColumn extends Column {
9
9
  table_name: string;
@@ -96,9 +96,9 @@ export interface IHookParameter {
96
96
  database: Knex | Knex.Transaction;
97
97
  conditions: IQuery | null;
98
98
  query: Knex.QueryBuilder | null;
99
- result: any | null;
100
- item: any | null;
101
- formData: any | null;
99
+ result: any;
100
+ item: any;
101
+ formData: any;
102
102
  }
103
103
  export interface IMethodBaseConfig {
104
104
  [HttpMethods.POST]?: string[];
@@ -115,14 +115,14 @@ export interface IModelService {
115
115
  relations: IRelation[];
116
116
  columns: IColumn[];
117
117
  columnNames: string[];
118
- hooks: Record<HookFunctionTypes, (params: IHookParameter) => void>;
119
- events: Record<HookFunctionTypes, (params: IHookParameter) => void>;
118
+ hooks: Record<HookFunctionTypes, HookFunction>;
119
+ events: Record<HookFunctionTypes, HookFunction>;
120
120
  isRecursive: boolean;
121
121
  children: IModelService[];
122
122
  queryLimits: IQueryLimitConfig[];
123
123
  serialize: SerializationFunction | null;
124
124
  setColumns(columns: IColumn[]): void;
125
- setExtensions(type: Extensions, hookFunctionType: HookFunctionTypes, data: (params: IHookParameter) => void): void;
125
+ setExtensions(type: Extensions, hookFunctionType: HookFunctionTypes, data: HookFunction): void;
126
126
  setQueryLimits(limits: IQueryLimitConfig[]): void;
127
127
  setSerialization(callback: SerializationFunction): void;
128
128
  }
@@ -1,14 +1,14 @@
1
- import { Request, Response, NextFunction } from "express";
2
1
  import { IRelation, IMethodBaseConfig, IMethodBaseValidations, IHandlerBaseMiddleware, IHandlerBasedTransactionConfig, IQueryLimitConfig } from "./Interfaces";
3
2
  import { HandlerTypes, HttpMethods } from "./Enums";
3
+ import { FieldList, MiddlewareFunction, ModelValidation } from "./Types";
4
4
  declare class Model {
5
5
  get primaryKey(): string;
6
6
  get table(): string;
7
- get fillable(): string[] | IMethodBaseConfig;
8
- get validations(): IMethodBaseValidations | Record<string, string>;
7
+ get fillable(): FieldList | IMethodBaseConfig;
8
+ get validations(): IMethodBaseValidations | ModelValidation;
9
9
  get handlers(): HandlerTypes[];
10
- get middlewares(): ((req: Request, res: Response, next: NextFunction) => void)[] | IHandlerBaseMiddleware[] | IHandlerBaseMiddleware;
11
- get hiddens(): string[];
10
+ get middlewares(): MiddlewareFunction[] | IHandlerBaseMiddleware[] | IHandlerBaseMiddleware;
11
+ get hiddens(): FieldList;
12
12
  get createdAtColumn(): string | null;
13
13
  get updatedAtColumn(): string | null;
14
14
  get deletedAtColumn(): string | null;
@@ -16,8 +16,8 @@ declare class Model {
16
16
  get ignore(): boolean;
17
17
  get limits(): Array<IQueryLimitConfig[]>;
18
18
  getFillableFields(methodType: HttpMethods): string[];
19
- getValidationRules(methodType: HttpMethods): Record<string, string> | null;
20
- getMiddlewares(handlerType: HandlerTypes): ((req: Request, res: Response, next: NextFunction) => void)[];
19
+ getValidationRules(methodType: HttpMethods): ModelValidation | null;
20
+ getMiddlewares(handlerType: HandlerTypes): MiddlewareFunction[];
21
21
  hasMany(relatedModel: string, primaryKey?: string, foreignKey?: string): IRelation;
22
22
  hasOne(relatedModel: string, primaryKey?: string, foreignKey?: string): IRelation;
23
23
  belongsTo(relatedModel: string, primaryKey: string, foreignKey: string): IRelation;
@@ -48,6 +48,7 @@ class Model {
48
48
  return [];
49
49
  }
50
50
  getFillableFields(methodType) {
51
+ var _a, _b, _c;
51
52
  if (this.fillable === null) {
52
53
  return [];
53
54
  }
@@ -57,26 +58,27 @@ class Model {
57
58
  const values = this.fillable;
58
59
  switch (methodType) {
59
60
  case Enums_1.HttpMethods.PATCH:
60
- return values.PATCH || [];
61
+ return (_a = values.PATCH) !== null && _a !== void 0 ? _a : [];
61
62
  case Enums_1.HttpMethods.POST:
62
- return values.POST || [];
63
+ return (_b = values.POST) !== null && _b !== void 0 ? _b : [];
63
64
  case Enums_1.HttpMethods.PUT:
64
- return values.PUT || [];
65
+ return (_c = values.PUT) !== null && _c !== void 0 ? _c : [];
65
66
  default:
66
67
  return [];
67
68
  }
68
69
  }
69
70
  getValidationRules(methodType) {
71
+ var _a, _b;
70
72
  if (this.hasStringValue()) {
71
73
  return this.validations;
72
74
  }
73
75
  const values = this.validations;
74
76
  switch (methodType) {
75
77
  case Enums_1.HttpMethods.POST:
76
- return values.POST || null;
78
+ return (_a = values.POST) !== null && _a !== void 0 ? _a : null;
77
79
  case Enums_1.HttpMethods.PATCH:
78
80
  case Enums_1.HttpMethods.PUT:
79
- return values.PUT || null;
81
+ return (_b = values.PUT) !== null && _b !== void 0 ? _b : null;
80
82
  default:
81
83
  return null;
82
84
  }
@@ -18,7 +18,7 @@ class GeneralHookResolver {
18
18
  return __awaiter(this, void 0, void 0, function* () {
19
19
  const fileResolver = new _1.FileResolver();
20
20
  const content = yield fileResolver.resolveContent(this.version.folders.root);
21
- if (content && content.init) {
21
+ if (content === null || content === void 0 ? void 0 : content.init) {
22
22
  const { onBeforeInit = null, onAfterInit = null } = content.init;
23
23
  return { onBeforeInit, onAfterInit };
24
24
  }
@@ -11,7 +11,7 @@ class DocumentationService {
11
11
  return DocumentationService.instance;
12
12
  }
13
13
  push(version, handler, method, url, model) {
14
- var _a, _b;
14
+ var _a, _b, _c;
15
15
  this.routes.push({
16
16
  version: version.name,
17
17
  handler,
@@ -25,7 +25,7 @@ class DocumentationService {
25
25
  fillables: model.instance.getFillableFields(method),
26
26
  validations: model.instance.getValidationRules(method),
27
27
  queryLimits: model.queryLimits,
28
- queryDefaults: ((_b = (_a = version.config) === null || _a === void 0 ? void 0 : _a.query) === null || _b === void 0 ? void 0 : _b.defaults) || {},
28
+ queryDefaults: (_c = (_b = (_a = version.config) === null || _a === void 0 ? void 0 : _a.query) === null || _b === void 0 ? void 0 : _b.defaults) !== null && _c !== void 0 ? _c : {},
29
29
  });
30
30
  }
31
31
  get() {
@@ -9,7 +9,7 @@ declare class LogService {
9
9
  warn(message: string): void;
10
10
  info(message: string): void;
11
11
  success(message: string): void;
12
- log(message: string): void;
13
12
  debug(message: string): void;
13
+ log(message: string): void;
14
14
  }
15
15
  export default LogService;
@@ -33,12 +33,10 @@ class LogService {
33
33
  console.info(fgGreen, "[axe]", message, fgReset);
34
34
  }
35
35
  }
36
- log(message) {
37
- if (this.level === Enums_1.LogLevels.ALL) {
38
- console.log(message);
39
- }
40
- }
41
36
  debug(message) {
37
+ this.log(message);
38
+ }
39
+ log(message) {
42
40
  if (this.level === Enums_1.LogLevels.ALL) {
43
41
  console.log(message);
44
42
  }
@@ -1,22 +1,22 @@
1
1
  import { HookFunctionTypes, Extensions } from "../Enums";
2
- import { IColumn, IHookParameter, IModelService, IQueryLimitConfig, IRelation } from "../Interfaces";
2
+ import { IColumn, IModelService, IQueryLimitConfig, IRelation } from "../Interfaces";
3
3
  import Model from "./../Model";
4
- import { SerializationFunction } from "../Types";
4
+ import { HookFunction, SerializationFunction } from "../Types";
5
5
  declare class ModelService implements IModelService {
6
6
  name: string;
7
7
  instance: Model;
8
8
  relations: IRelation[];
9
9
  columns: IColumn[];
10
10
  columnNames: string[];
11
- hooks: Record<HookFunctionTypes, (params: IHookParameter) => void>;
12
- events: Record<HookFunctionTypes, (params: IHookParameter) => void>;
11
+ hooks: Record<HookFunctionTypes, HookFunction>;
12
+ events: Record<HookFunctionTypes, HookFunction>;
13
13
  children: IModelService[];
14
14
  isRecursive: boolean;
15
15
  queryLimits: IQueryLimitConfig[];
16
16
  serialize: SerializationFunction | null;
17
17
  constructor(name: string, instance: Model);
18
18
  setColumns(columns: IColumn[]): void;
19
- setExtensions(type: Extensions, hookFunctionType: HookFunctionTypes, data: (params: IHookParameter) => void): void;
19
+ setExtensions(type: Extensions, hookFunctionType: HookFunctionTypes, data: HookFunction): void;
20
20
  setQueryLimits(limits: IQueryLimitConfig[]): void;
21
21
  setSerialization(callback: SerializationFunction): void;
22
22
  private setHooks;
@@ -247,10 +247,10 @@ class QueryService {
247
247
  let type = Enums_1.SortTypes.ASC;
248
248
  if (field.indexOf("-") === 0) {
249
249
  type = Enums_1.SortTypes.DESC;
250
- field = field.substr(1);
250
+ field = field.substring(1);
251
251
  }
252
252
  if (field.indexOf("+") === 0) {
253
- field = field.substr(1);
253
+ field = field.substring(1);
254
254
  }
255
255
  this.shouldBeAcceptableColumn(field);
256
256
  result.push({
@@ -326,14 +326,6 @@ 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"]) {
339
331
  where.value = where.value.replace(/\*/g, "%");
@@ -1,2 +1,8 @@
1
- import { Request } from "express";
1
+ import { NextFunction, Request, Response } from "express";
2
+ import { IRequestPack, IHookParameter } from "./Interfaces";
2
3
  export type SerializationFunction = (item: any, request: Request) => any;
4
+ export type HandlerFunction = (pack: IRequestPack) => void;
5
+ export type MiddlewareFunction = (req: Request, res: Response, next: NextFunction) => void;
6
+ export type ModelValidation = Record<string, string>;
7
+ export type FieldList = string[];
8
+ export type HookFunction = (pack: IHookParameter) => Promise<void>;
@@ -27,3 +27,4 @@ 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[];
@@ -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.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,4 @@ exports.DEFAULT_VERSION_CONFIG = {
115
115
  },
116
116
  },
117
117
  };
118
+ exports.NUMERIC_PRIMARY_KEY_TYPES = ["integer", "bigint"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axe-api",
3
- "version": "0.31.2",
3
+ "version": "0.31.4",
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
  },
package/readme.md CHANGED
@@ -9,8 +9,8 @@
9
9
  <a href="https://badge.fury.io/js/axe-api">
10
10
  <img src="https://badge.fury.io/js/axe-api.svg" alt="npm version" height="18">
11
11
  </a>
12
- <a href="https://github.com/axe-api/axe-api/actions/workflows/npm-publish.yml" target="_blank">
13
- <img src="https://github.com/axe-api/axe-api/actions/workflows/npm-publish.yml/badge.svg?branch=master">
12
+ <a href="https://github.com/axe-api/axe-api/actions/workflows/npm-release-publish.yml" target="_blank">
13
+ <img src="https://github.com/axe-api/axe-api/actions/workflows/npm-release-publish.yml/badge.svg?branch=master">
14
14
  </a>
15
15
  <a href="https://sonarcloud.io/dashboard?id=axe-api_axe-api" target="_blank">
16
16
  <img src="https://sonarcloud.io/api/project_badges/measure?project=axe-api_axe-api&metric=alert_status">
@@ -23,138 +23,24 @@
23
23
  </a>
24
24
  </h1>
25
25
 
26
- Next Generation Rest API Framework
26
+ **Axe API** is a **TypeScript-based** **Node.js** framework designed to eliminate the need for repetitive tasks associated with common elements while allowing developers to focus on custom logic.
27
27
 
28
- > Axe API has great documentation. Please [check it out in here](https://axe-api.com/).
28
+ It offers a comprehensive structure for your API, including numerous features and best practices that will save you time.
29
29
 
30
- ## What Is Axe API?
30
+ ## Video Introduction
31
31
 
32
- Axe API is a [Node.js](https://nodejs.org/) framework that helps you create a **Rest API** in a declarative way quickly. :axe:
32
+ <div style="display: flex; justify-content: center;">
33
33
 
34
- It has been written with [TypeScript](https://www.typescriptlang.org/) and built on [Express](https://expressjs.com/) and [Knex.js](https://knexjs.org/).
34
+ <a href="https://www.youtube.com/watch?v=3p4jggsNrJA" target="_blank">
35
+ <img src="./youtube.png" />
36
+ </a>
35
37
 
36
- ## Motivation
37
-
38
- You would understand easily what you are going to code when you look at a bunch of database tables and their relations with each other, more or less. Because, as a developer, you already know that _Rest API_ best practices.
39
-
40
- Therefore I asked a simple question more than two years ago;
41
-
42
- **_"Can we create a Rest API in a declarative way, and handle all endpoints automatically?"_**
43
-
44
- As a result of our work, we have a framework called Axe API that provides a solution to analyze your API definitions and handle all of the endpoints.
45
-
46
- Basically, you define your models which are your API definitions, and Axe API analyzes them and processes all of your endpoints instead of you.
47
-
48
- ## Showcase
49
-
50
- Let's look at an example!
51
-
52
- You have two database tables; `users` and `posts`. These tables are related to each other and we aim that create a **Rest API** for basic **CRUD** endpoints.
53
-
54
- The only thing to do is creating models like the following example;
55
-
56
- ```ts
57
- class User extends Model {
58
- get fillable(): string[] {
59
- return ["email", "name", "surname"];
60
- }
61
-
62
- posts(): IRelation {
63
- return this.hasMany("Post", "id", "user_id");
64
- }
65
- }
66
- ```
67
-
68
- ```ts
69
- class Post extends Model {
70
- get fillable(): string[] {
71
- return ["title", "description"];
72
- }
73
-
74
- user(): IRelation {
75
- return this.belongsTo("User", "user_id", "id");
76
- }
77
- }
78
- ```
79
-
80
- Tada! :tada:
81
-
82
- Your API is ready to process all of the following endpoints after those model definitions are done.
83
-
84
- - [GET] `api/users`
85
- - [POST] `api/users`
86
- - [GET] `api/users/:id`
87
- - [PUT] `api/users/:id`
88
- - [DELETE] `api/users/:id`
89
- - [GET] `api/users/:userId/posts`
90
- - [POST] `api/users/:userId/posts`
91
- - [GET] `api/users/:userId/posts/:id`
92
- - [PUT] `api/users/:userId/posts/:id`
93
- - [DELETE] `api/users/:userId/posts/:id`
94
-
95
- This is the main power of Axe API. Nevertheless, it is not limited only to this power. There are many more features are waiting to discover. :bulb:
96
-
97
- ## Installation
98
-
99
- Using **Axe API** in an application is very easy. We've created a CLI tool for you; [axe-magic](https://github.com/axe-api/axe-magic).
100
-
101
- You can create a new Axe API project by using [axe-magic](https://github.com/axe-api/axe-magic). But first, you can install it in your development environment. When you installed it, you can be able to access **axe-magic** command via CLI. You can use the following command to install **axe-magic** to your machine;
102
-
103
- ```bash
104
- $ npm i -g axe-magic
105
- $ axe-magic --version
106
- 1.0.0
107
- ```
108
-
109
- After that, creating a new project is very easy. Just you can execute the following command;
110
-
111
- ```bash
112
- $ axe-magic new my-api
113
- ```
114
-
115
- This command will pull [axe-api-template](https://github.com/axe-api/axe-api-template) project to your current directory with a new name, **my-api**.
116
-
117
- To install your project's depencies, you can execute the following commands in the root directory;
118
-
119
- ```bash
120
- $ cd my-api
121
- $ npm install
122
- ```
123
-
124
- To serve this application, you can execute the following command;
125
-
126
- ```bash
127
- $ npm run start:dev
128
- ```
129
-
130
- After that, your first **Axe API** application will be running in `localhost:3000`.
131
-
132
- You will see the following API response if you visit [localhost:3000](http://localhost:3000).
133
-
134
- ```json
135
- {
136
- "name": "AXE API",
137
- "description": "The best API creation tool in the world."
138
- }
139
- ```
140
-
141
- If you can see that response, it means that your project is running properly.
38
+ </div>
142
39
 
143
40
  ## Documentation
144
41
 
145
42
  Axe API has great documentation. Please [check it out in here](https://axe-api.com/).
146
43
 
147
- ## Contributors
148
-
149
- <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
150
- <!-- prettier-ignore-start -->
151
- <!-- markdownlint-disable -->
152
-
153
- <!-- markdownlint-restore -->
154
- <!-- prettier-ignore-end -->
155
-
156
- <!-- ALL-CONTRIBUTORS-LIST:END -->
157
-
158
44
  ## License
159
45
 
160
46
  [MIT License](LICENSE)
package/CHANGELOG.md DELETED
@@ -1,263 +0,0 @@
1
- # Release Notes
2
-
3
- ## [0.31.2 (2023-07-04)](https://github.com/axe-api/axe-api/compare/0.31.2...0.31.1)
4
-
5
- ### Fixed
6
-
7
- - Fixed many internal issues. [#219](https://github.com/axe-api/axe-api/issues/219), [#174](https://github.com/axe-api/axe-api/issues/174), [#183](https://github.com/axe-api/axe-api/issues/183), [#149](https://github.com/axe-api/axe-api/issues/149), [#186](https://github.com/axe-api/axe-api/issues/186)
8
-
9
- ## [0.31.1 (2023-05-08)](https://github.com/axe-api/axe-api/compare/0.31.1...0.31.0)
10
-
11
- ### Fixed
12
-
13
- - The app crashes on database errors [#155](https://github.com/axe-api/axe-api/issues/155)
14
- - We should return 404 if the record is not found [#169](https://github.com/axe-api/axe-api/issues/169)
15
- - An error should be thrown if the per_page value is not acceptable [#172](https://github.com/axe-api/axe-api/issues/172)
16
-
17
- ## [0.31.0 (2023-05-05)](https://github.com/axe-api/axe-api/compare/0.31.0...0.30.3)
18
-
19
- ### Features
20
-
21
- - Added new auto-created documentation values [#179](https://github.com/axe-api/axe-api/issues/179)
22
-
23
- ### Fixed
24
-
25
- - Fixed PostgreSQL-related issues [#204](https://github.com/axe-api/axe-api/issues/204)
26
-
27
- ## [0.30.3 (2023-05-05)](https://github.com/axe-api/axe-api/compare/0.30.3...0.30.2)
28
-
29
- ### Fixed
30
-
31
- - Fixed security issues on dependencies.
32
-
33
- ## [0.30.2 (2023-04-18)](https://github.com/axe-api/axe-api/compare/0.30.2...0.30.1)
34
-
35
- ### Features
36
-
37
- - Event/Hook type warning added [#163](https://github.com/axe-api/axe-api/issues/163)
38
-
39
- ## [0.30.1 (2023-04-15)](https://github.com/axe-api/axe-api/compare/0.30.1...0.30.0)
40
-
41
- ### Fixed
42
-
43
- - Fixed URL slash character difference between windows and \*nix [#164](https://github.com/axe-api/axe-api/issues/164)
44
-
45
- ## [0.30.0 (2023-04-05)](https://github.com/axe-api/axe-api/compare/0.30.0...0.22.0)
46
-
47
- ### Breaking Changes
48
-
49
- - Added new Serizaliation folder [#125](https://github.com/axe-api/axe-api/issues/125)
50
- - New hook/event folder structure [#146](https://github.com/axe-api/axe-api/issues/146)
51
- - Limiting query features by configurations [#38](https://github.com/axe-api/axe-api/issues/38)
52
- - Removing external dependencies from axe-core [#151](https://github.com/axe-api/axe-api/issues/151)
53
-
54
- ## [0.22.0 (2023-01-29)](https://github.com/axe-api/axe-api/compare/0.22.0...0.21.0)
55
-
56
- ### Features
57
-
58
- - Added Soft-Deleting feature [#41](https://github.com/axe-api/axe-api/issues/41)
59
-
60
- ### Fixed
61
-
62
- - Fixed model relation route URLs [#141](https://github.com/axe-api/axe-api/issues/141)
63
-
64
- ## [0.21.0 (2022-12-28)](https://github.com/axe-api/axe-api/compare/0.21.0...0.20.4)
65
-
66
- ### Features
67
-
68
- - Added `i18n` support. [#44](https://github.com/axe-api/axe-api/issues/44)
69
-
70
- ## [0.20.4 (2022-12-24)](https://github.com/axe-api/axe-api/compare/0.20.4...0.20.3)
71
-
72
- ### Fixed
73
-
74
- - Fixed [#124](https://github.com/axe-api/axe-api/issues/124)
75
- - Throwing errors in the `development` environment has been fixed.
76
- - Unbuilt integration test issue has been fixed.
77
-
78
- ## [0.20.3 (2022-12-24)](https://github.com/axe-api/axe-api/compare/0.20.3...0.20.0)
79
-
80
- ### Fixed
81
-
82
- - NPM publish bugs
83
-
84
- ## [0.20.0 (2022-12-24)](https://github.com/axe-api/axe-api/compare/0.20.0...0.19.2)
85
-
86
- In the whole application, TypeScript becomes the new language except for migration files and it's structure. You can read the documentation about how to migrate from `0.19.2` to `0.20.0`.
87
-
88
- ### Breaking Changes
89
-
90
- #### Naming Changes
91
-
92
- - File extensions: `User.js` to `User.ts`
93
- - `LOG_LEVELS` constant variable has been changed with `LogLevels` enum.
94
- - `HANDLERS` constant variable has been changed with `HandlerTypes` enum.
95
- - `IoC` service has been renamed as `IoCService`.
96
- - Hooks and Event files' names should be singular;
97
- - `UserHooks.js` => `UserHook.ts`
98
- - `UserEvents.js` => `UserEvent.ts`
99
-
100
- #### Interface Changes
101
-
102
- - `validations()` getter should return `IMethodBaseValidations` interface.
103
- - In hook functions, `IHookParameter` interface should be used as the parameter type.
104
- - Init functions (`onBeforeInit`, `onAfterInit`) should be use the `Express` type;
105
- - `const onBeforeInit = async ({ app }) => {` => `const onBeforeInit = async (app: Express) => {`
106
- - `const onAfterInit = async ({ app }) => {` => `const onAfterInit = async (app: Express) => {`
107
- - Application config should be implemented `IApplicationConfig` interface.
108
-
109
- #### Implementation Changes
110
-
111
- - Starting server part has been changed;
112
- - `const server = new Server(appFolder)` => `const server = new Server()`
113
- - `server.listen()` => `server.start(__dirname);`
114
- - `knexfile.js` should not use the `app/Application/Config.js` anymore.
115
-
116
- ## [0.19.2 (2022-01-22)](https://github.com/axe-api/axe-api/compare/0.19.2...0.19.1)
117
-
118
- ### Fixed
119
-
120
- - Fixed the calling `onBeforePaginate` and `onBeforeShow` hooks bug.
121
-
122
- ## [0.19.1 (2022-01-22)](https://github.com/axe-api/axe-api/compare/0.19.1...0.19.0)
123
-
124
- ### Fixed
125
-
126
- - knex.js version update.
127
-
128
- ## [0.19.0 (2021-12-05)](https://github.com/axe-api/axe-api/compare/0.19.0...0.18.1)
129
-
130
- ### Fixed
131
-
132
- - [#110](https://github.com/axe-api/axe-api/issues/110)
133
-
134
- ### Enhancements
135
-
136
- - [#106](https://github.com/axe-api/axe-api/issues/106)
137
-
138
- ## [0.18.1 (2021-12-02)](https://github.com/axe-api/axe-api/compare/0.18.1...0.18.0)
139
-
140
- ### Fixed
141
-
142
- - [#117](https://github.com/axe-api/axe-api/issues/117)
143
-
144
- ## [0.18.0 (2021-11-30)](https://github.com/axe-api/axe-api/compare/0.18.0...0.17.5)
145
-
146
- ### Fixed
147
-
148
- - [#115](https://github.com/axe-api/axe-api/issues/115)
149
- - [#114](https://github.com/axe-api/axe-api/issues/114)
150
-
151
- ### Enhancements
152
-
153
- - [#113](https://github.com/axe-api/axe-api/issues/113)
154
- - [#107](https://github.com/axe-api/axe-api/issues/107)
155
- - [#108](https://github.com/axe-api/axe-api/issues/108)
156
-
157
- ## [0.17.5 (2021-11-27)](https://github.com/axe-api/axe-api/compare/0.17.5...0.17.4)
158
-
159
- ### Fixed
160
-
161
- - [#111](https://github.com/axe-api/axe-api/issues/111)
162
-
163
- ## [0.17.4 (2021-10-28)](https://github.com/axe-api/axe-api/compare/0.17.4...0.17.3)
164
-
165
- ### Fixed
166
-
167
- - [#97](https://github.com/axe-api/axe-api/issues/97)
168
- - [#104](https://github.com/axe-api/axe-api/issues/104)
169
-
170
- ## [0.17.3 (2021-10-28)](https://github.com/axe-api/axe-api/compare/0.17.3...0.17.2)
171
-
172
- ### Fixed
173
-
174
- - [#98](https://github.com/axe-api/axe-api/issues/98)
175
-
176
- ## [0.17.2 (2021-10-17)](https://github.com/axe-api/axe-api/compare/0.17.2...0.17.1)
177
-
178
- ### Fixed
179
-
180
- - Fixed table join on the related table filter.
181
-
182
- ## [0.17.1 (2021-10-17)](https://github.com/axe-api/axe-api/compare/0.17.1...0.17.0)
183
-
184
- ### Fixed
185
-
186
- - Query bug on child models [#93](https://github.com/axe-api/axe-api/issues/93)
187
-
188
- ## [0.17.0 (2021-10-17)](https://github.com/axe-api/axe-api/compare/0.17.0...0.16.0)
189
-
190
- ### Fixed
191
-
192
- - Related query column name check bug has been fixed.
193
-
194
- ### Features
195
-
196
- - Global serializer for HTTP results [#37](https://github.com/axe-api/axe-api/issues/37)
197
-
198
- ## [0.16.0 (2021-10-06)](https://github.com/axe-api/axe-api/compare/0.16.0...0.15.0)
199
-
200
- ### Features
201
-
202
- - Fixes [#89](https://github.com/axe-api/axe-api/issues/89)
203
-
204
- ## [0.15.0 (2021-10-03)](https://github.com/axe-api/axe-api/compare/0.15.0...0.14.1)
205
-
206
- ### Features
207
-
208
- - Fixes [#87](https://github.com/axe-api/axe-api/issues/87)
209
-
210
- ## [0.14.1 (2021-09-20)](https://github.com/axe-api/axe-api/compare/0.14.1...0.14.0)
211
-
212
- ### Fixed
213
-
214
- - Fixes [#83](https://github.com/axe-api/axe-api/issues/83)
215
-
216
- ## [0.14.0 (2021-09-15)](https://github.com/axe-api/axe-api/compare/0.14.0...0.13.3)
217
-
218
- ### Features
219
-
220
- - General hooks definition feature has been added. ([#81](https://github.com/axe-api/axe-api/issues/81))
221
-
222
- ## [0.13.3 (2021-09-15)](https://github.com/axe-api/axe-api/compare/0.13.2...0.13.3)
223
-
224
- ### Fixed
225
-
226
- - Fixed CORS bugs.
227
-
228
- ## [0.13.2 (2021-08-20)](https://github.com/axe-api/axe-api/compare/0.13.1...0.13.2)
229
-
230
- ### Fixed
231
-
232
- - Fixes [#27](https://github.com/axe-api/axe-api/issues/27)
233
- - Fixes [#29](https://github.com/axe-api/axe-api/issues/29)
234
- - Fixes [#75](https://github.com/axe-api/axe-api/issues/75)
235
- - Fixes [#78](https://github.com/axe-api/axe-api/issues/78)
236
-
237
- ## [0.13.1 (2021-08-09)](https://github.com/axe-api/axe-api/compare/0.13.0...0.13.1)
238
-
239
- ### Fixed
240
-
241
- - Fixes [#69](https://github.com/axe-api/axe-api/issues/69)
242
- - Fixes [#70](https://github.com/axe-api/axe-api/issues/70)
243
- - Fixes [#71](https://github.com/axe-api/axe-api/issues/71)
244
- - Fixes [#72](https://github.com/axe-api/axe-api/issues/72)
245
-
246
- ## [0.13.0 (2021-07-25)](https://github.com/axe-api/axe-api/compare/0.12.2...0.13.0)
247
-
248
- ### Features
249
-
250
- - PostgreSQL database analyzer and integration tests have been added.
251
-
252
- ## [0.12.2 (2021-07-24)](https://github.com/axe-api/axe-api/compare/0.12.1...0.12.2)
253
-
254
- ### Fixed
255
-
256
- - Throwing an error if the primary key column isn't in the database table bug has been fixed. (#61)[https://github.com/axe-api/axe-api/issues/61]
257
- - Using numeric column name bug has been fixed. (#24)[https://github.com/axe-api/axe-api/issues/24]
258
-
259
- ## [0.12.1 (2021-07-24)](https://github.com/axe-api/axe-api/compare/0.12.0...0.12.1)
260
-
261
- ### Fixed
262
-
263
- - Fixed security issues.