@simplysm/service-common 14.0.4 → 14.0.5

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/README.md CHANGED
@@ -1,233 +1,114 @@
1
1
  # @simplysm/service-common
2
2
 
3
- Shared service protocol and types -- binary protocol V2 with chunking, message types, service event definitions.
4
-
5
- This package provides the platform-neutral foundation shared by both `@simplysm/service-client` and `@simplysm/service-server`.
6
-
7
- ## API
8
-
9
- | Export | Kind | Category | Description |
10
- |--------|------|----------|-------------|
11
- | `PROTOCOL_CONFIG` | const | Protocol | Protocol configuration constants (max size, chunk size, GC interval, expiry) |
12
- | `ServiceMessage` | type | Protocol | Union of all message types (client + server) |
13
- | `ServiceServerMessage` | type | Protocol | Union of server-to-client message types |
14
- | `ServiceServerRawMessage` | type | Protocol | Server raw message (includes progress) |
15
- | `ServiceClientMessage` | type | Protocol | Union of client-to-server message types |
16
- | `ServiceProgressMessage` | interface | Protocol | Chunk receive progress notification |
17
- | `ServiceErrorMessage` | interface | Protocol | Error notification from server |
18
- | `ServiceAuthMessage` | interface | Protocol | Authentication message from client |
19
- | `ServiceRequestMessage` | interface | Protocol | Service method request from client |
20
- | `ServiceResponseMessage` | interface | Protocol | Service method response from server |
21
- | `ServiceAddEventListenerMessage` | interface | Protocol | Add event listener request |
22
- | `ServiceRemoveEventListenerMessage` | interface | Protocol | Remove event listener request |
23
- | `ServiceGetEventListenerInfosMessage` | interface | Protocol | Get event listener info list request |
24
- | `ServiceEmitEventMessage` | interface | Protocol | Emit event request |
25
- | `ServiceEventMessage` | interface | Protocol | Event notification from server |
26
- | `ServiceProtocol` | interface | Protocol | Protocol encoder/decoder interface |
27
- | `ServiceMessageDecodeResult` | type | Protocol | Decode result (complete or progress) |
28
- | `createServiceProtocol` | function | Protocol | Create a protocol encoder/decoder instance |
29
- | `OrmService` | interface | Service Types | ORM service interface (connect, transaction, query) |
30
- | `DbConnOptions` | type | Service Types | Database connection options |
31
- | `AutoUpdateService` | interface | Service Types | Auto-update service interface |
32
- | `ServiceUploadResult` | interface | Types | File upload result |
33
- | `ServiceEventDef` | interface | Definitions | Event definition created by `defineEvent()` |
34
- | `defineEvent` | function | Definitions | Define a typed service event |
35
-
36
- ## Protocol
37
-
38
- ### PROTOCOL_CONFIG
39
-
40
- Protocol configuration constants.
41
-
42
- ```ts
43
- import { PROTOCOL_CONFIG } from "@simplysm/service-common";
44
- ```
45
-
46
- | Field | Type | Default | Description |
47
- |-------|------|---------|-------------|
48
- | `MAX_TOTAL_SIZE` | `number` | `104,857,600` (100 MB) | Maximum message size |
49
- | `SPLIT_MESSAGE_SIZE` | `number` | `3,145,728` (3 MB) | Chunking threshold -- messages larger than this are split |
50
- | `CHUNK_SIZE` | `number` | `307,200` (300 KB) | Size of each chunk |
51
- | `GC_INTERVAL` | `number` | `10,000` (10 s) | Garbage collection interval for incomplete messages |
52
- | `EXPIRE_TIME` | `number` | `60,000` (60 s) | Expiry time for incomplete chunked messages |
53
-
54
- ### Message Types
55
-
56
- All messages exchanged between client and server are strongly typed.
57
-
58
- #### Client-to-Server Messages
59
-
60
- | Interface | `name` Field | Description |
61
- |-----------|-------------|-------------|
62
- | `ServiceAuthMessage` | `"auth"` | Authenticate with a token string |
63
- | `ServiceRequestMessage` | `` `${service}.${method}` `` | Call a service method with parameters |
64
- | `ServiceAddEventListenerMessage` | `"evt:add"` | Register an event listener with key, event name, and filter info |
65
- | `ServiceRemoveEventListenerMessage` | `"evt:remove"` | Unregister an event listener by key |
66
- | `ServiceGetEventListenerInfosMessage` | `"evt:gets"` | Query listener info list for an event name |
67
- | `ServiceEmitEventMessage` | `"evt:emit"` | Emit an event to specific listener keys |
68
-
69
- #### Server-to-Client Messages
70
-
71
- | Interface | `name` Field | Description |
72
- |-----------|-------------|-------------|
73
- | `ServiceProgressMessage` | `"progress"` | Chunk receive progress (`totalSize`, `completedSize`) |
74
- | `ServiceResponseMessage` | `"response"` | Service method return value |
75
- | `ServiceErrorMessage` | `"error"` | Error with name, message, code, optional stack/detail/cause |
76
- | `ServiceEventMessage` | `"evt:on"` | Event broadcast to listener keys with data |
77
-
78
- ### ServiceProtocol
79
-
80
- Binary protocol V2 interface. Header: 28 bytes (UUID 16 + TotalSize 8 + Index 4), body: JSON. Auto-chunks messages exceeding 3 MB into 300 KB chunks. Maximum message size: 100 MB.
81
-
82
- ```ts
83
- interface ServiceProtocol {
84
- encode(uuid: string, message: ServiceMessage): { chunks: Bytes[]; totalSize: number };
85
- decode<T extends ServiceMessage>(bytes: Bytes): ServiceMessageDecodeResult<T>;
86
- dispose(): void;
87
- }
88
- ```
89
-
90
- | Method | Parameters | Return | Description |
91
- |--------|-----------|--------|-------------|
92
- | `encode` | `uuid: string`, `message: ServiceMessage` | `{ chunks: Bytes[]; totalSize: number }` | Encode a message into binary chunks |
93
- | `decode` | `bytes: Bytes` | `ServiceMessageDecodeResult<T>` | Decode received bytes; returns `"complete"` or `"progress"` |
94
- | `dispose` | -- | `void` | Clean up internal GC timers |
95
-
96
- ### ServiceMessageDecodeResult\<TMessage\>
97
-
98
- ```ts
99
- type ServiceMessageDecodeResult<TMessage extends ServiceMessage> =
100
- | { type: "complete"; uuid: string; message: TMessage }
101
- | { type: "progress"; uuid: string; totalSize: number; completedSize: number };
102
- ```
103
-
104
- - `"complete"` -- all chunks received; the full message is available.
105
- - `"progress"` -- chunked message still in progress.
3
+ Shared types and protocol for the Simplysm service framework. Provides the binary protocol V2 encoder/decoder, message type definitions, service interface contracts (ORM, auto-update), and event definition utilities used by both `@simplysm/service-client` and `@simplysm/service-server`.
106
4
 
107
- ### createServiceProtocol
5
+ ## Installation
108
6
 
109
- ```ts
110
- function createServiceProtocol(): ServiceProtocol;
7
+ ```bash
8
+ npm install @simplysm/service-common
111
9
  ```
112
10
 
113
- Creates a binary protocol V2 encoder/decoder instance.
114
-
115
- ## Service Types
116
-
117
- ### OrmService
118
-
119
- ORM service interface. Supports MySQL, MSSQL, and PostgreSQL.
120
-
121
- ```ts
122
- interface OrmService {
123
- getInfo(opt: DbConnOptions & { configName: string }): Promise<{ dialect: Dialect; database?: string; schema?: string }>;
124
- connect(opt: DbConnOptions & { configName: string }): Promise<number>;
125
- close(connId: number): Promise<void>;
126
- beginTransaction(connId: number, isolationLevel?: IsolationLevel): Promise<void>;
127
- commitTransaction(connId: number): Promise<void>;
128
- rollbackTransaction(connId: number): Promise<void>;
129
- executeParametrized(connId: number, query: string, params?: unknown[]): Promise<unknown[][]>;
130
- executeDefs(connId: number, defs: QueryDef[], options?: (ResultMeta | undefined)[]): Promise<unknown[][]>;
131
- bulkInsert(connId: number, tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]): Promise<void>;
132
- }
133
- ```
134
-
135
- | Method | Parameters | Return | Description |
136
- |--------|-----------|--------|-------------|
137
- | `getInfo` | `opt: DbConnOptions & { configName: string }` | `Promise<{ dialect; database?; schema? }>` | Get database dialect and schema info |
138
- | `connect` | `opt: DbConnOptions & { configName: string }` | `Promise<number>` | Open a connection; returns connection ID |
139
- | `close` | `connId: number` | `Promise<void>` | Close a connection |
140
- | `beginTransaction` | `connId: number`, `isolationLevel?: IsolationLevel` | `Promise<void>` | Begin a transaction |
141
- | `commitTransaction` | `connId: number` | `Promise<void>` | Commit the current transaction |
142
- | `rollbackTransaction` | `connId: number` | `Promise<void>` | Rollback the current transaction |
143
- | `executeParametrized` | `connId: number`, `query: string`, `params?: unknown[]` | `Promise<unknown[][]>` | Execute a parameterized query |
144
- | `executeDefs` | `connId: number`, `defs: QueryDef[]`, `options?: (ResultMeta \| undefined)[]` | `Promise<unknown[][]>` | Execute query definitions |
145
- | `bulkInsert` | `connId: number`, `tableName: string`, `columnDefs: Record<string, ColumnMeta>`, `records: Record<string, unknown>[]` | `Promise<void>` | Bulk insert records |
146
-
147
- ### DbConnOptions
148
-
149
- ```ts
150
- type DbConnOptions = { configName?: string; config?: Record<string, unknown> };
151
- ```
152
-
153
- | Field | Type | Description |
154
- |-------|------|-------------|
155
- | `configName` | `string?` | Configuration name to look up |
156
- | `config` | `Record<string, unknown>?` | Inline configuration object |
157
-
158
- ### AutoUpdateService
159
-
160
- Auto-update service interface. Retrieves the latest version information for client applications.
161
-
162
- ```ts
163
- interface AutoUpdateService {
164
- getLastVersion(platform: string): Promise<{ version: string; downloadPath: string } | undefined>;
165
- }
166
- ```
167
-
168
- | Method | Parameters | Return | Description |
169
- |--------|-----------|--------|-------------|
170
- | `getLastVersion` | `platform: string` | `Promise<{ version: string; downloadPath: string } \| undefined>` | Get latest version info for a platform |
171
-
172
- ## Types
173
-
174
- ### ServiceUploadResult
175
-
176
- File upload result containing server-side storage information.
177
-
178
- ```ts
179
- interface ServiceUploadResult {
180
- path: string;
181
- filename: string;
182
- size: number;
183
- }
184
- ```
185
-
186
- | Field | Type | Description |
187
- |-------|------|-------------|
188
- | `path` | `string` | Server-side storage path |
189
- | `filename` | `string` | Original file name |
190
- | `size` | `number` | File size in bytes |
191
-
192
- ## Definitions
193
-
194
- ### ServiceEventDef\<TInfo, TData\>
195
-
196
- Event definition created by `defineEvent()`. The `$info` and `$data` fields are type-only markers (not used at runtime).
11
+ ## API Overview
12
+
13
+ ### Protocol Types
14
+ | API | Type | Description |
15
+ |-----|------|-------------|
16
+ | `PROTOCOL_CONFIG` | `const` | Protocol configuration constants (max size, chunk size, GC interval, expiry) |
17
+ | `ServiceMessage` | `type` | Union of all message types |
18
+ | `ServiceServerMessage` | `type` | Union of server-to-client message types |
19
+ | `ServiceServerRawMessage` | `type` | Union of progress + server message types |
20
+ | `ServiceClientMessage` | `type` | Union of client-to-server message types |
21
+ | `ServiceProgressMessage` | `interface` | Chunked message progress notification |
22
+ | `ServiceErrorMessage` | `interface` | Error notification from server |
23
+ | `ServiceAuthMessage` | `interface` | Authentication message from client |
24
+ | `ServiceRequestMessage` | `interface` | Service method request from client |
25
+ | `ServiceResponseMessage` | `interface` | Service method response from server |
26
+ | `ServiceAddEventListenerMessage` | `interface` | Add event listener request |
27
+ | `ServiceRemoveEventListenerMessage` | `interface` | Remove event listener request |
28
+ | `ServiceGetEventListenerInfosMessage` | `interface` | Get event listener infos request |
29
+ | `ServiceEmitEventMessage` | `interface` | Emit event request |
30
+ | `ServiceEventMessage` | `interface` | Event notification from server |
31
+
32
+ -> See [docs/protocol-types.md](./docs/protocol-types.md) for details.
33
+
34
+ ### Service Protocol
35
+ | API | Type | Description |
36
+ |-----|------|-------------|
37
+ | `ServiceProtocol` | `interface` | Binary protocol encoder/decoder interface |
38
+ | `ServiceMessageDecodeResult` | `type` | Decode result union (complete or progress) |
39
+ | `createServiceProtocol` | `function` | Creates a protocol encoder/decoder instance |
40
+
41
+ -> See [docs/service-protocol.md](./docs/service-protocol.md) for details.
42
+
43
+ ### ORM Service Types
44
+ | API | Type | Description |
45
+ |-----|------|-------------|
46
+ | `OrmService` | `interface` | ORM service interface for DB operations |
47
+ | `DbConnOptions` | `type` | Database connection options |
48
+
49
+ -> See [docs/orm-service-types.md](./docs/orm-service-types.md) for details.
50
+
51
+ ### Auto-Update Service Types
52
+ | API | Type | Description |
53
+ |-----|------|-------------|
54
+ | `AutoUpdateService` | `interface` | Auto-update service interface |
55
+
56
+ -> See [docs/auto-update-service-types.md](./docs/auto-update-service-types.md) for details.
57
+
58
+ ### Common Types
59
+ | API | Type | Description |
60
+ |-----|------|-------------|
61
+ | `ServiceUploadResult` | `interface` | File upload result containing path, filename, and size |
62
+
63
+ -> See [docs/common-types.md](./docs/common-types.md) for details.
64
+
65
+ ### Events
66
+ | API | Type | Description |
67
+ |-----|------|-------------|
68
+ | `ServiceEventDef` | `interface` | Type-safe event definition with info and data markers |
69
+ | `defineEvent` | `function` | Creates a typed service event definition |
70
+
71
+ -> See [docs/events.md](./docs/events.md) for details.
72
+
73
+ ## Usage Examples
74
+
75
+ ### Creating a Protocol Instance
76
+
77
+ ```typescript
78
+ import { createServiceProtocol } from "@simplysm/service-common";
79
+
80
+ const protocol = createServiceProtocol();
81
+
82
+ // Encode a message
83
+ const { chunks, totalSize } = protocol.encode("some-uuid", {
84
+ name: "SomeService.someMethod",
85
+ body: [arg1, arg2],
86
+ });
197
87
 
198
- ```ts
199
- interface ServiceEventDef<TInfo = unknown, TData = unknown> {
200
- eventName: string;
201
- readonly $info: TInfo;
202
- readonly $data: TData;
88
+ // Decode received bytes
89
+ const result = protocol.decode(receivedBytes);
90
+ if (result.type === "complete") {
91
+ console.log(result.message);
92
+ } else {
93
+ console.log(`Progress: ${result.completedSize}/${result.totalSize}`);
203
94
  }
204
- ```
205
-
206
- | Field | Type | Description |
207
- |-------|------|-------------|
208
- | `eventName` | `string` | Event name identifier |
209
- | `$info` | `TInfo` | Type-only marker for listener filter info |
210
- | `$data` | `TData` | Type-only marker for event payload data |
211
-
212
- ### defineEvent
213
95
 
214
- ```ts
215
- function defineEvent<TInfo = unknown, TData = unknown>(eventName: string): ServiceEventDef<TInfo, TData>;
96
+ // Dispose when done
97
+ protocol.dispose();
216
98
  ```
217
99
 
218
- Define a typed service event for use with the event system.
100
+ ### Defining a Typed Event
219
101
 
220
- ```ts
102
+ ```typescript
221
103
  import { defineEvent } from "@simplysm/service-common";
222
104
 
223
- // Define an event with typed info and data
224
- const MyEvent = defineEvent<{ userId: number }, { message: string }>("MyEvent");
105
+ const OrderUpdated = defineEvent<{ orderId: number }, { status: string }>("OrderUpdated");
225
106
 
226
- // Server: emit the event
227
- await server.emitEvent(MyEvent, (info) => info.userId === 123, { message: "hello" });
107
+ // Server: emit event
108
+ await server.emitEvent(OrderUpdated, (info) => info.orderId === 123, { status: "shipped" });
228
109
 
229
- // Client: subscribe to the event
230
- await client.addListener(MyEvent, { userId: 123 }, async (data) => {
231
- console.log(data.message);
110
+ // Client: subscribe
111
+ await client.addListener(OrderUpdated, { orderId: 123 }, async (data) => {
112
+ console.log(data.status);
232
113
  });
233
114
  ```
@@ -0,0 +1,21 @@
1
+ # Auto-Update Service Types
2
+
3
+ ## `AutoUpdateService`
4
+
5
+ Auto-update service interface for querying the latest client application version.
6
+
7
+ ```typescript
8
+ export interface AutoUpdateService {
9
+ getLastVersion(platform: string): Promise<
10
+ | {
11
+ version: string;
12
+ downloadPath: string;
13
+ }
14
+ | undefined
15
+ >;
16
+ }
17
+ ```
18
+
19
+ | Method | Parameters | Return | Description |
20
+ |--------|-----------|--------|-------------|
21
+ | `getLastVersion` | `platform: string` | `Promise<{ version: string; downloadPath: string } \| undefined>` | Returns the latest version info for the given platform (e.g., `"win32"`, `"darwin"`, `"linux"`, `"android"`). Returns `undefined` if no version is available |
@@ -0,0 +1,19 @@
1
+ # Common Types
2
+
3
+ ## `ServiceUploadResult`
4
+
5
+ File upload result containing information about the uploaded file.
6
+
7
+ ```typescript
8
+ export interface ServiceUploadResult {
9
+ path: string;
10
+ filename: string;
11
+ size: number;
12
+ }
13
+ ```
14
+
15
+ | Field | Type | Description |
16
+ |-------|------|-------------|
17
+ | `path` | `string` | Server-side storage path (relative) |
18
+ | `filename` | `string` | Original filename |
19
+ | `size` | `number` | File size in bytes |
package/docs/events.md ADDED
@@ -0,0 +1,58 @@
1
+ # Events
2
+
3
+ ## `ServiceEventDef`
4
+
5
+ Type-safe event definition created by `defineEvent()`. The `$info` and `$data` fields are type-only markers not used at runtime.
6
+
7
+ ```typescript
8
+ export interface ServiceEventDef<TInfo = unknown, TData = unknown> {
9
+ eventName: string;
10
+ readonly $info: TInfo;
11
+ readonly $data: TData;
12
+ }
13
+ ```
14
+
15
+ | Field | Type | Description |
16
+ |-------|------|-------------|
17
+ | `eventName` | `string` | Event name identifier |
18
+ | `$info` | `TInfo` | Type-only marker for event filter info (not used at runtime) |
19
+ | `$data` | `TData` | Type-only marker for event data (not used at runtime) |
20
+
21
+ ## `defineEvent`
22
+
23
+ Creates a type-safe service event definition with typed info and data.
24
+
25
+ ```typescript
26
+ export function defineEvent<TInfo = unknown, TData = unknown>(
27
+ eventName: string,
28
+ ): ServiceEventDef<TInfo, TData>;
29
+ ```
30
+
31
+ **Parameters:**
32
+
33
+ | Parameter | Type | Description |
34
+ |-----------|------|-------------|
35
+ | `eventName` | `string` | Event name identifier |
36
+
37
+ **Type Parameters:**
38
+
39
+ | Parameter | Description |
40
+ |-----------|-------------|
41
+ | `TInfo` | Type of the event filter info |
42
+ | `TData` | Type of the event data payload |
43
+
44
+ **Returns:** `ServiceEventDef<TInfo, TData>`
45
+
46
+ **Example:**
47
+
48
+ ```typescript
49
+ const OrderUpdated = defineEvent<{ orderId: number }, { status: string }>("OrderUpdated");
50
+
51
+ // Server: emit event
52
+ ctx.socket?.emitEvent(OrderUpdated, { orderId: 123 }, { status: "shipped" });
53
+
54
+ // Client: subscribe
55
+ await client.addEventListener(OrderUpdated, { orderId: 123 }, (data) => {
56
+ console.log(data.status); // typed as string
57
+ });
58
+ ```
@@ -0,0 +1,57 @@
1
+ # ORM Service Types
2
+
3
+ ## `OrmService`
4
+
5
+ ORM service interface providing database connection, transaction management, and query execution. Supports MySQL, MSSQL, and PostgreSQL.
6
+
7
+ ```typescript
8
+ export interface OrmService {
9
+ getInfo(opt: DbConnOptions & { configName: string }): Promise<{
10
+ dialect: Dialect;
11
+ database?: string;
12
+ schema?: string;
13
+ }>;
14
+ connect(opt: DbConnOptions & { configName: string }): Promise<number>;
15
+ close(connId: number): Promise<void>;
16
+ beginTransaction(connId: number, isolationLevel?: IsolationLevel): Promise<void>;
17
+ commitTransaction(connId: number): Promise<void>;
18
+ rollbackTransaction(connId: number): Promise<void>;
19
+ executeParametrized(connId: number, query: string, params?: unknown[]): Promise<unknown[][]>;
20
+ executeDefs(
21
+ connId: number,
22
+ defs: QueryDef[],
23
+ options?: (ResultMeta | undefined)[],
24
+ ): Promise<unknown[][]>;
25
+ bulkInsert(
26
+ connId: number,
27
+ tableName: string,
28
+ columnDefs: Record<string, ColumnMeta>,
29
+ records: Record<string, unknown>[],
30
+ ): Promise<void>;
31
+ }
32
+ ```
33
+
34
+ | Method | Parameters | Return | Description |
35
+ |--------|-----------|--------|-------------|
36
+ | `getInfo` | `opt: DbConnOptions & { configName: string }` | `Promise<{ dialect: Dialect; database?: string; schema?: string }>` | Gets database connection info |
37
+ | `connect` | `opt: DbConnOptions & { configName: string }` | `Promise<number>` | Opens a connection, returns connection ID |
38
+ | `close` | `connId: number` | `Promise<void>` | Closes a connection |
39
+ | `beginTransaction` | `connId: number, isolationLevel?: IsolationLevel` | `Promise<void>` | Begins a transaction |
40
+ | `commitTransaction` | `connId: number` | `Promise<void>` | Commits a transaction |
41
+ | `rollbackTransaction` | `connId: number` | `Promise<void>` | Rolls back a transaction |
42
+ | `executeParametrized` | `connId: number, query: string, params?: unknown[]` | `Promise<unknown[][]>` | Executes a parameterized query |
43
+ | `executeDefs` | `connId: number, defs: QueryDef[], options?: (ResultMeta \| undefined)[]` | `Promise<unknown[][]>` | Executes query definitions |
44
+ | `bulkInsert` | `connId: number, tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]` | `Promise<void>` | Performs bulk insert |
45
+
46
+ ## `DbConnOptions`
47
+
48
+ Database connection options.
49
+
50
+ ```typescript
51
+ export type DbConnOptions = { configName?: string; config?: Record<string, unknown> };
52
+ ```
53
+
54
+ | Field | Type | Description |
55
+ |-------|------|-------------|
56
+ | `configName` | `string?` | Configuration name to look up from server config |
57
+ | `config` | `Record<string, unknown>?` | Additional configuration overrides |
@@ -0,0 +1,268 @@
1
+ # Protocol Types
2
+
3
+ ## `PROTOCOL_CONFIG`
4
+
5
+ Protocol configuration constants for message size limits and timing.
6
+
7
+ ```typescript
8
+ export const PROTOCOL_CONFIG: {
9
+ readonly MAX_TOTAL_SIZE: 104857600; // 100MB
10
+ readonly SPLIT_MESSAGE_SIZE: 3145728; // 3MB
11
+ readonly CHUNK_SIZE: 307200; // 300KB
12
+ readonly GC_INTERVAL: 10000; // 10s
13
+ readonly EXPIRE_TIME: 60000; // 60s
14
+ };
15
+ ```
16
+
17
+ | Field | Value | Description |
18
+ |-------|-------|-------------|
19
+ | `MAX_TOTAL_SIZE` | `104857600` (100MB) | Maximum total message size |
20
+ | `SPLIT_MESSAGE_SIZE` | `3145728` (3MB) | Threshold above which messages are split into chunks |
21
+ | `CHUNK_SIZE` | `307200` (300KB) | Size of each chunk when splitting |
22
+ | `GC_INTERVAL` | `10000` (10s) | Garbage collection interval for incomplete messages |
23
+ | `EXPIRE_TIME` | `60000` (60s) | Expiration time for incomplete messages |
24
+
25
+ ## `ServiceMessage`
26
+
27
+ Union of all service message types.
28
+
29
+ ```typescript
30
+ export type ServiceMessage =
31
+ | ServiceRequestMessage
32
+ | ServiceAuthMessage
33
+ | ServiceProgressMessage
34
+ | ServiceResponseMessage
35
+ | ServiceErrorMessage
36
+ | ServiceAddEventListenerMessage
37
+ | ServiceRemoveEventListenerMessage
38
+ | ServiceGetEventListenerInfosMessage
39
+ | ServiceEmitEventMessage
40
+ | ServiceEventMessage;
41
+ ```
42
+
43
+ ## `ServiceServerMessage`
44
+
45
+ Union of message types sent from server to client.
46
+
47
+ ```typescript
48
+ export type ServiceServerMessage =
49
+ | ServiceResponseMessage
50
+ | ServiceErrorMessage
51
+ | ServiceEventMessage;
52
+ ```
53
+
54
+ ## `ServiceServerRawMessage`
55
+
56
+ Union of server raw messages including progress notifications.
57
+
58
+ ```typescript
59
+ export type ServiceServerRawMessage = ServiceProgressMessage | ServiceServerMessage;
60
+ ```
61
+
62
+ ## `ServiceClientMessage`
63
+
64
+ Union of message types sent from client to server.
65
+
66
+ ```typescript
67
+ export type ServiceClientMessage =
68
+ | ServiceRequestMessage
69
+ | ServiceAuthMessage
70
+ | ServiceAddEventListenerMessage
71
+ | ServiceRemoveEventListenerMessage
72
+ | ServiceGetEventListenerInfosMessage
73
+ | ServiceEmitEventMessage;
74
+ ```
75
+
76
+ ## `ServiceProgressMessage`
77
+
78
+ Server notification about chunked message reception progress.
79
+
80
+ ```typescript
81
+ export interface ServiceProgressMessage {
82
+ name: "progress";
83
+ body: {
84
+ totalSize: number;
85
+ completedSize: number;
86
+ };
87
+ }
88
+ ```
89
+
90
+ | Field | Type | Description |
91
+ |-------|------|-------------|
92
+ | `name` | `"progress"` | Message type discriminator |
93
+ | `body.totalSize` | `number` | Total size in bytes |
94
+ | `body.completedSize` | `number` | Completed size in bytes |
95
+
96
+ ## `ServiceErrorMessage`
97
+
98
+ Server error notification.
99
+
100
+ ```typescript
101
+ export interface ServiceErrorMessage {
102
+ name: "error";
103
+ body: {
104
+ name: string;
105
+ message: string;
106
+ code: string;
107
+ stack?: string;
108
+ detail?: unknown;
109
+ cause?: unknown;
110
+ };
111
+ }
112
+ ```
113
+
114
+ | Field | Type | Description |
115
+ |-------|------|-------------|
116
+ | `name` | `"error"` | Message type discriminator |
117
+ | `body.name` | `string` | Error name |
118
+ | `body.message` | `string` | Error message |
119
+ | `body.code` | `string` | Error code (e.g., `"BAD_MESSAGE"`, `"INTERNAL_ERROR"`) |
120
+ | `body.stack` | `string?` | Stack trace (dev mode only) |
121
+ | `body.detail` | `unknown?` | Additional error detail |
122
+ | `body.cause` | `unknown?` | Error cause |
123
+
124
+ ## `ServiceAuthMessage`
125
+
126
+ Client authentication message.
127
+
128
+ ```typescript
129
+ export interface ServiceAuthMessage {
130
+ name: "auth";
131
+ body: string;
132
+ }
133
+ ```
134
+
135
+ | Field | Type | Description |
136
+ |-------|------|-------------|
137
+ | `name` | `"auth"` | Message type discriminator |
138
+ | `body` | `string` | Authentication token |
139
+
140
+ ## `ServiceRequestMessage`
141
+
142
+ Client service method request.
143
+
144
+ ```typescript
145
+ export interface ServiceRequestMessage {
146
+ name: `${string}.${string}`;
147
+ body: unknown[];
148
+ }
149
+ ```
150
+
151
+ | Field | Type | Description |
152
+ |-------|------|-------------|
153
+ | `name` | `` `${string}.${string}` `` | `${serviceName}.${methodName}` format |
154
+ | `body` | `unknown[]` | Method parameters |
155
+
156
+ ## `ServiceResponseMessage`
157
+
158
+ Server service method response.
159
+
160
+ ```typescript
161
+ export interface ServiceResponseMessage {
162
+ name: "response";
163
+ body?: unknown;
164
+ }
165
+ ```
166
+
167
+ | Field | Type | Description |
168
+ |-------|------|-------------|
169
+ | `name` | `"response"` | Message type discriminator |
170
+ | `body` | `unknown?` | Method return value |
171
+
172
+ ## `ServiceAddEventListenerMessage`
173
+
174
+ Client request to add an event listener.
175
+
176
+ ```typescript
177
+ export interface ServiceAddEventListenerMessage {
178
+ name: "evt:add";
179
+ body: {
180
+ key: string;
181
+ name: string;
182
+ info: unknown;
183
+ };
184
+ }
185
+ ```
186
+
187
+ | Field | Type | Description |
188
+ |-------|------|-------------|
189
+ | `name` | `"evt:add"` | Message type discriminator |
190
+ | `body.key` | `string` | Listener key (UUID) for removal |
191
+ | `body.name` | `string` | Event name |
192
+ | `body.info` | `unknown` | Additional listener info for event filtering |
193
+
194
+ ## `ServiceRemoveEventListenerMessage`
195
+
196
+ Client request to remove an event listener.
197
+
198
+ ```typescript
199
+ export interface ServiceRemoveEventListenerMessage {
200
+ name: "evt:remove";
201
+ body: {
202
+ key: string;
203
+ };
204
+ }
205
+ ```
206
+
207
+ | Field | Type | Description |
208
+ |-------|------|-------------|
209
+ | `name` | `"evt:remove"` | Message type discriminator |
210
+ | `body.key` | `string` | Listener key (UUID) |
211
+
212
+ ## `ServiceGetEventListenerInfosMessage`
213
+
214
+ Client request to get event listener information.
215
+
216
+ ```typescript
217
+ export interface ServiceGetEventListenerInfosMessage {
218
+ name: "evt:gets";
219
+ body: {
220
+ name: string;
221
+ };
222
+ }
223
+ ```
224
+
225
+ | Field | Type | Description |
226
+ |-------|------|-------------|
227
+ | `name` | `"evt:gets"` | Message type discriminator |
228
+ | `body.name` | `string` | Event name |
229
+
230
+ ## `ServiceEmitEventMessage`
231
+
232
+ Client request to emit an event to specific listeners.
233
+
234
+ ```typescript
235
+ export interface ServiceEmitEventMessage {
236
+ name: "evt:emit";
237
+ body: {
238
+ keys: string[];
239
+ data: unknown;
240
+ };
241
+ }
242
+ ```
243
+
244
+ | Field | Type | Description |
245
+ |-------|------|-------------|
246
+ | `name` | `"evt:emit"` | Message type discriminator |
247
+ | `body.keys` | `string[]` | Target listener keys |
248
+ | `body.data` | `unknown` | Event data |
249
+
250
+ ## `ServiceEventMessage`
251
+
252
+ Server event notification to client.
253
+
254
+ ```typescript
255
+ export interface ServiceEventMessage {
256
+ name: "evt:on";
257
+ body: {
258
+ keys: string[];
259
+ data: unknown;
260
+ };
261
+ }
262
+ ```
263
+
264
+ | Field | Type | Description |
265
+ |-------|------|-------------|
266
+ | `name` | `"evt:on"` | Message type discriminator |
267
+ | `body.keys` | `string[]` | Target listener keys |
268
+ | `body.data` | `unknown` | Event data |
@@ -0,0 +1,58 @@
1
+ # Service Protocol
2
+
3
+ ## `ServiceProtocol`
4
+
5
+ Binary protocol encoder/decoder interface. Uses a 28-byte header (UUID 16 + TotalSize 8 + Index 4) with JSON body. Automatically chunks messages larger than 3MB into 300KB chunks. Maximum message size is 100MB.
6
+
7
+ ```typescript
8
+ export interface ServiceProtocol {
9
+ encode(uuid: string, message: ServiceMessage): { chunks: Bytes[]; totalSize: number };
10
+ decode<T extends ServiceMessage>(bytes: Bytes): ServiceMessageDecodeResult<T>;
11
+ dispose(): void;
12
+ }
13
+ ```
14
+
15
+ | Method | Parameters | Return | Description |
16
+ |--------|-----------|--------|-------------|
17
+ | `encode` | `uuid: string, message: ServiceMessage` | `{ chunks: Bytes[]; totalSize: number }` | Encodes a message, auto-splitting if needed |
18
+ | `decode` | `bytes: Bytes` | `ServiceMessageDecodeResult<T>` | Decodes a message, auto-reassembling chunks |
19
+ | `dispose` | none | `void` | Releases the internal chunk accumulator GC timer. Must be called when the instance is no longer needed |
20
+
21
+ ## `ServiceMessageDecodeResult`
22
+
23
+ Decode result union type. Either a complete message or a progress indicator for chunked messages.
24
+
25
+ ```typescript
26
+ export type ServiceMessageDecodeResult<TMessage extends ServiceMessage> =
27
+ | { type: "complete"; uuid: string; message: TMessage }
28
+ | { type: "progress"; uuid: string; totalSize: number; completedSize: number };
29
+ ```
30
+
31
+ When `type` is `"complete"`:
32
+
33
+ | Field | Type | Description |
34
+ |-------|------|-------------|
35
+ | `type` | `"complete"` | All chunks received, message reassembled |
36
+ | `uuid` | `string` | Message UUID |
37
+ | `message` | `TMessage` | Decoded message |
38
+
39
+ When `type` is `"progress"`:
40
+
41
+ | Field | Type | Description |
42
+ |-------|------|-------------|
43
+ | `type` | `"progress"` | Partial chunks received |
44
+ | `uuid` | `string` | Message UUID |
45
+ | `totalSize` | `number` | Total size in bytes |
46
+ | `completedSize` | `number` | Completed size in bytes |
47
+
48
+ ## `createServiceProtocol`
49
+
50
+ Creates a service protocol encoder/decoder instance.
51
+
52
+ ```typescript
53
+ export function createServiceProtocol(): ServiceProtocol;
54
+ ```
55
+
56
+ **Returns:** `ServiceProtocol` -- A new protocol instance with encode/decode/dispose methods.
57
+
58
+ The instance maintains an internal `LazyGcMap` accumulator for reassembling chunked messages. The GC timer runs every 10 seconds and expires incomplete messages after 60 seconds.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/service-common",
3
- "version": "14.0.4",
3
+ "version": "14.0.5",
4
4
  "description": "심플리즘 패키지 - 서비스 (common)",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",
@@ -14,14 +14,15 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "files": [
16
16
  "dist",
17
- "src"
17
+ "src",
18
+ "docs"
18
19
  ],
19
20
  "sideEffects": false,
20
21
  "devDependencies": {
21
22
  "@types/node": "^20.19.37"
22
23
  },
23
24
  "dependencies": {
24
- "@simplysm/core-common": "14.0.4",
25
- "@simplysm/orm-common": "14.0.4"
25
+ "@simplysm/core-common": "14.0.5",
26
+ "@simplysm/orm-common": "14.0.5"
26
27
  }
27
28
  }