@simplysm/service-client 13.0.98 → 13.0.100

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,6 +1,8 @@
1
1
  # @simplysm/service-client
2
2
 
3
- Service module (client) -- WebSocket-based service client for communicating with `@simplysm/service-server`.
3
+ Simplysm package - Service module (client)
4
+
5
+ WebSocket-based service client for communicating with `@simplysm/service-server`. Provides type-safe service method calls, event pub/sub, file upload/download, and client-side ORM connectivity.
4
6
 
5
7
  ## Installation
6
8
 
@@ -8,41 +10,64 @@ Service module (client) -- WebSocket-based service client for communicating with
8
10
  npm install @simplysm/service-client
9
11
  ```
10
12
 
11
- ## Exports
12
-
13
- ```typescript
14
- import {
15
- // Main
16
- ServiceClient,
17
- createServiceClient,
18
- type ServiceProxy,
19
- // Types
20
- type ServiceConnectionOptions,
21
- type ServiceProgress,
22
- type ServiceProgressState,
23
- // Transport
24
- type SocketProvider,
25
- type SocketProviderEvents,
26
- createSocketProvider,
27
- type ServiceTransport,
28
- type ServiceTransportEvents,
29
- createServiceTransport,
30
- // Protocol
31
- type ClientProtocolWrapper,
32
- createClientProtocolWrapper,
33
- // Features
34
- type EventClient,
35
- createEventClient,
36
- type FileClient,
37
- createFileClient,
38
- type OrmConnectOptions,
39
- type OrmClientConnector,
40
- createOrmClientConnector,
41
- OrmClientDbContextExecutor,
42
- } from "@simplysm/service-client";
43
- ```
44
-
45
- ## Quick Start
13
+ ## API Overview
14
+
15
+ ### Types
16
+ | API | Type | Description |
17
+ |-----|------|-------------|
18
+ | `ServiceConnectionOptions` | interface | Connection options (host, port, ssl, reconnect) |
19
+ | `ServiceProgress` | interface | Progress callback config for requests |
20
+ | `ServiceProgressState` | interface | Progress state (uuid, totalSize, completedSize) |
21
+
22
+ -> See [docs/types.md](./docs/types.md) for details.
23
+
24
+ ### Transport
25
+ | API | Type | Description |
26
+ |-----|------|-------------|
27
+ | `SocketProvider` | interface | WebSocket connection provider |
28
+ | `SocketProviderEvents` | interface | Socket events (message, state) |
29
+ | `createSocketProvider` | function | Create socket with heartbeat and auto-reconnect |
30
+ | `ServiceTransport` | interface | Message routing and request/response correlation |
31
+ | `ServiceTransportEvents` | interface | Transport events (reload, event) |
32
+ | `createServiceTransport` | function | Create transport instance |
33
+
34
+ -> See [docs/transport.md](./docs/transport.md) for details.
35
+
36
+ ### Protocol
37
+ | API | Type | Description |
38
+ |-----|------|-------------|
39
+ | `ClientProtocolWrapper` | interface | Protocol wrapper with Web Worker offloading |
40
+ | `createClientProtocolWrapper` | function | Create protocol wrapper |
41
+
42
+ -> See [docs/protocol.md](./docs/protocol.md) for details.
43
+
44
+ ### Features (Event, File, ORM)
45
+ | API | Type | Description |
46
+ |-----|------|-------------|
47
+ | `EventClient` | interface | Event listener management |
48
+ | `createEventClient` | function | Create event client |
49
+ | `FileClient` | interface | File upload/download |
50
+ | `createFileClient` | function | Create file client |
51
+ | `OrmConnectOptions` | interface | ORM connection options |
52
+ | `OrmClientConnector` | interface | Client-side ORM connector |
53
+ | `createOrmClientConnector` | function | Create ORM connector |
54
+ | `OrmClientDbContextExecutor` | class | DbContext executor via service protocol |
55
+
56
+ -> See [docs/features.md](./docs/features.md) for details.
57
+
58
+ ### Main
59
+ | API | Type | Description |
60
+ |-----|------|-------------|
61
+ | `ServiceClient` | class | Main client (connect, auth, service calls, events, files) |
62
+ | `ServiceClientEvents` | interface | Client events (progress, state, reload) |
63
+ | `ServiceProxy` | type | Type wrapper for remote service methods |
64
+ | `createServiceClient` | function | Factory to create ServiceClient |
65
+
66
+ -> See [docs/service-client.md](./docs/service-client.md) for details.
67
+
68
+ ## Usage Examples
69
+
70
+ ### Connect and Call Service Methods
46
71
 
47
72
  ```typescript
48
73
  import { createServiceClient } from "@simplysm/service-client";
@@ -53,30 +78,49 @@ const client = createServiceClient("my-app", {
53
78
  });
54
79
 
55
80
  await client.connect();
81
+ await client.auth(jwtToken);
56
82
 
57
- // Authenticate
58
- await client.auth(token);
83
+ // Type-safe service proxy
84
+ interface UserService {
85
+ getProfile(): Promise<{ name: string; email: string }>;
86
+ updateName(name: string): Promise<void>;
87
+ }
59
88
 
60
- // Call a service method
61
- const service = client.getService<MyServiceType>("MyService");
62
- const result = await service.someMethod("arg1", "arg2");
89
+ const userService = client.getService<UserService>("User");
90
+ const profile = await userService.getProfile();
91
+ await userService.updateName("New Name");
92
+ ```
63
93
 
64
- // Listen for events
65
- await client.addListener(SomeEvent, { id: 1 }, async (data) => {
66
- // handle event
67
- });
94
+ ### Client-Side ORM
68
95
 
69
- // Upload files
70
- const results = await client.uploadFile(fileList);
96
+ ```typescript
97
+ import { createOrmClientConnector } from "@simplysm/service-client";
98
+
99
+ const orm = createOrmClientConnector(client);
71
100
 
72
- // Close
73
- await client.close();
101
+ const users = await orm.connect(
102
+ { dbContextDef: MyDb, connOpt: { configName: "main" } },
103
+ async (db) => {
104
+ return db.user().where((u) => [expr.eq(u.status, "active")]).execute();
105
+ },
106
+ );
74
107
  ```
75
108
 
76
- ## Documentation
109
+ ### Event Subscription
110
+
111
+ ```typescript
112
+ import { defineEvent } from "@simplysm/service-common";
77
113
 
78
- - [Types](docs/types.md)
79
- - [Transport](docs/transport.md)
80
- - [Protocol](docs/protocol.md)
81
- - [Features](docs/features.md)
82
- - [ServiceClient](docs/service-client.md)
114
+ const OrderUpdated = defineEvent<{ orderId: number }, { status: string }>("OrderUpdated");
115
+
116
+ const key = await client.addListener(
117
+ OrderUpdated,
118
+ { orderId: 123 },
119
+ async (data) => {
120
+ console.log("Order status:", data.status);
121
+ },
122
+ );
123
+
124
+ // Later: unsubscribe
125
+ await client.removeListener(key);
126
+ ```
package/docs/features.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # Features
2
2
 
3
- ## EventClient
3
+ ## `EventClient`
4
4
 
5
- Client-side event subscription manager. Handles adding/removing event listeners and auto-resubscription on reconnect.
6
-
7
- ### `EventClient`
5
+ Client-side event management interface. Handles event listener registration, removal, emission, and auto-recovery on reconnect.
8
6
 
9
7
  ```typescript
10
8
  interface EventClient {
@@ -13,38 +11,34 @@ interface EventClient {
13
11
  info: TInfo,
14
12
  cb: (data: TData) => PromiseLike<void>,
15
13
  ): Promise<string>;
16
-
17
14
  removeListener(key: string): Promise<void>;
18
-
19
15
  emit<TInfo, TData>(
20
16
  eventDef: ServiceEventDef<TInfo, TData>,
21
17
  infoSelector: (item: TInfo) => boolean,
22
18
  data: TData,
23
19
  ): Promise<void>;
24
-
25
20
  resubscribeAll(): Promise<void>;
26
21
  }
27
22
  ```
28
23
 
29
- ### `createEventClient`
24
+ | Method | Description |
25
+ |--------|-------------|
26
+ | `addListener()` | Register an event listener on the server, returns listener key |
27
+ | `removeListener()` | Remove an event listener by key |
28
+ | `emit()` | Emit an event to matching listeners (server-side filtering) |
29
+ | `resubscribeAll()` | Re-register all listeners on reconnect |
30
+
31
+ ## `createEventClient`
32
+
33
+ Create an event client instance.
30
34
 
31
35
  ```typescript
32
36
  function createEventClient(transport: ServiceTransport): EventClient;
33
37
  ```
34
38
 
35
- **Behavior:**
36
- - `addListener` registers on the server and stores locally for reconnect recovery
37
- - `removeListener` removes from local map and sends removal request to server
38
- - `emit` queries the server for matching listener infos, then sends event to matching keys
39
- - `resubscribeAll` re-registers all local listeners on the server (called on reconnect)
40
-
41
- ---
42
-
43
- ## FileClient
39
+ ## `FileClient`
44
40
 
45
- HTTP-based file upload/download client.
46
-
47
- ### `FileClient`
41
+ File upload/download client interface.
48
42
 
49
43
  ```typescript
50
44
  interface FileClient {
@@ -56,23 +50,27 @@ interface FileClient {
56
50
  }
57
51
  ```
58
52
 
59
- ### `createFileClient`
53
+ | Method | Description |
54
+ |--------|-------------|
55
+ | `download()` | Download a file by relative path, returns binary data |
56
+ | `upload()` | Upload files via multipart form, returns upload results |
57
+
58
+ ## `createFileClient`
59
+
60
+ Create a file client instance.
60
61
 
61
62
  ```typescript
62
63
  function createFileClient(hostUrl: string, clientName: string): FileClient;
63
64
  ```
64
65
 
65
- **Behavior:**
66
- - `download` fetches a file via HTTP GET and returns it as `Uint8Array`
67
- - `upload` sends files via multipart form POST to `/upload` with auth token in headers
68
-
69
- ---
70
-
71
- ## ORM Features
66
+ | Parameter | Type | Description |
67
+ |-----------|------|-------------|
68
+ | `hostUrl` | `string` | Server base URL (http:// or https://) |
69
+ | `clientName` | `string` | Client name for request headers |
72
70
 
73
- ### `OrmConnectOptions`
71
+ ## `OrmConnectOptions`
74
72
 
75
- Configuration for ORM database connections via the service client.
73
+ ORM connection options for client-side database access.
76
74
 
77
75
  ```typescript
78
76
  interface OrmConnectOptions<TDef extends DbContextDef<any, any, any>> {
@@ -85,9 +83,15 @@ interface OrmConnectOptions<TDef extends DbContextDef<any, any, any>> {
85
83
  }
86
84
  ```
87
85
 
88
- ### `OrmClientConnector`
86
+ | Field | Type | Description |
87
+ |-------|------|-------------|
88
+ | `dbContextDef` | `TDef` | DbContext definition |
89
+ | `connOpt` | `DbConnOptions & { configName: string }` | Connection options with config name |
90
+ | `dbContextOpt` | `{ database: string; schema: string }` | Override database/schema from server config |
89
91
 
90
- Manages ORM database connections through the service client.
92
+ ## `OrmClientConnector`
93
+
94
+ Client-side ORM connector interface. Creates DbContext instances that execute queries via the service protocol.
91
95
 
92
96
  ```typescript
93
97
  interface OrmClientConnector {
@@ -95,7 +99,6 @@ interface OrmClientConnector {
95
99
  config: OrmConnectOptions<TDef>,
96
100
  callback: (db: DbContextInstance<TDef>) => Promise<R> | R,
97
101
  ): Promise<R>;
98
-
99
102
  connectWithoutTransaction<TDef extends DbContextDef<any, any, any>, R>(
100
103
  config: OrmConnectOptions<TDef>,
101
104
  callback: (db: DbContextInstance<TDef>) => Promise<R> | R,
@@ -103,40 +106,38 @@ interface OrmClientConnector {
103
106
  }
104
107
  ```
105
108
 
106
- ### `createOrmClientConnector`
109
+ | Method | Description |
110
+ |--------|-------------|
111
+ | `connect()` | Connect with transaction (auto commit/rollback) |
112
+ | `connectWithoutTransaction()` | Connect without transaction |
113
+
114
+ ## `createOrmClientConnector`
115
+
116
+ Create an ORM client connector.
107
117
 
108
118
  ```typescript
109
119
  function createOrmClientConnector(serviceClient: ServiceClient): OrmClientConnector;
110
120
  ```
111
121
 
112
- **Behavior:**
113
- - `connect` creates a database context and executes the callback within a transaction
114
- - `connectWithoutTransaction` creates a database context without transaction wrapping
115
- - Foreign key constraint violations are caught and re-thrown with a user-friendly message
122
+ ## `OrmClientDbContextExecutor`
116
123
 
117
- ### `OrmClientDbContextExecutor`
118
-
119
- Implements `DbContextExecutor` by delegating all database operations to the remote `OrmService` via WebSocket.
124
+ Client-side DbContext executor. Implements `DbContextExecutor` by delegating to the ORM service over the service protocol.
120
125
 
121
126
  ```typescript
122
127
  class OrmClientDbContextExecutor implements DbContextExecutor {
123
- constructor(client: ServiceClient, opt: DbConnOptions & { configName: string });
124
-
125
- async getInfo(): Promise<{ dialect: Dialect; database?: string; schema?: string }>;
126
- async connect(): Promise<void>;
127
- async beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;
128
- async commitTransaction(): Promise<void>;
129
- async rollbackTransaction(): Promise<void>;
130
- async close(): Promise<void>;
131
- async executeDefs<T = Record<string, unknown>>(
132
- defs: QueryDef[],
133
- options?: (ResultMeta | undefined)[],
134
- ): Promise<T[][]>;
135
- async executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]>;
136
- async bulkInsert(
137
- tableName: string,
138
- columnDefs: Record<string, ColumnMeta>,
139
- records: Record<string, unknown>[],
140
- ): Promise<void>;
128
+ constructor(
129
+ private readonly _client: ServiceClient,
130
+ private readonly _opt: DbConnOptions & { configName: string },
131
+ );
132
+
133
+ getInfo(): Promise<{ dialect: Dialect; database?: string; schema?: string }>;
134
+ connect(): Promise<void>;
135
+ beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;
136
+ commitTransaction(): Promise<void>;
137
+ rollbackTransaction(): Promise<void>;
138
+ close(): Promise<void>;
139
+ executeDefs<T>(defs: QueryDef[], options?: (ResultMeta | undefined)[]): Promise<T[][]>;
140
+ executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]>;
141
+ bulkInsert(tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]): Promise<void>;
141
142
  }
142
143
  ```
package/docs/protocol.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Protocol
2
2
 
3
- Client-side protocol wrapper that handles message encoding/decoding with optional Web Worker offloading for large payloads.
4
-
5
3
  ## `ClientProtocolWrapper`
6
4
 
5
+ Client-side protocol wrapper interface. Handles message encoding/decoding with optional Web Worker offloading for large payloads (>30KB).
6
+
7
7
  ```typescript
8
8
  interface ClientProtocolWrapper {
9
9
  encode(uuid: string, message: ServiceMessage): Promise<{ chunks: Bytes[]; totalSize: number }>;
@@ -11,29 +11,19 @@ interface ClientProtocolWrapper {
11
11
  }
12
12
  ```
13
13
 
14
+ | Method | Description |
15
+ |--------|-------------|
16
+ | `encode()` | Encode a message (delegates to Web Worker for large payloads) |
17
+ | `decode()` | Decode a message (delegates to Web Worker for large payloads) |
18
+
14
19
  ## `createClientProtocolWrapper`
15
20
 
16
- Create a client protocol wrapper instance.
21
+ Create a client protocol wrapper instance. Automatically offloads heavy encoding/decoding to a Web Worker when available and payload exceeds 30KB.
17
22
 
18
23
  ```typescript
19
24
  function createClientProtocolWrapper(protocol: ServiceProtocol): ClientProtocolWrapper;
20
25
  ```
21
26
 
22
- **Parameters:**
23
- - `protocol` -- A `ServiceProtocol` instance (from `@simplysm/service-common`)
24
-
25
- **Behavior:**
26
- - Messages smaller than 30KB are processed on the main thread
27
- - Larger messages are offloaded to a Web Worker for encoding/decoding
28
- - Worker is automatically initialized as a lazy singleton
29
- - Worker tasks that do not complete within 60s are rejected (prevents memory leaks)
30
- - Falls back to main-thread processing when `Worker` is not available (e.g., SSR)
31
-
32
- **Worker delegation heuristics for encoding:**
33
- - `Uint8Array` body: always use worker
34
- - String body longer than 30KB: use worker
35
- - Array body with >100 elements or containing `Uint8Array`: use worker
36
-
37
- **Worker delegation heuristics for decoding:**
38
- - Byte size > 30KB: use worker
39
- - After worker decoding, `transfer.decode()` is applied to restore class instances (e.g., `DateTime`)
27
+ | Parameter | Type | Description |
28
+ |-----------|------|-------------|
29
+ | `protocol` | `ServiceProtocol` | Base protocol instance from `createServiceProtocol()` |
@@ -1,28 +1,62 @@
1
1
  # ServiceClient
2
2
 
3
- Main client class that orchestrates all service communication modules.
4
-
5
- ```typescript
6
- import { ServiceClient, createServiceClient, type ServiceProxy } from "@simplysm/service-client";
3
+ ## `ServiceClient`
4
+
5
+ Main client class that orchestrates all service communication modules. Extends `EventEmitter`.
6
+
7
+ ```typescript
8
+ class ServiceClient extends EventEmitter<ServiceClientEvents> {
9
+ readonly name: string;
10
+ readonly options: ServiceConnectionOptions;
11
+ get connected(): boolean;
12
+ get hostUrl(): string;
13
+
14
+ constructor(name: string, options: ServiceConnectionOptions);
15
+
16
+ getService<TService>(serviceName: string): ServiceProxy<TService>;
17
+ connect(): Promise<void>;
18
+ close(): Promise<void>;
19
+ send(serviceName: string, methodName: string, params: unknown[], progress?: ServiceProgress): Promise<unknown>;
20
+ auth(token: string): Promise<void>;
21
+ addListener<TInfo, TData>(
22
+ eventDef: ServiceEventDef<TInfo, TData>,
23
+ info: TInfo,
24
+ cb: (data: TData) => PromiseLike<void>,
25
+ ): Promise<string>;
26
+ removeListener(key: string): Promise<void>;
27
+ emitEvent<TInfo, TData>(
28
+ eventDef: ServiceEventDef<TInfo, TData>,
29
+ infoSelector: (item: TInfo) => boolean,
30
+ data: TData,
31
+ ): Promise<void>;
32
+ uploadFile(files: File[] | FileList | { name: string; data: BlobPart }[]): Promise<ServiceUploadResult[]>;
33
+ downloadFileBuffer(relPath: string): Promise<Bytes>;
34
+ }
7
35
  ```
8
36
 
9
- ## `ServiceProxy<TService>`
10
-
11
- Type transformer that wraps all method return types of `TService` with `Promise`.
12
-
13
- ```typescript
14
- type ServiceProxy<TService> = {
15
- [K in keyof TService]: TService[K] extends (...args: infer P) => infer R
16
- ? (...args: P) => Promise<Awaited<R>>
17
- : never;
18
- };
19
- ```
37
+ | Property | Type | Description |
38
+ |----------|------|-------------|
39
+ | `name` | `string` | Client name |
40
+ | `options` | `ServiceConnectionOptions` | Connection options |
41
+ | `connected` | `boolean` | Whether connected |
42
+ | `hostUrl` | `string` | HTTP(S) base URL |
20
43
 
21
- ## Class: `ServiceClient`
44
+ | Method | Description |
45
+ |--------|-------------|
46
+ | `getService()` | Create a typed service proxy for calling remote methods |
47
+ | `connect()` | Establish WebSocket connection |
48
+ | `close()` | Close connection |
49
+ | `send()` | Send a service method request |
50
+ | `auth()` | Authenticate with JWT token |
51
+ | `addListener()` | Add event listener |
52
+ | `removeListener()` | Remove event listener |
53
+ | `emitEvent()` | Emit event to matching listeners |
54
+ | `uploadFile()` | Upload files (requires prior auth) |
55
+ | `downloadFileBuffer()` | Download file as binary |
22
56
 
23
- Extends `EventEmitter<ServiceClientEvents>`.
57
+ ## `ServiceClientEvents`
24
58
 
25
- ### Events
59
+ Events emitted by `ServiceClient`.
26
60
 
27
61
  ```typescript
28
62
  interface ServiceClientEvents {
@@ -33,178 +67,27 @@ interface ServiceClientEvents {
33
67
  }
34
68
  ```
35
69
 
36
- ### Constructor
37
-
38
- ```typescript
39
- constructor(name: string, options: ServiceConnectionOptions)
40
- ```
41
-
42
- - `name` -- Client name (used for identification on the server)
43
- - `options` -- Connection options
44
-
45
- ### Properties
46
-
47
- #### `connected`
48
-
49
- ```typescript
50
- get connected(): boolean;
51
- ```
52
-
53
- #### `hostUrl`
54
-
55
- ```typescript
56
- get hostUrl(): string;
57
- ```
58
-
59
- Returns the HTTP(S) URL of the server (e.g., `"https://localhost:3000"`).
60
-
61
- ### Methods
62
-
63
- #### `connect`
64
-
65
- Connect to the server via WebSocket.
66
-
67
- ```typescript
68
- async connect(): Promise<void>;
69
- ```
70
-
71
- #### `close`
72
-
73
- Close the WebSocket connection.
74
-
75
- ```typescript
76
- async close(): Promise<void>;
77
- ```
78
-
79
- #### `auth`
80
-
81
- Authenticate with the server using a JWT token.
82
-
83
- ```typescript
84
- async auth(token: string): Promise<void>;
85
- ```
86
-
87
- #### `getService`
70
+ ## `ServiceProxy`
88
71
 
89
- Create a type-safe proxy for calling remote service methods.
72
+ Type transformer that wraps all method return types of a service with `Promise`.
90
73
 
91
74
  ```typescript
92
- getService<TService>(serviceName: string): ServiceProxy<TService>;
93
- ```
94
-
95
- **Example:**
96
- ```typescript
97
- const userService = client.getService<UserServiceType>("User");
98
- const profile = await userService.getProfile();
99
- ```
100
-
101
- #### `send`
102
-
103
- Send a raw service method call.
104
-
105
- ```typescript
106
- async send(
107
- serviceName: string,
108
- methodName: string,
109
- params: unknown[],
110
- progress?: ServiceProgress,
111
- ): Promise<unknown>;
112
- ```
113
-
114
- #### `addListener`
115
-
116
- Add a server-side event listener.
117
-
118
- ```typescript
119
- async addListener<TInfo, TData>(
120
- eventDef: ServiceEventDef<TInfo, TData>,
121
- info: TInfo,
122
- cb: (data: TData) => PromiseLike<void>,
123
- ): Promise<string>;
124
- ```
125
-
126
- Returns a listener key (UUID) that can be used with `removeListener`.
127
-
128
- #### `removeListener`
129
-
130
- Remove a server-side event listener.
131
-
132
- ```typescript
133
- async removeListener(key: string): Promise<void>;
134
- ```
135
-
136
- #### `emitEvent`
137
-
138
- Emit an event to matching server-side listeners.
139
-
140
- ```typescript
141
- async emitEvent<TInfo, TData>(
142
- eventDef: ServiceEventDef<TInfo, TData>,
143
- infoSelector: (item: TInfo) => boolean,
144
- data: TData,
145
- ): Promise<void>;
146
- ```
147
-
148
- #### `uploadFile`
149
-
150
- Upload files to the server. Requires prior authentication via `auth()`.
151
-
152
- ```typescript
153
- async uploadFile(
154
- files: File[] | FileList | { name: string; data: BlobPart }[],
155
- ): Promise<ServiceUploadResult[]>;
156
- ```
157
-
158
- #### `downloadFileBuffer`
159
-
160
- Download a file from the server as bytes.
161
-
162
- ```typescript
163
- async downloadFileBuffer(relPath: string): Promise<Bytes>;
75
+ type ServiceProxy<TService> = {
76
+ [K in keyof TService]: TService[K] extends (...args: infer P) => infer R
77
+ ? (...args: P) => Promise<Awaited<R>>
78
+ : never;
79
+ };
164
80
  ```
165
81
 
166
82
  ## `createServiceClient`
167
83
 
168
- Factory function.
84
+ Factory function to create a `ServiceClient` instance.
169
85
 
170
86
  ```typescript
171
87
  function createServiceClient(name: string, options: ServiceConnectionOptions): ServiceClient;
172
88
  ```
173
89
 
174
- ## Example
175
-
176
- ```typescript
177
- import { createServiceClient, type ServiceProxy } from "@simplysm/service-client";
178
- import { defineEvent } from "@simplysm/service-common";
179
-
180
- // Define event
181
- const OrderUpdated = defineEvent<{ orderId: number }, { status: string }>("OrderUpdated");
182
-
183
- // Create client
184
- const client = createServiceClient("my-app", {
185
- host: "localhost",
186
- port: 3000,
187
- });
188
-
189
- // Connect and authenticate
190
- await client.connect();
191
- await client.auth(jwtToken);
192
-
193
- // Call service
194
- const orderService = client.getService<OrderServiceType>("Order");
195
- const orders = await orderService.getAll();
196
-
197
- // Listen for events
198
- const key = await client.addListener(OrderUpdated, { orderId: 123 }, async (data) => {
199
- console.log(data.status);
200
- });
201
-
202
- // Track progress
203
- client.on("request-progress", (state) => {
204
- console.log(`Upload: ${state.completedSize}/${state.totalSize}`);
205
- });
206
-
207
- // Cleanup
208
- await client.removeListener(key);
209
- await client.close();
210
- ```
90
+ | Parameter | Type | Description |
91
+ |-----------|------|-------------|
92
+ | `name` | `string` | Client name identifier |
93
+ | `options` | `ServiceConnectionOptions` | Connection options |
package/docs/transport.md CHANGED
@@ -1,43 +1,45 @@
1
1
  # Transport
2
2
 
3
- The transport layer handles WebSocket connections and message routing.
3
+ ## `SocketProvider`
4
4
 
5
- ## SocketProvider
6
-
7
- Low-level WebSocket connection manager with automatic reconnection and heartbeat keep-alive.
8
-
9
- ### `SocketProviderEvents`
10
-
11
- ```typescript
12
- interface SocketProviderEvents {
13
- message: Bytes;
14
- state: "connected" | "closed" | "reconnecting";
15
- }
16
- ```
17
-
18
- ### `SocketProvider`
5
+ WebSocket connection provider interface. Manages connection lifecycle, heartbeat, and auto-reconnect.
19
6
 
20
7
  ```typescript
21
8
  interface SocketProvider {
22
9
  readonly clientName: string;
23
10
  readonly connected: boolean;
24
- on<K extends keyof SocketProviderEvents & string>(
25
- type: K,
26
- listener: (data: SocketProviderEvents[K]) => void,
27
- ): void;
28
- off<K extends keyof SocketProviderEvents & string>(
29
- type: K,
30
- listener: (data: SocketProviderEvents[K]) => void,
31
- ): void;
11
+ on<K extends keyof SocketProviderEvents & string>(type: K, listener: (data: SocketProviderEvents[K]) => void): void;
12
+ off<K extends keyof SocketProviderEvents & string>(type: K, listener: (data: SocketProviderEvents[K]) => void): void;
32
13
  connect(): Promise<void>;
33
14
  close(): Promise<void>;
34
15
  send(data: Bytes): Promise<void>;
35
16
  }
36
17
  ```
37
18
 
38
- ### `createSocketProvider`
19
+ | Property/Method | Description |
20
+ |-----------------|-------------|
21
+ | `clientName` | Client name identifier |
22
+ | `connected` | Whether WebSocket is currently open |
23
+ | `on()` | Register event listener |
24
+ | `off()` | Remove event listener |
25
+ | `connect()` | Establish WebSocket connection |
26
+ | `close()` | Close connection (graceful shutdown) |
27
+ | `send()` | Send binary data |
28
+
29
+ ## `SocketProviderEvents`
39
30
 
40
- Create a SocketProvider instance.
31
+ Events emitted by `SocketProvider`.
32
+
33
+ ```typescript
34
+ interface SocketProviderEvents {
35
+ message: Bytes;
36
+ state: "connected" | "closed" | "reconnecting";
37
+ }
38
+ ```
39
+
40
+ ## `createSocketProvider`
41
+
42
+ Create a WebSocket provider with heartbeat and auto-reconnect.
41
43
 
42
44
  ```typescript
43
45
  function createSocketProvider(
@@ -47,46 +49,44 @@ function createSocketProvider(
47
49
  ): SocketProvider;
48
50
  ```
49
51
 
50
- **Behavior:**
51
- - Heartbeat: sends ping every 5s, considers disconnected if no message for 30s
52
- - Reconnect: retries every 3s up to `maxReconnectCount` times
53
- - Binary protocol: uses `ArrayBuffer` for data transfer
54
- - Ping/Pong: `0x01` = ping, `0x02` = pong
55
-
56
- ---
52
+ | Parameter | Type | Description |
53
+ |-----------|------|-------------|
54
+ | `url` | `string` | WebSocket URL (ws:// or wss://) |
55
+ | `clientName` | `string` | Client name identifier |
56
+ | `maxReconnectCount` | `number` | Max reconnect attempts |
57
57
 
58
- ## ServiceTransport
58
+ ## `ServiceTransport`
59
59
 
60
- Higher-level transport that handles message encoding/decoding, request-response correlation, and event dispatching.
61
-
62
- ### `ServiceTransportEvents`
60
+ Service transport interface. Handles message routing and request/response correlation.
63
61
 
64
62
  ```typescript
65
- interface ServiceTransportEvents {
66
- reload: Set<string>;
67
- event: { keys: string[]; data: unknown };
63
+ interface ServiceTransport {
64
+ on<K extends keyof ServiceTransportEvents & string>(type: K, listener: (data: ServiceTransportEvents[K]) => void): void;
65
+ off<K extends keyof ServiceTransportEvents & string>(type: K, listener: (data: ServiceTransportEvents[K]) => void): void;
66
+ send(message: ServiceClientMessage, progress?: ServiceProgress): Promise<unknown>;
68
67
  }
69
68
  ```
70
69
 
71
- ### `ServiceTransport`
70
+ | Method | Description |
71
+ |--------|-------------|
72
+ | `on()` | Register event listener (reload, event) |
73
+ | `off()` | Remove event listener |
74
+ | `send()` | Send a client message and await response |
75
+
76
+ ## `ServiceTransportEvents`
77
+
78
+ Events emitted by `ServiceTransport`.
72
79
 
73
80
  ```typescript
74
- interface ServiceTransport {
75
- on<K extends keyof ServiceTransportEvents & string>(
76
- type: K,
77
- listener: (data: ServiceTransportEvents[K]) => void,
78
- ): void;
79
- off<K extends keyof ServiceTransportEvents & string>(
80
- type: K,
81
- listener: (data: ServiceTransportEvents[K]) => void,
82
- ): void;
83
- send(message: ServiceClientMessage, progress?: ServiceProgress): Promise<unknown>;
81
+ interface ServiceTransportEvents {
82
+ reload: Set<string>;
83
+ event: { keys: string[]; data: unknown };
84
84
  }
85
85
  ```
86
86
 
87
- ### `createServiceTransport`
87
+ ## `createServiceTransport`
88
88
 
89
- Create a ServiceTransport instance.
89
+ Create a service transport instance.
90
90
 
91
91
  ```typescript
92
92
  function createServiceTransport(
@@ -94,9 +94,3 @@ function createServiceTransport(
94
94
  protocol: ClientProtocolWrapper,
95
95
  ): ServiceTransport;
96
96
  ```
97
-
98
- **Behavior:**
99
- - Each `send()` call generates a unique UUID and registers a pending request
100
- - Incoming messages are correlated by UUID and resolved/rejected accordingly
101
- - Progress callbacks are invoked for chunked message transfers
102
- - All pending requests are rejected when the socket disconnects
package/docs/types.md CHANGED
@@ -1,22 +1,28 @@
1
1
  # Types
2
2
 
3
- ## ServiceConnectionOptions
3
+ ## `ServiceConnectionOptions`
4
4
 
5
- WebSocket connection configuration.
5
+ Connection options for `ServiceClient`.
6
6
 
7
7
  ```typescript
8
8
  interface ServiceConnectionOptions {
9
9
  port: number;
10
10
  host: string;
11
11
  ssl?: boolean;
12
- /** Set to 0 to disable reconnect; disconnects immediately */
13
12
  maxReconnectCount?: number;
14
13
  }
15
14
  ```
16
15
 
17
- ## ServiceProgress
16
+ | Field | Type | Description |
17
+ |-------|------|-------------|
18
+ | `port` | `number` | Server port |
19
+ | `host` | `string` | Server hostname |
20
+ | `ssl` | `boolean` | Use SSL/TLS (wss:// and https://) |
21
+ | `maxReconnectCount` | `number` | Max reconnect attempts (0 to disable, default: 10) |
18
22
 
19
- Progress callback interface for tracking request/response transfer progress.
23
+ ## `ServiceProgress`
24
+
25
+ Progress callback configuration for service requests.
20
26
 
21
27
  ```typescript
22
28
  interface ServiceProgress {
@@ -25,9 +31,14 @@ interface ServiceProgress {
25
31
  }
26
32
  ```
27
33
 
28
- ## ServiceProgressState
34
+ | Field | Type | Description |
35
+ |-------|------|-------------|
36
+ | `request` | `(s: ServiceProgressState) => void` | Request upload progress callback |
37
+ | `response` | `(s: ServiceProgressState) => void` | Response download progress callback |
38
+
39
+ ## `ServiceProgressState`
29
40
 
30
- Transfer progress state.
41
+ Progress state for chunked message transfers.
31
42
 
32
43
  ```typescript
33
44
  interface ServiceProgressState {
@@ -36,3 +47,9 @@ interface ServiceProgressState {
36
47
  completedSize: number;
37
48
  }
38
49
  ```
50
+
51
+ | Field | Type | Description |
52
+ |-------|------|-------------|
53
+ | `uuid` | `string` | Request UUID |
54
+ | `totalSize` | `number` | Total message size in bytes |
55
+ | `completedSize` | `number` | Completed size in bytes |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/service-client",
3
- "version": "13.0.98",
3
+ "version": "13.0.100",
4
4
  "description": "Simplysm package - Service module (client)",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -20,9 +20,9 @@
20
20
  "sideEffects": false,
21
21
  "dependencies": {
22
22
  "consola": "^3.4.2",
23
- "@simplysm/core-common": "13.0.98",
24
- "@simplysm/orm-common": "13.0.98",
25
- "@simplysm/service-common": "13.0.98"
23
+ "@simplysm/core-common": "13.0.100",
24
+ "@simplysm/orm-common": "13.0.100",
25
+ "@simplysm/service-common": "13.0.100"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/ws": "^8.18.1",