@simplysm/sd-cli 10.0.4 → 10.0.22
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/.eslintrc.cjs +1 -1
- package/dist/SdLinter.d.ts +5 -0
- package/dist/SdLinter.js.map +1 -0
- package/dist/SdLinter.mjs +37 -0
- package/dist/SdTsIncrementalBuilder.d.ts +16 -0
- package/dist/SdTsIncrementalBuilder.js.map +1 -0
- package/dist/SdTsIncrementalBuilder.mjs +54 -0
- package/dist/build-cluster.js.map +1 -1
- package/dist/build-cluster.mjs +124 -0
- package/dist/builders/SdCliClientBuilder.d.ts +13 -0
- package/dist/builders/SdCliClientBuilder.js.map +1 -0
- package/dist/builders/SdCliClientBuilder.mjs +167 -0
- package/dist/builders/SdCliJsLibLinter.d.ts +3 -7
- package/dist/builders/SdCliJsLibLinter.js.map +1 -1
- package/dist/builders/{SdCliJsLibLinter.js → SdCliJsLibLinter.mjs} +8 -17
- package/dist/builders/SdCliServerBuilder.d.ts +14 -0
- package/dist/builders/SdCliServerBuilder.js.map +1 -0
- package/dist/builders/SdCliServerBuilder.mjs +171 -0
- package/dist/builders/SdCliTsLibBuilder.d.ts +3 -10
- package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
- package/dist/builders/SdCliTsLibBuilder.mjs +75 -0
- package/dist/commons.d.ts +28 -2
- package/dist/entry/SdCliLocalUpdate.d.ts +7 -0
- package/dist/entry/SdCliLocalUpdate.js.map +1 -0
- package/dist/entry/SdCliLocalUpdate.mjs +55 -0
- package/dist/entry/SdCliProject.d.ts +1 -0
- package/dist/entry/SdCliProject.js.map +1 -1
- package/dist/entry/{SdCliProject.js → SdCliProject.mjs} +94 -10
- package/dist/sd-cli.js.map +1 -1
- package/dist/{sd-cli.js → sd-cli.mjs} +16 -0
- package/dist/sd-core-common/src/decorators/NotifyPropertyChange.d.ts +20 -0
- package/dist/sd-core-common/src/decorators/NotifyPropertyChange.js.map +1 -0
- package/dist/sd-core-common/src/decorators/NotifyPropertyChange.mjs +12 -0
- package/dist/sd-core-common/src/decorators/PropertyGetSetDecoratorBase.d.ts +43 -0
- package/dist/sd-core-common/src/decorators/PropertyGetSetDecoratorBase.js.map +1 -0
- package/dist/sd-core-common/src/decorators/PropertyGetSetDecoratorBase.mjs +54 -0
- package/dist/sd-core-common/src/decorators/PropertyValidate.d.ts +16 -0
- package/dist/sd-core-common/src/decorators/PropertyValidate.js.map +1 -0
- package/dist/sd-core-common/src/decorators/PropertyValidate.mjs +26 -0
- package/dist/sd-core-common/src/decorators/decorator-return-types.d.ts +14 -0
- package/dist/sd-core-common/src/decorators/decorator-return-types.js.map +1 -0
- package/dist/sd-core-common/src/decorators/decorator-return-types.mjs +2 -0
- package/dist/sd-core-common/src/errors/ArgumentError.d.ts +10 -0
- package/dist/sd-core-common/src/errors/ArgumentError.js.map +1 -0
- package/dist/sd-core-common/src/errors/ArgumentError.mjs +13 -0
- package/dist/sd-core-common/src/errors/NeverEntryError.d.ts +10 -0
- package/dist/sd-core-common/src/errors/NeverEntryError.js.map +1 -0
- package/dist/sd-core-common/src/errors/NeverEntryError.mjs +13 -0
- package/dist/sd-core-common/src/errors/NotImplementError.d.ts +10 -0
- package/dist/sd-core-common/src/errors/NotImplementError.js.map +1 -0
- package/dist/sd-core-common/src/errors/NotImplementError.mjs +13 -0
- package/dist/sd-core-common/src/errors/SdError.d.ts +23 -0
- package/dist/sd-core-common/src/errors/SdError.js.map +1 -0
- package/dist/sd-core-common/src/errors/SdError.mjs +40 -0
- package/dist/sd-core-common/src/errors/TimeoutError.d.ts +11 -0
- package/dist/sd-core-common/src/errors/TimeoutError.js.map +1 -0
- package/dist/sd-core-common/src/errors/TimeoutError.mjs +16 -0
- package/dist/sd-core-common/src/extensions/ArrayExtension.d.ts +147 -0
- package/dist/sd-core-common/src/extensions/ArrayExtension.js.map +1 -0
- package/dist/sd-core-common/src/extensions/ArrayExtension.mjs +448 -0
- package/dist/sd-core-common/src/extensions/MapExtension.d.ts +4 -0
- package/dist/sd-core-common/src/extensions/MapExtension.js.map +1 -0
- package/dist/sd-core-common/src/extensions/MapExtension.mjs +15 -0
- package/dist/sd-core-common/src/extensions/SetExtension.d.ts +3 -0
- package/dist/sd-core-common/src/extensions/SetExtension.js.map +1 -0
- package/dist/sd-core-common/src/extensions/SetExtension.mjs +10 -0
- package/dist/sd-core-common/src/index.d.ts +32 -0
- package/dist/sd-core-common/src/index.js.map +1 -0
- package/dist/sd-core-common/src/index.mjs +33 -0
- package/dist/sd-core-common/src/types/DateOnly.d.ts +135 -0
- package/dist/sd-core-common/src/types/DateOnly.js.map +1 -0
- package/dist/sd-core-common/src/types/DateOnly.mjs +220 -0
- package/dist/sd-core-common/src/types/DateTime.d.ts +42 -0
- package/dist/sd-core-common/src/types/DateTime.js.map +1 -0
- package/dist/sd-core-common/src/types/DateTime.mjs +156 -0
- package/dist/sd-core-common/src/types/DeepPartial.d.ts +3 -0
- package/dist/sd-core-common/src/types/DeepPartial.js.map +1 -0
- package/dist/sd-core-common/src/types/DeepPartial.mjs +2 -0
- package/dist/sd-core-common/src/types/ObjectSet.d.ts +4 -0
- package/dist/sd-core-common/src/types/ObjectSet.js.map +1 -0
- package/dist/sd-core-common/src/types/ObjectSet.mjs +18 -0
- package/dist/sd-core-common/src/types/Time.d.ts +27 -0
- package/dist/sd-core-common/src/types/Time.js.map +1 -0
- package/dist/sd-core-common/src/types/Time.mjs +108 -0
- package/dist/sd-core-common/src/types/Type.d.ts +7 -0
- package/dist/sd-core-common/src/types/Type.js.map +1 -0
- package/dist/sd-core-common/src/types/Type.mjs +2 -0
- package/dist/sd-core-common/src/types/UnwrappedType.d.ts +1 -0
- package/dist/sd-core-common/src/types/UnwrappedType.js.map +1 -0
- package/dist/sd-core-common/src/types/UnwrappedType.mjs +2 -0
- package/dist/sd-core-common/src/types/Uuid.d.ts +8 -0
- package/dist/sd-core-common/src/types/Uuid.js.map +1 -0
- package/dist/sd-core-common/src/types/Uuid.mjs +26 -0
- package/dist/sd-core-common/src/types/WrappedType.d.ts +1 -0
- package/dist/sd-core-common/src/types/WrappedType.js.map +1 -0
- package/dist/sd-core-common/src/types/WrappedType.mjs +2 -0
- package/dist/sd-core-common/src/utils/DateTimeFormatUtil.d.ts +12 -0
- package/dist/sd-core-common/src/utils/DateTimeFormatUtil.js.map +1 -0
- package/dist/sd-core-common/src/utils/DateTimeFormatUtil.mjs +67 -0
- package/dist/sd-core-common/src/utils/FunctionQueue.d.ts +8 -0
- package/dist/sd-core-common/src/utils/FunctionQueue.js.map +1 -0
- package/dist/sd-core-common/src/utils/FunctionQueue.mjs +46 -0
- package/dist/sd-core-common/src/utils/FunctionUtil.d.ts +6 -0
- package/dist/sd-core-common/src/utils/FunctionUtil.js.map +1 -0
- package/dist/sd-core-common/src/utils/FunctionUtil.mjs +31 -0
- package/dist/sd-core-common/src/utils/JsonConvert.d.ts +8 -0
- package/dist/sd-core-common/src/utils/JsonConvert.js.map +1 -0
- package/dist/sd-core-common/src/utils/JsonConvert.mjs +78 -0
- package/dist/sd-core-common/src/utils/MathUtil.d.ts +3 -0
- package/dist/sd-core-common/src/utils/MathUtil.js.map +1 -0
- package/dist/sd-core-common/src/utils/MathUtil.mjs +6 -0
- package/dist/sd-core-common/src/utils/NumberUtil.d.ts +6 -0
- package/dist/sd-core-common/src/utils/NumberUtil.js.map +1 -0
- package/dist/sd-core-common/src/utils/NumberUtil.mjs +32 -0
- package/dist/sd-core-common/src/utils/ObjectUtil.d.ts +80 -0
- package/dist/sd-core-common/src/utils/ObjectUtil.js.map +1 -0
- package/dist/sd-core-common/src/utils/ObjectUtil.mjs +452 -0
- package/dist/sd-core-common/src/utils/SdSyncEventEmitter.d.ts +6 -0
- package/dist/sd-core-common/src/utils/SdSyncEventEmitter.js.map +1 -0
- package/dist/sd-core-common/src/utils/SdSyncEventEmitter.mjs +27 -0
- package/dist/sd-core-common/src/utils/StringUtil.d.ts +8 -0
- package/dist/sd-core-common/src/utils/StringUtil.js.map +1 -0
- package/dist/sd-core-common/src/utils/StringUtil.mjs +77 -0
- package/dist/sd-core-common/src/utils/Wait.d.ts +4 -0
- package/dist/sd-core-common/src/utils/Wait.js.map +1 -0
- package/dist/sd-core-common/src/utils/Wait.mjs +23 -0
- package/dist/sd-core-node/src/index.d.ts +6 -0
- package/dist/sd-core-node/src/index.js.map +1 -0
- package/dist/sd-core-node/src/index.mjs +7 -0
- package/dist/sd-core-node/src/utils/FsUtil.d.ts +44 -0
- package/dist/sd-core-node/src/utils/FsUtil.js.map +1 -0
- package/dist/sd-core-node/src/utils/FsUtil.mjs +493 -0
- package/dist/sd-core-node/src/utils/Logger.d.ts +91 -0
- package/dist/sd-core-node/src/utils/Logger.js.map +1 -0
- package/dist/sd-core-node/src/utils/Logger.mjs +185 -0
- package/dist/sd-core-node/src/utils/PathUtil.d.ts +6 -0
- package/dist/sd-core-node/src/utils/PathUtil.js.map +1 -0
- package/dist/sd-core-node/src/utils/PathUtil.mjs +24 -0
- package/dist/sd-core-node/src/utils/SdFsWatcher.d.ts +15 -0
- package/dist/sd-core-node/src/utils/SdFsWatcher.js.map +1 -0
- package/dist/sd-core-node/src/utils/SdFsWatcher.mjs +43 -0
- package/dist/sd-core-node/src/utils/SdProcess.d.ts +5 -0
- package/dist/sd-core-node/src/utils/SdProcess.js.map +1 -0
- package/dist/sd-core-node/src/utils/SdProcess.mjs +36 -0
- package/dist/sd-orm-common/src/CaseQueryHelper.d.ts +12 -0
- package/dist/sd-orm-common/src/CaseQueryHelper.js.map +1 -0
- package/dist/sd-orm-common/src/CaseQueryHelper.mjs +19 -0
- package/dist/sd-orm-common/src/CaseWhenQueryHelper.d.ts +12 -0
- package/dist/sd-orm-common/src/CaseWhenQueryHelper.js.map +1 -0
- package/dist/sd-orm-common/src/CaseWhenQueryHelper.mjs +20 -0
- package/dist/sd-orm-common/src/DbContext.d.ts +81 -0
- package/dist/sd-orm-common/src/DbContext.js.map +1 -0
- package/dist/sd-orm-common/src/DbContext.mjs +635 -0
- package/dist/sd-orm-common/src/IDbConnection.d.ts +15 -0
- package/dist/sd-orm-common/src/IDbConnection.js.map +1 -0
- package/dist/sd-orm-common/src/IDbConnection.mjs +2 -0
- package/dist/sd-orm-common/src/IDbContextExecutor.d.ts +17 -0
- package/dist/sd-orm-common/src/IDbContextExecutor.js.map +1 -0
- package/dist/sd-orm-common/src/IDbContextExecutor.mjs +2 -0
- package/dist/sd-orm-common/src/IDbMigration.d.ts +4 -0
- package/dist/sd-orm-common/src/IDbMigration.js.map +1 -0
- package/dist/sd-orm-common/src/IDbMigration.mjs +2 -0
- package/dist/sd-orm-common/src/QueryBuilder.d.ts +48 -0
- package/dist/sd-orm-common/src/QueryBuilder.js.map +1 -0
- package/dist/sd-orm-common/src/QueryBuilder.mjs +1022 -0
- package/dist/sd-orm-common/src/QueryHelper.d.ts +75 -0
- package/dist/sd-orm-common/src/QueryHelper.js.map +1 -0
- package/dist/sd-orm-common/src/QueryHelper.mjs +627 -0
- package/dist/sd-orm-common/src/QueryUnit.d.ts +10 -0
- package/dist/sd-orm-common/src/QueryUnit.js.map +1 -0
- package/dist/sd-orm-common/src/QueryUnit.mjs +16 -0
- package/dist/sd-orm-common/src/Queryable.d.ts +105 -0
- package/dist/sd-orm-common/src/Queryable.js.map +1 -0
- package/dist/sd-orm-common/src/Queryable.mjs +1375 -0
- package/dist/sd-orm-common/src/SdOrmDataType.d.ts +21 -0
- package/dist/sd-orm-common/src/SdOrmDataType.js.map +1 -0
- package/dist/sd-orm-common/src/SdOrmDataType.mjs +2 -0
- package/dist/sd-orm-common/src/commons.d.ts +400 -0
- package/dist/sd-orm-common/src/commons.js.map +1 -0
- package/dist/sd-orm-common/src/commons.mjs +8 -0
- package/dist/sd-orm-common/src/decorators.d.ts +29 -0
- package/dist/sd-orm-common/src/decorators.js.map +1 -0
- package/dist/sd-orm-common/src/decorators.mjs +89 -0
- package/dist/sd-orm-common/src/index.d.ts +17 -0
- package/dist/sd-orm-common/src/index.js.map +1 -0
- package/dist/sd-orm-common/src/index.mjs +18 -0
- package/dist/sd-orm-common/src/models/SystemMigration.d.ts +3 -0
- package/dist/sd-orm-common/src/models/SystemMigration.js.map +1 -0
- package/dist/sd-orm-common/src/models/SystemMigration.mjs +13 -0
- package/dist/sd-orm-common/src/utils/DbDefinitionUtil.d.ts +14 -0
- package/dist/sd-orm-common/src/utils/DbDefinitionUtil.js.map +1 -0
- package/dist/sd-orm-common/src/utils/DbDefinitionUtil.mjs +66 -0
- package/dist/sd-orm-common/src/utils/SdOrmUtil.d.ts +8 -0
- package/dist/sd-orm-common/src/utils/SdOrmUtil.js.map +1 -0
- package/dist/sd-orm-common/src/utils/SdOrmUtil.mjs +248 -0
- package/dist/sd-orm-node/src/DbConnectionFactory.d.ts +4 -0
- package/dist/sd-orm-node/src/DbConnectionFactory.js.map +1 -0
- package/dist/sd-orm-node/src/DbConnectionFactory.mjs +17 -0
- package/dist/sd-orm-node/src/NodeDbContextExecutor.d.ts +19 -0
- package/dist/sd-orm-node/src/NodeDbContextExecutor.js.map +1 -0
- package/dist/sd-orm-node/src/NodeDbContextExecutor.mjs +71 -0
- package/dist/sd-orm-node/src/SdOrm.d.ts +10 -0
- package/dist/sd-orm-node/src/SdOrm.js.map +1 -0
- package/dist/sd-orm-node/src/SdOrm.mjs +25 -0
- package/dist/sd-orm-node/src/index.d.ts +4 -0
- package/dist/sd-orm-node/src/index.js.map +1 -0
- package/dist/sd-orm-node/src/index.mjs +5 -0
- package/dist/sd-orm-node-mssql/src/MssqlDbConnection.d.ts +25 -0
- package/dist/sd-orm-node-mssql/src/MssqlDbConnection.js.map +1 -0
- package/dist/sd-orm-node-mssql/src/MssqlDbConnection.mjs +321 -0
- package/dist/sd-orm-node-mssql/src/index.d.ts +2 -0
- package/dist/sd-orm-node-mssql/src/index.js.map +1 -0
- package/dist/sd-orm-node-mssql/src/index.mjs +3 -0
- package/dist/sd-orm-node-mysql/src/MysqlDbConnection.d.ts +22 -0
- package/dist/sd-orm-node-mysql/src/MysqlDbConnection.js.map +1 -0
- package/dist/sd-orm-node-mysql/src/MysqlDbConnection.mjs +200 -0
- package/dist/sd-orm-node-mysql/src/index.d.ts +2 -0
- package/dist/sd-orm-node-mysql/src/index.js.map +1 -0
- package/dist/sd-orm-node-mysql/src/index.mjs +3 -0
- package/dist/sd-orm-node-sqlite/src/SqliteDbConnection.d.ts +22 -0
- package/dist/sd-orm-node-sqlite/src/SqliteDbConnection.js.map +1 -0
- package/dist/sd-orm-node-sqlite/src/SqliteDbConnection.mjs +172 -0
- package/dist/sd-orm-node-sqlite/src/index.d.ts +2 -0
- package/dist/sd-orm-node-sqlite/src/index.js.map +1 -0
- package/dist/sd-orm-node-sqlite/src/index.mjs +3 -0
- package/dist/sd-service-common/src/commons-orm.d.ts +4 -0
- package/dist/sd-service-common/src/commons-orm.js.map +1 -0
- package/dist/sd-service-common/src/commons-orm.mjs +2 -0
- package/dist/sd-service-common/src/commons-smtp.d.ts +29 -0
- package/dist/sd-service-common/src/commons-smtp.js.map +1 -0
- package/dist/sd-service-common/src/commons-smtp.mjs +2 -0
- package/dist/sd-service-common/src/commons.d.ts +57 -0
- package/dist/sd-service-common/src/commons.js.map +1 -0
- package/dist/sd-service-common/src/commons.mjs +3 -0
- package/dist/sd-service-common/src/index.d.ts +3 -0
- package/dist/sd-service-common/src/index.js.map +1 -0
- package/dist/sd-service-common/src/index.mjs +4 -0
- package/dist/sd-service-server/src/ApiServiceError.d.ts +12 -0
- package/dist/sd-service-server/src/ApiServiceError.js.map +1 -0
- package/dist/sd-service-server/src/ApiServiceError.mjs +15 -0
- package/dist/sd-service-server/src/SdServiceServer.d.ts +39 -0
- package/dist/sd-service-server/src/SdServiceServer.js.map +1 -0
- package/dist/sd-service-server/src/SdServiceServer.mjs +513 -0
- package/dist/sd-service-server/src/commons.d.ts +23 -0
- package/dist/sd-service-server/src/commons.js.map +1 -0
- package/dist/sd-service-server/src/commons.mjs +3 -0
- package/dist/sd-service-server/src/index.d.ts +8 -0
- package/dist/sd-service-server/src/index.js.map +1 -0
- package/dist/sd-service-server/src/index.mjs +9 -0
- package/dist/sd-service-server/src/services/SdAutoUpdateService.d.ts +4 -0
- package/dist/sd-service-server/src/services/SdAutoUpdateService.js.map +1 -0
- package/dist/sd-service-server/src/services/SdAutoUpdateService.mjs +20 -0
- package/dist/sd-service-server/src/services/SdCryptoService.d.ts +7 -0
- package/dist/sd-service-server/src/services/SdCryptoService.js.map +1 -0
- package/dist/sd-service-server/src/services/SdCryptoService.mjs +39 -0
- package/dist/sd-service-server/src/services/SdOrmService.d.ts +22 -0
- package/dist/sd-service-server/src/services/SdOrmService.js.map +1 -0
- package/dist/sd-service-server/src/services/SdOrmService.mjs +115 -0
- package/dist/sd-service-server/src/services/SdSmtpClientService.d.ts +6 -0
- package/dist/sd-service-server/src/services/SdSmtpClientService.js.map +1 -0
- package/dist/sd-service-server/src/services/SdSmtpClientService.mjs +44 -0
- package/dist/sd-service-server/src/utils/SdServiceServerConfigUtil.d.ts +4 -0
- package/dist/sd-service-server/src/utils/SdServiceServerConfigUtil.js.map +1 -0
- package/dist/sd-service-server/src/utils/SdServiceServerConfigUtil.mjs +36 -0
- package/dist/server-worker.d.ts +1 -0
- package/dist/server-worker.js.map +1 -0
- package/dist/server-worker.mjs +36 -0
- package/package.json +12 -5
- package/src/SdLinter.ts +41 -0
- package/src/SdTsIncrementalBuilder.ts +75 -0
- package/src/build-cluster.ts +69 -18
- package/src/builders/SdCliClientBuilder.ts +189 -0
- package/src/builders/SdCliJsLibLinter.ts +11 -23
- package/src/builders/SdCliServerBuilder.ts +191 -0
- package/src/builders/SdCliTsLibBuilder.ts +33 -202
- package/src/commons.ts +33 -2
- package/src/entry/SdCliLocalUpdate.ts +70 -0
- package/src/entry/SdCliProject.ts +133 -17
- package/src/sd-cli.ts +20 -0
- package/src/server-worker.ts +45 -0
- package/tsconfig.json +1 -10
- package/dist/build-cluster.js +0 -75
- package/dist/builders/SdCliTsLibBuilder.js +0 -205
- /package/dist/{commons.js → commons.mjs} +0 -0
- /package/dist/utils/{SdCliBuildResultUtil.js → SdCliBuildResultUtil.mjs} +0 -0
- /package/dist/utils/{SdCliConfigUtil.js → SdCliConfigUtil.mjs} +0 -0
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import https from "https";
|
|
2
|
+
import http from "http";
|
|
3
|
+
import url from "url";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { FsUtil, Logger } from "@simplysm/sd-core-node";
|
|
6
|
+
import { EventEmitter } from "events";
|
|
7
|
+
import { DateTime, JsonConvert, Wait } from "@simplysm/sd-core-common";
|
|
8
|
+
import { WebSocket, WebSocketServer } from "ws";
|
|
9
|
+
import mime from "mime";
|
|
10
|
+
import { ApiServiceError } from "./ApiServiceError";
|
|
11
|
+
export class SdServiceServer extends EventEmitter {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super();
|
|
14
|
+
this.options = options;
|
|
15
|
+
this._logger = Logger.get(["simplysm", "sd-service", this.constructor.name]);
|
|
16
|
+
this.isOpen = false;
|
|
17
|
+
this._splitReqCache = new Map();
|
|
18
|
+
this._eventListeners = [];
|
|
19
|
+
// public devMiddlewares?: NextHandleFunction[];
|
|
20
|
+
/***
|
|
21
|
+
* 경로 프록시 (브라우저에 입력된 경로를 기본 파일경로가 아닌 다른 파일경로로 바꾸어 리턴함)
|
|
22
|
+
*
|
|
23
|
+
* * from: 서버내 'www' 이후의 상대경로 (절대경로 입력 불가)
|
|
24
|
+
* * to: 서버내 파일의 절대경로 혹은 DEVSERVER의 port
|
|
25
|
+
* * 'from'에 'api'로 시작하는 경로 사용 불가
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
this.pathProxy = {};
|
|
29
|
+
}
|
|
30
|
+
async getWsClientAsync(socketId) {
|
|
31
|
+
try {
|
|
32
|
+
await Wait.until(() => {
|
|
33
|
+
if (!this._wsServer)
|
|
34
|
+
return false;
|
|
35
|
+
const wsClients = Array.from(this._wsServer.clients).filter((item) => item.readyState === WebSocket.OPEN && item["id"] === socketId);
|
|
36
|
+
if (wsClients.length > 1) {
|
|
37
|
+
this._logger.debug("클라이언트 중복: " + socketId + ": " + wsClients.length + "\n" + wsClients.map((item) => " - " + item["connectedAtDateTime"].toFormatString("yyyy:MM:dd HH:mm:ss.fff")).join("\n"));
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return wsClients.length === 1;
|
|
42
|
+
}
|
|
43
|
+
}, 500, 1000);
|
|
44
|
+
return Array.from(this._wsServer.clients).single((item) => item.readyState === WebSocket.OPEN && item["id"] === socketId);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
this._logger.error("소켓요청을 처리하는 중에 클라이언트 소켓이 끊김", err);
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async listenAsync() {
|
|
52
|
+
await new Promise(async (resolve) => {
|
|
53
|
+
this._logger.debug("서버 시작..." + process.env["SD_VERSION"]);
|
|
54
|
+
if (this.options.ssl) {
|
|
55
|
+
const pfx = typeof this.options.ssl.pfxBuffer === "function" ? await this.options.ssl.pfxBuffer() : this.options.ssl.pfxBuffer;
|
|
56
|
+
this._httpServer = https.createServer({
|
|
57
|
+
pfx,
|
|
58
|
+
passphrase: this.options.ssl.passphrase,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this._httpServer = http.createServer();
|
|
63
|
+
}
|
|
64
|
+
this._httpServer.on("request", async (req, res) => {
|
|
65
|
+
await this._onWebRequestAsync(req, res);
|
|
66
|
+
});
|
|
67
|
+
this._wsServer = new WebSocketServer({ server: this._httpServer });
|
|
68
|
+
this._wsServer.on("connection", async (wsClient) => {
|
|
69
|
+
wsClient["isAlive"] = true;
|
|
70
|
+
wsClient.on("pong", () => {
|
|
71
|
+
wsClient["isAlive"] = true;
|
|
72
|
+
});
|
|
73
|
+
await this._onWsClientConnectionAsync(wsClient);
|
|
74
|
+
});
|
|
75
|
+
clearInterval(this._pingInterval);
|
|
76
|
+
this._pingInterval = setInterval(() => {
|
|
77
|
+
this._wsServer.clients.forEach((wsClient) => {
|
|
78
|
+
if (wsClient["isAlive"] === false)
|
|
79
|
+
return wsClient.terminate();
|
|
80
|
+
wsClient["isAlive"] = false;
|
|
81
|
+
wsClient.ping();
|
|
82
|
+
});
|
|
83
|
+
}, 10000);
|
|
84
|
+
this._httpServer.listen(this.options.port, () => {
|
|
85
|
+
resolve();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
this.isOpen = true;
|
|
89
|
+
this._logger.debug("서버 시작됨");
|
|
90
|
+
this.emit("ready");
|
|
91
|
+
}
|
|
92
|
+
async closeAsync() {
|
|
93
|
+
clearInterval(this._pingInterval);
|
|
94
|
+
if (this._wsServer) {
|
|
95
|
+
this._wsServer.clients.forEach((client) => {
|
|
96
|
+
client.terminate();
|
|
97
|
+
});
|
|
98
|
+
await new Promise((resolve, reject) => {
|
|
99
|
+
this._wsServer.close((err) => {
|
|
100
|
+
if (err) {
|
|
101
|
+
reject(err);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
resolve();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
await new Promise((resolve, reject) => {
|
|
109
|
+
if (!this._httpServer || !this._httpServer.listening) {
|
|
110
|
+
resolve();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this._httpServer.close((err) => {
|
|
114
|
+
if (err) {
|
|
115
|
+
reject(err);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
resolve();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
this.isOpen = false;
|
|
122
|
+
this._logger.debug("서버 종료됨");
|
|
123
|
+
this.emit("close");
|
|
124
|
+
}
|
|
125
|
+
broadcastReload() {
|
|
126
|
+
this._logger.debug("서버내 모든 클라이언트 RELOAD 명령 전송");
|
|
127
|
+
this._wsServer?.clients.forEach(async (wsClient) => {
|
|
128
|
+
await this._sendAsync(wsClient, { name: "client-reload" });
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async _getWsClientIdAsync(wsClient) {
|
|
132
|
+
return await new Promise(async (resolve) => {
|
|
133
|
+
const msgFn = (msgJson) => {
|
|
134
|
+
const msg = JsonConvert.parse(msgJson);
|
|
135
|
+
if (msg.name === "client-get-id-response") {
|
|
136
|
+
wsClient.off("message", msgFn);
|
|
137
|
+
resolve(msg.body);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
wsClient.on("message", msgFn);
|
|
141
|
+
await this._sendAsync(wsClient, { name: "client-get-id" });
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
async _onWsClientConnectionAsync(wsClient) {
|
|
145
|
+
const wsClientId = await this._getWsClientIdAsync(wsClient);
|
|
146
|
+
this._wsServer?.clients.forEach((client) => {
|
|
147
|
+
if (client["id"] === wsClientId) {
|
|
148
|
+
this._logger.debug("클라이언트 기존연결 끊기: " + wsClientId + ": " + client["connectedAtDateTime"].toFormatString("yyyy:MM:dd HH:mm:ss.fff"));
|
|
149
|
+
client.terminate();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
wsClient["id"] = wsClientId;
|
|
153
|
+
wsClient["connectedAtDateTime"] = new DateTime();
|
|
154
|
+
this._logger.debug("클라이언트 연결됨: " + wsClientId + ": " + this._wsServer?.clients.size);
|
|
155
|
+
wsClient.on("close", (code) => {
|
|
156
|
+
this._onWsClientClosed(wsClientId, code);
|
|
157
|
+
});
|
|
158
|
+
wsClient.on("message", async (msgJson) => {
|
|
159
|
+
await this._onWsClientMessageAsync(wsClientId, msgJson);
|
|
160
|
+
});
|
|
161
|
+
await this._sendAsync(wsClient, { name: "connected" });
|
|
162
|
+
}
|
|
163
|
+
_onWsClientClosed(wsClientId, code) {
|
|
164
|
+
this._logger.debug("클라이언트 연결 끊김: " + wsClientId + ": " + this._wsServer?.clients.size + ": " + code);
|
|
165
|
+
// 클라이언트 창이 닫히거나 RELOAD 될때
|
|
166
|
+
if (code === 1001) {
|
|
167
|
+
this._logger.debug("닫힌 소켓의 이벤트 리스너 비우기...");
|
|
168
|
+
const disconnectedListeners = this._eventListeners.filter((item) => item.socketId === wsClientId);
|
|
169
|
+
for (const disconnectedListener of disconnectedListeners) {
|
|
170
|
+
this._eventListeners.remove(disconnectedListener);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async _onWsClientMessageAsync(socketId, msgJson) {
|
|
175
|
+
const msg = JsonConvert.parse(msgJson);
|
|
176
|
+
if (msg.name === "request") {
|
|
177
|
+
await this._onSocketRequestAsync(socketId, msg);
|
|
178
|
+
}
|
|
179
|
+
else if (msg.name === "request-split") {
|
|
180
|
+
await this._onSocketRequestSplitAsync(socketId, msg);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async _onSocketRequestAsync(socketId, req) {
|
|
184
|
+
this._logger.debug("요청 받음", req);
|
|
185
|
+
const res = await this._processSocketRequestAsync(socketId, req);
|
|
186
|
+
this._logger.debug(`응답 전송 (size: ${Buffer.from(JsonConvert.stringify(res)).length})`);
|
|
187
|
+
await this._sendAsync(socketId, res);
|
|
188
|
+
}
|
|
189
|
+
async _onSocketRequestSplitAsync(socketId, splitReq) {
|
|
190
|
+
this._logger.debug("분할요청 받음", splitReq.uuid + "(" + splitReq.index + ")");
|
|
191
|
+
const cacheInfo = this._splitReqCache.getOrCreate(splitReq.uuid, { completedSize: 0, data: [] });
|
|
192
|
+
cacheInfo.data[splitReq.index] = splitReq.body;
|
|
193
|
+
cacheInfo.completedSize += splitReq.body.length;
|
|
194
|
+
const isCompleted = cacheInfo.completedSize === splitReq.fullSize;
|
|
195
|
+
await this._sendAsync(socketId, {
|
|
196
|
+
name: "response-for-split",
|
|
197
|
+
reqUuid: splitReq.uuid,
|
|
198
|
+
completedSize: cacheInfo.completedSize
|
|
199
|
+
});
|
|
200
|
+
if (isCompleted) {
|
|
201
|
+
const req = JsonConvert.parse(cacheInfo.data.join(""));
|
|
202
|
+
await this._onSocketRequestAsync(socketId, req);
|
|
203
|
+
this._splitReqCache.delete(splitReq.uuid);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async _sendAsync(arg, cmd) {
|
|
207
|
+
const cmdJson = JsonConvert.stringify(cmd);
|
|
208
|
+
if (cmd.name === "response" && cmdJson.length > 1000 * 1000) {
|
|
209
|
+
const splitSize = 1000 * 100;
|
|
210
|
+
let index = 0;
|
|
211
|
+
let currSize = 0;
|
|
212
|
+
while (currSize !== cmdJson.length) {
|
|
213
|
+
const splitBody = cmdJson.substring(currSize, currSize + splitSize - 1);
|
|
214
|
+
const splitReq = {
|
|
215
|
+
name: "response-split",
|
|
216
|
+
reqUuid: cmd.reqUuid,
|
|
217
|
+
fullSize: cmdJson.length,
|
|
218
|
+
index,
|
|
219
|
+
body: splitBody
|
|
220
|
+
};
|
|
221
|
+
const splitReqJson = JsonConvert.stringify(splitReq);
|
|
222
|
+
try {
|
|
223
|
+
const wsClient = arg instanceof WebSocket ? arg : await this.getWsClientAsync(arg);
|
|
224
|
+
wsClient?.send(splitReqJson);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
this._logger.error("소켓요청을 처리하는 중에 클라이언트 소켓이 끊김", err);
|
|
228
|
+
}
|
|
229
|
+
currSize += splitBody.length;
|
|
230
|
+
index++;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
try {
|
|
235
|
+
const wsClient = arg instanceof WebSocket ? arg : await this.getWsClientAsync(arg);
|
|
236
|
+
wsClient?.send(cmdJson);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
this._logger.error("소켓요청을 처리하는 중에 클라이언트 소켓이 끊김", err);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async _runServiceMethodAsync(def) {
|
|
244
|
+
// 서비스 가져오기
|
|
245
|
+
const serviceClass = this.options.services.last((item) => item.name === def.serviceName);
|
|
246
|
+
if (!serviceClass) {
|
|
247
|
+
throw new Error(`서비스[${def.serviceName}]를 찾을 수 없습니다.`);
|
|
248
|
+
}
|
|
249
|
+
const service = new serviceClass();
|
|
250
|
+
service.server = this;
|
|
251
|
+
service.request = def.request;
|
|
252
|
+
service.socketId = def.socketId;
|
|
253
|
+
service.apiHeaders = def.apiHeaders;
|
|
254
|
+
// 메소드 가져오기
|
|
255
|
+
const method = service[def.methodName];
|
|
256
|
+
if (method === undefined) {
|
|
257
|
+
throw new Error(`메소드[${def.serviceName}.${def.methodName}]를 찾을 수 없습니다.`);
|
|
258
|
+
}
|
|
259
|
+
// 실행
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/return-await
|
|
261
|
+
return await method.apply(service, def.params);
|
|
262
|
+
}
|
|
263
|
+
async _processSocketRequestAsync(socketId, req) {
|
|
264
|
+
try {
|
|
265
|
+
const cmdSplit = req.command.split(".");
|
|
266
|
+
if (cmdSplit.length === 2) {
|
|
267
|
+
const serviceName = cmdSplit[0];
|
|
268
|
+
const methodName = cmdSplit[1];
|
|
269
|
+
const result = await this._runServiceMethodAsync({
|
|
270
|
+
socketId,
|
|
271
|
+
request: req,
|
|
272
|
+
serviceName,
|
|
273
|
+
methodName,
|
|
274
|
+
params: req.params
|
|
275
|
+
});
|
|
276
|
+
// 응답
|
|
277
|
+
return {
|
|
278
|
+
name: "response",
|
|
279
|
+
reqUuid: req.uuid,
|
|
280
|
+
state: "success",
|
|
281
|
+
body: result
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
else if (req.command === "addEventListener") {
|
|
285
|
+
const key = req.params[0];
|
|
286
|
+
const eventName = req.params[1];
|
|
287
|
+
const info = req.params[2];
|
|
288
|
+
this._eventListeners.push({ key, eventName, info, socketId });
|
|
289
|
+
return {
|
|
290
|
+
name: "response",
|
|
291
|
+
reqUuid: req.uuid,
|
|
292
|
+
state: "success",
|
|
293
|
+
body: undefined
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
else if (req.command === "removeEventListener") {
|
|
297
|
+
const key = req.params[0];
|
|
298
|
+
this._eventListeners.remove((item) => item.key === key);
|
|
299
|
+
return {
|
|
300
|
+
name: "response",
|
|
301
|
+
reqUuid: req.uuid,
|
|
302
|
+
state: "success",
|
|
303
|
+
body: undefined
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
else if (req.command === "getEventListenerInfos") {
|
|
307
|
+
const eventName = req.params[0];
|
|
308
|
+
return {
|
|
309
|
+
name: "response",
|
|
310
|
+
reqUuid: req.uuid,
|
|
311
|
+
state: "success",
|
|
312
|
+
body: this._eventListeners
|
|
313
|
+
.filter((item) => item.eventName === eventName)
|
|
314
|
+
.map((item) => ({ key: item.key, info: item.info }))
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
else if (req.command === "emitEvent") {
|
|
318
|
+
const targetKeys = req.params[0];
|
|
319
|
+
const data = req.params[1];
|
|
320
|
+
const listeners = this._eventListeners.filter((item) => targetKeys.includes(item.key));
|
|
321
|
+
for (const listener of listeners) {
|
|
322
|
+
const wsClient = await this.getWsClientAsync(listener.socketId);
|
|
323
|
+
if (wsClient?.readyState === WebSocket.OPEN) {
|
|
324
|
+
const evtMsg = {
|
|
325
|
+
name: "event",
|
|
326
|
+
key: listener.key,
|
|
327
|
+
body: data
|
|
328
|
+
};
|
|
329
|
+
wsClient.send(JsonConvert.stringify(evtMsg));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
name: "response",
|
|
334
|
+
reqUuid: req.uuid,
|
|
335
|
+
state: "success",
|
|
336
|
+
body: undefined
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
// 에러 응답
|
|
341
|
+
return {
|
|
342
|
+
name: "response",
|
|
343
|
+
reqUuid: req.uuid,
|
|
344
|
+
state: "error",
|
|
345
|
+
body: "요청이 잘못되었습니다."
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (err) {
|
|
350
|
+
// 에러 응답
|
|
351
|
+
return {
|
|
352
|
+
name: "response",
|
|
353
|
+
reqUuid: req.uuid,
|
|
354
|
+
state: "error",
|
|
355
|
+
body: err.stack
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async _onWebRequestAsync(req, res) {
|
|
360
|
+
try {
|
|
361
|
+
if (this.options.middlewares) {
|
|
362
|
+
for (const optMdw of this.options.middlewares) {
|
|
363
|
+
await new Promise((resolve, reject) => {
|
|
364
|
+
optMdw(req, res, (err) => {
|
|
365
|
+
if (err != null) {
|
|
366
|
+
reject(err);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
resolve();
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const urlObj = url.parse(req.url, true, false);
|
|
375
|
+
const urlPath = decodeURI(urlObj.pathname.slice(1));
|
|
376
|
+
const urlPathChain = urlPath.split("/");
|
|
377
|
+
if (urlPathChain[0] === "api") {
|
|
378
|
+
if (req.headers.origin?.includes("://localhost") && req.method === "OPTIONS") {
|
|
379
|
+
res.writeHead(204, { "Access-Control-Allow-Origin": "*" });
|
|
380
|
+
res.end();
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const serviceName = urlPathChain[1];
|
|
384
|
+
const methodName = urlPathChain[2];
|
|
385
|
+
let params;
|
|
386
|
+
if (req.method === "GET") {
|
|
387
|
+
if (typeof urlObj.query["json"] !== "string")
|
|
388
|
+
throw new Error();
|
|
389
|
+
if (req.headers["content-type"]?.toLowerCase().includes("json")) {
|
|
390
|
+
params = JsonConvert.parse(urlObj.query["json"]);
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
params = [urlObj.query];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else if (req.method === "POST") {
|
|
397
|
+
const body = await new Promise((resolve) => {
|
|
398
|
+
let tmp = Buffer.from([]);
|
|
399
|
+
req.on("data", chunk => {
|
|
400
|
+
tmp = Buffer.concat([tmp, chunk]);
|
|
401
|
+
});
|
|
402
|
+
req.on("end", () => {
|
|
403
|
+
resolve(tmp);
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
if (req.headers["content-type"]?.toLowerCase().includes("json")) {
|
|
407
|
+
params = JsonConvert.parse(body.toString());
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
params = [body.toString()];
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (params) {
|
|
414
|
+
const serviceResult = await this._runServiceMethodAsync({
|
|
415
|
+
serviceName,
|
|
416
|
+
methodName,
|
|
417
|
+
params,
|
|
418
|
+
apiHeaders: req.headers
|
|
419
|
+
});
|
|
420
|
+
const result = req.headers["content-type"]?.toLowerCase().includes("json") ? JsonConvert.stringify(serviceResult) : serviceResult;
|
|
421
|
+
res.writeHead(200, {
|
|
422
|
+
"Content-Length": Buffer.from(result).length,
|
|
423
|
+
"Content-Type": req.headers["content-type"]?.toLowerCase()
|
|
424
|
+
});
|
|
425
|
+
res.end(result);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (req.method === "GET") {
|
|
430
|
+
let targetFilePath;
|
|
431
|
+
const currPathProxyFrom = Object.keys(this.pathProxy).single((from) => urlPath.startsWith(from));
|
|
432
|
+
if (currPathProxyFrom !== undefined) {
|
|
433
|
+
if (typeof this.pathProxy[currPathProxyFrom] === "number") {
|
|
434
|
+
const proxyReq = http.request({
|
|
435
|
+
port: this.pathProxy[currPathProxyFrom],
|
|
436
|
+
path: req.url,
|
|
437
|
+
method: req.method,
|
|
438
|
+
headers: req.headers
|
|
439
|
+
}, (proxyRes) => {
|
|
440
|
+
if (proxyRes.statusCode === 404) {
|
|
441
|
+
res.writeHead(404, { "Content-Type": "text/html" });
|
|
442
|
+
res.end("<h1>A custom 404 page</h1>");
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
446
|
+
proxyRes.pipe(res, { end: true });
|
|
447
|
+
});
|
|
448
|
+
req.pipe(proxyReq, { end: true });
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
targetFilePath = path.resolve(this.pathProxy[currPathProxyFrom] + urlPath.substring(currPathProxyFrom.length));
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
targetFilePath = path.resolve(this.options.rootPath, "www", urlPath);
|
|
457
|
+
}
|
|
458
|
+
targetFilePath = FsUtil.exists(targetFilePath) && FsUtil.stat(targetFilePath).isDirectory() ? path.resolve(targetFilePath, "index.html") : targetFilePath;
|
|
459
|
+
if (!FsUtil.exists(targetFilePath)) {
|
|
460
|
+
const errorMessage = "파일을 찾을 수 없습니다.";
|
|
461
|
+
this._responseErrorHtml(res, 404, errorMessage);
|
|
462
|
+
this._logger.warn(`[404] ${errorMessage} (${targetFilePath})`);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
if (path.basename(targetFilePath).startsWith(".")) {
|
|
466
|
+
const errorMessage = "파일을 사용할 권한이 없습니다.";
|
|
467
|
+
this._responseErrorHtml(res, 403, errorMessage);
|
|
468
|
+
this._logger.warn(`[403] ${errorMessage} (${targetFilePath})`);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const fileStream = FsUtil.createReadStream(targetFilePath);
|
|
472
|
+
const targetFileSize = (await FsUtil.lstatAsync(targetFilePath)).size;
|
|
473
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
474
|
+
res.setHeader("Content-Length", targetFileSize);
|
|
475
|
+
res.setHeader("Content-Type", mime.getType(targetFilePath));
|
|
476
|
+
res.writeHead(200);
|
|
477
|
+
fileStream.pipe(res);
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
const errorMessage = "요청이 잘못되었습니다.";
|
|
481
|
+
this._responseErrorHtml(res, 405, errorMessage);
|
|
482
|
+
this._logger.warn(`[405] ${errorMessage} (${req.method.toUpperCase()})`);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
catch (err) {
|
|
487
|
+
if (err instanceof ApiServiceError) {
|
|
488
|
+
res.writeHead(err.statusCode);
|
|
489
|
+
res.end(err.message);
|
|
490
|
+
this._logger.error(`[${err.statusCode}]\n${err.message}`, err);
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
const errorMessage = "요청 처리중 오류가 발생하였습니다.";
|
|
494
|
+
this._responseErrorHtml(res, 405, errorMessage);
|
|
495
|
+
this._logger.error(`[405] ${errorMessage}`, err);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
_responseErrorHtml(res, code, message) {
|
|
500
|
+
res.writeHead(code);
|
|
501
|
+
res.end(`
|
|
502
|
+
<!DOCTYPE html>
|
|
503
|
+
<html>
|
|
504
|
+
<head>
|
|
505
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
506
|
+
<meta charset="UTF-8">
|
|
507
|
+
<title>${code}: ${message}</title>
|
|
508
|
+
</head>
|
|
509
|
+
<body>${code}: ${message}</body>
|
|
510
|
+
</html>`);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
//# sourceMappingURL=SdServiceServer.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { Type } from "@simplysm/sd-core-common";
|
|
4
|
+
import { NextHandleFunction } from "connect";
|
|
5
|
+
import { SdServiceServer } from "./SdServiceServer";
|
|
6
|
+
import { ISdServiceRequest } from "@simplysm/sd-service-common";
|
|
7
|
+
import * as http from "http";
|
|
8
|
+
export interface ISdServiceServerOptions {
|
|
9
|
+
rootPath: string;
|
|
10
|
+
services: Type<SdServiceBase>[];
|
|
11
|
+
port: number | string;
|
|
12
|
+
middlewares?: NextHandleFunction[];
|
|
13
|
+
ssl?: {
|
|
14
|
+
pfxBuffer: Buffer | (() => (Promise<Buffer> | Buffer));
|
|
15
|
+
passphrase: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare class SdServiceBase {
|
|
19
|
+
server: SdServiceServer;
|
|
20
|
+
socketId?: string;
|
|
21
|
+
request?: ISdServiceRequest;
|
|
22
|
+
apiHeaders?: http.IncomingHttpHeaders;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commons.js","sourceRoot":"","sources":["../../../../sd-service-server/src/commons.ts"],"names":[],"mappings":"AAiBA,MAAM,OAAO,aAAa;CAKzB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./SdServiceServer";
|
|
2
|
+
export * from "./commons";
|
|
3
|
+
export * from "./ApiServiceError";
|
|
4
|
+
export * from "./utils/SdServiceServerConfigUtil";
|
|
5
|
+
export * from "./services/SdSmtpClientService";
|
|
6
|
+
export * from "./services/SdOrmService";
|
|
7
|
+
export * from "./services/SdCryptoService";
|
|
8
|
+
export * from "./services/SdAutoUpdateService";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../sd-service-server/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./SdServiceServer";
|
|
2
|
+
export * from "./commons";
|
|
3
|
+
export * from "./ApiServiceError";
|
|
4
|
+
export * from "./utils/SdServiceServerConfigUtil";
|
|
5
|
+
export * from "./services/SdSmtpClientService";
|
|
6
|
+
export * from "./services/SdOrmService";
|
|
7
|
+
export * from "./services/SdCryptoService";
|
|
8
|
+
export * from "./services/SdAutoUpdateService";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SdAutoUpdateService.js","sourceRoot":"","sources":["../../../../../sd-service-server/src/services/SdAutoUpdateService.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,MAAM,OAAO,mBAAoB,SAAQ,aAAa;IAC7C,KAAK,CAAC,mBAAmB,CAAC,UAAkB,EAAE,QAAgB;QACnE,IAAI;YACF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;YAC9H,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACtC,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;aACjD,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAEvD,OAAO,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;SACrF;QACD,OAAO,GAAG,EAAE;YACV,OAAO,SAAS,CAAC;SAClB;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import semver from "semver";
|
|
3
|
+
import { SdServiceBase } from "../commons";
|
|
4
|
+
import { FsUtil } from "@simplysm/sd-core-node";
|
|
5
|
+
export class SdAutoUpdateService extends SdServiceBase {
|
|
6
|
+
async getLastVersionAsync(clientName, platform) {
|
|
7
|
+
try {
|
|
8
|
+
const updates = await FsUtil.readdirAsync(path.resolve(this.server.options.rootPath, "www", clientName, platform, "updates"));
|
|
9
|
+
const versions = updates.map((item) => ({
|
|
10
|
+
fileName: item,
|
|
11
|
+
version: path.basename(item, path.extname(item))
|
|
12
|
+
})).filter((item) => (/^[0-9.]*$/).test(item.version));
|
|
13
|
+
return semver.maxSatisfying(versions.map((item) => item.version), "*") ?? undefined;
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=SdAutoUpdateService.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { SdServiceBase } from "../commons";
|
|
3
|
+
export declare class SdCryptoService extends SdServiceBase {
|
|
4
|
+
encryptAsync(data: string | Buffer): Promise<string>;
|
|
5
|
+
encryptAesAsync(data: Buffer): Promise<string>;
|
|
6
|
+
decryptAesAsync(encText: string): Promise<Buffer>;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SdCryptoService.js","sourceRoot":"","sources":["../../../../../sd-service-server/src/services/SdCryptoService.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,OAAO,eAAgB,SAAQ,aAAa;IACzC,KAAK,CAAC,YAAY,CAAC,IAAqB;QAC7C,MAAM,MAAM,GAAG,CACb,MAAM,yBAAyB,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CACvG,CAAC,QAAQ,CAAC,CAAC;QACZ,IAAI,MAAM,KAAK,SAAS,EAAE;YACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;SACvC;QAED,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;aAC3C,MAAM,CAAC,IAAI,CAAC;aACZ,MAAM,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,IAAY;QACvC,MAAM,MAAM,GAAG,CACb,MAAM,yBAAyB,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CACvG,CAAC,QAAQ,CAAC,CAAC;QACZ,IAAI,MAAM,KAAK,SAAS,EAAE;YACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;SACvC;QAED,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAClC,aAAa,EACb,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EACvB,EAAE,CACH,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEtC,OAAO,CACL,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YAClB,GAAG;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC3D,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,OAAe;QAC1C,MAAM,MAAM,GAAG,CACb,MAAM,yBAAyB,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CACvG,CAAC,QAAQ,CAAC,CAAC;QACZ,IAAI,MAAM,KAAK,SAAS,EAAE;YACxB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;SACvC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAG,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CACtC,aAAa,EACb,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EACvB,EAAE,CACH,CAAC;QACF,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAEjD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import { SdServiceServerConfigUtil } from "../utils/SdServiceServerConfigUtil";
|
|
3
|
+
import { SdServiceBase } from "../commons";
|
|
4
|
+
export class SdCryptoService extends SdServiceBase {
|
|
5
|
+
async encryptAsync(data) {
|
|
6
|
+
const config = (await SdServiceServerConfigUtil.getConfigAsync(this.server.options.rootPath, this.request?.clientName))["crypto"];
|
|
7
|
+
if (config === undefined) {
|
|
8
|
+
throw new Error("암호화 설정을 찾을 수 없습니다.");
|
|
9
|
+
}
|
|
10
|
+
return crypto.createHmac("sha256", config.key)
|
|
11
|
+
.update(data)
|
|
12
|
+
.digest("hex");
|
|
13
|
+
}
|
|
14
|
+
async encryptAesAsync(data) {
|
|
15
|
+
const config = (await SdServiceServerConfigUtil.getConfigAsync(this.server.options.rootPath, this.request?.clientName))["crypto"];
|
|
16
|
+
if (config === undefined) {
|
|
17
|
+
throw new Error("암호화 설정을 찾을 수 없습니다.");
|
|
18
|
+
}
|
|
19
|
+
const iv = crypto.randomBytes(16);
|
|
20
|
+
const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(config.key), iv);
|
|
21
|
+
const encrypted = cipher.update(data);
|
|
22
|
+
return (iv.toString("hex") +
|
|
23
|
+
":" +
|
|
24
|
+
Buffer.concat([encrypted, cipher.final()]).toString("hex"));
|
|
25
|
+
}
|
|
26
|
+
async decryptAesAsync(encText) {
|
|
27
|
+
const config = (await SdServiceServerConfigUtil.getConfigAsync(this.server.options.rootPath, this.request?.clientName))["crypto"];
|
|
28
|
+
if (config === undefined) {
|
|
29
|
+
throw new Error("암호화 설정을 찾을 수 없습니다.");
|
|
30
|
+
}
|
|
31
|
+
const textParts = encText.split(":");
|
|
32
|
+
const iv = Buffer.from(textParts.shift(), "hex");
|
|
33
|
+
const encryptedText = Buffer.from(textParts.join(":"), "hex");
|
|
34
|
+
const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(config.key), iv);
|
|
35
|
+
const decrypted = decipher.update(encryptedText);
|
|
36
|
+
return Buffer.concat([decrypted, decipher.final()]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=SdCryptoService.js.map
|