UNPKG

16.3 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __importDefault = (this && this.__importDefault) || function (mod) {
12 return (mod && mod.__esModule) ? mod : { "default": mod };
13};
14Object.defineProperty(exports, "__esModule", { value: true });
15const http_1 = __importDefault(require("http"));
16const AbstractEnvProvider_1 = require("./environment/AbstractEnvProvider");
17const AbstractLogger_1 = require("./logger/AbstractLogger");
18const AbstractHttpRequestHandler_1 = require("./controller/http/AbstractHttpRequestHandler");
19const AbstractSocketRequestHandler_1 = require("./controller/socket/AbstractSocketRequestHandler");
20const AbstractDatabaseAdapter_1 = require("./database/AbstractDatabaseAdapter");
21const DefaultLogger_1 = require("./logger/DefaultLogger");
22const DefaultEnvProvider_1 = require("./default-implementations/DefaultEnvProvider");
23const DefaultHttpRequestHandler_1 = require("./default-implementations/DefaultHttpRequestHandler");
24const DefaultSocketRequestHandler_1 = require("./default-implementations/DefaultSocketRequestHandler");
25const DefaultInMemoryDatabaseAdapter_1 = require("./default-implementations/DefaultInMemoryDatabaseAdapter");
26const DefaultDataValidator_1 = require("./default-implementations/DefaultDataValidator");
27const GlobalInjection_1 = require("./system/GlobalInjection");
28const ClaireError_1 = require("./system/ClaireError");
29const errors_1 = require("./system/errors");
30const DefaultHttpErrorHandler_1 = require("./default-implementations/DefaultHttpErrorHandler");
31class Claire {
32 constructor() {
33 this.port = 1992;
34 this.bootstrap = new class {
35 init() {
36 return __awaiter(this, void 0, void 0, function* () {
37 return;
38 });
39 }
40 stop() {
41 return __awaiter(this, void 0, void 0, function* () {
42 return;
43 });
44 }
45 };
46 this.envProvider = new DefaultEnvProvider_1.DefaultEnvProvider();
47 this.logger = new DefaultLogger_1.DefaultLogger();
48 this.httpRequestHandler = new DefaultHttpRequestHandler_1.DefaultHttpRequestHandler();
49 this.httpRequestHandler.errorHandler = new DefaultHttpErrorHandler_1.DefaultHttpErrorHandler();
50 this.socketRequestHandler = new DefaultSocketRequestHandler_1.DefaultSocketRequestHandler();
51 this.databaseAdapter = new DefaultInMemoryDatabaseAdapter_1.DefaultInMemoryDatabaseAdapter();
52 this.dataValidator = new DefaultDataValidator_1.DefaultDataValidator();
53 }
54 get envProvider() {
55 return this._envProvider;
56 }
57 set envProvider(envProvider) {
58 this._envProvider = envProvider;
59 GlobalInjection_1.getGlobalInjection().findAndReplace(envProvider, AbstractEnvProvider_1.AbstractEnvProvider);
60 }
61 get logger() {
62 return this._logger;
63 }
64 set logger(logger) {
65 this._logger = logger;
66 GlobalInjection_1.getGlobalInjection().findAndReplace(logger, AbstractLogger_1.AbstractLogger);
67 }
68 set socketRequestHandler(socketRequestHandler) {
69 this._socketRequestHandler = socketRequestHandler;
70 GlobalInjection_1.getGlobalInjection().findAndReplace(socketRequestHandler, AbstractSocketRequestHandler_1.AbstractSocketRequestHandler);
71 }
72 get socketRequestHandler() {
73 return this._socketRequestHandler;
74 }
75 set httpRequestHandler(httpRequestHandler) {
76 this._httpRequestHandler = httpRequestHandler;
77 GlobalInjection_1.getGlobalInjection().findAndReplace(httpRequestHandler, AbstractHttpRequestHandler_1.AbstractHttpRequestHandler);
78 }
79 get httpRequestHandler() {
80 return this._httpRequestHandler;
81 }
82 set dataValidator(dataValidator) {
83 this._dataValidator = dataValidator;
84 }
85 get dataValidator() {
86 return this._dataValidator;
87 }
88 get databaseAdapter() {
89 return this._databaseAdapter;
90 }
91 set databaseAdapter(databaseAdapter) {
92 this._databaseAdapter = databaseAdapter;
93 GlobalInjection_1.getGlobalInjection().findAndReplace(databaseAdapter, AbstractDatabaseAdapter_1.AbstractDatabaseAdapter);
94 }
95 stop() {
96 return __awaiter(this, void 0, void 0, function* () {
97 const globalInjection = GlobalInjection_1.getGlobalInjection();
98 yield this.bootstrap.stop();
99 yield this.databaseAdapter.stop();
100 for (const service of globalInjection.services) {
101 if (service.instance) {
102 yield service.instance.stop();
103 }
104 }
105 this.logger.info("Program terminate.");
106 process.exit(0);
107 });
108 }
109 start() {
110 return __awaiter(this, void 0, void 0, function* () {
111 //-- handle exceptions
112 process.on('SIGTERM', () => {
113 this.logger.warn("SIGTERM interrupt signal");
114 return this.stop();
115 });
116 process.on('SIGINT', () => {
117 this.logger.warn("SIGINT interrupt signal");
118 return this.stop();
119 });
120 process.on('uncaughtException', (err) => {
121 this.logger.error('uncaughtException', err.stack);
122 return this.stop();
123 });
124 process.on('unhandledRejection', (reason, p) => {
125 this.logger.error('unhandledRejection', reason, p);
126 return this.stop();
127 });
128 //-- perform injection
129 const globalInjection = GlobalInjection_1.getGlobalInjection();
130 for (const injectable of globalInjection.injectables) {
131 if (!injectable.instance) {
132 injectable.instance = new injectable.constructorFn();
133 }
134 }
135 for (const registry of globalInjection.injectRegistry) {
136 const matchedInjectable = globalInjection.injectables.filter(injectable => injectable.instance instanceof registry.keyPrototype && (!injectable.env || injectable.env.includes(this.envProvider.currentEnv)));
137 if (matchedInjectable.length === 0) {
138 throw new ClaireError_1.ClaireError(errors_1.NO_MATCHED_INJECTABLE, `${registry.prototype.constructor.name}:${registry.propertyKey}`);
139 }
140 if (matchedInjectable.length > 1) {
141 throw new ClaireError_1.ClaireError(errors_1.MULTIPLE_VERSIONS_OF_INJECTABLE, `${registry.prototype.constructor.name}:${registry.propertyKey}`);
142 }
143 registry.prototype[registry.propertyKey] = matchedInjectable[0].instance;
144 }
145 //-- init database adapters
146 yield this.databaseAdapter.init();
147 //-- init services
148 for (const service of globalInjection.services) {
149 if (service.instance) {
150 yield service.instance.init();
151 }
152 }
153 //-- bootstrap
154 yield this.bootstrap.init();
155 //-- mount request handlers;
156 let server = http_1.default.createServer();
157 //-- config http and socket
158 if (this.httpRequestHandler.controllers.length) {
159 this.httpRequestHandler.dataValidator = this.dataValidator;
160 //-- init controllers
161 for (const controller of this.httpRequestHandler.controllers) {
162 yield controller.init();
163 }
164 if (this.httpRequestHandler.authorizationProvider) {
165 yield this.httpRequestHandler.authorizationProvider.init();
166 }
167 server = this.httpRequestHandler.configure(server);
168 }
169 if (this.socketRequestHandler.controllers.length) {
170 this.socketRequestHandler.dataValidator = this.dataValidator;
171 //-- init controllers
172 for (const controller of this.socketRequestHandler.controllers) {
173 yield controller.init();
174 }
175 server = this.socketRequestHandler.configure(server);
176 }
177 return new Promise((resolve, reject) => {
178 try {
179 server.listen(this.port, () => {
180 return resolve();
181 });
182 }
183 catch (err) {
184 return reject(err);
185 }
186 });
187 });
188 }
189}
190exports.Claire = Claire;
191//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2xhaXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vbGliL0NsYWlyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUF3QjtBQUN4QiwyRUFBc0U7QUFDdEUsNERBQXVEO0FBQ3ZELDZGQUF3RjtBQUN4RixtR0FBOEY7QUFFOUYsZ0ZBQTJFO0FBQzNFLDBEQUFxRDtBQUNyRCxxRkFBZ0Y7QUFDaEYsbUdBQThGO0FBQzlGLHVHQUFrRztBQUNsRyw2R0FBd0c7QUFDeEcseUZBQW9GO0FBQ3BGLDhEQUE0RDtBQUM1RCxzREFBaUQ7QUFDakQsNENBQXVGO0FBQ3ZGLCtGQUEwRjtBQUkxRixNQUFhLE1BQU07SUFvQmY7UUFYTyxTQUFJLEdBQVcsSUFBSSxDQUFDO1FBQ3BCLGNBQVMsR0FBYSxJQUFJO1lBQ2hCLElBQUk7O29CQUNiLE9BQU87Z0JBQ1gsQ0FBQzthQUFBO1lBRVksSUFBSTs7b0JBQ2IsT0FBTztnQkFDWCxDQUFDO2FBQUE7U0FDSixDQUFDO1FBR0UsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLHVDQUFrQixFQUFFLENBQUM7UUFDNUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLDZCQUFhLEVBQUUsQ0FBQztRQUNsQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxxREFBeUIsRUFBRSxDQUFDO1FBQzFELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLEdBQUcsSUFBSSxpREFBdUIsRUFBRSxDQUFDO1FBQ3JFLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLHlEQUEyQixFQUFFLENBQUM7UUFDOUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLCtEQUE4QixFQUFFLENBQUM7UUFDNUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLDJDQUFvQixFQUFFLENBQUM7SUFDcEQsQ0FBQztJQUVELElBQVcsV0FBVztRQUNsQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQUVE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
\No newline at end of file