xtaskjs 1.0.0
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/.github/workflows/publish.yml +44 -0
- package/app.ts +7 -0
- package/babel.config.js +4 -0
- package/dist/packages/common/index.js +17 -0
- package/dist/packages/common/src/decorators/core/server/applicationrunner.js +11 -0
- package/dist/packages/common/src/decorators/core/server/commandlinerunner.js +11 -0
- package/dist/packages/common/src/decorators/core/server/constants.js +5 -0
- package/dist/packages/common/src/decorators/core/server/index.js +20 -0
- package/dist/packages/common/src/decorators/core/server/onevent.js +11 -0
- package/dist/packages/common/src/index.js +24 -0
- package/dist/packages/common/src/logger/index.js +17 -0
- package/dist/packages/common/src/logger/logger.js +40 -0
- package/dist/packages/common/src/types/eventhandlermeta.js +2 -0
- package/dist/packages/common/src/types/index.js +19 -0
- package/dist/packages/common/src/types/lifecycle-events.js +2 -0
- package/dist/packages/common/src/types/runnermeta.js +2 -0
- package/dist/packages/common/test/logger/logger.test.js +12 -0
- package/dist/packages/core/index.js +17 -0
- package/dist/packages/core/src/bootstrap.js +13 -0
- package/dist/packages/core/src/di/autowired.js +41 -0
- package/dist/packages/core/src/di/component.js +19 -0
- package/dist/packages/core/src/di/container.js +225 -0
- package/dist/packages/core/src/di/index.js +27 -0
- package/dist/packages/core/src/di/lifecycle.js +27 -0
- package/dist/packages/core/src/di/managedinstance.js +2 -0
- package/dist/packages/core/src/di/qualifier.js +26 -0
- package/dist/packages/core/src/di/stereotypes.js +10 -0
- package/dist/packages/core/src/index.js +21 -0
- package/dist/packages/core/src/kernel/index.js +18 -0
- package/dist/packages/core/src/kernel/kernel.js +26 -0
- package/dist/packages/core/src/kernel/kernellisteners.js +72 -0
- package/dist/packages/core/src/server/application-lifecycle.js +103 -0
- package/dist/packages/core/src/server/index.js +19 -0
- package/dist/packages/core/src/server/registereventhandlers.js +15 -0
- package/dist/packages/core/test/di/autowired.test.js +92 -0
- package/dist/packages/core/test/di/container.test.js +43 -0
- package/dist/packages/core/test/di/qualifier.test.js +71 -0
- package/dist/packages/core/test/logger/logger.test.js +12 -0
- package/dist/packages/core/test/server/applicationlifecycle.test.js +28 -0
- package/jest.config.js +9 -0
- package/package.json +36 -0
- package/packages/common/README.md +21 -0
- package/packages/common/babel.config.js +3 -0
- package/packages/common/index.ts +1 -0
- package/packages/common/jest.config.js +11 -0
- package/packages/common/package.json +50 -0
- package/packages/common/src/decorators/core/server/applicationrunner.ts +10 -0
- package/packages/common/src/decorators/core/server/commandlinerunner.ts +10 -0
- package/packages/common/src/decorators/core/server/constants.ts +2 -0
- package/packages/common/src/decorators/core/server/index.ts +4 -0
- package/packages/common/src/decorators/core/server/onevent.ts +10 -0
- package/packages/common/src/index.ts +5 -0
- package/packages/common/src/logger/index.ts +1 -0
- package/packages/common/src/logger/logger.ts +26 -0
- package/packages/common/src/types/eventhandlermeta.ts +7 -0
- package/packages/common/src/types/index.ts +3 -0
- package/packages/common/src/types/lifecycle-events.ts +10 -0
- package/packages/common/src/types/runnermeta.ts +5 -0
- package/packages/common/test/logger/logger.test.ts +11 -0
- package/packages/common/tsconfig.json +13 -0
- package/packages/core/README.md +21 -0
- package/packages/core/babel.config.js +3 -0
- package/packages/core/index.ts +1 -0
- package/packages/core/jest.config.js +15 -0
- package/packages/core/package.json +51 -0
- package/packages/core/src/bootstrap.ts +11 -0
- package/packages/core/src/di/autowired.ts +56 -0
- package/packages/core/src/di/component.ts +34 -0
- package/packages/core/src/di/container.ts +216 -0
- package/packages/core/src/di/index.ts +8 -0
- package/packages/core/src/di/lifecycle.ts +25 -0
- package/packages/core/src/di/managedinstance.ts +4 -0
- package/packages/core/src/di/qualifier.ts +25 -0
- package/packages/core/src/di/stereotypes.ts +10 -0
- package/packages/core/src/index.ts +5 -0
- package/packages/core/src/kernel/index.ts +2 -0
- package/packages/core/src/kernel/kernel.ts +31 -0
- package/packages/core/src/kernel/kernellisteners.ts +36 -0
- package/packages/core/src/server/application-lifecycle.ts +85 -0
- package/packages/core/src/server/index.ts +3 -0
- package/packages/core/src/server/registereventhandlers.ts +18 -0
- package/packages/core/test/di/autowired.test.ts +83 -0
- package/packages/core/test/di/container.test.ts +49 -0
- package/packages/core/test/di/qualifier.test.ts +60 -0
- package/packages/core/test/logger/logger.test.ts +11 -0
- package/packages/core/test/server/applicationlifecycle.test.ts +13 -0
- package/packages/core/tsconfig.json +19 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Qualifier = Qualifier;
|
|
4
|
+
exports.getQualifier = getQualifier;
|
|
5
|
+
exports.getConstructorQualifiers = getConstructorQualifiers;
|
|
6
|
+
require("reflect-metadata");
|
|
7
|
+
const QUALIFIER_KEY = Symbol("xtaskjs:qualifier");
|
|
8
|
+
function Qualifier(name) {
|
|
9
|
+
return function (target, propertyKey, parameterIndex) {
|
|
10
|
+
if (parameterIndex !== undefined) {
|
|
11
|
+
// Parameter decorator
|
|
12
|
+
const existingQualifiers = Reflect.getMetadata(QUALIFIER_KEY, target) || {};
|
|
13
|
+
existingQualifiers[parameterIndex] = name;
|
|
14
|
+
Reflect.defineMetadata(QUALIFIER_KEY, existingQualifiers, target);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function getQualifier(target, propertyKey) {
|
|
19
|
+
if (propertyKey) {
|
|
20
|
+
return Reflect.getMetadata(QUALIFIER_KEY, target, propertyKey);
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
function getConstructorQualifiers(target) {
|
|
25
|
+
return Reflect.getMetadata(QUALIFIER_KEY, target);
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Repository = exports.Controller = exports.Service = void 0;
|
|
4
|
+
const component_1 = require("./component");
|
|
5
|
+
const Service = (options = {}) => (0, component_1.Component)({ ...options, type: "service" });
|
|
6
|
+
exports.Service = Service;
|
|
7
|
+
const Controller = (options = {}) => (0, component_1.Component)({ ...options, type: "controller" });
|
|
8
|
+
exports.Controller = Controller;
|
|
9
|
+
const Repository = (options = {}) => (0, component_1.Component)({ ...options, type: "repository" });
|
|
10
|
+
exports.Repository = Repository;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
require("reflect-metadata");
|
|
18
|
+
__exportStar(require("./bootstrap"), exports);
|
|
19
|
+
__exportStar(require("./kernel"), exports);
|
|
20
|
+
__exportStar(require("./di"), exports);
|
|
21
|
+
__exportStar(require("./server"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./kernel"), exports);
|
|
18
|
+
__exportStar(require("./kernellisteners"), exports);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Kernel = void 0;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const core_1 = require("@xtaskjs/core");
|
|
6
|
+
const common_1 = require("@xtaskjs/common");
|
|
7
|
+
class Kernel {
|
|
8
|
+
container;
|
|
9
|
+
logger;
|
|
10
|
+
constructor() {
|
|
11
|
+
}
|
|
12
|
+
async boot() {
|
|
13
|
+
// Bootstrapping logic here
|
|
14
|
+
this.container = new core_1.Container();
|
|
15
|
+
// Autoload components from the "packages" directory
|
|
16
|
+
await this.container.autoload("packages");
|
|
17
|
+
this.logger = await this.container.get(common_1.Logger);
|
|
18
|
+
// Simulate some async operation
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
20
|
+
this.logger.info("🚀 Kernel started successfully.");
|
|
21
|
+
}
|
|
22
|
+
async getContainer() {
|
|
23
|
+
return this.container;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.Kernel = Kernel;
|
|
@@ -0,0 +1,72 @@
|
|
|
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.KernelListeners = void 0;
|
|
13
|
+
require("reflect-metadata");
|
|
14
|
+
const common_1 = require("@xtaskjs/common");
|
|
15
|
+
// Clase que escucha eventos del ciclo de vida
|
|
16
|
+
class KernelListeners {
|
|
17
|
+
onStarting() {
|
|
18
|
+
console.log("[Lifecycle] Starting...");
|
|
19
|
+
}
|
|
20
|
+
onReady() {
|
|
21
|
+
console.log("[Lifecycle] Application ready!");
|
|
22
|
+
}
|
|
23
|
+
async afterStart() {
|
|
24
|
+
console.log("[Runner] ApplicationRunner ejecutado después de arrancar Kernel");
|
|
25
|
+
}
|
|
26
|
+
async cli(args) {
|
|
27
|
+
console.log("[Runner] CommandLineRunner con args:", args);
|
|
28
|
+
}
|
|
29
|
+
memory(mem) {
|
|
30
|
+
console.log("[Metrics] Heap MB:", (mem.heapUsed / 1024 / 1024).toFixed(2));
|
|
31
|
+
}
|
|
32
|
+
cpu(calc) {
|
|
33
|
+
console.log("CPU", (calc));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.KernelListeners = KernelListeners;
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, common_1.OnEvent)("starting"),
|
|
39
|
+
__metadata("design:type", Function),
|
|
40
|
+
__metadata("design:paramtypes", []),
|
|
41
|
+
__metadata("design:returntype", void 0)
|
|
42
|
+
], KernelListeners.prototype, "onStarting", null);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, common_1.OnEvent)("ready"),
|
|
45
|
+
__metadata("design:type", Function),
|
|
46
|
+
__metadata("design:paramtypes", []),
|
|
47
|
+
__metadata("design:returntype", void 0)
|
|
48
|
+
], KernelListeners.prototype, "onReady", null);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, common_1.ApplicationRunner)(5),
|
|
51
|
+
__metadata("design:type", Function),
|
|
52
|
+
__metadata("design:paramtypes", []),
|
|
53
|
+
__metadata("design:returntype", Promise)
|
|
54
|
+
], KernelListeners.prototype, "afterStart", null);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, common_1.CommandLineRunner)(0),
|
|
57
|
+
__metadata("design:type", Function),
|
|
58
|
+
__metadata("design:paramtypes", [Array]),
|
|
59
|
+
__metadata("design:returntype", Promise)
|
|
60
|
+
], KernelListeners.prototype, "cli", null);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, common_1.OnEvent)("memoryReport"),
|
|
63
|
+
__metadata("design:type", Function),
|
|
64
|
+
__metadata("design:paramtypes", [Object]),
|
|
65
|
+
__metadata("design:returntype", void 0)
|
|
66
|
+
], KernelListeners.prototype, "memory", null);
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, common_1.OnEvent)("cpuReport"),
|
|
69
|
+
__metadata("design:type", Function),
|
|
70
|
+
__metadata("design:paramtypes", [Object]),
|
|
71
|
+
__metadata("design:returntype", void 0)
|
|
72
|
+
], KernelListeners.prototype, "cpu", null);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ApplicationLifeCycle = void 0;
|
|
37
|
+
const os = __importStar(require("os"));
|
|
38
|
+
const process = __importStar(require("process"));
|
|
39
|
+
class ApplicationLifeCycle {
|
|
40
|
+
listeners = new Map();
|
|
41
|
+
metricsInterval;
|
|
42
|
+
runners = [];
|
|
43
|
+
constructor() { }
|
|
44
|
+
on(event, Listener, priority = 0) {
|
|
45
|
+
const list = this.listeners.get(event) || [];
|
|
46
|
+
list.push({ fn: Listener, priority });
|
|
47
|
+
this.listeners.set(event, list.sort((a, b) => b.priority - a.priority));
|
|
48
|
+
}
|
|
49
|
+
registerRunner(fn, type = "ApplicationRunner", priority = 0) {
|
|
50
|
+
this.runners.push({ fn, type, priority });
|
|
51
|
+
this.runners.sort((a, b) => b.priority - a.priority);
|
|
52
|
+
}
|
|
53
|
+
async emit(event, payload) {
|
|
54
|
+
const list = this.listeners.get(event) || [];
|
|
55
|
+
for (const { fn, priority } of list) {
|
|
56
|
+
try {
|
|
57
|
+
await Promise.resolve(fn(payload));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(`Error in lifecycle handler for phase ${event} (priority ${priority}):`, error);
|
|
61
|
+
if (event != "error") {
|
|
62
|
+
await this.emit("error", error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async runRunners(type) {
|
|
68
|
+
for (const runner of this.runners.filter(r => r.type === type)) {
|
|
69
|
+
await Promise.resolve(runner.fn(process.argv.slice(2)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async boot(startFn) {
|
|
73
|
+
try {
|
|
74
|
+
await this.emit("starting");
|
|
75
|
+
await this.emit("environmentPrepared", { env: process.env, args: process.argv });
|
|
76
|
+
await this.emit("contextPrepared");
|
|
77
|
+
await this.emit("serverStarting");
|
|
78
|
+
await startFn();
|
|
79
|
+
await this.emit("serverStarted");
|
|
80
|
+
this.metricsInterval = setInterval(async () => {
|
|
81
|
+
await this.emit("memoryReport", process.memoryUsage());
|
|
82
|
+
await this.emit("cpuReport", {
|
|
83
|
+
loadavg: os.loadavg(),
|
|
84
|
+
usage: process.cpuUsage()
|
|
85
|
+
});
|
|
86
|
+
}, 5000); //every minute
|
|
87
|
+
await this.runRunners("ApplicationRunner");
|
|
88
|
+
await this.emit("ready");
|
|
89
|
+
await this.runRunners("CommandLineRunner");
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
await this.emit("error", error);
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async stop() {
|
|
97
|
+
if (this.metricsInterval) {
|
|
98
|
+
clearInterval(this.metricsInterval);
|
|
99
|
+
this.metricsInterval = undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.ApplicationLifeCycle = ApplicationLifeCycle;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./application-lifecycle"), exports);
|
|
18
|
+
__exportStar(require("./registereventhandlers"), exports);
|
|
19
|
+
__exportStar(require("../../../common/src/types/runnermeta"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerEventHandlers = registerEventHandlers;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const common_1 = require("@xtaskjs/common");
|
|
6
|
+
function registerEventHandlers(instance, app) {
|
|
7
|
+
const handlers = Reflect.getMetadata(common_1.HANDLERS_KEY, instance.constructor) || [];
|
|
8
|
+
for (const { phase, method, priority } of handlers.sort((a, b) => b.priority - a.priority)) {
|
|
9
|
+
app.on(phase, async (...args) => instance[method](...args), priority);
|
|
10
|
+
}
|
|
11
|
+
const runners = Reflect.getMetadata(common_1.RUNNERS_KEY, instance.constructor) || [];
|
|
12
|
+
for (const { type, method, priority } of runners.sort((a, b) => b.priority - a.priority)) {
|
|
13
|
+
app.registerRunner((args) => instance[method](...args), type, priority);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
const index_1 = require("../../src/di/index");
|
|
13
|
+
let Logger = class Logger {
|
|
14
|
+
log(message) {
|
|
15
|
+
return `Log: ${message}`;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
Logger = __decorate([
|
|
19
|
+
(0, index_1.Service)()
|
|
20
|
+
], Logger);
|
|
21
|
+
let Database = class Database {
|
|
22
|
+
query(sql) {
|
|
23
|
+
return `Result of "${sql}"`;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
Database = __decorate([
|
|
27
|
+
(0, index_1.Service)()
|
|
28
|
+
], Database);
|
|
29
|
+
let UserService = class UserService {
|
|
30
|
+
logger;
|
|
31
|
+
database;
|
|
32
|
+
getUser(id) {
|
|
33
|
+
this.logger.log(`Fetching user with id: ${id}`);
|
|
34
|
+
return this.database.query(`SELECT * FROM users WHERE id = ${id}`);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, index_1.AutoWired)(),
|
|
39
|
+
__metadata("design:type", Logger)
|
|
40
|
+
], UserService.prototype, "logger", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
(0, index_1.AutoWired)(),
|
|
43
|
+
__metadata("design:type", Database)
|
|
44
|
+
], UserService.prototype, "database", void 0);
|
|
45
|
+
UserService = __decorate([
|
|
46
|
+
(0, index_1.Service)()
|
|
47
|
+
], UserService);
|
|
48
|
+
let OptionalDependencyService = class OptionalDependencyService {
|
|
49
|
+
optionalLogger;
|
|
50
|
+
hasLogger() {
|
|
51
|
+
return this.optionalLogger !== undefined;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
__decorate([
|
|
55
|
+
(0, index_1.AutoWired)({ required: false }),
|
|
56
|
+
__metadata("design:type", Logger)
|
|
57
|
+
], OptionalDependencyService.prototype, "optionalLogger", void 0);
|
|
58
|
+
OptionalDependencyService = __decorate([
|
|
59
|
+
(0, index_1.Service)()
|
|
60
|
+
], OptionalDependencyService);
|
|
61
|
+
describe("AutoWired Decorator", () => {
|
|
62
|
+
let container;
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
container = new index_1.Container();
|
|
65
|
+
});
|
|
66
|
+
it("should inject dependencies into UserService", () => {
|
|
67
|
+
container.register(Logger, { scope: "singleton" });
|
|
68
|
+
container.register(Database, { scope: "singleton" });
|
|
69
|
+
container.register(UserService, { scope: "singleton" });
|
|
70
|
+
const userService = container.get(UserService);
|
|
71
|
+
expect(userService).toBeInstanceOf(UserService);
|
|
72
|
+
// expect(userService.getUser(1)).toBe('Result of "SELECT * FROM users WHERE id = 1"');
|
|
73
|
+
});
|
|
74
|
+
it("should handle optional dependencies", () => {
|
|
75
|
+
container.register(OptionalDependencyService, { scope: "singleton" });
|
|
76
|
+
const optionalService = container.get(OptionalDependencyService);
|
|
77
|
+
expect(optionalService).toBeInstanceOf(OptionalDependencyService);
|
|
78
|
+
expect(optionalService.hasLogger()).toBe(false); // Logger is not registered, should be undefined
|
|
79
|
+
});
|
|
80
|
+
it("should throw error for missing required dependencies", () => {
|
|
81
|
+
container.register(UserService, { scope: "singleton" });
|
|
82
|
+
expect(() => container.get(UserService)).toThrow();
|
|
83
|
+
});
|
|
84
|
+
it("should inject dependencies into constructor and field dependencies", () => {
|
|
85
|
+
container.register(Logger, { scope: "singleton" });
|
|
86
|
+
container.register(Database, { scope: "singleton" });
|
|
87
|
+
container.register(UserService, { scope: "singleton" });
|
|
88
|
+
const userService = container.get(UserService);
|
|
89
|
+
expect(userService).toBeDefined();
|
|
90
|
+
expect(userService.getUser(1)).toBeDefined();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const index_1 = require("../../src/di/index");
|
|
10
|
+
let TestService = class TestService {
|
|
11
|
+
getValue() {
|
|
12
|
+
return 42;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
TestService = __decorate([
|
|
16
|
+
(0, index_1.Service)()
|
|
17
|
+
], TestService);
|
|
18
|
+
describe("Container", () => {
|
|
19
|
+
let container;
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
container = new index_1.Container();
|
|
22
|
+
});
|
|
23
|
+
it("should register and resolve a singleton service", () => {
|
|
24
|
+
container.register(TestService, { scope: "singleton" });
|
|
25
|
+
const resolved = container.get(TestService);
|
|
26
|
+
expect(resolved.getValue()).toBe(42);
|
|
27
|
+
});
|
|
28
|
+
it("should return singleton instances y default ", () => {
|
|
29
|
+
container.register(TestService, { scope: "singleton" });
|
|
30
|
+
const instance1 = container.get(TestService);
|
|
31
|
+
const instance2 = container.get(TestService);
|
|
32
|
+
expect(instance1).toBe(instance2); // Same instance
|
|
33
|
+
});
|
|
34
|
+
it("should return new instances for transient scope", () => {
|
|
35
|
+
container.register(TestService, { scope: "transient" });
|
|
36
|
+
const instance1 = container.get(TestService);
|
|
37
|
+
const instance2 = container.get(TestService);
|
|
38
|
+
expect(instance1).not.toBe(instance2); // Different instances
|
|
39
|
+
});
|
|
40
|
+
it("should throw error for unregistered services", () => {
|
|
41
|
+
expect(() => container.get(TestService)).toThrow("No provider found for TestService");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const index_1 = require("../../src/di/index");
|
|
16
|
+
let EmailNotificationService = class EmailNotificationService {
|
|
17
|
+
send(message) {
|
|
18
|
+
return `Email sent: ${message}`;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
EmailNotificationService = __decorate([
|
|
22
|
+
(0, index_1.Service)({ name: "emailNotificer" })
|
|
23
|
+
], EmailNotificationService);
|
|
24
|
+
let SMSNotificationService = class SMSNotificationService {
|
|
25
|
+
send(message) {
|
|
26
|
+
return `SMS sent: ${message}`;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
SMSNotificationService = __decorate([
|
|
30
|
+
(0, index_1.Service)({ name: "smsNotificer" })
|
|
31
|
+
], SMSNotificationService);
|
|
32
|
+
let OrderService = class OrderService {
|
|
33
|
+
emailService;
|
|
34
|
+
smsService;
|
|
35
|
+
constructor(emailService, smsService) {
|
|
36
|
+
this.emailService = emailService;
|
|
37
|
+
this.smsService = smsService;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
OrderService = __decorate([
|
|
41
|
+
(0, index_1.Service)(),
|
|
42
|
+
__param(0, (0, index_1.Qualifier)("emailNotificer")),
|
|
43
|
+
__param(1, (0, index_1.Qualifier)("smsNotificer")),
|
|
44
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
45
|
+
], OrderService);
|
|
46
|
+
describe("Qualifier Decorator", () => {
|
|
47
|
+
let container;
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
container = new index_1.Container();
|
|
50
|
+
});
|
|
51
|
+
it("should inject beans by qualifier name", () => {
|
|
52
|
+
container.registerWithName(EmailNotificationService, { scope: "singleton" }, "emailNotificer");
|
|
53
|
+
container.registerWithName(SMSNotificationService, { scope: "singleton" }, "smsNotificer");
|
|
54
|
+
container.register(OrderService, { scope: "singleton" });
|
|
55
|
+
const orderService = container.get(OrderService);
|
|
56
|
+
expect(orderService).toBeInstanceOf(OrderService);
|
|
57
|
+
expect(orderService['emailService']).toBeInstanceOf(EmailNotificationService);
|
|
58
|
+
expect(orderService['smsService']).toBeInstanceOf(SMSNotificationService);
|
|
59
|
+
expect(orderService.emailService.send("Hello")).toBe("Email sent: Hello");
|
|
60
|
+
expect(orderService.smsService.send("Hello")).toBe("SMS sent: Hello");
|
|
61
|
+
});
|
|
62
|
+
it("should retrieve beans by name from container", () => {
|
|
63
|
+
container.registerWithName(EmailNotificationService, { scope: "singleton" }, "emailNotificer");
|
|
64
|
+
const notifier = container.getByName("emailNotificer");
|
|
65
|
+
expect(notifier).toBeInstanceOf(EmailNotificationService);
|
|
66
|
+
expect(notifier.send("Test")).toBe("Email sent: Test");
|
|
67
|
+
});
|
|
68
|
+
it("should throw error for unknown qualifier names", () => {
|
|
69
|
+
expect(() => container.getByName("unknownService")).toThrow("No component found with name: unknownService");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const common_1 = require("@xtaskjs/common");
|
|
4
|
+
describe("Logger", () => {
|
|
5
|
+
it("Should print logs", () => {
|
|
6
|
+
const logger = new common_1.Logger();
|
|
7
|
+
const spy = jest.spyOn(console, "log").mockImplementation();
|
|
8
|
+
logger.info("hello");
|
|
9
|
+
expect(spy).toHaveBeenCalledWith(expect.stringContaining("hello"));
|
|
10
|
+
spy.mockRestore();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
const common_1 = require("@xtaskjs/common");
|
|
13
|
+
const src_1 = require("packages/core/src");
|
|
14
|
+
let TestLifeCycleListener = class TestLifeCycleListener {
|
|
15
|
+
events = [];
|
|
16
|
+
async onStarting() {
|
|
17
|
+
this.events.push("starting");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, common_1.OnEvent)('starting', 10),
|
|
22
|
+
__metadata("design:type", Function),
|
|
23
|
+
__metadata("design:paramtypes", []),
|
|
24
|
+
__metadata("design:returntype", Promise)
|
|
25
|
+
], TestLifeCycleListener.prototype, "onStarting", null);
|
|
26
|
+
TestLifeCycleListener = __decorate([
|
|
27
|
+
(0, src_1.Service)()
|
|
28
|
+
], TestLifeCycleListener);
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "xtaskjs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"workspaces": [
|
|
7
|
+
"packages/*"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "ts-node -r tsconfig-paths/register app.ts",
|
|
11
|
+
"build": "npm run clean; tsc",
|
|
12
|
+
"test": "npm run test --prefix packages/core && npm run test --prefix packages/common",
|
|
13
|
+
"clean": "rm -r dist"
|
|
14
|
+
},
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"express": "^5.1.0",
|
|
19
|
+
"reflect-metadata": "^0.2.2",
|
|
20
|
+
"ts-morph": "^27.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@babel/core": "^7.28.4",
|
|
24
|
+
"@babel/preset-env": "^7.28.3",
|
|
25
|
+
"@jest/globals": "^30.1.2",
|
|
26
|
+
"@types/express": "^5.0.3",
|
|
27
|
+
"@types/jest": "^30.0.0",
|
|
28
|
+
"babel-jest": "^30.1.2",
|
|
29
|
+
"jest": "^30.1.3",
|
|
30
|
+
"nodemon": "^3.1.10",
|
|
31
|
+
"ts-jest": "^29.4.4",
|
|
32
|
+
"ts-node": "^10.9.2",
|
|
33
|
+
"tsconfig-paths": "^4.2.0",
|
|
34
|
+
"typescript": "^5.9.2"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @xtaskjs/common
|
|
2
|
+
|
|
3
|
+
Common utilities for xtaskjs, a modern, fast Node.js web framework.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
```bash
|
|
7
|
+
npm install @xtaskjs/common
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
```typescript
|
|
12
|
+
import { ... } from '@xtaskjs/common';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
- Logger
|
|
17
|
+
- Decorators
|
|
18
|
+
- Shared types and constants
|
|
19
|
+
|
|
20
|
+
## Documentation
|
|
21
|
+
See [xtaskjs.com](https://xtaskjs.com) for full documentation.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src";
|