axe-api 1.0.0-rc9 → 1.0.1
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 +1 -0
- package/build/index.js +1 -0
- package/build/src/Builders/IndexBuilder.d.ts +7 -0
- package/build/src/Builders/IndexBuilder.js +35 -0
- package/build/src/Builders/ModelTreeBuilder.js +2 -1
- package/build/src/Builders/RouterBuilder.js +22 -11
- package/build/src/Builders/SwaggerBuilder.d.ts +2 -0
- package/build/src/Builders/SwaggerBuilder.js +609 -0
- package/build/src/Enums.d.ts +6 -1
- package/build/src/Enums.js +7 -1
- package/build/src/Handlers/DocsHandler.js +41 -0
- package/build/src/Handlers/ErrorHandler.d.ts +6 -0
- package/build/src/Handlers/ErrorHandler.js +12 -0
- package/build/src/Handlers/Helpers.d.ts +16 -4
- package/build/src/Handlers/Helpers.js +202 -5
- package/build/src/Handlers/RequestHandler.d.ts +4 -1
- package/build/src/Handlers/RequestHandler.js +36 -40
- package/build/src/Handlers/{DocsHTMLHandler.js → SwaggerHandler.js} +8 -7
- package/build/src/Interfaces.d.ts +103 -35
- package/build/src/Middlewares/RateLimit/AdaptorFactory.d.ts +3 -3
- package/build/src/Middlewares/RateLimit/MemoryAdaptor.d.ts +2 -2
- package/build/src/Middlewares/RateLimit/RedisAdaptor.d.ts +12 -4
- package/build/src/Middlewares/RateLimit/RedisAdaptor.js +24 -0
- package/build/src/Middlewares/RateLimit/index.d.ts +22 -3
- package/build/src/Middlewares/RateLimit/index.js +23 -3
- package/build/src/Model.d.ts +256 -10
- package/build/src/Model.js +322 -30
- package/build/src/Phases/All/FetchPhase.d.ts +2 -2
- package/build/src/Phases/All/PreparePhase.d.ts +2 -2
- package/build/src/Phases/All/index.d.ts +1 -1
- package/build/src/Phases/CacheTagCleanPhase.d.ts +3 -0
- package/build/src/{Handlers/MetadataHandler.js → Phases/CacheTagCleanPhase.js} +6 -10
- package/build/src/Phases/Delete/ActionPhase.d.ts +2 -2
- package/build/src/Phases/Delete/ActionPhase.js +21 -2
- package/build/src/Phases/Delete/PreparePhase.d.ts +2 -2
- package/build/src/Phases/Delete/QueryPhase.d.ts +2 -2
- package/build/src/Phases/Delete/ResponsePhase.d.ts +2 -2
- package/build/src/Phases/Delete/ResponsePhase.js +2 -1
- package/build/src/Phases/Delete/index.d.ts +4 -4
- package/build/src/Phases/ForceDelete/ActionPhase.d.ts +2 -2
- package/build/src/Phases/ForceDelete/ActionPhase.js +7 -0
- package/build/src/Phases/ForceDelete/PreparePhase.d.ts +2 -2
- package/build/src/Phases/ForceDelete/QueryPhase.d.ts +2 -2
- package/build/src/Phases/ForceDelete/index.d.ts +3 -3
- package/build/src/Phases/GetCachePhase.d.ts +3 -0
- package/build/src/Phases/GetCachePhase.js +39 -0
- package/build/src/Phases/List/RelationalPhase.d.ts +2 -2
- package/build/src/Phases/List/ResultPhase.d.ts +2 -2
- package/build/src/Phases/List/ResultPhase.js +9 -1
- package/build/src/Phases/List/SerializePhase.d.ts +2 -2
- package/build/src/Phases/List/index.d.ts +3 -3
- package/build/src/Phases/Paginate/FetchPhase.d.ts +2 -2
- package/build/src/Phases/Paginate/PreparePhase.d.ts +2 -2
- package/build/src/Phases/Paginate/index.d.ts +2 -2
- package/build/src/Phases/Patch/PrepareActionPhase.d.ts +2 -2
- package/build/src/Phases/Patch/PrepareActionPhase.js +13 -10
- package/build/src/Phases/Patch/index.d.ts +1 -1
- package/build/src/Phases/Search/FetchPhase.d.ts +3 -0
- package/build/src/Phases/Search/FetchPhase.js +66 -0
- package/build/src/Phases/Search/PreparePhase.d.ts +3 -0
- package/build/src/Phases/Search/PreparePhase.js +19 -0
- package/build/src/Phases/Search/index.d.ts +5 -0
- package/build/src/Phases/Search/index.js +11 -0
- package/build/src/Phases/Show/FetchPhase.d.ts +2 -2
- package/build/src/Phases/Show/FetchPhase.js +11 -1
- package/build/src/Phases/Show/PreparePhase.d.ts +2 -2
- package/build/src/Phases/Show/PreparePhase.js +5 -13
- package/build/src/Phases/Show/index.d.ts +2 -2
- package/build/src/Phases/Single/GetPhase.d.ts +2 -2
- package/build/src/Phases/Single/PrepareGetPhase.d.ts +2 -2
- package/build/src/Phases/Single/RelationalPhase.d.ts +2 -2
- package/build/src/Phases/Single/ResultPhase.d.ts +2 -2
- package/build/src/Phases/Single/ResultPhase.js +9 -1
- package/build/src/Phases/Single/SerializePhase.d.ts +2 -2
- package/build/src/Phases/Single/index.d.ts +5 -5
- package/build/src/Phases/Store/ActionPhase.d.ts +2 -2
- package/build/src/Phases/Store/ActionPhase.js +18 -7
- package/build/src/Phases/Store/PreparePhase.d.ts +2 -2
- package/build/src/Phases/Store/PreparePhase.js +14 -9
- package/build/src/Phases/Store/ResultPhase.d.ts +3 -0
- package/build/src/Phases/Store/ResultPhase.js +23 -0
- package/build/src/Phases/Store/index.d.ts +3 -2
- package/build/src/Phases/Store/index.js +2 -0
- package/build/src/Phases/URLSearchParamPhase.d.ts +3 -0
- package/build/src/Phases/URLSearchParamPhase.js +37 -0
- package/build/src/Phases/Update/ActionPhase.d.ts +2 -2
- package/build/src/Phases/Update/ActionPhase.js +14 -3
- package/build/src/Phases/Update/PrepareActionPhase.d.ts +2 -2
- package/build/src/Phases/Update/PrepareActionPhase.js +13 -10
- package/build/src/Phases/Update/index.d.ts +2 -2
- package/build/src/Resolvers/ModelResolver.d.ts +1 -0
- package/build/src/Resolvers/ModelResolver.js +21 -2
- package/build/src/Resolvers/TransactionResolver.js +3 -15
- package/build/src/Resolvers/VersionConfigResolver.js +6 -1
- package/build/src/Resolvers/VersionResolver.js +1 -0
- package/build/src/Server.d.ts +5 -0
- package/build/src/Server.js +44 -11
- package/build/src/Services/APIService.d.ts +3 -3
- package/build/src/Services/APIService.js +3 -16
- package/build/src/Services/App.d.ts +94 -8
- package/build/src/Services/App.js +94 -29
- package/build/src/Services/AxeRequest.d.ts +51 -2
- package/build/src/Services/AxeRequest.js +51 -4
- package/build/src/Services/AxeResponse.d.ts +28 -1
- package/build/src/Services/AxeResponse.js +28 -0
- package/build/src/Services/ConverterService.d.ts +5 -3
- package/build/src/Services/DocumentationService.d.ts +5 -2
- package/build/src/Services/DocumentationService.js +13 -1
- package/build/src/Services/ElasticService.d.ts +14 -0
- package/build/src/Services/ElasticService.js +74 -0
- package/build/src/Services/IoCService.d.ts +29 -2
- package/build/src/Services/IoCService.js +33 -6
- package/build/src/Services/LimitService.d.ts +18 -0
- package/build/src/Services/LimitService.js +18 -0
- package/build/src/Services/ModelService.d.ts +9 -5
- package/build/src/Services/ModelService.js +11 -0
- package/build/src/Services/QueryService.d.ts +3 -3
- package/build/src/Services/QueryService.js +6 -0
- package/build/src/Services/SchemaValidatorService.d.ts +1 -0
- package/build/src/Services/SchemaValidatorService.js +4 -0
- package/build/src/Services/URLService.d.ts +6 -14
- package/build/src/Services/URLService.js +10 -8
- package/build/src/Steps/Event.d.ts +11 -0
- package/build/src/Steps/Event.js +17 -0
- package/build/src/Steps/Hook.d.ts +11 -0
- package/build/src/Steps/Hook.js +17 -0
- package/build/src/Steps/Phase.d.ts +11 -0
- package/build/src/Steps/Phase.js +18 -0
- package/build/src/Types.d.ts +12 -10
- package/build/src/constants.d.ts +8 -9
- package/build/src/constants.js +217 -152
- package/package.json +51 -37
- package/build/dev-kit.d.ts +0 -1
- package/build/dev-kit.js +0 -16
- package/build/src/Middlewares/RateLimit/IAdaptor.d.ts +0 -6
- package/build/src/Middlewares/RateLimit/IAdaptor.js +0 -2
- /package/build/src/Handlers/{DocsHTMLHandler.d.ts → DocsHandler.d.ts} +0 -0
- /package/build/src/Handlers/{MetadataHandler.d.ts → SwaggerHandler.d.ts} +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = (err, req, res, next) => {
|
|
4
|
+
// Sett the HTTP status code
|
|
5
|
+
res.statusCode = 500;
|
|
6
|
+
// Set the default HTTP message
|
|
7
|
+
res.write(JSON.stringify({
|
|
8
|
+
error: "Internal server error",
|
|
9
|
+
}));
|
|
10
|
+
res.end();
|
|
11
|
+
next();
|
|
12
|
+
};
|
|
@@ -1,17 +1,29 @@
|
|
|
1
|
-
import { IModelService, IRelation, IQuery, IVersion, IWith,
|
|
1
|
+
import { IModelService, IRelation, IQuery, IVersion, IWith, IContext, ICacheConfiguration } from "../Interfaces";
|
|
2
2
|
import { Knex } from "knex";
|
|
3
3
|
import { HandlerTypes, HookFunctionTypes, TimestampColumns } from "../Enums";
|
|
4
4
|
import { ModelListService } from "../Services";
|
|
5
5
|
import { SerializationFunction } from "../Types";
|
|
6
|
-
import AxeRequest from "
|
|
6
|
+
import AxeRequest from "../Services/AxeRequest";
|
|
7
7
|
export declare const bindTimestampValues: (formData: Record<string, any>, model: IModelService, columnTypes?: TimestampColumns[]) => void;
|
|
8
8
|
export declare const getMergedFormData: (req: AxeRequest, fillables: string[]) => Record<string, any>;
|
|
9
|
-
export declare const callHooks: (model: IModelService, type: HookFunctionTypes, params:
|
|
10
|
-
export declare const getParentColumn: (relation: IRelation | null) => string | null;
|
|
9
|
+
export declare const callHooks: (model: IModelService, type: HookFunctionTypes, params: IContext) => Promise<void>;
|
|
10
|
+
export declare const getParentColumn: (model: IModelService, relation: IRelation | null) => string | null;
|
|
11
11
|
export declare const checkPrimaryKeyValueType: (model: IModelService, value: any) => void;
|
|
12
12
|
export declare const addForeignKeyQuery: (request: AxeRequest, query: Knex.QueryBuilder, relation: IRelation | null, parentModel: IModelService | null) => void;
|
|
13
|
+
export declare const getParentIndexQuery: (request: AxeRequest, relation: IRelation | null, parentModel: IModelService | null) => any;
|
|
13
14
|
export declare const serializeData: (version: IVersion, itemArray: any, modelSerializer: SerializationFunction | null, handler: HandlerTypes, request: AxeRequest) => Promise<any[]>;
|
|
14
15
|
export declare const filterHiddenFields: (itemArray: any[], hiddens: string[] | null) => void;
|
|
15
16
|
export declare const addSoftDeleteQuery: (model: IModelService, conditions: IQuery | null, query: Knex.QueryBuilder) => void;
|
|
16
17
|
export declare const getRelatedData: (version: IVersion, data: any[], withArray: IWith[], model: IModelService, modelList: ModelListService, database: Knex | Knex.Transaction, handler: HandlerTypes, request: AxeRequest) => Promise<void>;
|
|
17
18
|
export declare const isBoolean: (value: any) => boolean;
|
|
19
|
+
export declare const getModelCacheConfiguration: (model: IModelService, apiConfig: ICacheConfiguration, versionConfig: ICacheConfiguration | null, handler: string) => ICacheConfiguration;
|
|
20
|
+
export declare const defaultCacheKeyFunction: (req: AxeRequest) => string;
|
|
21
|
+
export declare const toCacheTagKey: (model: IModelService, primaryKeyValue: string, config?: ICacheConfiguration | null) => string;
|
|
22
|
+
export declare const toCacheKey: (context: IContext) => string;
|
|
23
|
+
export declare const putCache: (context: IContext, data: any) => Promise<void>;
|
|
24
|
+
export declare const deleteCacheTagMembers: (key: string) => Promise<void>;
|
|
25
|
+
export declare const cleanRelatedCachedObjectByModel: (model: IModelService, config?: ICacheConfiguration | null) => Promise<void>;
|
|
26
|
+
export declare const clearCacheTags: (tag: string) => Promise<void>;
|
|
27
|
+
export declare const toCachePrefix: (value: string | undefined | null) => string;
|
|
28
|
+
export declare const getForeignKeyValueErrors: (context: IContext) => Promise<(string | null)[]>;
|
|
29
|
+
export declare const getSearchData: (model: IModelService, item: any) => Record<string, any>;
|
|
@@ -12,7 +12,8 @@ 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
|
-
exports.isBoolean = exports.getRelatedData = exports.addSoftDeleteQuery = exports.filterHiddenFields = exports.serializeData = exports.addForeignKeyQuery = exports.checkPrimaryKeyValueType = exports.getParentColumn = exports.callHooks = exports.getMergedFormData = exports.bindTimestampValues = void 0;
|
|
15
|
+
exports.getSearchData = exports.getForeignKeyValueErrors = exports.toCachePrefix = exports.clearCacheTags = exports.cleanRelatedCachedObjectByModel = exports.deleteCacheTagMembers = exports.putCache = exports.toCacheKey = exports.toCacheTagKey = exports.defaultCacheKeyFunction = exports.getModelCacheConfiguration = exports.isBoolean = exports.getRelatedData = exports.addSoftDeleteQuery = exports.filterHiddenFields = exports.serializeData = exports.getParentIndexQuery = exports.addForeignKeyQuery = exports.checkPrimaryKeyValueType = exports.getParentColumn = exports.callHooks = exports.getMergedFormData = exports.bindTimestampValues = void 0;
|
|
16
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
16
17
|
const change_case_1 = require("change-case");
|
|
17
18
|
const Enums_1 = require("../Enums");
|
|
18
19
|
const ApiError_1 = __importDefault(require("../Exceptions/ApiError"));
|
|
@@ -50,18 +51,18 @@ const callHooks = (model, type, params) => __awaiter(void 0, void 0, void 0, fun
|
|
|
50
51
|
// we don't await for the events. If the developer uses the transaction and
|
|
51
52
|
// try to commit something, it would be lost cause the transaction could be
|
|
52
53
|
// already completed.
|
|
53
|
-
const database =
|
|
54
|
+
const database = yield Services_1.IoCService.use("Database");
|
|
54
55
|
params.database = database;
|
|
55
56
|
// Calling the events
|
|
56
57
|
model.events[type](params);
|
|
57
58
|
}
|
|
58
59
|
});
|
|
59
60
|
exports.callHooks = callHooks;
|
|
60
|
-
const getParentColumn = (relation) => {
|
|
61
|
+
const getParentColumn = (model, relation) => {
|
|
61
62
|
if (!relation) {
|
|
62
63
|
return null;
|
|
63
64
|
}
|
|
64
|
-
return (0, change_case_1.camelCase)(relation.
|
|
65
|
+
return (0, change_case_1.camelCase)(`${model.name}-${relation.primaryKey}`);
|
|
65
66
|
};
|
|
66
67
|
exports.getParentColumn = getParentColumn;
|
|
67
68
|
const checkPrimaryKeyValueType = (model, value) => {
|
|
@@ -75,13 +76,24 @@ const checkPrimaryKeyValueType = (model, value) => {
|
|
|
75
76
|
exports.checkPrimaryKeyValueType = checkPrimaryKeyValueType;
|
|
76
77
|
const addForeignKeyQuery = (request, query, relation, parentModel) => {
|
|
77
78
|
if (relation && parentModel) {
|
|
78
|
-
const parentColumn = (0, exports.getParentColumn)(relation);
|
|
79
|
+
const parentColumn = (0, exports.getParentColumn)(parentModel, relation);
|
|
79
80
|
if (parentColumn) {
|
|
80
81
|
query.where(relation.foreignKey, request.params[parentColumn]);
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
85
|
exports.addForeignKeyQuery = addForeignKeyQuery;
|
|
86
|
+
const getParentIndexQuery = (request, relation, parentModel) => {
|
|
87
|
+
const result = {};
|
|
88
|
+
if (relation && parentModel) {
|
|
89
|
+
const parentColumn = (0, exports.getParentColumn)(parentModel, relation);
|
|
90
|
+
if (parentColumn) {
|
|
91
|
+
result[relation.foreignKey] = request.params[parentColumn];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
};
|
|
96
|
+
exports.getParentIndexQuery = getParentIndexQuery;
|
|
85
97
|
const getPrimaryOrForeignKeyByRelation = (relation, dataField) => {
|
|
86
98
|
if (dataField === "primaryKey") {
|
|
87
99
|
return relation.primaryKey;
|
|
@@ -221,6 +233,10 @@ const getRelatedData = (version, data, withArray, model, modelList, database, ha
|
|
|
221
233
|
}
|
|
222
234
|
// Fetching related records by foreignKey and primary key values.
|
|
223
235
|
let relatedRecords = yield foreignModelQuery.whereIn(searchFieldKey, parentPrimaryKeyValues);
|
|
236
|
+
// Adding related data source to the request tags to set cache tag values
|
|
237
|
+
const { primaryKey } = foreignModel.instance;
|
|
238
|
+
const cacheConfig = foreignModel.getCacheConfiguration(handler);
|
|
239
|
+
request.original.tags.push(...relatedRecords.map((i) => (0, exports.toCacheTagKey)(foreignModel, i[primaryKey], cacheConfig)));
|
|
224
240
|
// We should serialize related data if there is any serialization function
|
|
225
241
|
relatedRecords = yield (0, exports.serializeData)(version, relatedRecords, foreignModel.serialize, handler, request);
|
|
226
242
|
// We should hide hidden fields if there is any
|
|
@@ -251,3 +267,184 @@ const isBoolean = (value) => {
|
|
|
251
267
|
return false;
|
|
252
268
|
};
|
|
253
269
|
exports.isBoolean = isBoolean;
|
|
270
|
+
const getModelCacheConfiguration = (model, apiConfig, versionConfig, handler) => {
|
|
271
|
+
let base = Object.assign(Object.assign({}, constants_1.DEFAULT_CACHE_CONFIGURATION), apiConfig);
|
|
272
|
+
if (model.instance.cache) {
|
|
273
|
+
const data = model.instance.cache;
|
|
274
|
+
if (Array.isArray(data)) {
|
|
275
|
+
const handlerBasedConfigs = data;
|
|
276
|
+
for (const item of handlerBasedConfigs) {
|
|
277
|
+
const isFound = item.handlers.map((i) => i).includes(handler);
|
|
278
|
+
if (isFound) {
|
|
279
|
+
base = Object.assign(Object.assign({}, base), item.cache);
|
|
280
|
+
return base;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
base = Object.assign(Object.assign({}, base), data);
|
|
286
|
+
return base;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (versionConfig) {
|
|
290
|
+
base = Object.assign(Object.assign({}, base), versionConfig);
|
|
291
|
+
}
|
|
292
|
+
return base;
|
|
293
|
+
};
|
|
294
|
+
exports.getModelCacheConfiguration = getModelCacheConfiguration;
|
|
295
|
+
const defaultCacheKeyFunction = (req) => {
|
|
296
|
+
return JSON.stringify({
|
|
297
|
+
url: req.url,
|
|
298
|
+
method: req.method,
|
|
299
|
+
headers: {
|
|
300
|
+
Accept: req.header("Accept"),
|
|
301
|
+
"Accept-Encoding": req.header("Accept-Encoding"),
|
|
302
|
+
"Accept-Language": req.header("Accept-Language"),
|
|
303
|
+
Authorization: req.header("Authorization"),
|
|
304
|
+
Host: req.header("Host"),
|
|
305
|
+
Origin: req.header("Origin"),
|
|
306
|
+
Referer: req.header("Referer"),
|
|
307
|
+
"User-Agent": req.header("User-Agent"),
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
exports.defaultCacheKeyFunction = defaultCacheKeyFunction;
|
|
312
|
+
const toCacheTagKey = (model, primaryKeyValue, config) => {
|
|
313
|
+
const prefix = (0, exports.toCachePrefix)(config === null || config === void 0 ? void 0 : config.cachePrefix);
|
|
314
|
+
const tagPrefix = (config === null || config === void 0 ? void 0 : config.tagPrefix) ? config === null || config === void 0 ? void 0 : config.tagPrefix : "";
|
|
315
|
+
const modelName = model.name.toLowerCase();
|
|
316
|
+
return `${prefix}:${tagPrefix}:${modelName}:${primaryKeyValue}`;
|
|
317
|
+
};
|
|
318
|
+
exports.toCacheTagKey = toCacheTagKey;
|
|
319
|
+
const toCacheKey = (context) => {
|
|
320
|
+
const { model, handlerType } = context;
|
|
321
|
+
const config = model.getCacheConfiguration(handlerType);
|
|
322
|
+
const keyData = (config === null || config === void 0 ? void 0 : config.cacheKey)
|
|
323
|
+
? config.cacheKey(context.req)
|
|
324
|
+
: (0, exports.defaultCacheKeyFunction)(context.req);
|
|
325
|
+
const key = crypto_1.default.createHash("sha256").update(keyData).digest("hex");
|
|
326
|
+
const prefix = (0, exports.toCachePrefix)(config === null || config === void 0 ? void 0 : config.cachePrefix);
|
|
327
|
+
const modelName = model.name.toLowerCase();
|
|
328
|
+
return `${prefix}:${modelName}:${key}`;
|
|
329
|
+
};
|
|
330
|
+
exports.toCacheKey = toCacheKey;
|
|
331
|
+
const putCache = (context, data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
332
|
+
// Getting the correct configuration
|
|
333
|
+
const { model, handlerType } = context;
|
|
334
|
+
const config = model.getCacheConfiguration(handlerType);
|
|
335
|
+
// Check if the cache enable for this handler
|
|
336
|
+
if (!(config === null || config === void 0 ? void 0 : config.enable)) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
// Getting the redis service
|
|
340
|
+
const redis = yield Services_1.IoCService.use("Redis");
|
|
341
|
+
// Generating the cache key
|
|
342
|
+
const key = (0, exports.toCacheKey)(context);
|
|
343
|
+
// Setting the tags if the cache configuration of the model has been set as
|
|
344
|
+
// tag-based cache invalidation strategy. Which means, the key cached value
|
|
345
|
+
// can be deleted if the tagged items updated/delete
|
|
346
|
+
if (config.invalidation === Enums_1.CacheStrategies.TagBased) {
|
|
347
|
+
redis.tags(context.req.original.tags, key);
|
|
348
|
+
}
|
|
349
|
+
// Putting the cache data
|
|
350
|
+
redis.set(key, JSON.stringify(data), config.ttl || 1000);
|
|
351
|
+
if (config.responseHeader) {
|
|
352
|
+
context.res.header(config.responseHeader, "Missed");
|
|
353
|
+
}
|
|
354
|
+
// Logging
|
|
355
|
+
Services_1.LogService.debug(`\t🔄 redis.cache(${key},${config.ttl})`);
|
|
356
|
+
});
|
|
357
|
+
exports.putCache = putCache;
|
|
358
|
+
const deleteCacheTagMembers = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
359
|
+
const redis = yield Services_1.IoCService.use("Redis");
|
|
360
|
+
const members = yield redis.getTagMemebers(key);
|
|
361
|
+
yield redis.delete(members);
|
|
362
|
+
});
|
|
363
|
+
exports.deleteCacheTagMembers = deleteCacheTagMembers;
|
|
364
|
+
const cleanRelatedCachedObjectByModel = (model, config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
365
|
+
const redis = yield Services_1.IoCService.use("Redis");
|
|
366
|
+
const prefix = (0, exports.toCachePrefix)(config === null || config === void 0 ? void 0 : config.cachePrefix);
|
|
367
|
+
const tagPrefix = (config === null || config === void 0 ? void 0 : config.tagPrefix) ? config === null || config === void 0 ? void 0 : config.tagPrefix : "";
|
|
368
|
+
const modelName = model.name.toLowerCase();
|
|
369
|
+
const searchKey = `${prefix}:${tagPrefix}:${modelName}:*`;
|
|
370
|
+
// Logging
|
|
371
|
+
Services_1.LogService.debug(`\t🔄 redis.cleaByTag(${searchKey})`);
|
|
372
|
+
const { keys } = yield redis.searchTags(searchKey);
|
|
373
|
+
const tasks = keys.map((key) => (0, exports.deleteCacheTagMembers)(key));
|
|
374
|
+
Promise.all(tasks);
|
|
375
|
+
});
|
|
376
|
+
exports.cleanRelatedCachedObjectByModel = cleanRelatedCachedObjectByModel;
|
|
377
|
+
const clearCacheTags = (tag) => __awaiter(void 0, void 0, void 0, function* () {
|
|
378
|
+
const redis = yield Services_1.IoCService.use("Redis");
|
|
379
|
+
const members = yield redis.getTagMemebers(tag);
|
|
380
|
+
if (members.length > 0) {
|
|
381
|
+
yield redis.delete(members);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
exports.clearCacheTags = clearCacheTags;
|
|
385
|
+
const toCachePrefix = (value) => {
|
|
386
|
+
return value ? value : "";
|
|
387
|
+
};
|
|
388
|
+
exports.toCachePrefix = toCachePrefix;
|
|
389
|
+
const validateForeignValues = (database, version, relation, value) => __awaiter(void 0, void 0, void 0, function* () {
|
|
390
|
+
if (!value) {
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
const foreignModel = version.modelList
|
|
394
|
+
.get()
|
|
395
|
+
.find((model) => model.name === relation.model);
|
|
396
|
+
if (!foreignModel) {
|
|
397
|
+
throw new Error(`The model not found: ${relation.model}`);
|
|
398
|
+
}
|
|
399
|
+
const found = yield database(foreignModel.instance.table)
|
|
400
|
+
.where(foreignModel.instance.primaryKey, value)
|
|
401
|
+
.first();
|
|
402
|
+
return !!found;
|
|
403
|
+
});
|
|
404
|
+
const getForeignKeyValueErrors = (context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
405
|
+
const { model, database, version } = context;
|
|
406
|
+
// Getting all foreign rules.
|
|
407
|
+
const foreignRelations = model.relations.filter((relation) => relation.type === Enums_1.Relationships.HAS_ONE);
|
|
408
|
+
const tasks = [];
|
|
409
|
+
for (const relation of foreignRelations) {
|
|
410
|
+
const value = context.formData[relation.foreignKey];
|
|
411
|
+
tasks.push({
|
|
412
|
+
data: {
|
|
413
|
+
value,
|
|
414
|
+
relation,
|
|
415
|
+
},
|
|
416
|
+
promise: validateForeignValues(database, version, relation, value),
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
const results = yield Promise.all(tasks.map((promise) => promise.promise));
|
|
420
|
+
return results
|
|
421
|
+
.map((result, index) => {
|
|
422
|
+
if (result) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
const data = tasks[index].data;
|
|
426
|
+
return `Invalid value: ${data.relation.foreignKey} = ${data.value}`;
|
|
427
|
+
})
|
|
428
|
+
.filter((error) => error);
|
|
429
|
+
});
|
|
430
|
+
exports.getForeignKeyValueErrors = getForeignKeyValueErrors;
|
|
431
|
+
const getSearchData = (model, item) => {
|
|
432
|
+
const result = {};
|
|
433
|
+
if (model.instance.search) {
|
|
434
|
+
for (const field of model.instance.search) {
|
|
435
|
+
result[field] = item[field];
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// If there is a deleted at column, we should put it to the index data
|
|
439
|
+
if (model.instance.deletedAtColumn) {
|
|
440
|
+
result[model.instance.deletedAtColumn] =
|
|
441
|
+
item[model.instance.deletedAtColumn];
|
|
442
|
+
}
|
|
443
|
+
// We should add the parent relations if there is any
|
|
444
|
+
const relations = model.relations.filter((relation) => relation.type === Enums_1.Relationships.HAS_ONE);
|
|
445
|
+
for (const relation of relations) {
|
|
446
|
+
result[relation.foreignKey] = item[relation.foreignKey];
|
|
447
|
+
}
|
|
448
|
+
return result;
|
|
449
|
+
};
|
|
450
|
+
exports.getSearchData = getSearchData;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="express" />
|
|
1
3
|
import { IncomingMessage, ServerResponse } from "http";
|
|
2
|
-
|
|
4
|
+
import { NextFunction } from "connect";
|
|
5
|
+
declare const _default: (request: IncomingMessage, response: ServerResponse, next: NextFunction) => Promise<void>;
|
|
3
6
|
export default _default;
|
|
@@ -15,30 +15,49 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const Services_1 = require("../Services");
|
|
16
16
|
const URLService_1 = __importDefault(require("../Services/URLService"));
|
|
17
17
|
const ConverterService_1 = require("../Services/ConverterService");
|
|
18
|
-
const api = Services_1.APIService.getInstance();
|
|
19
18
|
const return404 = (response) => {
|
|
20
19
|
response.statusCode = 404;
|
|
21
20
|
response.write(JSON.stringify({ error: "Resource not found" }));
|
|
22
21
|
response.end();
|
|
23
22
|
};
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
exports.default = (request, response, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
|
+
const api = Services_1.APIService.getInstance();
|
|
25
|
+
Services_1.LogService.debug(`📥 ${request.method} ${request.url}`);
|
|
26
|
+
const { axeRequest, axeResponse } = (0, ConverterService_1.toAxeRequestResponsePair)(request, response);
|
|
27
|
+
const match = URLService_1.default.match(axeRequest);
|
|
28
|
+
if (!match) {
|
|
29
|
+
Services_1.LogService.warn(`The URL is not matched! ${request.method} ${request.url}`);
|
|
30
|
+
return return404(response);
|
|
31
|
+
}
|
|
32
|
+
// We should set the params
|
|
33
|
+
axeRequest.params = match.params;
|
|
34
|
+
const database = yield Services_1.IoCService.use("Database");
|
|
35
|
+
// Prepare the database by the transaction option
|
|
36
|
+
let trx = null;
|
|
37
|
+
if (match.hasTransaction) {
|
|
38
|
+
Services_1.LogService.info("\t🛢 DBTransaction:created()");
|
|
39
|
+
trx = yield database.transaction();
|
|
40
|
+
}
|
|
41
|
+
const context = Object.assign(Object.assign({}, match.data), { params: match.params, api, req: axeRequest, res: axeResponse, isTransactionOpen: match.hasTransaction, database: match.hasTransaction && trx ? trx : database });
|
|
42
|
+
response.setHeader("Content-Type", "application/json");
|
|
43
|
+
response.setHeader("x-powered-by", "Axe API");
|
|
44
|
+
for (const phase of match.phases) {
|
|
26
45
|
// If there is an non-async phase, it should be an Event function
|
|
27
46
|
if (phase.isAsync === false) {
|
|
28
|
-
Services_1.LogService.debug(`\t${phase.name}()`);
|
|
29
|
-
|
|
47
|
+
Services_1.LogService.debug(`\t🔄 ${phase.name}()`);
|
|
48
|
+
phase.callback(context);
|
|
30
49
|
continue;
|
|
31
50
|
}
|
|
32
51
|
// Middleware and hook calls
|
|
33
52
|
try {
|
|
34
|
-
Services_1.LogService.debug(`\t${phase.name}()`);
|
|
35
|
-
yield phase.callback(
|
|
53
|
+
Services_1.LogService.debug(`\t🔄 ${phase.name}()`);
|
|
54
|
+
yield phase.callback(context);
|
|
36
55
|
}
|
|
37
56
|
catch (error) {
|
|
38
|
-
Services_1.LogService.error(
|
|
57
|
+
Services_1.LogService.error(error);
|
|
39
58
|
// Rollback transaction
|
|
40
59
|
if (match.hasTransaction && trx) {
|
|
41
|
-
Services_1.LogService.
|
|
60
|
+
Services_1.LogService.info("\t🛢 DBTransaction:rollback()");
|
|
42
61
|
trx.rollback();
|
|
43
62
|
}
|
|
44
63
|
if (error.type === "ApiError") {
|
|
@@ -47,53 +66,30 @@ const callPhases = (phases, pack, match, trx, axeResponse) => __awaiter(void 0,
|
|
|
47
66
|
.status(apiError.status)
|
|
48
67
|
.json({ error: apiError.message });
|
|
49
68
|
}
|
|
50
|
-
|
|
51
|
-
axeResponse.status(500).json({ error: error.toString() });
|
|
69
|
+
next(error);
|
|
52
70
|
break;
|
|
53
71
|
}
|
|
54
72
|
// If the response is not created, we should go to the next phase
|
|
55
|
-
if (
|
|
73
|
+
if (context.res.isResponded() === false) {
|
|
56
74
|
continue;
|
|
57
75
|
}
|
|
58
76
|
// If the response is an error, and we have an active transaction,
|
|
59
77
|
// we should rollback it before the HTTP request end.
|
|
60
|
-
if (
|
|
78
|
+
if (context.res.statusCode() >= 400 && context.res.statusCode() < 599) {
|
|
61
79
|
if (match.hasTransaction && trx) {
|
|
62
|
-
Services_1.LogService.
|
|
80
|
+
Services_1.LogService.info("\t🛢 DBTransaction:rollback()");
|
|
63
81
|
trx.rollback();
|
|
64
82
|
}
|
|
65
|
-
Services_1.LogService.debug(`\tResponse ${
|
|
83
|
+
Services_1.LogService.debug(`\tResponse ${context.res.statusCode()}`);
|
|
66
84
|
break;
|
|
67
85
|
}
|
|
68
|
-
//
|
|
86
|
+
// We should commit the transaction if there is any
|
|
69
87
|
if (match.hasTransaction && trx) {
|
|
70
|
-
Services_1.LogService.
|
|
88
|
+
Services_1.LogService.info("\t🛢 DBTransaction:commit()");
|
|
71
89
|
trx.commit();
|
|
72
90
|
}
|
|
73
|
-
Services_1.LogService.debug(`\
|
|
91
|
+
Services_1.LogService.debug(`\t🟢 Response ${context.res.statusCode()}`);
|
|
74
92
|
// We should brake the for-loop
|
|
75
93
|
break;
|
|
76
94
|
}
|
|
77
95
|
});
|
|
78
|
-
exports.default = (request, response) => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
|
-
Services_1.LogService.debug(`${request.method} ${request.url}`);
|
|
80
|
-
const { axeRequest, axeResponse } = (0, ConverterService_1.toAxeRequestResponsePair)(request, response);
|
|
81
|
-
const match = URLService_1.default.match(axeRequest);
|
|
82
|
-
if (!match) {
|
|
83
|
-
Services_1.LogService.warn(`The URL is not matched! ${request.method} ${request.url}`);
|
|
84
|
-
return return404(response);
|
|
85
|
-
}
|
|
86
|
-
// We should set the params
|
|
87
|
-
axeRequest.params = match.params;
|
|
88
|
-
const database = (yield Services_1.IoCService.use("Database"));
|
|
89
|
-
// Prepare the database by the transaction option
|
|
90
|
-
let trx = null;
|
|
91
|
-
if (match.hasTransaction) {
|
|
92
|
-
Services_1.LogService.warn("\tDB transaction created");
|
|
93
|
-
trx = yield database.transaction();
|
|
94
|
-
}
|
|
95
|
-
const pack = Object.assign(Object.assign({}, match.data), { params: match.params, api, req: axeRequest, res: axeResponse, database: match.hasTransaction && trx ? trx : database });
|
|
96
|
-
response.setHeader("Content-Type", "application/json");
|
|
97
|
-
response.setHeader("x-powered-by", "Axe API");
|
|
98
|
-
yield callPhases(match.phases, pack, match, trx, axeResponse);
|
|
99
|
-
});
|
|
@@ -8,17 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const
|
|
15
|
+
const SwaggerBuilder_1 = __importDefault(require("../Builders/SwaggerBuilder"));
|
|
16
|
+
const Services_1 = require("../Services");
|
|
13
17
|
exports.default = (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
14
18
|
try {
|
|
15
|
-
|
|
16
|
-
const content = (yield result.text())
|
|
17
|
-
.replaceAll(`src="`, `src="${CLOUD_FRONT_DOMAIN}`)
|
|
18
|
-
.replaceAll(`href="`, `href="${CLOUD_FRONT_DOMAIN}`);
|
|
19
|
-
res.send(content);
|
|
19
|
+
res.json(yield (0, SwaggerBuilder_1.default)());
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
|
-
|
|
22
|
+
Services_1.LogService.error(error);
|
|
23
|
+
res.status(500).json({ error: error.message });
|
|
23
24
|
}
|
|
24
25
|
});
|