@simplysm/service-common 13.0.100 → 14.0.1

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 (46) hide show
  1. package/dist/define-event.d.ts +7 -7
  2. package/dist/define-event.d.ts.map +1 -1
  3. package/dist/define-event.js +21 -10
  4. package/dist/define-event.js.map +1 -6
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +5 -2
  8. package/dist/index.js.map +1 -6
  9. package/dist/protocol/create-service-protocol.d.ts +20 -20
  10. package/dist/protocol/create-service-protocol.d.ts.map +1 -1
  11. package/dist/protocol/create-service-protocol.js +149 -112
  12. package/dist/protocol/create-service-protocol.js.map +1 -6
  13. package/dist/protocol/protocol.types.d.ts +17 -17
  14. package/dist/protocol/protocol.types.d.ts.map +1 -1
  15. package/dist/protocol/protocol.types.js +16 -15
  16. package/dist/protocol/protocol.types.js.map +1 -6
  17. package/dist/service-types/auto-update-service.types.d.ts +5 -5
  18. package/dist/service-types/auto-update-service.types.js +2 -1
  19. package/dist/service-types/auto-update-service.types.js.map +1 -6
  20. package/dist/service-types/orm-service.types.d.ts +7 -5
  21. package/dist/service-types/orm-service.types.d.ts.map +1 -1
  22. package/dist/service-types/orm-service.types.js +2 -1
  23. package/dist/service-types/orm-service.types.js.map +1 -6
  24. package/dist/types.d.ts +5 -5
  25. package/dist/types.d.ts.map +1 -1
  26. package/dist/types.js +2 -1
  27. package/dist/types.js.map +1 -6
  28. package/package.json +6 -8
  29. package/src/define-event.ts +7 -7
  30. package/src/index.ts +4 -6
  31. package/src/protocol/create-service-protocol.ts +45 -38
  32. package/src/protocol/protocol.types.ts +39 -39
  33. package/src/service-types/auto-update-service.types.ts +5 -5
  34. package/src/service-types/orm-service.types.ts +5 -5
  35. package/src/types.ts +5 -5
  36. package/README.md +0 -111
  37. package/dist/service-types/smtp-client-service.types.d.ts +0 -38
  38. package/dist/service-types/smtp-client-service.types.d.ts.map +0 -1
  39. package/dist/service-types/smtp-client-service.types.js +0 -1
  40. package/dist/service-types/smtp-client-service.types.js.map +0 -6
  41. package/docs/events.md +0 -51
  42. package/docs/protocol.md +0 -252
  43. package/docs/service-types.md +0 -162
  44. package/src/service-types/smtp-client-service.types.ts +0 -41
  45. package/tests/define-event.spec.ts +0 -11
  46. package/tests/protocol/service-protocol.spec.ts +0 -251
@@ -1,16 +1,17 @@
1
- const PROTOCOL_CONFIG = {
2
- /** Max message size (100MB) */
3
- MAX_TOTAL_SIZE: 100 * 1024 * 1024,
4
- /** Chunking threshold (3MB) */
5
- SPLIT_MESSAGE_SIZE: 3 * 1024 * 1024,
6
- /** Chunk size (300KB) */
7
- CHUNK_SIZE: 300 * 1024,
8
- /** GC interval (10s) */
9
- GC_INTERVAL: 10 * 1e3,
10
- /** Incomplete message expiry time (60s) */
11
- EXPIRE_TIME: 60 * 1e3
1
+ // ----------------------------------------------------------------------
2
+ // 프로토콜 상수
3
+ // ----------------------------------------------------------------------
4
+ /** 서비스 프로토콜 설정 */
5
+ export const PROTOCOL_CONFIG = {
6
+ /** 최대 메시지 크기 (100MB) */
7
+ MAX_TOTAL_SIZE: 100 * 1024 * 1024,
8
+ /** 청킹 임계값 (3MB) */
9
+ SPLIT_MESSAGE_SIZE: 3 * 1024 * 1024,
10
+ /** 청크 크기 (300KB) */
11
+ CHUNK_SIZE: 300 * 1024,
12
+ /** GC 주기 (10초) */
13
+ GC_INTERVAL: 10 * 1000,
14
+ /** 미완성 메시지 만료 시간 (60초) */
15
+ EXPIRE_TIME: 60 * 1000,
12
16
  };
13
- export {
14
- PROTOCOL_CONFIG
15
- };
16
- //# sourceMappingURL=protocol.types.js.map
17
+ //# sourceMappingURL=protocol.types.js.map
@@ -1,6 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/protocol/protocol.types.ts"],
4
- "mappings": "AAKO,MAAM,kBAAkB;AAAA;AAAA,EAE7B,gBAAgB,MAAM,OAAO;AAAA;AAAA,EAE7B,oBAAoB,IAAI,OAAO;AAAA;AAAA,EAE/B,YAAY,MAAM;AAAA;AAAA,EAElB,aAAa,KAAK;AAAA;AAAA,EAElB,aAAa,KAAK;AACpB;",
5
- "names": []
6
- }
1
+ {"version":3,"file":"protocol.types.js","sourceRoot":"","sources":["..\\..\\src\\protocol\\protocol.types.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,UAAU;AACV,yEAAyE;AAEzE,kBAAkB;AAClB,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,wBAAwB;IACxB,cAAc,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;IACjC,mBAAmB;IACnB,kBAAkB,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IACnC,oBAAoB;IACpB,UAAU,EAAE,GAAG,GAAG,IAAI;IACtB,kBAAkB;IAClB,WAAW,EAAE,EAAE,GAAG,IAAI;IACtB,0BAA0B;IAC1B,WAAW,EAAE,EAAE,GAAG,IAAI;CACd,CAAC"}
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Auto-update service interface
2
+ * 자동 업데이트 서비스 인터페이스
3
3
  *
4
- * Retrieves the latest version info for client applications.
4
+ * 클라이언트 애플리케이션의 최신 버전 정보를 조회한다.
5
5
  */
6
6
  export interface AutoUpdateService {
7
7
  /**
8
- * Retrieve the latest version info for the specified platform.
9
- * @param platform Target platform (e.g., "win32", "darwin", "linux")
10
- * @returns Latest version info, or undefined if no version exists
8
+ * 지정된 플랫폼의 최신 버전 정보를 조회한다.
9
+ * @param platform 대상 플랫폼 (예: "win32", "darwin", "linux")
10
+ * @returns 최신 버전 정보, 버전이 없으면 undefined
11
11
  */
12
12
  getLastVersion(platform: string): Promise<{
13
13
  version: string;
@@ -1 +1,2 @@
1
- //# sourceMappingURL=auto-update-service.types.js.map
1
+ export {};
2
+ //# sourceMappingURL=auto-update-service.types.js.map
@@ -1,6 +1 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "mappings": "",
5
- "names": []
6
- }
1
+ {"version":3,"file":"auto-update-service.types.js","sourceRoot":"","sources":["..\\..\\src\\service-types\\auto-update-service.types.ts"],"names":[],"mappings":""}
@@ -1,9 +1,9 @@
1
1
  import type { Dialect, IsolationLevel, QueryDef, ColumnMeta, ResultMeta } from "@simplysm/orm-common";
2
2
  /**
3
- * ORM service interface
3
+ * ORM 서비스 인터페이스
4
4
  *
5
- * Provides database connection, transaction management, and query execution.
6
- * Supports MySQL, MSSQL, and PostgreSQL.
5
+ * 데이터베이스 연결, 트랜잭션 관리, 쿼리 실행을 제공한다.
6
+ * MySQL, MSSQL, PostgreSQL을 지원한다.
7
7
  */
8
8
  export interface OrmService {
9
9
  getInfo(opt: DbConnOptions & {
@@ -13,7 +13,9 @@ export interface OrmService {
13
13
  database?: string;
14
14
  schema?: string;
15
15
  }>;
16
- connect(opt: Record<string, unknown>): Promise<number>;
16
+ connect(opt: DbConnOptions & {
17
+ configName: string;
18
+ }): Promise<number>;
17
19
  close(connId: number): Promise<void>;
18
20
  beginTransaction(connId: number, isolationLevel?: IsolationLevel): Promise<void>;
19
21
  commitTransaction(connId: number): Promise<void>;
@@ -22,7 +24,7 @@ export interface OrmService {
22
24
  executeDefs(connId: number, defs: QueryDef[], options?: (ResultMeta | undefined)[]): Promise<unknown[][]>;
23
25
  bulkInsert(connId: number, tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]): Promise<void>;
24
26
  }
25
- /** Database connection options */
27
+ /** 데이터베이스 연결 옵션 */
26
28
  export type DbConnOptions = {
27
29
  configName?: string;
28
30
  config?: Record<string, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"orm-service.types.d.ts","sourceRoot":"","sources":["..\\..\\src\\service-types\\orm-service.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,QAAQ,EACR,UAAU,EACV,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAC5D,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjF,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE7F,WAAW,CACT,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,EAAE,EAChB,OAAO,CAAC,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,GACnC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAExB,UAAU,CACR,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,kCAAkC;AAClC,MAAM,MAAM,aAAa,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"orm-service.types.d.ts","sourceRoot":"","sources":["..\\..\\src\\service-types\\orm-service.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,QAAQ,EACR,UAAU,EACV,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAC5D,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtE,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjF,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE7F,WAAW,CACT,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,EAAE,EAChB,OAAO,CAAC,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,GACnC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAExB,UAAU,CACR,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,mBAAmB;AACnB,MAAM,MAAM,aAAa,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC"}
@@ -1 +1,2 @@
1
- //# sourceMappingURL=orm-service.types.js.map
1
+ export {};
2
+ //# sourceMappingURL=orm-service.types.js.map
@@ -1,6 +1 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "mappings": "",
5
- "names": []
6
- }
1
+ {"version":3,"file":"orm-service.types.js","sourceRoot":"","sources":["..\\..\\src\\service-types\\orm-service.types.ts"],"names":[],"mappings":""}
package/dist/types.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  /**
2
- * File upload result
2
+ * 파일 업로드 결과
3
3
  *
4
- * Contains information about a file uploaded to the server.
4
+ * 서버에 업로드된 파일의 정보를 포함한다.
5
5
  */
6
6
  export interface ServiceUploadResult {
7
- /** Storage path on the server */
7
+ /** 서버 저장 경로 */
8
8
  path: string;
9
- /** Original filename */
9
+ /** 원본 파일명 */
10
10
  filename: string;
11
- /** File size (bytes) */
11
+ /** 파일 크기 (바이트) */
12
12
  size: number;
13
13
  }
14
14
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["..\\src\\types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["..\\src\\types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;CACd"}
package/dist/types.js CHANGED
@@ -1 +1,2 @@
1
- //# sourceMappingURL=types.js.map
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1,6 +1 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "mappings": "",
5
- "names": []
6
- }
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["..\\src\\types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@simplysm/service-common",
3
- "version": "13.0.100",
4
- "description": "Simplysm package - Service module (common)",
5
- "author": "simplysm",
3
+ "version": "14.0.1",
4
+ "description": "심플리즘 패키지 - 서비스 (common)",
5
+ "author": "심플리즘",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
@@ -14,13 +14,11 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "files": [
16
16
  "dist",
17
- "docs",
18
- "src",
19
- "tests"
17
+ "src"
20
18
  ],
21
19
  "sideEffects": false,
22
20
  "dependencies": {
23
- "@simplysm/core-common": "13.0.100",
24
- "@simplysm/orm-common": "13.0.100"
21
+ "@simplysm/core-common": "14.0.1",
22
+ "@simplysm/orm-common": "14.0.1"
25
23
  }
26
24
  }
@@ -1,25 +1,25 @@
1
1
  /**
2
- * Event definition created by defineEvent().
3
- * $info and $data are type-only markers (not used at runtime).
2
+ * defineEvent()로 생성된 이벤트 정의.
3
+ * $info $data 타입 전용 마커임 (런타임에서는 사용되지 않음).
4
4
  */
5
5
  export interface ServiceEventDef<TInfo = unknown, TData = unknown> {
6
6
  eventName: string;
7
- /** Type extraction only (not used at runtime) */
7
+ /** 타입 추출 전용 (런타임에서는 사용되지 않음) */
8
8
  readonly $info: TInfo;
9
- /** Type extraction only (not used at runtime) */
9
+ /** 타입 추출 전용 (런타임에서는 사용되지 않음) */
10
10
  readonly $data: TData;
11
11
  }
12
12
 
13
13
  /**
14
- * Define a service event with type-safe info and data.
14
+ * 타입 안전한 info와 data를 가진 서비스 이벤트를 정의한다.
15
15
  *
16
16
  * @example
17
17
  * const OrderUpdated = defineEvent<{ orderId: number }, { status: string }>("OrderUpdated");
18
18
  *
19
- * // Server emit
19
+ * // 서버에서 이벤트 발생
20
20
  * ctx.socket?.emitEvent(OrderUpdated, { orderId: 123 }, { status: "shipped" });
21
21
  *
22
- * // Client subscribe
22
+ * // 클라이언트에서 구독
23
23
  * await client.addEventListener(OrderUpdated, { orderId: 123 }, (data) => {
24
24
  * console.log(data.status); // typed
25
25
  * });
package/src/index.ts CHANGED
@@ -1,14 +1,12 @@
1
- // Protocol
1
+ // 프로토콜
2
2
  export * from "./protocol/protocol.types";
3
3
  export * from "./protocol/create-service-protocol";
4
4
 
5
- // Service Types
5
+ // 서비스 타입
6
6
  export * from "./service-types/orm-service.types";
7
7
  export * from "./service-types/auto-update-service.types";
8
- export * from "./service-types/smtp-client-service.types";
9
-
10
- // Types
8
+ // 타입
11
9
  export * from "./types";
12
10
 
13
- // Define
11
+ // 정의
14
12
  export * from "./define-event";
@@ -10,56 +10,56 @@ import {
10
10
  import { PROTOCOL_CONFIG, type ServiceMessage } from "./protocol.types";
11
11
 
12
12
  /**
13
- * Service protocol interface
13
+ * 서비스 프로토콜 인터페이스
14
14
  *
15
- * Binary Protocol V2:
16
- * - Header: 28 bytes (UUID 16 + TotalSize 8 + Index 4)
17
- * - Body: JSON
18
- * - Auto chunking: splits into 300KB chunks when exceeding 3MB
19
- * - Max message size: 100MB
15
+ * 바이너리 프로토콜 V2:
16
+ * - 헤더: 28바이트 (UUID 16 + TotalSize 8 + Index 4)
17
+ * - 본문: JSON
18
+ * - 자동 청킹: 3MB 초과 300KB 청크로 분할
19
+ * - 최대 메시지 크기: 100MB
20
20
  */
21
21
  export interface ServiceProtocol {
22
22
  /**
23
- * Encode a message (auto-split if needed)
23
+ * 메시지를 인코딩한다 (필요 자동 분할)
24
24
  */
25
25
  encode(uuid: string, message: ServiceMessage): { chunks: Bytes[]; totalSize: number };
26
26
 
27
27
  /**
28
- * Decode a message (auto-reassemble chunked packets)
28
+ * 메시지를 디코딩한다 (청크 패킷 자동 재조립)
29
29
  */
30
30
  decode<T extends ServiceMessage>(bytes: Bytes): ServiceMessageDecodeResult<T>;
31
31
 
32
32
  /**
33
- * Dispose the protocol instance.
33
+ * 프로토콜 인스턴스를 해제한다.
34
34
  *
35
- * Releases the internal chunk accumulator's GC timer and frees memory.
36
- * Must be called when the protocol instance is no longer needed.
35
+ * 내부 청크 누적기의 GC 타이머를 해제하고 메모리를 반환한다.
36
+ * 프로토콜 인스턴스가 이상 필요하지 않을 반드시 호출해야 한다.
37
37
  */
38
38
  dispose(): void;
39
39
  }
40
40
 
41
41
  /**
42
- * Message decode result type (union)
42
+ * 메시지 디코딩 결과 타입 (유니언)
43
43
  *
44
- * - `type: "complete"`: all chunks received and message reassembly is complete
45
- * - `type: "progress"`: chunked message in progress (only some chunks arrived)
44
+ * - `type: "complete"`: 모든 청크를 수신하여 메시지 재조립이 완료됨
45
+ * - `type: "progress"`: 청크 메시지 진행 (일부 청크만 도착)
46
46
  */
47
47
  export type ServiceMessageDecodeResult<TMessage extends ServiceMessage> =
48
48
  | { type: "complete"; uuid: string; message: TMessage }
49
49
  | { type: "progress"; uuid: string; totalSize: number; completedSize: number };
50
50
 
51
51
  /**
52
- * Create a service protocol encoder/decoder
52
+ * 서비스 프로토콜 인코더/디코더를 생성한다
53
53
  *
54
- * Binary Protocol V2:
55
- * - Header: 28 bytes (UUID 16 + TotalSize 8 + Index 4)
56
- * - Body: JSON
57
- * - Auto chunking: splits into 300KB chunks when exceeding 3MB
58
- * - Max message size: 100MB
54
+ * 바이너리 프로토콜 V2:
55
+ * - 헤더: 28바이트 (UUID 16 + TotalSize 8 + Index 4)
56
+ * - 본문: JSON
57
+ * - 자동 청킹: 3MB 초과 300KB 청크로 분할
58
+ * - 최대 메시지 크기: 100MB
59
59
  */
60
60
  export function createServiceProtocol(): ServiceProtocol {
61
61
  // -------------------------------------------------------------------
62
- // State
62
+ // 상태
63
63
  // -------------------------------------------------------------------
64
64
 
65
65
  const accumulator = new LazyGcMap<
@@ -75,17 +75,17 @@ export function createServiceProtocol(): ServiceProtocol {
75
75
  });
76
76
 
77
77
  // -------------------------------------------------------------------
78
- // Encoding Helper
78
+ // 인코딩 헬퍼
79
79
  // -------------------------------------------------------------------
80
80
 
81
81
  /**
82
- * Encode a message chunk (header + body)
82
+ * 메시지 청크를 인코딩한다 (헤더 + 본문)
83
83
  *
84
- * Header structure (28 bytes, Big Endian):
84
+ * 헤더 구조 (28바이트, Big Endian):
85
85
  * ```
86
86
  * Offset Size Field
87
87
  * ------ ---- -----
88
- * 0 16 UUID (binary)
88
+ * 0 16 UUID (바이너리)
89
89
  * 16 8 TotalSize (uint64)
90
90
  * 24 4 Index (uint32)
91
91
  * ```
@@ -117,7 +117,7 @@ export function createServiceProtocol(): ServiceProtocol {
117
117
  }
118
118
 
119
119
  // -------------------------------------------------------------------
120
- // Public API
120
+ // 공개 API
121
121
  // -------------------------------------------------------------------
122
122
 
123
123
  return {
@@ -127,20 +127,20 @@ export function createServiceProtocol(): ServiceProtocol {
127
127
 
128
128
  const totalSize = msgBytes.length;
129
129
 
130
- // Total size limit check (performed first)
130
+ // 전체 크기 제한 확인 (우선 수행)
131
131
  if (totalSize > PROTOCOL_CONFIG.MAX_TOTAL_SIZE) {
132
- throw new ArgumentError("Message size exceeds the limit.", {
132
+ throw new ArgumentError("메시지 크기가 제한을 초과했습니다.", {
133
133
  totalSize,
134
134
  maxSize: PROTOCOL_CONFIG.MAX_TOTAL_SIZE,
135
135
  });
136
136
  }
137
137
 
138
- // Return as-is if small enough
138
+ // 충분히 작으면 그대로 반환
139
139
  if (totalSize <= PROTOCOL_CONFIG.SPLIT_MESSAGE_SIZE) {
140
140
  return { chunks: [encodeChunk({ uuid, totalSize, index: 0 }, msgBytes)], totalSize };
141
141
  }
142
142
 
143
- // Split into chunks
143
+ // 청크로 분할
144
144
  const chunks: Bytes[] = [];
145
145
  let offset = 0;
146
146
  let index = 0;
@@ -160,13 +160,13 @@ export function createServiceProtocol(): ServiceProtocol {
160
160
 
161
161
  decode<T extends ServiceMessage>(bytes: Bytes): ServiceMessageDecodeResult<T> {
162
162
  if (bytes.length < 28) {
163
- throw new ArgumentError("Buffer size is smaller than header size.", {
163
+ throw new ArgumentError("버퍼 크기가 헤더 크기보다 작습니다.", {
164
164
  bufferSize: bytes.length,
165
165
  minimumSize: 28,
166
166
  });
167
167
  }
168
168
 
169
- // 1. Read header
169
+ // 1. 헤더 읽기
170
170
 
171
171
  // UUID
172
172
  const uuidBytes = bytes.subarray(0, 16);
@@ -177,9 +177,9 @@ export function createServiceProtocol(): ServiceProtocol {
177
177
  const totalSize = Number(headerView.getBigUint64(16, false));
178
178
  const index = headerView.getUint32(24, false);
179
179
 
180
- // Total size limit check (performed first)
180
+ // 전체 크기 제한 확인 (우선 수행)
181
181
  if (totalSize > PROTOCOL_CONFIG.MAX_TOTAL_SIZE) {
182
- throw new ArgumentError("Message size exceeds the limit.", {
182
+ throw new ArgumentError("메시지 크기가 제한을 초과했습니다.", {
183
183
  totalSize,
184
184
  maxSize: PROTOCOL_CONFIG.MAX_TOTAL_SIZE,
185
185
  });
@@ -193,7 +193,7 @@ export function createServiceProtocol(): ServiceProtocol {
193
193
  chunks: [],
194
194
  }));
195
195
  if (accItem.chunks[index] == null) {
196
- // Duplicate packet guard
196
+ // 중복 패킷 방어
197
197
  accItem.chunks[index] = bodyBytes;
198
198
  accItem.completedSize += bodyBytes.length;
199
199
  }
@@ -205,15 +205,15 @@ export function createServiceProtocol(): ServiceProtocol {
205
205
  totalSize: totalSize,
206
206
  completedSize: accItem.completedSize,
207
207
  };
208
- } else {
209
- accumulator.delete(uuid); // Free memory
208
+ } else if (accItem.completedSize === accItem.totalSize) {
209
+ accumulator.delete(uuid); // 메모리 해제
210
210
 
211
211
  const resultBytes = bytesU.concat(accItem.chunks.filterExists());
212
212
  let messageArr: [string, unknown];
213
213
  try {
214
214
  messageArr = json.parse<[string, unknown]>(new TextDecoder().decode(resultBytes));
215
215
  } catch (err) {
216
- throw new ArgumentError("Failed to decode message.", { uuid, cause: err });
216
+ throw new ArgumentError("메시지 디코딩에 실패했습니다.", { uuid, cause: err });
217
217
  }
218
218
  return {
219
219
  type: "complete",
@@ -223,6 +223,13 @@ export function createServiceProtocol(): ServiceProtocol {
223
223
  body: messageArr[1],
224
224
  } as T,
225
225
  };
226
+ } else {
227
+ accumulator.delete(uuid);
228
+ throw new ArgumentError("프로토콜 무결성 위반: completedSize가 totalSize를 초과했습니다.", {
229
+ uuid,
230
+ completedSize: accItem.completedSize,
231
+ totalSize: accItem.totalSize,
232
+ });
226
233
  }
227
234
  },
228
235
 
@@ -1,23 +1,23 @@
1
1
  // ----------------------------------------------------------------------
2
- // Protocol Constants
2
+ // 프로토콜 상수
3
3
  // ----------------------------------------------------------------------
4
4
 
5
- /** Service protocol configuration */
5
+ /** 서비스 프로토콜 설정 */
6
6
  export const PROTOCOL_CONFIG = {
7
- /** Max message size (100MB) */
7
+ /** 최대 메시지 크기 (100MB) */
8
8
  MAX_TOTAL_SIZE: 100 * 1024 * 1024,
9
- /** Chunking threshold (3MB) */
9
+ /** 청킹 임계값 (3MB) */
10
10
  SPLIT_MESSAGE_SIZE: 3 * 1024 * 1024,
11
- /** Chunk size (300KB) */
11
+ /** 청크 크기 (300KB) */
12
12
  CHUNK_SIZE: 300 * 1024,
13
- /** GC interval (10s) */
13
+ /** GC 주기 (10초) */
14
14
  GC_INTERVAL: 10 * 1000,
15
- /** Incomplete message expiry time (60s) */
15
+ /** 미완성 메시지 만료 시간 (60초) */
16
16
  EXPIRE_TIME: 60 * 1000,
17
17
  } as const;
18
18
 
19
19
  // ----------------------------------------------------------------------
20
- // Message Types
20
+ // 메시지 타입
21
21
  // ----------------------------------------------------------------------
22
22
 
23
23
  export type ServiceMessage =
@@ -34,10 +34,10 @@ export type ServiceMessage =
34
34
  | ServiceEventMessage;
35
35
 
36
36
  export type ServiceServerMessage =
37
- | ServiceReloadMessage // Notification
37
+ | ServiceReloadMessage // 알림
38
38
  | ServiceResponseMessage
39
39
  | ServiceErrorMessage
40
- | ServiceEventMessage; // Notification
40
+ | ServiceEventMessage; // 알림
41
41
 
42
42
  export type ServiceServerRawMessage = ServiceProgressMessage | ServiceServerMessage;
43
43
 
@@ -50,28 +50,28 @@ export type ServiceClientMessage =
50
50
  | ServiceEmitEventMessage;
51
51
 
52
52
  // ----------------------------------------------------------------------
53
- // System (common)
53
+ // 시스템 (공통)
54
54
  // ----------------------------------------------------------------------
55
55
 
56
- /** Server: reload command to client */
56
+ /** 서버: 클라이언트에 리로드 명령 */
57
57
  export interface ServiceReloadMessage {
58
58
  name: "reload";
59
59
  body: {
60
- clientName: string | undefined; // Client name
61
- changedFileSet: Set<string>; // Changed file list
60
+ clientName: string | undefined; // 클라이언트 이름
61
+ changedFileSet: Set<string>; // 변경된 파일 목록
62
62
  };
63
63
  }
64
64
 
65
- /** Server: progress notification for received chunked message */
65
+ /** 서버: 수신된 청크 메시지의 진행 상태 알림 */
66
66
  export interface ServiceProgressMessage {
67
67
  name: "progress";
68
68
  body: {
69
- totalSize: number; // Total size (bytes)
70
- completedSize: number; // Completed size (bytes)
69
+ totalSize: number; // 전체 크기 (바이트)
70
+ completedSize: number; // 완료된 크기 (바이트)
71
71
  };
72
72
  }
73
73
 
74
- /** Server: error notification */
74
+ /** 서버: 에러 알림 */
75
75
  export interface ServiceErrorMessage {
76
76
  name: "error";
77
77
  body: {
@@ -84,72 +84,72 @@ export interface ServiceErrorMessage {
84
84
  };
85
85
  }
86
86
 
87
- /** Client: authentication message */
87
+ /** 클라이언트: 인증 메시지 */
88
88
  export interface ServiceAuthMessage {
89
89
  name: "auth";
90
- body: string; // Token
90
+ body: string; // 토큰
91
91
  }
92
92
 
93
93
  // ----------------------------------------------------------------------
94
94
  // Service.Method
95
95
  // ----------------------------------------------------------------------
96
96
 
97
- /** Client: service method request */
97
+ /** 클라이언트: 서비스 메서드 요청 */
98
98
  export interface ServiceRequestMessage {
99
99
  name: `${string}.${string}`; // ${service}.${method}
100
- body: unknown[]; // params
100
+ body: unknown[]; // 매개변수
101
101
  }
102
102
 
103
- /** Server: service method response */
103
+ /** 서버: 서비스 메서드 응답 */
104
104
  export interface ServiceResponseMessage {
105
105
  name: "response";
106
- body?: unknown; // result
106
+ body?: unknown; // 결과
107
107
  }
108
108
 
109
109
  // ----------------------------------------------------------------------
110
- // Events
110
+ // 이벤트
111
111
  // ----------------------------------------------------------------------
112
112
 
113
- /** Client: add event listener */
113
+ /** 클라이언트: 이벤트 리스너 추가 */
114
114
  export interface ServiceAddEventListenerMessage {
115
115
  name: "evt:add";
116
116
  body: {
117
- key: string; // Listener key (uuid) - needed for removeEventListener
118
- name: string; // Event name (Type.name)
119
- info: unknown; // Additional listener info for filtering when events fire
117
+ key: string; // 리스너 (uuid) - removeEventListener에 필요
118
+ name: string; // 이벤트 이름 (Type.name)
119
+ info: unknown; // 이벤트 발생 필터링을 위한 추가 리스너 정보
120
120
  };
121
121
  }
122
122
 
123
- /** Client: remove event listener */
123
+ /** 클라이언트: 이벤트 리스너 제거 */
124
124
  export interface ServiceRemoveEventListenerMessage {
125
125
  name: "evt:remove";
126
126
  body: {
127
- key: string; // Listener key (uuid)
127
+ key: string; // 리스너 (uuid)
128
128
  };
129
129
  }
130
130
 
131
- /** Client: request event listener info list */
131
+ /** 클라이언트: 이벤트 리스너 정보 목록 요청 */
132
132
  export interface ServiceGetEventListenerInfosMessage {
133
133
  name: "evt:gets";
134
134
  body: {
135
- name: string; // Event name
135
+ name: string; // 이벤트 이름
136
136
  };
137
137
  }
138
138
 
139
- /** Client: emit event */
139
+ /** 클라이언트: 이벤트 발생 */
140
140
  export interface ServiceEmitEventMessage {
141
141
  name: "evt:emit";
142
142
  body: {
143
- keys: string[]; // Listener key list
144
- data: unknown; // Data
143
+ keys: string[]; // 리스너 목록
144
+ data: unknown; // 데이터
145
145
  };
146
146
  }
147
147
 
148
- /** Server: event notification */
148
+ /** 서버: 이벤트 알림 */
149
149
  export interface ServiceEventMessage {
150
150
  name: "evt:on";
151
151
  body: {
152
- keys: string[]; // Listener key list
153
- data: unknown; // Data
152
+ keys: string[]; // 리스너 목록
153
+ data: unknown; // 데이터
154
154
  };
155
155
  }