1 | ;
|
2 | var __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 | };
|
11 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
12 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
13 | };
|
14 | Object.defineProperty(exports, "__esModule", { value: true });
|
15 | const http_1 = __importDefault(require("http"));
|
16 | const AbstractEnvProvider_1 = require("./environment/AbstractEnvProvider");
|
17 | const AbstractLogger_1 = require("./logger/AbstractLogger");
|
18 | const AbstractHttpRequestHandler_1 = require("./controller/http/AbstractHttpRequestHandler");
|
19 | const AbstractSocketRequestHandler_1 = require("./controller/socket/AbstractSocketRequestHandler");
|
20 | const AbstractDatabaseAdapter_1 = require("./database/AbstractDatabaseAdapter");
|
21 | const DefaultLogger_1 = require("./logger/DefaultLogger");
|
22 | const DefaultEnvProvider_1 = require("./default-implementations/DefaultEnvProvider");
|
23 | const DefaultHttpRequestHandler_1 = require("./default-implementations/DefaultHttpRequestHandler");
|
24 | const DefaultSocketRequestHandler_1 = require("./default-implementations/DefaultSocketRequestHandler");
|
25 | const DefaultInMemoryDatabaseAdapter_1 = require("./default-implementations/DefaultInMemoryDatabaseAdapter");
|
26 | const DefaultDataValidator_1 = require("./default-implementations/DefaultDataValidator");
|
27 | const GlobalInjection_1 = require("./system/GlobalInjection");
|
28 | const ClaireError_1 = require("./system/ClaireError");
|
29 | const errors_1 = require("./system/errors");
|
30 | const DefaultHttpErrorHandler_1 = require("./default-implementations/DefaultHttpErrorHandler");
|
31 | class 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 | }
|
190 | exports.Claire = Claire;
|
191 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2xhaXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vbGliL0NsYWlyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUF3QjtBQUN4QiwyRUFBc0U7QUFDdEUsNERBQXVEO0FBQ3ZELDZGQUF3RjtBQUN4RixtR0FBOEY7QUFFOUYsZ0ZBQTJFO0FBQzNFLDBEQUFxRDtBQUNyRCxxRkFBZ0Y7QUFDaEYsbUdBQThGO0FBQzlGLHVHQUFrRztBQUNsRyw2R0FBd0c7QUFDeEcseUZBQW9GO0FBQ3BGLDhEQUE0RDtBQUM1RCxzREFBaUQ7QUFDakQsNENBQXVGO0FBQ3ZGLCtGQUEwRjtBQUkxRixNQUFhLE1BQU07SUFvQmY7UUFYTyxTQUFJLEdBQVcsSUFBSSxDQUFDO1FBQ3BCLGNBQVMsR0FBYSxJQUFJO1lBQ2hCLElBQUk7O29CQUNiLE9BQU87Z0JBQ1gsQ0FBQzthQUFBO1lBRVksSUFBSTs7b0JBQ2IsT0FBTztnQkFDWCxDQUFDO2FBQUE7U0FDSixDQUFDO1FBR0UsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLHVDQUFrQixFQUFFLENBQUM7UUFDNUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLDZCQUFhLEVBQUUsQ0FBQztRQUNsQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxxREFBeUIsRUFBRSxDQUFDO1FBQzFELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLEdBQUcsSUFBSSxpREFBdUIsRUFBRSxDQUFDO1FBQ3JFLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLHlEQUEyQixFQUFFLENBQUM7UUFDOUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLCtEQUE4QixFQUFFLENBQUM7UUFDNUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLDJDQUFvQixFQUFFLENBQUM7SUFDcEQsQ0FBQztJQUVELElBQVcsV0FBVztRQUNsQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQUVE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 |
\ | No newline at end of file |