@avleon/core 0.0.4 → 0.0.6
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/README.md +3 -0
- package/dist/authentication.d.ts +7 -0
- package/dist/authentication.js +11 -0
- package/dist/collection.d.ts +52 -0
- package/dist/collection.js +282 -0
- package/dist/config.d.ts +7 -8
- package/dist/config.js +10 -8
- package/dist/container.d.ts +5 -5
- package/dist/container.js +10 -13
- package/dist/controller.d.ts +2 -1
- package/dist/controller.js +17 -3
- package/dist/decorators.d.ts +2 -1
- package/dist/decorators.js +12 -2
- package/dist/environment-variables.d.ts +3 -0
- package/dist/environment-variables.js +33 -0
- package/dist/exceptions/http-exceptions.d.ts +24 -1
- package/dist/exceptions/http-exceptions.js +33 -2
- package/dist/helpers.d.ts +9 -1
- package/dist/helpers.js +78 -27
- package/dist/icore.d.ts +70 -16
- package/dist/icore.js +408 -135
- package/dist/index.d.ts +11 -6
- package/dist/index.js +7 -1
- package/dist/map-types.js +1 -2
- package/dist/middleware.d.ts +24 -0
- package/dist/middleware.js +59 -0
- package/dist/params.d.ts +1 -0
- package/dist/params.js +13 -9
- package/dist/queue.d.ts +30 -0
- package/dist/queue.js +96 -0
- package/dist/render.d.ts +1 -0
- package/dist/render.js +8 -0
- package/dist/response.d.ts +3 -2
- package/dist/response.js +9 -15
- package/dist/types/app-builder.interface.d.ts +9 -0
- package/dist/types/app-builder.interface.js +2 -0
- package/dist/types/application.interface.d.ts +2 -0
- package/dist/types/application.interface.js +2 -0
- package/dist/validation.d.ts +23 -0
- package/dist/validation.js +98 -0
- package/dist/validator-extend.js +2 -2
- package/package.json +45 -39
- package/dist/repository.d.ts +0 -0
- package/dist/repository.js +0 -1
package/dist/icore.js
CHANGED
|
@@ -32,208 +32,481 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
36
|
+
var t = {};
|
|
37
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
38
|
+
t[p] = s[p];
|
|
39
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
40
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
41
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
42
|
+
t[p[i]] = s[p[i]];
|
|
43
|
+
}
|
|
44
|
+
return t;
|
|
45
|
+
};
|
|
46
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
47
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
48
|
+
var m = o[Symbol.asyncIterator], i;
|
|
49
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
50
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
51
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
52
|
+
};
|
|
35
53
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
54
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
55
|
};
|
|
38
56
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
57
|
+
exports.Builder = void 0;
|
|
40
58
|
const fastify_1 = __importDefault(require("fastify"));
|
|
41
59
|
const typedi_1 = __importDefault(require("typedi"));
|
|
42
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
60
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
43
61
|
const path_1 = __importDefault(require("path"));
|
|
44
62
|
const container_1 = __importStar(require("./container"));
|
|
45
63
|
const helpers_1 = require("./helpers");
|
|
46
64
|
const system_exception_1 = require("./exceptions/system-exception");
|
|
47
|
-
const
|
|
65
|
+
const fs_1 = require("fs");
|
|
66
|
+
const exceptions_1 = require("./exceptions");
|
|
67
|
+
const swagger_1 = __importDefault(require("@fastify/swagger"));
|
|
68
|
+
const fastify_api_reference_1 = __importDefault(require("@scalar/fastify-api-reference"));
|
|
69
|
+
const environment_variables_1 = require("./environment-variables");
|
|
70
|
+
const isTsNode = process.env.TS_NODE_DEV ||
|
|
71
|
+
process.env.TS_NODE_PROJECT ||
|
|
72
|
+
process[Symbol.for("ts-node.register.instance")];
|
|
48
73
|
const controllerDir = path_1.default.join(process.cwd(), isTsNode ? "./src/controllers" : "./dist/cotrollers");
|
|
49
|
-
|
|
74
|
+
// InternalApplication
|
|
75
|
+
class AvleonApplication {
|
|
50
76
|
constructor() {
|
|
51
77
|
this.routeSet = new Set(); // Use Set for fast duplicate detection
|
|
52
78
|
this.alreadyRun = false;
|
|
53
79
|
this.routes = new Map();
|
|
80
|
+
this.middlewares = new Map();
|
|
81
|
+
this.rMap = new Map();
|
|
82
|
+
this.hasSwagger = false;
|
|
83
|
+
this.globalSwaggerOptions = {};
|
|
84
|
+
this.controllers = [];
|
|
85
|
+
this.authorizeMiddleware = undefined;
|
|
86
|
+
this.metaCache = new Map();
|
|
54
87
|
this.app = (0, fastify_1.default)();
|
|
88
|
+
// this.app.setValidatorCompiler(() => () => true);
|
|
55
89
|
}
|
|
56
90
|
static getInternalApp(buildOptions) {
|
|
57
|
-
if (!
|
|
58
|
-
|
|
91
|
+
if (!AvleonApplication.instance) {
|
|
92
|
+
AvleonApplication.instance = new AvleonApplication();
|
|
93
|
+
}
|
|
94
|
+
AvleonApplication.buildOptions = buildOptions;
|
|
95
|
+
if (buildOptions.controllers) {
|
|
96
|
+
}
|
|
97
|
+
return AvleonApplication.instance;
|
|
98
|
+
}
|
|
99
|
+
isDevelopment() {
|
|
100
|
+
return environment_variables_1.env["NODE_ENV"] == "development";
|
|
101
|
+
}
|
|
102
|
+
async initSwagger(options) {
|
|
103
|
+
const { routePrefix } = options, restOptions = __rest(options, ["routePrefix"]);
|
|
104
|
+
this.app.register(swagger_1.default, {
|
|
105
|
+
openapi: Object.assign({ openapi: "3.0.0" }, restOptions),
|
|
106
|
+
});
|
|
107
|
+
const rPrefix = routePrefix ? routePrefix : "/docs";
|
|
108
|
+
//import fastifyApiReference from "@scalar/fastify-api-reference";
|
|
109
|
+
await this.app.register(fastify_api_reference_1.default, {
|
|
110
|
+
routePrefix: rPrefix,
|
|
111
|
+
configuration: {
|
|
112
|
+
metaData: {
|
|
113
|
+
title: "Avleon Api",
|
|
114
|
+
ogTitle: "Avleon",
|
|
115
|
+
},
|
|
116
|
+
theme: "kepler",
|
|
117
|
+
favicon: "/static/favicon.png",
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async useSwagger(options) {
|
|
122
|
+
this.hasSwagger = true;
|
|
123
|
+
this.globalSwaggerOptions = options;
|
|
124
|
+
}
|
|
125
|
+
handleMiddlewares(mclasses) {
|
|
126
|
+
for (const mclass of mclasses) {
|
|
127
|
+
const cls = typedi_1.default.get(mclass.constructor);
|
|
128
|
+
this.middlewares.set(mclass.name, cls);
|
|
129
|
+
this.app.addHook("preHandler", cls.invoke);
|
|
59
130
|
}
|
|
60
|
-
|
|
61
|
-
|
|
131
|
+
}
|
|
132
|
+
executeMiddlewares(target, propertyKey) {
|
|
133
|
+
const classMiddlewares = Reflect.getMetadata("controller:middleware", target.constructor) || [];
|
|
134
|
+
const methodMiddlewares = propertyKey
|
|
135
|
+
? Reflect.getMetadata("route:middleware", target, propertyKey) || []
|
|
136
|
+
: [];
|
|
137
|
+
return [...classMiddlewares, ...methodMiddlewares];
|
|
62
138
|
}
|
|
63
139
|
async buildController(controller) {
|
|
140
|
+
var _a, e_1, _b, _c;
|
|
64
141
|
const ctrl = typedi_1.default.get(controller);
|
|
65
142
|
const controllerMeta = Reflect.getMetadata(container_1.CONTROLLER_META_KEY, ctrl.constructor);
|
|
66
143
|
if (!controllerMeta)
|
|
67
144
|
return;
|
|
68
145
|
const prototype = Object.getPrototypeOf(ctrl);
|
|
69
146
|
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
147
|
+
let classMiddlewares = [];
|
|
148
|
+
const tag = ctrl.constructor.name.replace("Controller", "");
|
|
149
|
+
const swaggerControllerMeta = Reflect.getMetadata("controller:openapi", ctrl.constructor) || {};
|
|
150
|
+
const authClsMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor) || { authorize: false, options: undefined };
|
|
151
|
+
if (authClsMeata.authorize && this.authorizeMiddleware) {
|
|
152
|
+
this.app.addHook("preHandler", (req, res) => {
|
|
153
|
+
return this.authorizeMiddleware.authorize(req);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
console.log("ClassMiddlware:", tag + ":", authClsMeata);
|
|
157
|
+
try {
|
|
158
|
+
for (var _d = true, methods_1 = __asyncValues(methods), methods_1_1; methods_1_1 = await methods_1.next(), _a = methods_1_1.done, !_a; _d = true) {
|
|
159
|
+
_c = methods_1_1.value;
|
|
160
|
+
_d = false;
|
|
161
|
+
const method = _c;
|
|
162
|
+
const methodMeta = Reflect.getMetadata(container_1.ROUTE_META_KEY, prototype, method);
|
|
163
|
+
if (!methodMeta)
|
|
164
|
+
continue;
|
|
165
|
+
const methodmetaOptions = {
|
|
166
|
+
method: methodMeta.method.toLowerCase(),
|
|
167
|
+
path: (0, helpers_1.formatUrl)(controllerMeta.path + methodMeta.path),
|
|
168
|
+
};
|
|
169
|
+
const routeKey = `${methodmetaOptions.method}:${methodmetaOptions.path}`;
|
|
170
|
+
if (!this.routeSet.has(routeKey)) {
|
|
171
|
+
this.routeSet.add(routeKey);
|
|
172
|
+
}
|
|
173
|
+
const classMiddlewares = this.executeMiddlewares(ctrl, method);
|
|
174
|
+
// handle openapi data
|
|
175
|
+
const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
|
|
176
|
+
const authClsMethodMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor, method) || { authorize: false, options: undefined };
|
|
177
|
+
console.log(tag, ":", method, authClsMethodMeata);
|
|
178
|
+
// if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
|
|
179
|
+
// this.app.addHook('preHandler', async (req, res) => {
|
|
180
|
+
// if (res.sent) return;
|
|
181
|
+
// console.log(this.authorizeMiddleware)
|
|
182
|
+
// const cls = container.get(this.authorizeMiddleware) as any;
|
|
183
|
+
// console.log(cls)
|
|
184
|
+
// cls.authorize(req);
|
|
185
|
+
// })
|
|
186
|
+
// }
|
|
187
|
+
const allMeta = this._processMeta(prototype, method);
|
|
188
|
+
const routePath = methodmetaOptions.path == "" ? "/" : methodmetaOptions.path;
|
|
189
|
+
this.app.route({
|
|
190
|
+
url: routePath,
|
|
191
|
+
method: methodmetaOptions.method.toUpperCase(),
|
|
192
|
+
schema: Object.assign(Object.assign(Object.assign({}, swaggerControllerMeta), swaggerMeta), { tags: [tag] }),
|
|
193
|
+
handler: async (req, res) => {
|
|
194
|
+
let reqClone = req;
|
|
195
|
+
if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
|
|
196
|
+
const cls = container_1.default.get(this.authorizeMiddleware);
|
|
197
|
+
await cls.authorize(reqClone, authClsMethodMeata.options);
|
|
198
|
+
if (res.sent)
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (classMiddlewares.length > 0) {
|
|
202
|
+
for (let m of classMiddlewares) {
|
|
203
|
+
const cls = typedi_1.default.get(m.constructor);
|
|
204
|
+
reqClone = (await cls.invoke(reqClone, res));
|
|
205
|
+
if (res.sent)
|
|
206
|
+
return;
|
|
97
207
|
}
|
|
98
208
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
209
|
+
const args = await this._mapArgs(reqClone, allMeta);
|
|
210
|
+
for (let bodyMeta of allMeta.body) {
|
|
211
|
+
if (bodyMeta.validatorClass) {
|
|
212
|
+
const err = await (0, helpers_1.validateObjectByInstance)(bodyMeta.dataType, args[bodyMeta.index]);
|
|
213
|
+
if (err) {
|
|
214
|
+
return await res.code(400).send({
|
|
215
|
+
code: 400,
|
|
216
|
+
error: "ValidationError",
|
|
217
|
+
errors: err,
|
|
218
|
+
message: err.message,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const result = await prototype[method].apply(ctrl, args);
|
|
224
|
+
return result;
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
230
|
+
finally {
|
|
231
|
+
try {
|
|
232
|
+
if (!_d && !_a && (_b = methods_1.return)) await _b.call(methods_1);
|
|
233
|
+
}
|
|
234
|
+
finally { if (e_1) throw e_1.error; }
|
|
117
235
|
}
|
|
118
236
|
}
|
|
119
237
|
async _mapArgs(req, meta) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
args[param.index] = value;
|
|
238
|
+
if (!req.hasOwnProperty("_argsCache")) {
|
|
239
|
+
Object.defineProperty(req, "_argsCache", {
|
|
240
|
+
value: new Map(),
|
|
241
|
+
enumerable: false,
|
|
125
242
|
});
|
|
126
243
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
244
|
+
const cache = req._argsCache;
|
|
245
|
+
const cacheKey = JSON.stringify(meta); // Faster key-based lookup
|
|
246
|
+
if (cache.has(cacheKey)) {
|
|
247
|
+
return cache.get(cacheKey);
|
|
132
248
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
249
|
+
const args = meta.params.map((p) => req.params[p.key] || null);
|
|
250
|
+
meta.query.forEach((q) => (args[q.index] = q.key === "all" ? req.query : req.query[q.key]));
|
|
251
|
+
meta.body.forEach((body) => (args[body.index] = req.body));
|
|
252
|
+
meta.currentUser.forEach((user) => (args[user.index] = req.user));
|
|
253
|
+
meta.headers.forEach((header) => (args[header.index] =
|
|
254
|
+
header.key === "all" ? req.headers : req.headers[header.key]));
|
|
255
|
+
cache.set(cacheKey, args);
|
|
256
|
+
return args;
|
|
257
|
+
}
|
|
258
|
+
_processMeta(prototype, method) {
|
|
259
|
+
const cacheKey = `${prototype.constructor.name}_${method}`;
|
|
260
|
+
if (this.metaCache.has(cacheKey)) {
|
|
261
|
+
return this.metaCache.get(cacheKey);
|
|
137
262
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
263
|
+
const meta = {
|
|
264
|
+
params: Reflect.getMetadata(container_1.PARAM_META_KEY, prototype, method) || [],
|
|
265
|
+
query: Reflect.getMetadata(container_1.QUERY_META_KEY, prototype, method) || [],
|
|
266
|
+
body: Reflect.getMetadata(container_1.REQUEST_BODY_META_KEY, prototype, method) || [],
|
|
267
|
+
headers: Reflect.getMetadata(container_1.REQUEST_HEADER_META_KEY, prototype, method) || [],
|
|
268
|
+
currentUser: Reflect.getMetadata(container_1.REQUEST_USER_META_KEY, prototype, method) || [],
|
|
269
|
+
// swagger: Reflect.getMetadata("route:openapi", prototype, method) || {}
|
|
270
|
+
};
|
|
271
|
+
this.metaCache.set(cacheKey, meta);
|
|
272
|
+
return meta;
|
|
273
|
+
}
|
|
274
|
+
async autoControllers() {
|
|
275
|
+
const controllers = [];
|
|
276
|
+
const files = await promises_1.default.readdir(controllerDir);
|
|
277
|
+
for (const file of files) {
|
|
278
|
+
if (isTsNode ? file.endsWith(".ts") : file.endsWith(".js")) {
|
|
279
|
+
const filePath = path_1.default.join(controllerDir, file);
|
|
280
|
+
const module = await Promise.resolve(`${filePath}`).then(s => __importStar(require(s)));
|
|
281
|
+
for (const exported of Object.values(module)) {
|
|
282
|
+
if (typeof exported === "function" && (0, container_1.isApiController)(exported)) {
|
|
283
|
+
//controllers.push(exported);
|
|
284
|
+
this.buildController(exported);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
143
288
|
}
|
|
144
|
-
return args;
|
|
145
289
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const queryMetaList = Reflect.getMetadata(container_1.QUERY_META_KEY, prototype, method) || [];
|
|
149
|
-
const bodyMetaList = Reflect.getMetadata(container_1.REQUEST_BODY_META_KEY, prototype, method) || [];
|
|
150
|
-
const headerMetaList = Reflect.getMetadata(container_1.REQUEST_HEADER_META_KEY, prototype, method) || [];
|
|
151
|
-
return { params: paramsMetaList, query: queryMetaList, body: bodyMetaList, headers: headerMetaList };
|
|
290
|
+
mapControllers(controllers) {
|
|
291
|
+
this.controllers = controllers;
|
|
152
292
|
}
|
|
153
|
-
async
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
293
|
+
async _mapControllers() {
|
|
294
|
+
if (this.controllers.length > 0) {
|
|
295
|
+
for (let controller of this.controllers) {
|
|
296
|
+
if ((0, container_1.isApiController)(controller)) {
|
|
297
|
+
this.buildController(controller);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
157
301
|
}
|
|
158
|
-
|
|
302
|
+
mapControllersAuto() {
|
|
303
|
+
const isExists = (0, fs_1.existsSync)(controllerDir);
|
|
304
|
+
if (isExists) {
|
|
305
|
+
this.autoControllers();
|
|
306
|
+
}
|
|
159
307
|
}
|
|
160
308
|
async handleRoute(args) {
|
|
161
309
|
console.log(args);
|
|
162
310
|
}
|
|
163
|
-
async
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
311
|
+
async mapFn(fn) {
|
|
312
|
+
const original = fn;
|
|
313
|
+
fn = function () {
|
|
314
|
+
console.log(arguments);
|
|
315
|
+
};
|
|
316
|
+
return fn;
|
|
317
|
+
}
|
|
318
|
+
useMiddlewares(mclasses) {
|
|
319
|
+
for (const mclass of mclasses) {
|
|
320
|
+
const cls = typedi_1.default.get(mclass);
|
|
321
|
+
this.middlewares.set(mclass.name, cls);
|
|
322
|
+
this.app.addHook("preHandler", cls.invoke);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
useAuthoriztion(middleware) {
|
|
326
|
+
this.authorizeMiddleware = middleware;
|
|
327
|
+
}
|
|
328
|
+
_handleError(error) {
|
|
329
|
+
if (error instanceof exceptions_1.BaseHttpException) {
|
|
330
|
+
return {
|
|
331
|
+
code: error.code,
|
|
332
|
+
error: error.name,
|
|
333
|
+
message: (0, helpers_1.isValidJsonString)(error.message)
|
|
334
|
+
? JSON.parse(error.message)
|
|
335
|
+
: error.message,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
code: 500,
|
|
340
|
+
error: "INTERNALERROR",
|
|
341
|
+
message: error.message ? error.message : "Something going wrong.",
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
async mapRoute(method, path = "", fn) {
|
|
345
|
+
await this.mapFn(fn); // Assuming mapFn is needed for all methods
|
|
346
|
+
this.app[method](path, async (req, res) => {
|
|
347
|
+
// Dynamic method call
|
|
348
|
+
try {
|
|
349
|
+
const result = await fn.apply(this, [req, res]);
|
|
350
|
+
if (typeof result === "object" && result !== null) {
|
|
351
|
+
res.json(result); // Use res.json for objects
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
res.send(result); // Fallback for other types
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
console.error(`Error in ${method} route handler:`, error);
|
|
359
|
+
const handledErr = this._handleError(error);
|
|
360
|
+
res.status(handledErr.code).send(handledErr);
|
|
361
|
+
}
|
|
167
362
|
});
|
|
168
|
-
/* this.handleRoute = fn.apply(this, arguments);
|
|
169
|
-
|
|
170
|
-
this.routes.set(path, async (...args: any[]) => {
|
|
171
|
-
try {
|
|
172
|
-
const result = await fn(...args);
|
|
173
|
-
return result;
|
|
174
|
-
} catch (error) {
|
|
175
|
-
console.error(`Error handling route ${path}:`, error);
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
178
|
-
}); */
|
|
179
363
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
364
|
+
_routeHandler(routePath, method, fn) {
|
|
365
|
+
const routeKey = method + ":" + routePath;
|
|
366
|
+
this.rMap.set(routeKey, {
|
|
367
|
+
handler: fn,
|
|
368
|
+
middlewares: [],
|
|
369
|
+
schema: {},
|
|
370
|
+
});
|
|
371
|
+
this.mapFn(fn);
|
|
372
|
+
const route = {
|
|
373
|
+
useMiddleware: (middlewares) => {
|
|
374
|
+
const midds = Array.isArray(middlewares) ? middlewares : [middlewares];
|
|
375
|
+
const ms = midds.map((mclass) => {
|
|
376
|
+
const cls = typedi_1.default.get(mclass);
|
|
377
|
+
this.middlewares.set(mclass.name, cls);
|
|
378
|
+
return cls.invoke; // Ensure `invoke` runs in the correct context
|
|
379
|
+
});
|
|
380
|
+
const r = this.rMap.get(routeKey);
|
|
381
|
+
if (r) {
|
|
382
|
+
r.middlewares = ms; // Update middlewares array
|
|
383
|
+
}
|
|
384
|
+
return route; // Ensure chaining by returning the same route object
|
|
385
|
+
},
|
|
386
|
+
useSwagger: (options) => {
|
|
387
|
+
const r = this.rMap.get(routeKey);
|
|
388
|
+
if (r) {
|
|
389
|
+
r.schema = options; // Update schema
|
|
390
|
+
}
|
|
391
|
+
return route; // Ensure chaining
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
return route;
|
|
395
|
+
}
|
|
396
|
+
mapGet(path = "", fn) {
|
|
397
|
+
return this._routeHandler(path, "GET", fn);
|
|
398
|
+
}
|
|
399
|
+
mapPost(path = "", fn) {
|
|
400
|
+
return this._routeHandler(path, "POST", fn);
|
|
401
|
+
}
|
|
402
|
+
mapPut(path = "", fn) {
|
|
403
|
+
return this._routeHandler(path, "PUT", fn);
|
|
404
|
+
}
|
|
405
|
+
mapDelete(path = "", fn) {
|
|
406
|
+
return this._routeHandler(path, "DELETE", fn);
|
|
407
|
+
}
|
|
408
|
+
useStaticFiles(options = { path: undefined, prefix: undefined }) {
|
|
409
|
+
this.app.register(require("@fastify/static"), {
|
|
410
|
+
root: options.path ? options.path : path_1.default.join(process.cwd(), "public"),
|
|
411
|
+
prefix: options.prefix ? options.prefix : "/static/",
|
|
412
|
+
});
|
|
186
413
|
}
|
|
187
414
|
async run(port = 4000) {
|
|
188
415
|
if (this.alreadyRun)
|
|
189
416
|
throw new system_exception_1.SystemUseError("App already running");
|
|
190
417
|
this.alreadyRun = true;
|
|
191
|
-
if (
|
|
418
|
+
if (AvleonApplication.buildOptions.database) {
|
|
419
|
+
}
|
|
420
|
+
//this.app.swagger();
|
|
421
|
+
if (this.hasSwagger) {
|
|
422
|
+
await this.initSwagger(this.globalSwaggerOptions);
|
|
192
423
|
}
|
|
193
|
-
|
|
424
|
+
await this._mapControllers();
|
|
425
|
+
// this.controllers.forEach(controller => {
|
|
426
|
+
// this.buildController(controller)
|
|
427
|
+
// })
|
|
428
|
+
this.rMap.forEach((value, key) => {
|
|
429
|
+
const [m, r] = key.split(":");
|
|
430
|
+
this.app.route({
|
|
431
|
+
method: m,
|
|
432
|
+
url: r,
|
|
433
|
+
schema: value.schema || {},
|
|
434
|
+
preHandler: value.middlewares ? value.middlewares : [],
|
|
435
|
+
handler: async (req, res) => {
|
|
436
|
+
const result = await value.handler.apply(this, [req, res]);
|
|
437
|
+
return result;
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
this.app.setErrorHandler(async (error, req, res) => {
|
|
442
|
+
const handledErr = this._handleError(error);
|
|
443
|
+
if (error instanceof exceptions_1.ValidationErrorException) {
|
|
444
|
+
return res.status(handledErr.code).send({
|
|
445
|
+
code: handledErr.code,
|
|
446
|
+
error: handledErr.error,
|
|
447
|
+
errors: handledErr.message,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
return res.status(handledErr.code).send(handledErr);
|
|
451
|
+
});
|
|
452
|
+
await this.app.ready();
|
|
194
453
|
await this.app.listen({ port });
|
|
195
|
-
console.log(`Application running on port:
|
|
454
|
+
console.log(`Application running on port: 0.0.0.0:${port}`);
|
|
455
|
+
}
|
|
456
|
+
getTestApp(app) {
|
|
457
|
+
return this.app;
|
|
196
458
|
}
|
|
197
459
|
}
|
|
198
|
-
|
|
199
|
-
|
|
460
|
+
AvleonApplication.buildOptions = {};
|
|
461
|
+
// Applciation Builder
|
|
462
|
+
class Builder {
|
|
200
463
|
constructor() {
|
|
201
464
|
this.alreadyBuilt = false;
|
|
202
|
-
this.
|
|
465
|
+
this.database = false;
|
|
466
|
+
}
|
|
467
|
+
static createAppBuilder() {
|
|
468
|
+
if (!Builder.instance) {
|
|
469
|
+
Builder.instance = new Builder();
|
|
470
|
+
}
|
|
471
|
+
return Builder.instance;
|
|
203
472
|
}
|
|
204
|
-
static
|
|
205
|
-
if (!
|
|
206
|
-
|
|
473
|
+
static creatTestAppBilder() {
|
|
474
|
+
if (!Builder.instance) {
|
|
475
|
+
Builder.instance = new Builder();
|
|
207
476
|
}
|
|
208
|
-
return
|
|
477
|
+
return Builder.instance;
|
|
209
478
|
}
|
|
210
479
|
async registerPlugin(plugin, options) {
|
|
211
480
|
container_1.default.set(plugin, plugin.prototype);
|
|
212
481
|
}
|
|
213
|
-
async
|
|
214
|
-
this.
|
|
482
|
+
async addDataSource(config) {
|
|
483
|
+
if (this.database) {
|
|
484
|
+
throw new system_exception_1.SystemUseError("Datasource already added.");
|
|
485
|
+
}
|
|
486
|
+
this.database = true;
|
|
487
|
+
try {
|
|
488
|
+
const typeorm = await Promise.resolve().then(() => __importStar(require("typeorm")));
|
|
489
|
+
if (!typeorm) {
|
|
490
|
+
throw new system_exception_1.SystemUseError("TypeOrm not installed");
|
|
491
|
+
}
|
|
492
|
+
const datasource = new typeorm.DataSource(config);
|
|
493
|
+
typedi_1.default.set("idatasource", datasource);
|
|
494
|
+
this.dataSource = datasource;
|
|
495
|
+
await datasource.initialize();
|
|
496
|
+
}
|
|
497
|
+
catch (error) {
|
|
498
|
+
console.log(error);
|
|
499
|
+
console.error("Database Initialize Error:", error.message);
|
|
500
|
+
}
|
|
215
501
|
}
|
|
216
|
-
|
|
217
|
-
//console.log("Hello", hello())
|
|
502
|
+
build() {
|
|
218
503
|
if (this.alreadyBuilt)
|
|
219
504
|
throw new Error("Already built");
|
|
220
505
|
this.alreadyBuilt = true;
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (isTsNode ? file.endsWith(".ts") : file.endsWith(".js")) {
|
|
225
|
-
const filePath = path_1.default.join(controllerDir, file);
|
|
226
|
-
const module = await Promise.resolve(`${filePath}`).then(s => __importStar(require(s)));
|
|
227
|
-
for (const exported of Object.values(module)) {
|
|
228
|
-
if (typeof exported === "function" && (0, container_1.isApiController)(exported)) {
|
|
229
|
-
controllers.push(exported);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
const app = _InternalApplication.getInternalApp({ database: this.databse });
|
|
235
|
-
controllers.forEach(container_1.registerController);
|
|
506
|
+
const app = AvleonApplication.getInternalApp({
|
|
507
|
+
database: this.database,
|
|
508
|
+
});
|
|
236
509
|
return app;
|
|
237
510
|
}
|
|
238
511
|
}
|
|
239
|
-
exports.
|
|
512
|
+
exports.Builder = Builder;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export { inject } from
|
|
1
|
+
export * from "./icore";
|
|
2
|
+
export { inject, validateRequestBody } from "./helpers";
|
|
3
3
|
export * from "./decorators";
|
|
4
|
+
export * from "./middleware";
|
|
4
5
|
export * from "./config";
|
|
5
6
|
export * from "./openapi";
|
|
6
7
|
export * from "./map-types";
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export * from
|
|
10
|
-
export
|
|
8
|
+
export * from "./response";
|
|
9
|
+
export * from "./exceptions";
|
|
10
|
+
export * from "./validator-extend";
|
|
11
|
+
export * from "./validation";
|
|
12
|
+
export * from "./environment-variables";
|
|
13
|
+
export * from "./collection";
|
|
14
|
+
export * from "./queue";
|
|
15
|
+
export { default as Container } from "./container";
|