@simplysm/service-client 13.0.29 → 13.0.30

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 (2) hide show
  1. package/README.md +218 -14
  2. package/package.json +4 -4
package/README.md CHANGED
@@ -46,6 +46,8 @@ pnpm add @simplysm/service-client
46
46
  | `ServiceConnectionConfig` | Server connection config (host, port, ssl, maxReconnectCount) |
47
47
  | `ServiceProgress` | Request/response progress callback |
48
48
  | `ServiceProgressState` | Progress state (uuid, totalSize, completedSize) |
49
+ | `SocketProviderEvents` | Event map for SocketProvider (message, state) |
50
+ | `ServiceTransportEvents` | Event map for ServiceTransport (reload, event) |
49
51
  | `OrmConnectConfig<T>` | ORM connection config (DbContext type, connection options, DB/schema override) |
50
52
  | `RemoteService<T>` | Utility type that wraps all method return types of a service interface with `Promise` |
51
53
 
@@ -70,6 +72,7 @@ await client.connect();
70
72
  // Check connection status
71
73
  console.log(client.connected); // true
72
74
  console.log(client.hostUrl); // "http://localhost:8080"
75
+ console.log(client.name); // "my-app"
73
76
 
74
77
  // Direct RPC call
75
78
  const result = await client.send("MyService", "getUsers", [{ page: 1 }]);
@@ -299,6 +302,10 @@ await connector.connectWithoutTransaction(
299
302
 
300
303
  Server connection configuration interface.
301
304
 
305
+ ```typescript
306
+ import type { ServiceConnectionConfig } from "@simplysm/service-client";
307
+ ```
308
+
302
309
  | Property | Type | Required | Description |
303
310
  |------|------|------|------|
304
311
  | `host` | `string` | Yes | Server host address |
@@ -311,6 +318,8 @@ Server connection configuration interface.
311
318
  Factory function for creating a ServiceClient instance.
312
319
 
313
320
  ```typescript
321
+ import { createServiceClient } from "@simplysm/service-client";
322
+
314
323
  function createServiceClient(name: string, options: ServiceConnectionConfig): ServiceClient
315
324
  ```
316
325
 
@@ -331,19 +340,27 @@ const client = createServiceClient("my-app", {
331
340
 
332
341
  ### ServiceClient
333
342
 
334
- | Method/Property | Return Type | Description |
343
+ ```typescript
344
+ import { ServiceClient } from "@simplysm/service-client";
345
+ ```
346
+
347
+ Extends `EventEmitter<ServiceClientEvents>`.
348
+
349
+ | Method/Property | Type / Return Type | Description |
335
350
  |-------------|----------|------|
336
351
  | `constructor(name, options)` | - | Create client instance. `name` is the client identifier. **Note: Prefer using `createServiceClient()` factory function.** |
352
+ | `name` | `string` | Client identifier (read-only) |
353
+ | `options` | `ServiceConnectionConfig` | Connection configuration (read-only) |
337
354
  | `connected` | `boolean` | WebSocket connection status |
338
355
  | `hostUrl` | `string` | HTTP URL (e.g., `http://localhost:8080`) |
339
356
  | `connect()` | `Promise<void>` | Connect to server via WebSocket |
340
357
  | `close()` | `Promise<void>` | Close connection (Graceful Shutdown) |
341
358
  | `send(serviceName, methodName, params, progress?)` | `Promise<unknown>` | Remote call to service method |
342
- | `getService<T>(serviceName)` | `RemoteService<T>` | Create type-safe service proxy |
359
+ | `getService<TService>(serviceName)` | `RemoteService<TService>` | Create type-safe service proxy |
343
360
  | `auth(token)` | `Promise<void>` | Send auth token (auto re-auth on reconnection) |
344
- | `addEventListener(eventType, info, cb)` | `Promise<string>` | Register event listener. Returns listener key |
361
+ | `addEventListener(eventDef, info, cb)` | `Promise<string>` | Register event listener. Returns listener key |
345
362
  | `removeEventListener(key)` | `Promise<void>` | Remove event listener |
346
- | `emitToServer(eventType, infoSelector, data)` | `Promise<void>` | Publish event to other clients through server |
363
+ | `emitToServer(eventDef, infoSelector, data)` | `Promise<void>` | Publish event to other clients through server |
347
364
  | `uploadFile(files)` | `Promise<ServiceUploadResult[]>` | File upload (auth required) |
348
365
  | `downloadFileBuffer(relPath)` | `Promise<Uint8Array>` | File download |
349
366
 
@@ -352,6 +369,8 @@ const client = createServiceClient("my-app", {
352
369
  Interfaces for tracking progress of large message transmissions.
353
370
 
354
371
  ```typescript
372
+ import type { ServiceProgress, ServiceProgressState } from "@simplysm/service-client";
373
+
355
374
  interface ServiceProgress {
356
375
  request?: (s: ServiceProgressState) => void; // Request transmission progress
357
376
  response?: (s: ServiceProgressState) => void; // Response reception progress
@@ -364,19 +383,51 @@ interface ServiceProgressState {
364
383
  }
365
384
  ```
366
385
 
367
- ### OrmConnectConfig\<T\>
386
+ ### RemoteService\<TService\>
368
387
 
369
- ORM remote connection configuration interface.
388
+ Utility type that converts all methods of a service interface so their return types are wrapped with `Promise`. Methods already returning `Promise` are not double-wrapped. Non-function properties become `never`.
370
389
 
371
- | Property | Type | Required | Description |
372
- |------|------|------|------|
373
- | `dbContextDef` | `TDef` | Yes | DbContext class |
374
- | `connOpt` | `DbConnOptions & { configName: string }` | Yes | DB connection options. `configName` identifies the server-side DB config; `config` can pass additional connection settings |
375
- | `dbContextOpt` | `{ database: string; schema: string }` | No | Database/schema override |
390
+ ```typescript
391
+ import type { RemoteService } from "@simplysm/service-client";
376
392
 
377
- ### SocketProvider
393
+ type RemoteService<TService> = {
394
+ [K in keyof TService]: TService[K] extends (...args: infer P) => infer R
395
+ ? (...args: P) => Promise<Awaited<R>>
396
+ : never;
397
+ };
398
+ ```
399
+
400
+ ### SocketProvider / SocketProviderEvents
378
401
 
379
- Handles low-level management of WebSocket connections. Not typically used directly, but indirectly through `ServiceClient`.
402
+ Low-level WebSocket connection management interface. Not typically used directly accessed indirectly through `ServiceClient`.
403
+
404
+ ```typescript
405
+ import { createSocketProvider } from "@simplysm/service-client";
406
+ import type { SocketProvider, SocketProviderEvents } from "@simplysm/service-client";
407
+
408
+ function createSocketProvider(
409
+ url: string,
410
+ clientName: string,
411
+ maxReconnectCount: number,
412
+ ): SocketProvider
413
+ ```
414
+
415
+ ```typescript
416
+ interface SocketProviderEvents {
417
+ message: Bytes;
418
+ state: "connected" | "closed" | "reconnecting";
419
+ }
420
+
421
+ interface SocketProvider {
422
+ readonly clientName: string;
423
+ readonly connected: boolean;
424
+ on<K extends keyof SocketProviderEvents & string>(type: K, listener: (data: SocketProviderEvents[K]) => void): void;
425
+ off<K extends keyof SocketProviderEvents & string>(type: K, listener: (data: SocketProviderEvents[K]) => void): void;
426
+ connect(): Promise<void>;
427
+ close(): Promise<void>;
428
+ send(data: Bytes): Promise<void>;
429
+ }
430
+ ```
380
431
 
381
432
  | Constant | Value | Description |
382
433
  |------|-----|------|
@@ -384,9 +435,50 @@ Handles low-level management of WebSocket connections. Not typically used direct
384
435
  | Heartbeat Interval | 5s | Ping transmission interval |
385
436
  | Reconnect Delay | 3s | Reconnection attempt interval |
386
437
 
438
+ ### ServiceTransport / ServiceTransportEvents
439
+
440
+ Message transport layer interface. Handles request/response matching, progress tracking, and protocol encoding/decoding. Not typically used directly — accessed indirectly through `ServiceClient`.
441
+
442
+ ```typescript
443
+ import { createServiceTransport } from "@simplysm/service-client";
444
+ import type { ServiceTransport, ServiceTransportEvents } from "@simplysm/service-client";
445
+
446
+ function createServiceTransport(
447
+ socket: SocketProvider,
448
+ protocol: ClientProtocolWrapper,
449
+ ): ServiceTransport
450
+ ```
451
+
452
+ ```typescript
453
+ interface ServiceTransportEvents {
454
+ reload: Set<string>;
455
+ event: { keys: string[]; data: unknown };
456
+ }
457
+
458
+ interface ServiceTransport {
459
+ on<K extends keyof ServiceTransportEvents & string>(type: K, listener: (data: ServiceTransportEvents[K]) => void): void;
460
+ off<K extends keyof ServiceTransportEvents & string>(type: K, listener: (data: ServiceTransportEvents[K]) => void): void;
461
+ send(message: ServiceClientMessage, progress?: ServiceProgress): Promise<unknown>;
462
+ }
463
+ ```
464
+
387
465
  ### ClientProtocolWrapper
388
466
 
389
- Handles message encoding/decoding. In browser environments, data exceeding 30KB is automatically processed in a Web Worker to prevent main thread blocking.
467
+ Protocol wrapper interface. Automatically selects main thread/Web Worker for encoding/decoding based on data size. In browser environments, data exceeding 30KB is automatically processed in a Web Worker to prevent main thread blocking.
468
+
469
+ ```typescript
470
+ import { createClientProtocolWrapper } from "@simplysm/service-client";
471
+ import type { ClientProtocolWrapper } from "@simplysm/service-client";
472
+
473
+ function createClientProtocolWrapper(protocol: ServiceProtocol): ClientProtocolWrapper
474
+ ```
475
+
476
+ ```typescript
477
+ interface ClientProtocolWrapper {
478
+ encode(uuid: string, message: ServiceMessage): Promise<{ chunks: Bytes[]; totalSize: number }>;
479
+ decode(bytes: Bytes): Promise<ServiceMessageDecodeResult<ServiceMessage>>;
480
+ }
481
+ ```
390
482
 
391
483
  | Threshold | Condition |
392
484
  |--------|------|
@@ -398,6 +490,118 @@ Worker delegation conditions (during encoding):
398
490
  - Strings exceeding 30KB
399
491
  - Arrays exceeding 100 elements or arrays containing `Uint8Array`
400
492
 
493
+ ### EventClient
494
+
495
+ Server event subscription/publishing interface. Automatically recovers listeners on reconnection.
496
+
497
+ ```typescript
498
+ import { createEventClient } from "@simplysm/service-client";
499
+ import type { EventClient } from "@simplysm/service-client";
500
+
501
+ function createEventClient(transport: ServiceTransport): EventClient
502
+ ```
503
+
504
+ ```typescript
505
+ interface EventClient {
506
+ addListener<TInfo, TData>(eventDef: ServiceEventDef<TInfo, TData>, info: TInfo, cb: (data: TData) => PromiseLike<void>): Promise<string>;
507
+ removeListener(key: string): Promise<void>;
508
+ emitToServer<TInfo, TData>(eventDef: ServiceEventDef<TInfo, TData>, infoSelector: (item: TInfo) => boolean, data: TData): Promise<void>;
509
+ reRegisterAll(): Promise<void>;
510
+ }
511
+ ```
512
+
513
+ | Method | Description |
514
+ |--------|------|
515
+ | `addListener(eventDef, info, cb)` | Register event listener on the server. Returns a listener key for later removal. |
516
+ | `removeListener(key)` | Unregister event listener from the server by key. |
517
+ | `emitToServer(eventDef, infoSelector, data)` | Send event to all server-registered listeners matching `infoSelector`. |
518
+ | `reRegisterAll()` | Re-register all listeners (called automatically on reconnection). |
519
+
520
+ ### FileClient
521
+
522
+ HTTP-based file upload/download interface.
523
+
524
+ ```typescript
525
+ import { createFileClient } from "@simplysm/service-client";
526
+ import type { FileClient } from "@simplysm/service-client";
527
+
528
+ function createFileClient(hostUrl: string, clientName: string): FileClient
529
+ ```
530
+
531
+ ```typescript
532
+ interface FileClient {
533
+ download(relPath: string): Promise<Bytes>;
534
+ upload(
535
+ files: File[] | FileList | { name: string; data: BlobPart }[],
536
+ authToken: string,
537
+ ): Promise<ServiceUploadResult[]>;
538
+ }
539
+ ```
540
+
541
+ ### OrmConnectConfig\<TDef\>
542
+
543
+ ORM remote connection configuration interface.
544
+
545
+ ```typescript
546
+ import type { OrmConnectConfig } from "@simplysm/service-client";
547
+ ```
548
+
549
+ | Property | Type | Required | Description |
550
+ |------|------|------|------|
551
+ | `dbContextDef` | `TDef` | Yes | DbContext class |
552
+ | `connOpt` | `DbConnOptions & { configName: string }` | Yes | DB connection options. `configName` identifies the server-side DB config; `config` can pass additional connection settings |
553
+ | `dbContextOpt` | `{ database: string; schema: string }` | No | Database/schema override |
554
+
555
+ ### OrmClientConnector
556
+
557
+ ORM remote connection connector interface. Manages transaction lifecycle over RPC.
558
+
559
+ ```typescript
560
+ import { createOrmClientConnector } from "@simplysm/service-client";
561
+ import type { OrmClientConnector } from "@simplysm/service-client";
562
+
563
+ function createOrmClientConnector(serviceClient: ServiceClient): OrmClientConnector
564
+ ```
565
+
566
+ ```typescript
567
+ interface OrmClientConnector {
568
+ connect<TDef extends DbContextDef<any, any, any>, R>(
569
+ config: OrmConnectConfig<TDef>,
570
+ callback: (db: DbContextInstance<TDef>) => Promise<R> | R,
571
+ ): Promise<R>;
572
+ connectWithoutTransaction<TDef extends DbContextDef<any, any, any>, R>(
573
+ config: OrmConnectConfig<TDef>,
574
+ callback: (db: DbContextInstance<TDef>) => Promise<R> | R,
575
+ ): Promise<R>;
576
+ }
577
+ ```
578
+
579
+ | Method | Description |
580
+ |--------|------|
581
+ | `connect(config, callback)` | Open a transactional DB connection. Commits on success, rolls back on error. Foreign key errors are converted to user-friendly messages. |
582
+ | `connectWithoutTransaction(config, callback)` | Open a non-transactional DB connection. Suitable for read-only operations. |
583
+
584
+ ### OrmClientDbContextExecutor
585
+
586
+ Implements the `DbContextExecutor` interface from `@simplysm/orm-common`. Delegates all DB operations to the server's `OrmService` via RPC. Not typically used directly — used internally by `OrmClientConnector`.
587
+
588
+ ```typescript
589
+ import { OrmClientDbContextExecutor } from "@simplysm/service-client";
590
+
591
+ class OrmClientDbContextExecutor implements DbContextExecutor {
592
+ constructor(client: ServiceClient, opt: DbConnOptions & { configName: string })
593
+ getInfo(): Promise<{ dialect: Dialect; database?: string; schema?: string }>
594
+ connect(): Promise<void>
595
+ beginTransaction(isolationLevel?: IsolationLevel): Promise<void>
596
+ commitTransaction(): Promise<void>
597
+ rollbackTransaction(): Promise<void>
598
+ close(): Promise<void>
599
+ executeDefs<T>(defs: QueryDef[], options?: (ResultMeta | undefined)[]): Promise<T[][]>
600
+ executeParametrized(query: string, params?: unknown[]): Promise<unknown[][]>
601
+ bulkInsert(tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]): Promise<void>
602
+ }
603
+ ```
604
+
401
605
  ## Architecture
402
606
 
403
607
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/service-client",
3
- "version": "13.0.29",
3
+ "version": "13.0.30",
4
4
  "description": "심플리즘 패키지 - 서비스 모듈 (client)",
5
5
  "author": "김석래",
6
6
  "license": "Apache-2.0",
@@ -19,9 +19,9 @@
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
21
  "consola": "^3.4.2",
22
- "@simplysm/core-common": "13.0.29",
23
- "@simplysm/orm-common": "13.0.29",
24
- "@simplysm/service-common": "13.0.29"
22
+ "@simplysm/core-common": "13.0.30",
23
+ "@simplysm/orm-common": "13.0.30",
24
+ "@simplysm/service-common": "13.0.30"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/ws": "^8.18.1",