@simplysm/service-client 13.0.0-beta.6

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.
Files changed (209) hide show
  1. package/.cache/typecheck-browser.tsbuildinfo +1 -0
  2. package/.cache/typecheck-node.tsbuildinfo +1 -0
  3. package/README.md +397 -0
  4. package/dist/core-common/src/common.types.d.ts +74 -0
  5. package/dist/core-common/src/common.types.d.ts.map +1 -0
  6. package/dist/core-common/src/env.d.ts +6 -0
  7. package/dist/core-common/src/env.d.ts.map +1 -0
  8. package/dist/core-common/src/errors/argument-error.d.ts +25 -0
  9. package/dist/core-common/src/errors/argument-error.d.ts.map +1 -0
  10. package/dist/core-common/src/errors/not-implemented-error.d.ts +29 -0
  11. package/dist/core-common/src/errors/not-implemented-error.d.ts.map +1 -0
  12. package/dist/core-common/src/errors/sd-error.d.ts +27 -0
  13. package/dist/core-common/src/errors/sd-error.d.ts.map +1 -0
  14. package/dist/core-common/src/errors/timeout-error.d.ts +31 -0
  15. package/dist/core-common/src/errors/timeout-error.d.ts.map +1 -0
  16. package/dist/core-common/src/extensions/arr-ext.d.ts +15 -0
  17. package/dist/core-common/src/extensions/arr-ext.d.ts.map +1 -0
  18. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +19 -0
  19. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +1 -0
  20. package/dist/core-common/src/extensions/arr-ext.types.d.ts +215 -0
  21. package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +1 -0
  22. package/dist/core-common/src/extensions/map-ext.d.ts +57 -0
  23. package/dist/core-common/src/extensions/map-ext.d.ts.map +1 -0
  24. package/dist/core-common/src/extensions/set-ext.d.ts +36 -0
  25. package/dist/core-common/src/extensions/set-ext.d.ts.map +1 -0
  26. package/dist/core-common/src/features/debounce-queue.d.ts +53 -0
  27. package/dist/core-common/src/features/debounce-queue.d.ts.map +1 -0
  28. package/dist/core-common/src/features/event-emitter.d.ts +66 -0
  29. package/dist/core-common/src/features/event-emitter.d.ts.map +1 -0
  30. package/dist/core-common/src/features/serial-queue.d.ts +47 -0
  31. package/dist/core-common/src/features/serial-queue.d.ts.map +1 -0
  32. package/dist/core-common/src/index.d.ts +32 -0
  33. package/dist/core-common/src/index.d.ts.map +1 -0
  34. package/dist/core-common/src/types/date-only.d.ts +152 -0
  35. package/dist/core-common/src/types/date-only.d.ts.map +1 -0
  36. package/dist/core-common/src/types/date-time.d.ts +96 -0
  37. package/dist/core-common/src/types/date-time.d.ts.map +1 -0
  38. package/dist/core-common/src/types/lazy-gc-map.d.ts +80 -0
  39. package/dist/core-common/src/types/lazy-gc-map.d.ts.map +1 -0
  40. package/dist/core-common/src/types/time.d.ts +68 -0
  41. package/dist/core-common/src/types/time.d.ts.map +1 -0
  42. package/dist/core-common/src/types/uuid.d.ts +35 -0
  43. package/dist/core-common/src/types/uuid.d.ts.map +1 -0
  44. package/dist/core-common/src/utils/bytes.d.ts +51 -0
  45. package/dist/core-common/src/utils/bytes.d.ts.map +1 -0
  46. package/dist/core-common/src/utils/date-format.d.ts +90 -0
  47. package/dist/core-common/src/utils/date-format.d.ts.map +1 -0
  48. package/dist/core-common/src/utils/json.d.ts +34 -0
  49. package/dist/core-common/src/utils/json.d.ts.map +1 -0
  50. package/dist/core-common/src/utils/num.d.ts +60 -0
  51. package/dist/core-common/src/utils/num.d.ts.map +1 -0
  52. package/dist/core-common/src/utils/obj.d.ts +258 -0
  53. package/dist/core-common/src/utils/obj.d.ts.map +1 -0
  54. package/dist/core-common/src/utils/path.d.ts +23 -0
  55. package/dist/core-common/src/utils/path.d.ts.map +1 -0
  56. package/dist/core-common/src/utils/primitive.d.ts +18 -0
  57. package/dist/core-common/src/utils/primitive.d.ts.map +1 -0
  58. package/dist/core-common/src/utils/str.d.ts +103 -0
  59. package/dist/core-common/src/utils/str.d.ts.map +1 -0
  60. package/dist/core-common/src/utils/template-strings.d.ts +84 -0
  61. package/dist/core-common/src/utils/template-strings.d.ts.map +1 -0
  62. package/dist/core-common/src/utils/transferable.d.ts +47 -0
  63. package/dist/core-common/src/utils/transferable.d.ts.map +1 -0
  64. package/dist/core-common/src/utils/wait.d.ts +19 -0
  65. package/dist/core-common/src/utils/wait.d.ts.map +1 -0
  66. package/dist/core-common/src/utils/xml.d.ts +36 -0
  67. package/dist/core-common/src/utils/xml.d.ts.map +1 -0
  68. package/dist/core-common/src/zip/sd-zip.d.ts +80 -0
  69. package/dist/core-common/src/zip/sd-zip.d.ts.map +1 -0
  70. package/dist/features/event-client.js +74 -0
  71. package/dist/features/event-client.js.map +7 -0
  72. package/dist/features/file-client.js +42 -0
  73. package/dist/features/file-client.js.map +7 -0
  74. package/dist/features/orm/orm-client-connector.js +41 -0
  75. package/dist/features/orm/orm-client-connector.js.map +7 -0
  76. package/dist/features/orm/orm-client-db-context-executor.js +61 -0
  77. package/dist/features/orm/orm-client-db-context-executor.js.map +7 -0
  78. package/dist/features/orm/orm-connect-config.js +1 -0
  79. package/dist/features/orm/orm-connect-config.js.map +7 -0
  80. package/dist/index.js +12 -0
  81. package/dist/index.js.map +7 -0
  82. package/dist/orm-common/src/db-context.d.ts +669 -0
  83. package/dist/orm-common/src/db-context.d.ts.map +1 -0
  84. package/dist/orm-common/src/errors/db-transaction-error.d.ts +51 -0
  85. package/dist/orm-common/src/errors/db-transaction-error.d.ts.map +1 -0
  86. package/dist/orm-common/src/exec/executable.d.ts +79 -0
  87. package/dist/orm-common/src/exec/executable.d.ts.map +1 -0
  88. package/dist/orm-common/src/exec/queryable.d.ts +708 -0
  89. package/dist/orm-common/src/exec/queryable.d.ts.map +1 -0
  90. package/dist/orm-common/src/exec/search-parser.d.ts +72 -0
  91. package/dist/orm-common/src/exec/search-parser.d.ts.map +1 -0
  92. package/dist/orm-common/src/expr/expr-unit.d.ts +25 -0
  93. package/dist/orm-common/src/expr/expr-unit.d.ts.map +1 -0
  94. package/dist/orm-common/src/expr/expr.d.ts +1369 -0
  95. package/dist/orm-common/src/expr/expr.d.ts.map +1 -0
  96. package/dist/orm-common/src/index.d.ts +32 -0
  97. package/dist/orm-common/src/index.d.ts.map +1 -0
  98. package/dist/orm-common/src/models/system-migration.d.ts +10 -0
  99. package/dist/orm-common/src/models/system-migration.d.ts.map +1 -0
  100. package/dist/orm-common/src/query-builder/base/expr-renderer-base.d.ts +95 -0
  101. package/dist/orm-common/src/query-builder/base/expr-renderer-base.d.ts.map +1 -0
  102. package/dist/orm-common/src/query-builder/base/query-builder-base.d.ts +66 -0
  103. package/dist/orm-common/src/query-builder/base/query-builder-base.d.ts.map +1 -0
  104. package/dist/orm-common/src/query-builder/mssql/mssql-expr-renderer.d.ts +84 -0
  105. package/dist/orm-common/src/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -0
  106. package/dist/orm-common/src/query-builder/mssql/mssql-query-builder.d.ts +45 -0
  107. package/dist/orm-common/src/query-builder/mssql/mssql-query-builder.d.ts.map +1 -0
  108. package/dist/orm-common/src/query-builder/mysql/mysql-expr-renderer.d.ts +84 -0
  109. package/dist/orm-common/src/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -0
  110. package/dist/orm-common/src/query-builder/mysql/mysql-query-builder.d.ts +54 -0
  111. package/dist/orm-common/src/query-builder/mysql/mysql-query-builder.d.ts.map +1 -0
  112. package/dist/orm-common/src/query-builder/postgresql/postgresql-expr-renderer.d.ts +84 -0
  113. package/dist/orm-common/src/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -0
  114. package/dist/orm-common/src/query-builder/postgresql/postgresql-query-builder.d.ts +52 -0
  115. package/dist/orm-common/src/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -0
  116. package/dist/orm-common/src/query-builder/query-builder.d.ts +7 -0
  117. package/dist/orm-common/src/query-builder/query-builder.d.ts.map +1 -0
  118. package/dist/orm-common/src/schema/factory/column-builder.d.ts +394 -0
  119. package/dist/orm-common/src/schema/factory/column-builder.d.ts.map +1 -0
  120. package/dist/orm-common/src/schema/factory/index-builder.d.ts +151 -0
  121. package/dist/orm-common/src/schema/factory/index-builder.d.ts.map +1 -0
  122. package/dist/orm-common/src/schema/factory/relation-builder.d.ts +337 -0
  123. package/dist/orm-common/src/schema/factory/relation-builder.d.ts.map +1 -0
  124. package/dist/orm-common/src/schema/procedure-builder.d.ts +202 -0
  125. package/dist/orm-common/src/schema/procedure-builder.d.ts.map +1 -0
  126. package/dist/orm-common/src/schema/table-builder.d.ts +259 -0
  127. package/dist/orm-common/src/schema/table-builder.d.ts.map +1 -0
  128. package/dist/orm-common/src/schema/view-builder.d.ts +183 -0
  129. package/dist/orm-common/src/schema/view-builder.d.ts.map +1 -0
  130. package/dist/orm-common/src/types/column.d.ts +172 -0
  131. package/dist/orm-common/src/types/column.d.ts.map +1 -0
  132. package/dist/orm-common/src/types/db.d.ts +175 -0
  133. package/dist/orm-common/src/types/db.d.ts.map +1 -0
  134. package/dist/orm-common/src/types/expr.d.ts +474 -0
  135. package/dist/orm-common/src/types/expr.d.ts.map +1 -0
  136. package/dist/orm-common/src/types/query-def.d.ts +351 -0
  137. package/dist/orm-common/src/types/query-def.d.ts.map +1 -0
  138. package/dist/orm-common/src/utils/result-parser.d.ts +38 -0
  139. package/dist/orm-common/src/utils/result-parser.d.ts.map +1 -0
  140. package/dist/protocol/client-protocol-wrapper.js +92 -0
  141. package/dist/protocol/client-protocol-wrapper.js.map +7 -0
  142. package/dist/service-client/src/features/event-client.d.ts +14 -0
  143. package/dist/service-client/src/features/event-client.d.ts.map +1 -0
  144. package/dist/service-client/src/features/file-client.d.ts +13 -0
  145. package/dist/service-client/src/features/file-client.d.ts.map +1 -0
  146. package/dist/service-client/src/features/orm/orm-client-connector.d.ts +10 -0
  147. package/dist/service-client/src/features/orm/orm-client-connector.d.ts.map +1 -0
  148. package/dist/service-client/src/features/orm/orm-client-db-context-executor.d.ts +26 -0
  149. package/dist/service-client/src/features/orm/orm-client-db-context-executor.d.ts.map +1 -0
  150. package/dist/service-client/src/features/orm/orm-connect-config.d.ts +13 -0
  151. package/dist/service-client/src/features/orm/orm-connect-config.d.ts.map +1 -0
  152. package/dist/service-client/src/index.d.ts +12 -0
  153. package/dist/service-client/src/index.d.ts.map +1 -0
  154. package/dist/service-client/src/protocol/client-protocol-wrapper.d.ts +23 -0
  155. package/dist/service-client/src/protocol/client-protocol-wrapper.d.ts.map +1 -0
  156. package/dist/service-client/src/service-client.d.ts +41 -0
  157. package/dist/service-client/src/service-client.d.ts.map +1 -0
  158. package/dist/service-client/src/transport/service-transport.d.ts +24 -0
  159. package/dist/service-client/src/transport/service-transport.d.ts.map +1 -0
  160. package/dist/service-client/src/transport/socket-provider.d.ts +31 -0
  161. package/dist/service-client/src/transport/socket-provider.d.ts.map +1 -0
  162. package/dist/service-client/src/types/connection-config.d.ts +8 -0
  163. package/dist/service-client/src/types/connection-config.d.ts.map +1 -0
  164. package/dist/service-client/src/types/progress.types.d.ts +10 -0
  165. package/dist/service-client/src/types/progress.types.d.ts.map +1 -0
  166. package/dist/service-client/src/workers/client-protocol.worker.d.ts +2 -0
  167. package/dist/service-client/src/workers/client-protocol.worker.d.ts.map +1 -0
  168. package/dist/service-client.js +114 -0
  169. package/dist/service-client.js.map +7 -0
  170. package/dist/service-common/src/index.d.ts +8 -0
  171. package/dist/service-common/src/index.d.ts.map +1 -0
  172. package/dist/service-common/src/protocol/protocol.types.d.ts +100 -0
  173. package/dist/service-common/src/protocol/protocol.types.d.ts.map +1 -0
  174. package/dist/service-common/src/protocol/service-protocol.d.ts +63 -0
  175. package/dist/service-common/src/protocol/service-protocol.d.ts.map +1 -0
  176. package/dist/service-common/src/service-types/auto-update-service.types.d.ts +17 -0
  177. package/dist/service-common/src/service-types/auto-update-service.types.d.ts.map +1 -0
  178. package/dist/service-common/src/service-types/crypto-service.types.d.ts +22 -0
  179. package/dist/service-common/src/service-types/crypto-service.types.d.ts.map +1 -0
  180. package/dist/service-common/src/service-types/orm-service.types.d.ts +30 -0
  181. package/dist/service-common/src/service-types/orm-service.types.d.ts.map +1 -0
  182. package/dist/service-common/src/service-types/smtp-service.types.d.ts +55 -0
  183. package/dist/service-common/src/service-types/smtp-service.types.d.ts.map +1 -0
  184. package/dist/service-common/src/types.d.ts +43 -0
  185. package/dist/service-common/src/types.d.ts.map +1 -0
  186. package/dist/transport/service-transport.js +112 -0
  187. package/dist/transport/service-transport.js.map +7 -0
  188. package/dist/transport/socket-provider.js +170 -0
  189. package/dist/transport/socket-provider.js.map +7 -0
  190. package/dist/types/connection-config.js +1 -0
  191. package/dist/types/connection-config.js.map +7 -0
  192. package/dist/types/progress.types.js +1 -0
  193. package/dist/types/progress.types.js.map +7 -0
  194. package/dist/workers/client-protocol.worker.js +30 -0
  195. package/dist/workers/client-protocol.worker.js.map +7 -0
  196. package/package.json +26 -0
  197. package/src/features/event-client.ts +102 -0
  198. package/src/features/file-client.ts +56 -0
  199. package/src/features/orm/orm-client-connector.ts +50 -0
  200. package/src/features/orm/orm-client-db-context-executor.ts +98 -0
  201. package/src/features/orm/orm-connect-config.ts +11 -0
  202. package/src/index.ts +20 -0
  203. package/src/protocol/client-protocol-wrapper.ts +132 -0
  204. package/src/service-client.ts +157 -0
  205. package/src/transport/service-transport.ts +155 -0
  206. package/src/transport/socket-provider.ts +220 -0
  207. package/src/types/connection-config.ts +7 -0
  208. package/src/types/progress.types.ts +10 -0
  209. package/src/workers/client-protocol.worker.ts +54 -0
@@ -0,0 +1,220 @@
1
+ import type { Bytes } from "@simplysm/core-common";
2
+ import { EventEmitter, Uuid, waitUntil, waitTime } from "@simplysm/core-common";
3
+ import { createConsola } from "consola";
4
+
5
+ const logger = createConsola().withTag("service-client:SocketProvider");
6
+
7
+ interface SocketProviderEvents {
8
+ message: Bytes;
9
+ state: "connected" | "closed" | "reconnecting";
10
+ }
11
+
12
+ export class SocketProvider extends EventEmitter<SocketProviderEvents> {
13
+ // 설정상수
14
+ private readonly _HEARTBEAT_TIMEOUT = 30000; // 30초간 아무런 메시지가 없으면 끊김으로 간주
15
+ private readonly _HEARTBEAT_INTERVAL = 5000; // 5초마다 핑 전송
16
+ private readonly _RECONNECT_DELAY = 3000; // 3초마다 재연결 시도
17
+
18
+ // 1바이트 버퍼 미리 생성 (메모리 절약)
19
+ private readonly _PING_PACKET = new Uint8Array([0x01]);
20
+
21
+ // 상태
22
+ private _ws?: WebSocket;
23
+ private _isManualClose = false;
24
+ private _reconnectCount = 0;
25
+ private _heartbeatTimer?: ReturnType<typeof setInterval>;
26
+ private _lastHeartbeatTime = Date.now();
27
+
28
+ get connected(): boolean {
29
+ return this._ws?.readyState === WebSocket.OPEN;
30
+ }
31
+
32
+ constructor(
33
+ private readonly _url: string,
34
+ public readonly clientName: string,
35
+ private readonly _maxReconnectCount: number,
36
+ ) {
37
+ super();
38
+ }
39
+
40
+ async connect(): Promise<void> {
41
+ if (this.connected) return;
42
+ this._isManualClose = false;
43
+
44
+ try {
45
+ await this._createSocket();
46
+ this._startHeartbeat();
47
+ this._reconnectCount = 0; // 연결 성공 시 카운트 초기화
48
+ this.emit("state", "connected");
49
+ } catch (err) {
50
+ // 최초 연결 실패는 에러를 던짐 (호출자가 알 수 있게)
51
+ throw err;
52
+ }
53
+ }
54
+
55
+ async close(): Promise<void> {
56
+ this._isManualClose = true;
57
+ this._stopHeartbeat();
58
+ const ws = this._ws;
59
+ if (ws != null) {
60
+ ws.close();
61
+ // 완전히 닫힐 때까지 대기 (Graceful Shutdown)
62
+ await waitUntil(() => ws.readyState === WebSocket.CLOSED, 100, 30).catch(() => {});
63
+ }
64
+ this.emit("state", "closed");
65
+ }
66
+
67
+ async send(data: Bytes): Promise<void> {
68
+ try {
69
+ await waitUntil(() => this.connected, undefined, 50);
70
+ } catch {
71
+ throw new Error("서버와 연결되어있지 않습니다. 인터넷 연결을 확인하세요.");
72
+ }
73
+ const ws = this._ws;
74
+ if (ws == null) {
75
+ throw new Error("WebSocket이 연결되어있지 않습니다.");
76
+ }
77
+ ws.send(data);
78
+ }
79
+
80
+ private async _createSocket(): Promise<void> {
81
+ const clientId = Uuid.new().toString();
82
+ const params = new URLSearchParams({
83
+ ver: "2",
84
+ clientId,
85
+ clientName: this.clientName,
86
+ });
87
+
88
+ await new Promise<void>((resolve, reject) => {
89
+ const ws = new WebSocket(`${this._url}?${params.toString()}`);
90
+ ws.binaryType = "arraybuffer";
91
+
92
+ ws.onopen = () => {
93
+ this._ws = ws;
94
+ resolve();
95
+ };
96
+
97
+ ws.onerror = (event: Event) => {
98
+ // 연결 중 에러 발생 시 reject
99
+ if (!this.connected) {
100
+ const errorEvent = event as ErrorEvent;
101
+ const msg = errorEvent.message;
102
+ reject(new Error(msg));
103
+ }
104
+ };
105
+ });
106
+
107
+ // 이 시점에서 this._ws는 항상 할당되어 있음 (ws.onopen에서 할당)
108
+ const currentWs = this._ws;
109
+ if (currentWs == null) {
110
+ throw new Error("WebSocket 초기화 실패");
111
+ }
112
+
113
+ currentWs.onmessage = (event) => {
114
+ this._lastHeartbeatTime = Date.now(); // 하트비트 갱신
115
+
116
+ const data = event.data as ArrayBuffer;
117
+ const bytes = new Uint8Array(data);
118
+
119
+ // Raw Ping/Pong 처리 (가장 먼저 체크)
120
+ // 1바이트이고 첫 바이트가 0x02(Pong)이면 무시
121
+ // (하트비트 타임스탬프만 갱신하고 끝냄)
122
+ if (bytes.length === 1 && bytes[0] === 0x02) return;
123
+
124
+ this.emit("message", bytes);
125
+ };
126
+
127
+ currentWs.onclose = async () => {
128
+ this._stopHeartbeat();
129
+ if (!this._isManualClose) {
130
+ await this._tryReconnect();
131
+ }
132
+ };
133
+ }
134
+
135
+ private async _tryReconnect(): Promise<void> {
136
+ // 루프 기반 재연결 (재귀 대신 사용하여 스택 안전성 확보)
137
+ while (this._reconnectCount < this._maxReconnectCount) {
138
+ this._reconnectCount++;
139
+ this.emit("state", "reconnecting");
140
+ logger.warn("WebSocket 연결 끊김. 재연결 시도...", {
141
+ reconnectCount: this._reconnectCount,
142
+ maxReconnectCount: this._maxReconnectCount,
143
+ });
144
+
145
+ await waitTime(this._RECONNECT_DELAY);
146
+
147
+ try {
148
+ await this._createSocket();
149
+ this._startHeartbeat();
150
+ this._reconnectCount = 0;
151
+ this.emit("state", "connected"); // 재연결 성공 알림
152
+ logger.info("WebSocket 재연결 성공");
153
+ return; // 재연결 성공 시 종료
154
+ } catch {
155
+ // 실패 시 루프 계속
156
+ }
157
+ }
158
+
159
+ // 최대 재시도 횟수 초과
160
+ logger.error("재연결 시도 횟수 초과. 연결을 포기합니다.");
161
+ this.emit("state", "closed");
162
+ }
163
+
164
+ private _startHeartbeat(): void {
165
+ this._stopHeartbeat();
166
+ this._lastHeartbeatTime = Date.now();
167
+
168
+ this._heartbeatTimer = setInterval(() => {
169
+ // 타임아웃 체크
170
+ if (Date.now() - this._lastHeartbeatTime > this._HEARTBEAT_TIMEOUT) {
171
+ logger.warn("Heartbeat Timeout. Connection lost.");
172
+
173
+ // 타임아웃이 발생했으므로 즉시 타이머를 멈춰서 반복 실행을 막습니다.
174
+ this._stopHeartbeat();
175
+
176
+ // 소켓이 닫히기를 기다리지 말고(onclose 미발생 대비), 강제로 정리 후 재연결합니다.
177
+ if (this._ws != null) {
178
+ const tempWs = this._ws;
179
+ this._ws = undefined; // 연결 상태 끊김으로 간주
180
+
181
+ // 기존 소켓의 이벤트 핸들러 제거
182
+ // 뒤늦게 발생한 onclose에 따른 중복 재연결 방지
183
+ tempWs.onclose = null;
184
+ tempWs.onerror = null;
185
+ tempWs.onmessage = null;
186
+
187
+ // 소켓 닫기 시도 (에러 무시)
188
+ try {
189
+ tempWs.close();
190
+ } catch {
191
+ // ignore
192
+ }
193
+
194
+ // 수동 종료가 아니라면 재연결 로직 강제 실행
195
+ if (!this._isManualClose) {
196
+ void this._tryReconnect();
197
+ }
198
+ }
199
+ return;
200
+ }
201
+
202
+ // ping 전송
203
+ const ws = this._ws;
204
+ if (this.connected && ws != null) {
205
+ try {
206
+ ws.send(this._PING_PACKET);
207
+ } catch (err) {
208
+ logger.warn("Ping send failed", err);
209
+ }
210
+ }
211
+ }, this._HEARTBEAT_INTERVAL);
212
+ }
213
+
214
+ private _stopHeartbeat(): void {
215
+ if (this._heartbeatTimer != null) {
216
+ clearInterval(this._heartbeatTimer);
217
+ this._heartbeatTimer = undefined;
218
+ }
219
+ }
220
+ }
@@ -0,0 +1,7 @@
1
+ export interface ServiceConnectionConfig {
2
+ port: number;
3
+ host: string;
4
+ ssl?: boolean;
5
+ /** 0 입력시 reconnect안함. 바로 끊김 */
6
+ maxReconnectCount?: number;
7
+ }
@@ -0,0 +1,10 @@
1
+ export interface ServiceProgress {
2
+ request?: (s: ServiceProgressState) => void;
3
+ response?: (s: ServiceProgressState) => void;
4
+ }
5
+
6
+ export interface ServiceProgressState {
7
+ uuid: string;
8
+ totalSize: number;
9
+ completedSize: number;
10
+ }
@@ -0,0 +1,54 @@
1
+ /// <reference lib="webworker" />
2
+
3
+ import { ServiceProtocol } from "@simplysm/service-common";
4
+ import { transferableEncode } from "@simplysm/core-common";
5
+
6
+ const protocol = new ServiceProtocol();
7
+
8
+ self.onmessage = (event: MessageEvent) => {
9
+ const { id, type, data } = event.data as {
10
+ id: string;
11
+ type: "encode" | "decode";
12
+ data: unknown;
13
+ };
14
+
15
+ try {
16
+ let result: unknown;
17
+ let transferList: Transferable[] = [];
18
+
19
+ if (type === "encode") {
20
+ // [Main -> Worker] 인코딩 요청 (data: { uuid, message })
21
+ // message는 이미 Plain Object로 넘어옴 (Structured Clone)
22
+ const { uuid, message } = data as {
23
+ uuid: string;
24
+ message: Parameters<ServiceProtocol["encode"]>[1];
25
+ };
26
+ const { chunks } = protocol.encode(uuid, message);
27
+
28
+ // Buffer[]는 전송 가능하므로 결과로 반환
29
+ result = chunks;
30
+ // 결과물 청크들의 내부 ArrayBuffer를 소유권 이전 목록에 추가
31
+ transferList = chunks.map((chunk) => chunk.buffer as ArrayBuffer);
32
+ } else {
33
+ // [Main -> Worker] 디코딩 요청 (data: Uint8Array)
34
+ // data는 Uint8Array로 넘어옴
35
+ const bytes = new Uint8Array(data as ArrayBuffer);
36
+ const decodeResult = protocol.decode(bytes);
37
+
38
+ // 결과물(객체)을 전송 가능한 형태로 변환 (Zero-Copy 준비)
39
+ const encoded = transferableEncode(decodeResult);
40
+ result = encoded.result;
41
+ transferList = encoded.transferList;
42
+ }
43
+
44
+ // [Worker -> Main] 성공 응답
45
+ self.postMessage({ id, type: "success", result }, { transfer: transferList });
46
+ } catch (err) {
47
+ // [Worker -> Main] 에러 응답
48
+ self.postMessage({
49
+ id,
50
+ type: "error",
51
+ error: err instanceof Error ? { message: err.message, stack: err.stack } : { message: String(err) },
52
+ });
53
+ }
54
+ };