@avleon/core 0.0.32 → 0.0.37
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/License +21 -0
- package/README.md +39 -47
- package/dist/collection.js +0 -1
- package/dist/container.d.ts +2 -0
- package/dist/container.js +4 -6
- package/dist/environment-variables.d.ts +37 -0
- package/dist/environment-variables.js +37 -0
- package/dist/icore.d.ts +4 -1
- package/dist/icore.js +57 -26
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/kenx-provider.d.ts +7 -0
- package/dist/kenx-provider.js +44 -0
- package/package.json +20 -15
package/License
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Tareq Hossain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ Avleon is a powerful, TypeScript-based web framework built on top of Fastify, de
|
|
|
48
48
|
- [mapPost](#mappost)
|
|
49
49
|
- [mapPut](#mapput)
|
|
50
50
|
- [mapDelete](#mapdelete)
|
|
51
|
+
- [Testing](#testing)
|
|
51
52
|
|
|
52
53
|
## Features
|
|
53
54
|
|
|
@@ -77,7 +78,7 @@ pnpm add @avleon/core
|
|
|
77
78
|
|
|
78
79
|
## Quick Start
|
|
79
80
|
|
|
80
|
-
###
|
|
81
|
+
### Minimal
|
|
81
82
|
|
|
82
83
|
```typescript
|
|
83
84
|
import { Avleon, ApiController, Get, Results } from "@avleon/core";
|
|
@@ -349,10 +350,9 @@ class UserDto {
|
|
|
349
350
|
|
|
350
351
|
Generate API documentation automatically:
|
|
351
352
|
|
|
352
|
-
```typescript
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
openapi: {
|
|
353
|
+
```typescript
|
|
354
|
+
|
|
355
|
+
app.useOpenApi({
|
|
356
356
|
info: {
|
|
357
357
|
title: "User API",
|
|
358
358
|
version: "1.0.0",
|
|
@@ -364,9 +364,9 @@ const app = new Avleon({
|
|
|
364
364
|
description: "Development server",
|
|
365
365
|
},
|
|
366
366
|
],
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
```
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
```
|
|
370
370
|
|
|
371
371
|
You can also customize the OpenAPI UI:
|
|
372
372
|
|
|
@@ -430,6 +430,27 @@ app.useDataSource(DataSourceConfig);
|
|
|
430
430
|
// ... other impments
|
|
431
431
|
```
|
|
432
432
|
|
|
433
|
+
Now in your Controller or Injected service use can use like this
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import { AppService, InjectRepository } from "@avleon/core";
|
|
437
|
+
import { Repository } from "typeorm";
|
|
438
|
+
import { User } from "model_path";
|
|
439
|
+
|
|
440
|
+
@AppService
|
|
441
|
+
export class UserService {
|
|
442
|
+
constructor(
|
|
443
|
+
@InjectRepository(User)
|
|
444
|
+
private readonly _userRepository: Repository<User>,
|
|
445
|
+
) {}
|
|
446
|
+
|
|
447
|
+
async findAll() {
|
|
448
|
+
const users = await this._userRepository.find();
|
|
449
|
+
return users;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
433
454
|
### File Uploads
|
|
434
455
|
|
|
435
456
|
Handle file uploads with multipart support:
|
|
@@ -445,7 +466,7 @@ app.useMultipart({
|
|
|
445
466
|
|
|
446
467
|
// In your controller
|
|
447
468
|
@Post('/upload')
|
|
448
|
-
async uploadFile(@
|
|
469
|
+
async uploadFile(@MultipartFile() file: any) {
|
|
449
470
|
// Process uploaded file
|
|
450
471
|
return HttpResponse.Ok({ filename: file.filename });
|
|
451
472
|
}
|
|
@@ -462,46 +483,9 @@ app.useStaticFiles({
|
|
|
462
483
|
});
|
|
463
484
|
```
|
|
464
485
|
|
|
465
|
-
### Testing
|
|
466
|
-
|
|
467
|
-
Test your API endpoints with the built-in testing utilities:
|
|
468
|
-
|
|
469
|
-
```typescript
|
|
470
|
-
import { TestBuilder } from "@avleon/core";
|
|
471
|
-
|
|
472
|
-
const testBuilder = TestBuilder.createBuilder();
|
|
473
|
-
const app = testBuilder.getTestApplication({
|
|
474
|
-
controllers: [UserController],
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
// Test your API endpoints
|
|
478
|
-
const response = await app.get("/users");
|
|
479
|
-
expect(response.statusCode).toBe(200);
|
|
480
|
-
```
|
|
481
|
-
|
|
482
486
|
## Configuration
|
|
483
487
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
```typescript
|
|
487
|
-
// .env
|
|
488
|
-
PORT=3000
|
|
489
|
-
DATABASE_URL=postgres://user:password@localhost:5432/db
|
|
490
|
-
|
|
491
|
-
// app.ts
|
|
492
|
-
import { Environment } from '@avleon/core';
|
|
493
|
-
|
|
494
|
-
const env = new Environment();
|
|
495
|
-
env.load();
|
|
496
|
-
|
|
497
|
-
const app = new Avleon({
|
|
498
|
-
controllers: [UserController],
|
|
499
|
-
env: {
|
|
500
|
-
port: 'PORT',
|
|
501
|
-
databaseUrl: 'DATABASE_URL',
|
|
502
|
-
},
|
|
503
|
-
});
|
|
504
|
-
```
|
|
488
|
+
Coming soon...
|
|
505
489
|
|
|
506
490
|
## Route Mapping
|
|
507
491
|
|
|
@@ -558,6 +542,8 @@ app.mapDelete("/users/:id", async (req, res) => {
|
|
|
558
542
|
});
|
|
559
543
|
```
|
|
560
544
|
|
|
545
|
+
### Add openapi and middleware support for inline route
|
|
546
|
+
|
|
561
547
|
Each of these methods returns a route object that can be used to add middleware or Swagger documentation to the route.
|
|
562
548
|
|
|
563
549
|
```typescript
|
|
@@ -592,6 +578,12 @@ app
|
|
|
592
578
|
});
|
|
593
579
|
```
|
|
594
580
|
|
|
581
|
+
### Testing
|
|
582
|
+
|
|
583
|
+
Test your API endpoints with the built-in testing utilities:
|
|
584
|
+
|
|
585
|
+
Coming soon...
|
|
586
|
+
|
|
595
587
|
## License
|
|
596
588
|
|
|
597
589
|
ISC
|
package/dist/collection.js
CHANGED
package/dist/container.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
+
import { Knex } from "knex";
|
|
7
8
|
import TypediContainer from "typedi";
|
|
8
9
|
export declare const FEATURE_KEY: unique symbol;
|
|
9
10
|
export declare const ROUTE_META_KEY: unique symbol;
|
|
@@ -25,4 +26,5 @@ export declare function getRegisteredControllers(): Function[];
|
|
|
25
26
|
export declare const API_CONTROLLER_METADATA_KEY: unique symbol;
|
|
26
27
|
export declare function isApiController(target: Function): boolean;
|
|
27
28
|
export declare function registerDataSource(dataSource: any): void;
|
|
29
|
+
export declare function registerKnex(dataSource: Knex.Config): void;
|
|
28
30
|
export default Container;
|
package/dist/container.js
CHANGED
|
@@ -10,12 +10,7 @@ exports.getRegisteredServices = getRegisteredServices;
|
|
|
10
10
|
exports.getRegisteredControllers = getRegisteredControllers;
|
|
11
11
|
exports.isApiController = isApiController;
|
|
12
12
|
exports.registerDataSource = registerDataSource;
|
|
13
|
-
|
|
14
|
-
* @copyright 2024
|
|
15
|
-
* @author Tareq Hossain
|
|
16
|
-
* @email xtrinsic96@gmail.com
|
|
17
|
-
* @url https://github.com/xtareq
|
|
18
|
-
*/
|
|
13
|
+
exports.registerKnex = registerKnex;
|
|
19
14
|
const typedi_1 = __importDefault(require("typedi"));
|
|
20
15
|
exports.FEATURE_KEY = Symbol.for("features");
|
|
21
16
|
exports.ROUTE_META_KEY = Symbol("iroute:options");
|
|
@@ -54,4 +49,7 @@ Container.set("appName", "Iqra");
|
|
|
54
49
|
function registerDataSource(dataSource) {
|
|
55
50
|
Container.set("idatasource", dataSource);
|
|
56
51
|
}
|
|
52
|
+
function registerKnex(dataSource) {
|
|
53
|
+
Container.set("KnexConnection", dataSource);
|
|
54
|
+
}
|
|
57
55
|
exports.default = Container;
|
|
@@ -4,9 +4,46 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* @class Environment
|
|
9
|
+
* @description A service class to manage access to environment variables.
|
|
10
|
+
* It loads variables from `.env` file and merges them with `process.env`,
|
|
11
|
+
* giving precedence to `process.env` values.
|
|
12
|
+
*/
|
|
7
13
|
export declare class Environment {
|
|
14
|
+
/**
|
|
15
|
+
* Parses the given `.env` file and merges it with `process.env`.
|
|
16
|
+
* Values from `process.env` take precedence.
|
|
17
|
+
*
|
|
18
|
+
* @private
|
|
19
|
+
* @param filePath - Absolute path to the `.env` file.
|
|
20
|
+
* @returns A dictionary of merged environment variables.
|
|
21
|
+
*/
|
|
8
22
|
private parseEnvFile;
|
|
23
|
+
/**
|
|
24
|
+
* Retrieves the value of the specified environment variable.
|
|
25
|
+
*
|
|
26
|
+
* @template T
|
|
27
|
+
* @param key - The name of the environment variable.
|
|
28
|
+
* @returns The value of the variable, or `undefined` if not found.
|
|
29
|
+
*/
|
|
9
30
|
get<T = any>(key: string): T;
|
|
31
|
+
/**
|
|
32
|
+
* Retrieves the value of the specified environment variable.
|
|
33
|
+
* Throws an error if the variable is not found.
|
|
34
|
+
*
|
|
35
|
+
* @template T
|
|
36
|
+
* @param key - The name of the environment variable.
|
|
37
|
+
* @throws {EnvironmentVariableNotFound} If the variable does not exist.
|
|
38
|
+
* @returns The value of the variable.
|
|
39
|
+
*/
|
|
10
40
|
getOrThrow<T = any>(key: string): T;
|
|
41
|
+
/**
|
|
42
|
+
* Retrieves all available environment variables,
|
|
43
|
+
* with `process.env` values taking precedence over `.env` values.
|
|
44
|
+
*
|
|
45
|
+
* @template T
|
|
46
|
+
* @returns An object containing all environment variables.
|
|
47
|
+
*/
|
|
11
48
|
getAll<T = any>(): T;
|
|
12
49
|
}
|
|
@@ -55,7 +55,21 @@ const fs_1 = __importStar(require("fs"));
|
|
|
55
55
|
const typedi_1 = require("typedi");
|
|
56
56
|
const system_exception_1 = require("./exceptions/system-exception");
|
|
57
57
|
dotenv_1.default.config({ path: path_1.default.join(process.cwd(), ".env") });
|
|
58
|
+
/**
|
|
59
|
+
* @class Environment
|
|
60
|
+
* @description A service class to manage access to environment variables.
|
|
61
|
+
* It loads variables from `.env` file and merges them with `process.env`,
|
|
62
|
+
* giving precedence to `process.env` values.
|
|
63
|
+
*/
|
|
58
64
|
let Environment = class Environment {
|
|
65
|
+
/**
|
|
66
|
+
* Parses the given `.env` file and merges it with `process.env`.
|
|
67
|
+
* Values from `process.env` take precedence.
|
|
68
|
+
*
|
|
69
|
+
* @private
|
|
70
|
+
* @param filePath - Absolute path to the `.env` file.
|
|
71
|
+
* @returns A dictionary of merged environment variables.
|
|
72
|
+
*/
|
|
59
73
|
parseEnvFile(filePath) {
|
|
60
74
|
try {
|
|
61
75
|
const isExis = (0, fs_1.existsSync)(filePath);
|
|
@@ -71,10 +85,26 @@ let Environment = class Environment {
|
|
|
71
85
|
return {};
|
|
72
86
|
}
|
|
73
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Retrieves the value of the specified environment variable.
|
|
90
|
+
*
|
|
91
|
+
* @template T
|
|
92
|
+
* @param key - The name of the environment variable.
|
|
93
|
+
* @returns The value of the variable, or `undefined` if not found.
|
|
94
|
+
*/
|
|
74
95
|
get(key) {
|
|
75
96
|
const parsedEnv = this.parseEnvFile(path_1.default.join(process.cwd(), ".env"));
|
|
76
97
|
return parsedEnv[key];
|
|
77
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Retrieves the value of the specified environment variable.
|
|
101
|
+
* Throws an error if the variable is not found.
|
|
102
|
+
*
|
|
103
|
+
* @template T
|
|
104
|
+
* @param key - The name of the environment variable.
|
|
105
|
+
* @throws {EnvironmentVariableNotFound} If the variable does not exist.
|
|
106
|
+
* @returns The value of the variable.
|
|
107
|
+
*/
|
|
78
108
|
getOrThrow(key) {
|
|
79
109
|
const parsedEnv = this.parseEnvFile(path_1.default.join(process.cwd(), ".env"));
|
|
80
110
|
if (!Object(parsedEnv).hasOwnProperty(key)) {
|
|
@@ -82,6 +112,13 @@ let Environment = class Environment {
|
|
|
82
112
|
}
|
|
83
113
|
return parsedEnv[key];
|
|
84
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Retrieves all available environment variables,
|
|
117
|
+
* with `process.env` values taking precedence over `.env` values.
|
|
118
|
+
*
|
|
119
|
+
* @template T
|
|
120
|
+
* @returns An object containing all environment variables.
|
|
121
|
+
*/
|
|
85
122
|
getAll() {
|
|
86
123
|
const parsedEnv = this.parseEnvFile(path_1.default.join(process.cwd(), ".env"));
|
|
87
124
|
return parsedEnv;
|
package/dist/icore.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { FastifyCorsOptions } from "@fastify/cors";
|
|
|
16
16
|
import { FastifyMultipartOptions } from "@fastify/multipart";
|
|
17
17
|
import { MultipartFile } from "./multipart";
|
|
18
18
|
import { ServerOptions } from "socket.io";
|
|
19
|
+
import { Knex } from "knex";
|
|
19
20
|
export type FuncRoute = {
|
|
20
21
|
handler: any;
|
|
21
22
|
middlewares?: any[];
|
|
@@ -149,6 +150,7 @@ export declare class AvleonApplication {
|
|
|
149
150
|
useOpenApi<T = OpenApiUiOptions>(configOrClass: OpenApiConfigInput<T>): void;
|
|
150
151
|
useMultipart<T extends MultipartOptions>(options: ConfigInput<T>): void;
|
|
151
152
|
useDataSource<T extends DataSourceOptions>(options: ConfigInput<T>): void;
|
|
153
|
+
useKnex<T extends Knex.Config>(options: ConfigInput<T>): void;
|
|
152
154
|
private _useCache;
|
|
153
155
|
useMiddlewares<T extends AvleonMiddleware>(mclasses: Constructor<T>[]): void;
|
|
154
156
|
useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
|
|
@@ -218,12 +220,13 @@ export interface IAppBuilder {
|
|
|
218
220
|
export declare class AvleonTest {
|
|
219
221
|
private constructor();
|
|
220
222
|
static getController<T>(controller: Constructor<T>, deps?: any[]): T;
|
|
221
|
-
|
|
223
|
+
static getProvider<T>(service: Constructor<T>, deps?: any[]): T;
|
|
222
224
|
static createTestApplication(options: TestAppOptions): TestApplication;
|
|
223
225
|
static from(app: AvleonApplication): TestApplication;
|
|
224
226
|
static clean(): void;
|
|
225
227
|
}
|
|
226
228
|
export declare class Avleon {
|
|
227
229
|
static createApplication(): AvleonApplication;
|
|
230
|
+
static createTestApplication(options: TestAppOptions): TestApplication;
|
|
228
231
|
}
|
|
229
232
|
export {};
|
package/dist/icore.js
CHANGED
|
@@ -229,6 +229,18 @@ class AvleonApplication {
|
|
|
229
229
|
this.dataSource = datasource;
|
|
230
230
|
typedi_1.default.set("idatasource", datasource);
|
|
231
231
|
}
|
|
232
|
+
useKnex(options) {
|
|
233
|
+
let dataSourceOptions;
|
|
234
|
+
if (this._isConfigClass(options)) {
|
|
235
|
+
dataSourceOptions = this.appConfig.get(options);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
dataSourceOptions = options;
|
|
239
|
+
}
|
|
240
|
+
if (!dataSourceOptions)
|
|
241
|
+
throw new system_exception_1.SystemUseError("Invlaid datasource options.");
|
|
242
|
+
(0, container_1.registerKnex)(dataSourceOptions);
|
|
243
|
+
}
|
|
232
244
|
_useCache(options) { }
|
|
233
245
|
useMiddlewares(mclasses) {
|
|
234
246
|
for (const mclass of mclasses) {
|
|
@@ -308,7 +320,6 @@ class AvleonApplication {
|
|
|
308
320
|
method: methodmetaOptions.method.toUpperCase(),
|
|
309
321
|
schema: { ...schema },
|
|
310
322
|
handler: async (req, res) => {
|
|
311
|
-
var _a;
|
|
312
323
|
let reqClone = req;
|
|
313
324
|
// class level authrization
|
|
314
325
|
if (authClsMeata.authorize && this.authorizeMiddleware) {
|
|
@@ -368,18 +379,44 @@ class AvleonApplication {
|
|
|
368
379
|
}
|
|
369
380
|
}
|
|
370
381
|
const result = await prototype[method].apply(ctrl, args);
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
382
|
+
// Custom wrapped file download
|
|
383
|
+
if (result === null || result === void 0 ? void 0 : result.__isFileDownload) {
|
|
384
|
+
const { stream, filename, contentType = "application/octet-stream", } = result;
|
|
385
|
+
if (!stream || typeof stream.pipe !== "function") {
|
|
386
|
+
return res.code(500).send({
|
|
387
|
+
code: 500,
|
|
388
|
+
error: "INTERNAL_ERROR",
|
|
389
|
+
message: "Invalid stream object",
|
|
390
|
+
});
|
|
375
391
|
}
|
|
376
|
-
|
|
392
|
+
res.header("Content-Type", contentType);
|
|
393
|
+
res.header("Content-Disposition", `attachment; filename="${filename}"`);
|
|
394
|
+
stream.on("error", (err) => {
|
|
395
|
+
console.error("Stream error:", err);
|
|
396
|
+
if (!res.sent) {
|
|
397
|
+
res.code(500).send({
|
|
398
|
+
code: 500,
|
|
399
|
+
error: "StreamError",
|
|
400
|
+
message: "Error while streaming file.",
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
return res.send(stream);
|
|
377
405
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
406
|
+
// Native stream (not wrapped)
|
|
407
|
+
if (result instanceof stream_1.default || typeof (result === null || result === void 0 ? void 0 : result.pipe) === "function") {
|
|
408
|
+
result.on("error", (err) => {
|
|
409
|
+
console.error("Stream error:", err);
|
|
410
|
+
if (!res.sent) {
|
|
411
|
+
res.code(500).send({
|
|
412
|
+
code: 500,
|
|
413
|
+
error: "StreamError",
|
|
414
|
+
message: "Error while streaming file.",
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
res.header("Content-Type", "application/octet-stream");
|
|
419
|
+
return res.send(result);
|
|
383
420
|
}
|
|
384
421
|
return res.send(result);
|
|
385
422
|
},
|
|
@@ -514,14 +551,6 @@ class AvleonApplication {
|
|
|
514
551
|
}
|
|
515
552
|
}
|
|
516
553
|
}
|
|
517
|
-
// addFeature(feature:{controllers:Function[]}){
|
|
518
|
-
// feature.controllers.forEach(c=> this.controllers.push(c))
|
|
519
|
-
// }
|
|
520
|
-
// mapFeature(){
|
|
521
|
-
// if(!this.isMapFeatures){
|
|
522
|
-
// this.isMapFeatures = true;
|
|
523
|
-
// }
|
|
524
|
-
// }
|
|
525
554
|
async _mapControllers() {
|
|
526
555
|
if (this.controllers.length > 0) {
|
|
527
556
|
for (let controller of this.controllers) {
|
|
@@ -534,10 +563,6 @@ class AvleonApplication {
|
|
|
534
563
|
}
|
|
535
564
|
}
|
|
536
565
|
}
|
|
537
|
-
// useControllersAuto(controllerPath?:string) {
|
|
538
|
-
// this.registerControllerAuto = true;
|
|
539
|
-
// //this.autoControllers();
|
|
540
|
-
// }
|
|
541
566
|
async mapFn(fn) {
|
|
542
567
|
const original = fn;
|
|
543
568
|
fn = function () { };
|
|
@@ -694,8 +719,6 @@ class AvleonApplication {
|
|
|
694
719
|
}
|
|
695
720
|
getTestApp(buildOptions) {
|
|
696
721
|
try {
|
|
697
|
-
// }
|
|
698
|
-
// this.initializeDatabase();
|
|
699
722
|
this._mapControllers();
|
|
700
723
|
this.rMap.forEach((value, key) => {
|
|
701
724
|
const [m, r] = key.split(":");
|
|
@@ -758,7 +781,11 @@ class AvleonTest {
|
|
|
758
781
|
});
|
|
759
782
|
return typedi_1.default.get(controller);
|
|
760
783
|
}
|
|
761
|
-
|
|
784
|
+
static getProvider(service, deps = []) {
|
|
785
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", service) || [];
|
|
786
|
+
deps.forEach((dep, i) => {
|
|
787
|
+
typedi_1.default.set(paramTypes[i], dep);
|
|
788
|
+
});
|
|
762
789
|
return typedi_1.default.get(service);
|
|
763
790
|
}
|
|
764
791
|
static createTestApplication(options) {
|
|
@@ -781,5 +808,9 @@ class Avleon {
|
|
|
781
808
|
const app = AvleonApplication.getApp();
|
|
782
809
|
return app;
|
|
783
810
|
}
|
|
811
|
+
static createTestApplication(options) {
|
|
812
|
+
const app = AvleonTest.createTestApplication(options);
|
|
813
|
+
return app;
|
|
814
|
+
}
|
|
784
815
|
}
|
|
785
816
|
exports.Avleon = Avleon;
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export * from "./multipart";
|
|
|
25
25
|
export * from "./file-storage";
|
|
26
26
|
export * from "./logger";
|
|
27
27
|
export * from "./event-dispatcher";
|
|
28
|
+
export * from "./kenx-provider";
|
|
28
29
|
export { Subscribe, Private } from "./event-subscriber";
|
|
29
30
|
export declare const GetSchema: typeof sw.generateSwaggerSchema;
|
|
30
31
|
export { default as AvleonContainer } from "./container";
|
package/dist/index.js
CHANGED
|
@@ -71,6 +71,7 @@ __exportStar(require("./multipart"), exports);
|
|
|
71
71
|
__exportStar(require("./file-storage"), exports);
|
|
72
72
|
__exportStar(require("./logger"), exports);
|
|
73
73
|
__exportStar(require("./event-dispatcher"), exports);
|
|
74
|
+
__exportStar(require("./kenx-provider"), exports);
|
|
74
75
|
var event_subscriber_1 = require("./event-subscriber");
|
|
75
76
|
Object.defineProperty(exports, "Subscribe", { enumerable: true, get: function () { return event_subscriber_1.Subscribe; } });
|
|
76
77
|
Object.defineProperty(exports, "Private", { enumerable: true, get: function () { return event_subscriber_1.Private; } });
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DB = void 0;
|
|
13
|
+
const typedi_1 = require("typedi");
|
|
14
|
+
const typedi_2 = require("typedi");
|
|
15
|
+
let DB = class DB {
|
|
16
|
+
constructor() {
|
|
17
|
+
const existing = typedi_2.Container.has("KnexConnection")
|
|
18
|
+
? typedi_2.Container.get("KnexConnection")
|
|
19
|
+
: null;
|
|
20
|
+
if (existing) {
|
|
21
|
+
this.connection = existing;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Initialize manually (call this in main if you want)
|
|
25
|
+
init(config) {
|
|
26
|
+
if (!this.connection) {
|
|
27
|
+
const knex = require("knex");
|
|
28
|
+
this.connection = knex(config);
|
|
29
|
+
typedi_2.Container.set("KnexConnection", this.connection);
|
|
30
|
+
}
|
|
31
|
+
return this.connection;
|
|
32
|
+
}
|
|
33
|
+
get client() {
|
|
34
|
+
if (!this.connection) {
|
|
35
|
+
throw new Error("Knex is not initialized. Call DB.init(config) first.");
|
|
36
|
+
}
|
|
37
|
+
return this.connection;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.DB = DB;
|
|
41
|
+
exports.DB = DB = __decorate([
|
|
42
|
+
(0, typedi_1.Service)(),
|
|
43
|
+
__metadata("design:paramtypes", [])
|
|
44
|
+
], DB);
|
package/package.json
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avleon/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.37",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build": "npm run clean && tsc",
|
|
8
|
-
"clean": "rimraf dist",
|
|
9
|
-
"watch": "tsc-watch",
|
|
10
|
-
"lint": "eslint .",
|
|
11
|
-
"lint:fix": "eslint . --fix",
|
|
12
|
-
"format": "prettier --write .",
|
|
13
|
-
"test": "jest",
|
|
14
|
-
"test:watch": "jest --watch",
|
|
15
|
-
"prepare": "husky install"
|
|
16
|
-
},
|
|
17
6
|
"keywords": [
|
|
18
7
|
"restapi",
|
|
19
8
|
"avleon",
|
|
@@ -35,6 +24,7 @@
|
|
|
35
24
|
"husky": "^8.0.0",
|
|
36
25
|
"ioredis": "^5.6.1",
|
|
37
26
|
"jest": "^29.7.0",
|
|
27
|
+
"knex": "^3.1.0",
|
|
38
28
|
"lint-staged": "^16.0.0",
|
|
39
29
|
"mssql": "^11.0.1",
|
|
40
30
|
"mysql2": "^3.14.1",
|
|
@@ -75,7 +65,8 @@
|
|
|
75
65
|
"@scalar/fastify-api-reference": "*",
|
|
76
66
|
"ioredis": "*",
|
|
77
67
|
"sharp": "*",
|
|
78
|
-
"typeorm": "*"
|
|
68
|
+
"typeorm": "*",
|
|
69
|
+
"knex": "*"
|
|
79
70
|
},
|
|
80
71
|
"peerDependenciesMeta": {
|
|
81
72
|
"@scalar/fastify-api-reference": {
|
|
@@ -89,6 +80,9 @@
|
|
|
89
80
|
},
|
|
90
81
|
"typeorm": {
|
|
91
82
|
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"knex": {
|
|
85
|
+
"optional": true
|
|
92
86
|
}
|
|
93
87
|
},
|
|
94
88
|
"lint-staged": {
|
|
@@ -111,5 +105,16 @@
|
|
|
111
105
|
},
|
|
112
106
|
"files": [
|
|
113
107
|
"dist"
|
|
114
|
-
]
|
|
115
|
-
|
|
108
|
+
],
|
|
109
|
+
"scripts": {
|
|
110
|
+
"build": "npm run clean && tsc",
|
|
111
|
+
"clean": "rimraf dist",
|
|
112
|
+
"watch": "tsc-watch",
|
|
113
|
+
"lint": "eslint .",
|
|
114
|
+
"lint:fix": "eslint . --fix",
|
|
115
|
+
"format": "prettier --write .",
|
|
116
|
+
"test": "jest",
|
|
117
|
+
"test:watch": "jest --watch",
|
|
118
|
+
"husky:init": "husky install"
|
|
119
|
+
}
|
|
120
|
+
}
|