@simplysm/service-server 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,63 +1,133 @@
1
1
  # @simplysm/service-server
2
2
 
3
- Service server framework -- Fastify-based RPC server with WebSocket support, JWT authentication, service definitions, file upload/download, and built-in ORM/auto-update services.
4
-
5
- Depends on `@simplysm/service-common` for shared protocol and types.
6
-
7
- ## API
8
-
9
- | Export | Kind | Category | Docs |
10
- |--------|------|----------|------|
11
- | `ServiceServerOptions` | interface | Types | [docs/types.md](docs/types.md) |
12
- | `AuthTokenPayload` | interface | Auth | [docs/auth.md](docs/auth.md) |
13
- | `signJwt` | function | Auth | [docs/auth.md](docs/auth.md) |
14
- | `verifyJwt` | function | Auth | [docs/auth.md](docs/auth.md) |
15
- | `decodeJwt` | function | Auth | [docs/auth.md](docs/auth.md) |
16
- | `ServiceContext` | interface | Core | [docs/core.md](docs/core.md) |
17
- | `createServiceContext` | function | Core | [docs/core.md](docs/core.md) |
18
- | `getServiceAuthPermissions` | function | Core | [docs/core.md](docs/core.md) |
19
- | `auth` | function | Core | [docs/core.md](docs/core.md) |
20
- | `ServiceDefinition` | interface | Core | [docs/core.md](docs/core.md) |
21
- | `defineService` | function | Core | [docs/core.md](docs/core.md) |
22
- | `ServiceMethods` | type | Core | [docs/core.md](docs/core.md) |
23
- | `executeServiceMethod` | function | Core | [docs/core.md](docs/core.md) |
24
- | `WebSocketHandler` | interface | Transport | [docs/transport.md](docs/transport.md) |
25
- | `createWebSocketHandler` | function | Transport | [docs/transport.md](docs/transport.md) |
26
- | `ServiceSocket` | interface | Transport | [docs/transport.md](docs/transport.md) |
27
- | `createServiceSocket` | function | Transport | [docs/transport.md](docs/transport.md) |
28
- | `handleHttpRequest` | function | Transport | [docs/transport.md](docs/transport.md) |
29
- | `handleUpload` | function | Transport | [docs/transport.md](docs/transport.md) |
30
- | `handleStaticFile` | function | Transport | [docs/transport.md](docs/transport.md) |
31
- | `ServerProtocolWrapper` | interface | Protocol | [docs/protocol.md](docs/protocol.md) |
32
- | `createServerProtocolWrapper` | function | Protocol | [docs/protocol.md](docs/protocol.md) |
33
- | `OrmService` | const | Services | [docs/services.md](docs/services.md) |
34
- | `OrmServiceType` | type | Services | [docs/services.md](docs/services.md) |
35
- | `AutoUpdateService` | const | Services | [docs/services.md](docs/services.md) |
36
- | `AutoUpdateServiceType` | type | Services | [docs/services.md](docs/services.md) |
37
- | `getConfig` | function | Utilities | [docs/utilities.md](docs/utilities.md) |
38
- | `handleV1Connection` | function | Legacy | [docs/legacy.md](docs/legacy.md) |
39
- | `ServiceServer` | class | Main | [docs/main.md](docs/main.md) |
40
- | `createServiceServer` | function | Main | [docs/main.md](docs/main.md) |
41
-
42
- ## Usage
3
+ Fastify-based RPC server with WebSocket support, JWT authentication, service definitions, file upload/download, static file serving, and built-in ORM/auto-update services. Depends on `@simplysm/service-common` for shared protocol and types.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @simplysm/service-server
9
+ ```
10
+
11
+ ## API Overview
12
+
13
+ ### Server Options
14
+ | API | Type | Description |
15
+ |-----|------|-------------|
16
+ | `ServiceServerOptions` | `interface` | Server configuration (rootPath, port, SSL, auth, services) |
17
+
18
+ -> See [docs/server-options.md](./docs/server-options.md) for details.
19
+
20
+ ### Authentication (JWT)
21
+ | API | Type | Description |
22
+ |-----|------|-------------|
23
+ | `AuthTokenPayload` | `interface` | JWT token payload with roles and custom data |
24
+ | `signJwt` | `function` | Signs a JWT token (HS256, 12h expiry) |
25
+ | `verifyJwt` | `function` | Verifies a JWT token |
26
+ | `decodeJwt` | `function` | Decodes a JWT token without verification |
27
+
28
+ -> See [docs/auth.md](./docs/auth.md) for details.
29
+
30
+ ### Service Definition/Context
31
+ | API | Type | Description |
32
+ |-----|------|-------------|
33
+ | `ServiceContext` | `interface` | Service execution context (server, socket, auth, config) |
34
+ | `createServiceContext` | `function` | Creates a service context instance |
35
+ | `getServiceAuthPermissions` | `function` | Reads auth permissions from an auth-wrapped function |
36
+ | `auth` | `function` | Authentication wrapper for service factories and methods |
37
+ | `ServiceDefinition` | `interface` | Service definition with name and factory |
38
+ | `defineService` | `function` | Defines a named service with a factory function |
39
+ | `ServiceMethods` | `type` | Extracts method signatures from a ServiceDefinition |
40
+
41
+ -> See [docs/service-definition.md](./docs/service-definition.md) for details.
42
+
43
+ ### Service Executor
44
+ | API | Type | Description |
45
+ |-----|------|-------------|
46
+ | `executeServiceMethod` | `function` | Executes a service method with auth checking |
47
+
48
+ -> See [docs/service-executor.md](./docs/service-executor.md) for details.
49
+
50
+ ### WebSocket Handler
51
+ | API | Type | Description |
52
+ |-----|------|-------------|
53
+ | `WebSocketHandler` | `interface` | Multi-connection WebSocket handler with event broadcasting |
54
+ | `createWebSocketHandler` | `function` | Creates a WebSocket handler instance |
55
+
56
+ -> See [docs/websocket-handler.md](./docs/websocket-handler.md) for details.
57
+
58
+ ### Service Socket
59
+ | API | Type | Description |
60
+ |-----|------|-------------|
61
+ | `ServiceSocket` | `interface` | Single WebSocket connection with protocol and events |
62
+ | `createServiceSocket` | `function` | Creates a service socket instance |
63
+
64
+ -> See [docs/service-socket.md](./docs/service-socket.md) for details.
65
+
66
+ ### HTTP Handlers
67
+ | API | Type | Description |
68
+ |-----|------|-------------|
69
+ | `handleHttpRequest` | `function` | Handles HTTP RPC requests (GET/POST) |
70
+ | `handleUpload` | `function` | Handles multipart file uploads |
71
+ | `handleStaticFile` | `function` | Serves static files with security guards |
72
+
73
+ -> See [docs/http-handlers.md](./docs/http-handlers.md) for details.
74
+
75
+ ### Protocol Wrapper
76
+ | API | Type | Description |
77
+ |-----|------|-------------|
78
+ | `ServerProtocolWrapper` | `interface` | Server-side protocol wrapper with worker thread offloading |
79
+ | `createServerProtocolWrapper` | `function` | Creates a server protocol wrapper instance |
80
+
81
+ -> See [docs/protocol-wrapper.md](./docs/protocol-wrapper.md) for details.
82
+
83
+ ### ORM/AutoUpdate Services
84
+ | API | Type | Description |
85
+ |-----|------|-------------|
86
+ | `OrmService` | `const (ServiceDefinition)` | Built-in ORM service definition |
87
+ | `OrmServiceType` | `type` | ORM service method signatures |
88
+ | `AutoUpdateService` | `const (ServiceDefinition)` | Built-in auto-update service definition |
89
+ | `AutoUpdateServiceType` | `type` | Auto-update service method signatures |
90
+
91
+ -> See [docs/built-in-services.md](./docs/built-in-services.md) for details.
92
+
93
+ ### Config Manager
94
+ | API | Type | Description |
95
+ |-----|------|-------------|
96
+ | `getConfig` | `function` | Loads JSON config with file-watching and caching |
97
+
98
+ -> See [docs/config-manager.md](./docs/config-manager.md) for details.
99
+
100
+ ### Legacy V1
101
+ | API | Type | Description |
102
+ |-----|------|-------------|
103
+ | `handleV1Connection` | `function` | V1 legacy WebSocket handler (auto-update only) |
104
+
105
+ -> See [docs/legacy-v1.md](./docs/legacy-v1.md) for details.
106
+
107
+ ### Main ServiceServer
108
+ | API | Type | Description |
109
+ |-----|------|-------------|
110
+ | `ServiceServer` | `class` | Main server class (Fastify + WebSocket + auth) |
111
+ | `createServiceServer` | `function` | Factory function to create a ServiceServer |
112
+
113
+ -> See [docs/service-server.md](./docs/service-server.md) for details.
114
+
115
+ ## Usage Examples
43
116
 
44
117
  ### Basic Server Setup
45
118
 
46
- ```ts
119
+ ```typescript
47
120
  import { createServiceServer, defineService, auth } from "@simplysm/service-server";
48
121
 
49
- // Define a service
50
122
  const GreetService = defineService("Greet", (ctx) => ({
51
123
  hello(name: string) {
52
- return `Hello, ${name}!`;
124
+ return \`Hello, \${name}!\`;
53
125
  },
54
- // Protected method requiring authentication
55
126
  secret: auth(["admin"], (msg: string) => {
56
- return `Secret for ${ctx.authInfo}: ${msg}`;
127
+ return \`Secret for \${ctx.authInfo}: \${msg}\`;
57
128
  }),
58
129
  }));
59
130
 
60
- // Create and start the server
61
131
  const server = createServiceServer({
62
132
  rootPath: process.cwd(),
63
133
  port: 3000,
@@ -70,40 +140,35 @@ await server.listen();
70
140
 
71
141
  ### JWT Authentication
72
142
 
73
- ```ts
143
+ ```typescript
74
144
  import { signJwt, verifyJwt } from "@simplysm/service-server";
75
145
 
76
- // Sign a token
77
146
  const token = await signJwt("my-secret", {
78
147
  roles: ["admin"],
79
148
  data: { userId: 1 },
80
149
  });
81
150
 
82
- // Verify a token
83
151
  const payload = await verifyJwt("my-secret", token);
84
152
  ```
85
153
 
86
154
  ### Event Broadcasting
87
155
 
88
- ```ts
156
+ ```typescript
89
157
  import { defineEvent } from "@simplysm/service-common";
90
158
 
91
159
  const NotifyEvent = defineEvent<{ userId: number }, { text: string }>("Notify");
92
-
93
- // Emit from server
94
160
  await server.emitEvent(NotifyEvent, (info) => info.userId === 42, { text: "Hello!" });
95
161
  ```
96
162
 
97
- ### ORM Service
163
+ ### Built-in ORM Service
98
164
 
99
- The server includes a built-in `OrmService` for database operations. Include it in your service list:
100
-
101
- ```ts
165
+ ```typescript
102
166
  import { createServiceServer, OrmService } from "@simplysm/service-server";
103
167
 
104
168
  const server = createServiceServer({
105
169
  rootPath: process.cwd(),
106
170
  port: 3000,
171
+ auth: { jwtSecret: "my-secret" },
107
172
  services: [OrmService],
108
173
  });
109
174
  ```
package/docs/auth.md CHANGED
@@ -1,13 +1,11 @@
1
- # Auth
1
+ # Authentication (JWT)
2
2
 
3
- JWT authentication utilities for signing, verifying, and decoding tokens.
3
+ ## `AuthTokenPayload`
4
4
 
5
- ## AuthTokenPayload\<TAuthInfo\>
5
+ JWT token payload extending `JWTPayload` from `jose`. Contains roles and custom authentication data.
6
6
 
7
- JWT token payload extending the standard `JWTPayload` with role-based access and custom data.
8
-
9
- ```ts
10
- interface AuthTokenPayload<TAuthInfo = unknown> extends JWTPayload {
7
+ ```typescript
8
+ export interface AuthTokenPayload<TAuthInfo = unknown> extends JWTPayload {
11
9
  roles: string[];
12
10
  data: TAuthInfo;
13
11
  }
@@ -15,17 +13,16 @@ interface AuthTokenPayload<TAuthInfo = unknown> extends JWTPayload {
15
13
 
16
14
  | Field | Type | Description |
17
15
  |-------|------|-------------|
18
- | `roles` | `string[]` | Role names for permission checking |
19
- | `data` | `TAuthInfo` | Custom authentication data (e.g., user info) |
20
-
21
- Inherits all standard JWT fields from `JWTPayload` (e.g., `iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`).
16
+ | `roles` | `string[]` | User roles for permission checking |
17
+ | `data` | `TAuthInfo` | Custom authentication data (user info, etc.) |
18
+ | *(inherited from JWTPayload)* | | Standard JWT claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`) |
22
19
 
23
- ## signJwt
20
+ ## `signJwt`
24
21
 
25
- Sign a JWT token with the given secret and payload.
22
+ Signs a JWT token using HS256 algorithm with 12-hour expiration.
26
23
 
27
- ```ts
28
- async function signJwt<TAuthInfo = unknown>(
24
+ ```typescript
25
+ export async function signJwt<TAuthInfo = unknown>(
29
26
  jwtSecret: string,
30
27
  payload: AuthTokenPayload<TAuthInfo>,
31
28
  ): Promise<string>;
@@ -33,17 +30,17 @@ async function signJwt<TAuthInfo = unknown>(
33
30
 
34
31
  | Parameter | Type | Description |
35
32
  |-----------|------|-------------|
36
- | `jwtSecret` | `string` | Secret key for signing |
33
+ | `jwtSecret` | `string` | JWT signing secret |
37
34
  | `payload` | `AuthTokenPayload<TAuthInfo>` | Token payload with roles and data |
38
35
 
39
- Returns the signed JWT string.
36
+ **Returns:** `Promise<string>` -- Signed JWT token string.
40
37
 
41
- ## verifyJwt
38
+ ## `verifyJwt`
42
39
 
43
- Verify a JWT token and return its payload. Throws if the token is invalid or expired.
40
+ Verifies a JWT token and returns the decoded payload. Throws on expired or invalid tokens.
44
41
 
45
- ```ts
46
- async function verifyJwt<TAuthInfo = unknown>(
42
+ ```typescript
43
+ export async function verifyJwt<TAuthInfo = unknown>(
47
44
  jwtSecret: string,
48
45
  token: string,
49
46
  ): Promise<AuthTokenPayload<TAuthInfo>>;
@@ -51,21 +48,27 @@ async function verifyJwt<TAuthInfo = unknown>(
51
48
 
52
49
  | Parameter | Type | Description |
53
50
  |-----------|------|-------------|
54
- | `jwtSecret` | `string` | Secret key for verification |
55
- | `token` | `string` | JWT token string |
51
+ | `jwtSecret` | `string` | JWT verification secret |
52
+ | `token` | `string` | JWT token string to verify |
56
53
 
57
- Returns the decoded and verified `AuthTokenPayload`.
54
+ **Returns:** `Promise<AuthTokenPayload<TAuthInfo>>` -- Decoded token payload.
58
55
 
59
- ## decodeJwt
56
+ **Throws:**
57
+ - `Error("Token expired")` when the token has expired
58
+ - `Error("Invalid token")` for any other verification failure
60
59
 
61
- Decode a JWT token without verification. Useful for inspecting token contents without validating the signature.
60
+ ## `decodeJwt`
62
61
 
63
- ```ts
64
- function decodeJwt<TAuthInfo = unknown>(token: string): AuthTokenPayload<TAuthInfo>;
62
+ Decodes a JWT token without verification. Useful for reading claims before verification.
63
+
64
+ ```typescript
65
+ export function decodeJwt<TAuthInfo = unknown>(
66
+ token: string,
67
+ ): AuthTokenPayload<TAuthInfo>;
65
68
  ```
66
69
 
67
70
  | Parameter | Type | Description |
68
71
  |-----------|------|-------------|
69
- | `token` | `string` | JWT token string |
72
+ | `token` | `string` | JWT token string to decode |
70
73
 
71
- Returns the decoded `AuthTokenPayload` (unverified).
74
+ **Returns:** `AuthTokenPayload<TAuthInfo>` -- Decoded token payload (not verified).
@@ -0,0 +1,61 @@
1
+ # ORM/AutoUpdate Services
2
+
3
+ ## `OrmService`
4
+
5
+ Built-in ORM service definition. Provides database connection, transaction management, and query execution over the WebSocket RPC layer. Requires authentication (wrapped with `auth()`).
6
+
7
+ ```typescript
8
+ export const OrmService: ServiceDefinition;
9
+ ```
10
+
11
+ The ORM service is registered with the name `"Orm"` and requires WebSocket transport (HTTP is not supported).
12
+
13
+ Database connections are tracked per socket. When a WebSocket connection closes, all associated DB connections are automatically cleaned up.
14
+
15
+ Methods (matching the `OrmService` interface from `@simplysm/service-common`):
16
+
17
+ | Method | Parameters | Return | Description |
18
+ |--------|-----------|--------|-------------|
19
+ | `getInfo` | `opt: DbConnOptions & { configName: string }` | `Promise<{ dialect: Dialect; database?: string; schema?: string }>` | Gets database info from server config |
20
+ | `connect` | `opt: DbConnOptions & { configName: string }` | `Promise<number>` | Opens a DB connection. Returns connection ID |
21
+ | `close` | `connId: number` | `Promise<void>` | Closes a DB connection |
22
+ | `beginTransaction` | `connId: number, isolationLevel?: IsolationLevel` | `Promise<void>` | Begins a transaction |
23
+ | `commitTransaction` | `connId: number` | `Promise<void>` | Commits a transaction |
24
+ | `rollbackTransaction` | `connId: number` | `Promise<void>` | Rolls back a transaction |
25
+ | `executeParametrized` | `connId: number, query: string, params?: unknown[]` | `Promise<unknown[][]>` | Executes a parameterized query |
26
+ | `executeDefs` | `connId: number, defs: QueryDef[], options?: (ResultMeta \| undefined)[]` | `Promise<unknown[][]>` | Executes query definitions with optional result parsing |
27
+ | `bulkInsert` | `connId: number, tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]` | `Promise<void>` | Performs bulk insert |
28
+
29
+ Configuration: Reads from the `"orm"` section of the server config file (`.config.json`).
30
+
31
+ ## `OrmServiceType`
32
+
33
+ Type alias for the ORM service methods. Useful for client-side type sharing.
34
+
35
+ ```typescript
36
+ export type OrmServiceType = ServiceMethods<typeof OrmService>;
37
+ ```
38
+
39
+ ## `AutoUpdateService`
40
+
41
+ Built-in auto-update service definition. Provides version lookup for client applications. Does not require authentication.
42
+
43
+ ```typescript
44
+ export const AutoUpdateService: ServiceDefinition;
45
+ ```
46
+
47
+ Registered with the name `"AutoUpdate"`. Scans `{clientPath}/{platform}/updates/` for versioned files (`.exe` for desktop, `.apk` for Android).
48
+
49
+ Methods:
50
+
51
+ | Method | Parameters | Return | Description |
52
+ |--------|-----------|--------|-------------|
53
+ | `getLastVersion` | `platform: string` | `Promise<{ version: string; downloadPath: string } \| undefined>` | Returns the latest version info for the given platform. Uses `semver.maxSatisfying` to find the highest version |
54
+
55
+ ## `AutoUpdateServiceType`
56
+
57
+ Type alias for the auto-update service methods.
58
+
59
+ ```typescript
60
+ export type AutoUpdateServiceType = ServiceMethods<typeof AutoUpdateService>;
61
+ ```
@@ -0,0 +1,24 @@
1
+ # Config Manager
2
+
3
+ ## `getConfig`
4
+
5
+ Loads a JSON configuration file with automatic caching and file-watching for live reload.
6
+
7
+ ```typescript
8
+ export async function getConfig<TConfig>(
9
+ filePath: string,
10
+ ): Promise<TConfig | undefined>;
11
+ ```
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `filePath` | `string` | Absolute path to the JSON config file |
16
+
17
+ **Returns:** `Promise<TConfig | undefined>` -- Parsed config object, or `undefined` if the file does not exist.
18
+
19
+ Behavior:
20
+ - **Caching:** Uses `LazyGcMap` with 10-minute GC interval and 1-hour expiry
21
+ - **File watching:** Registers a file watcher on first load. Config is automatically reloaded when the file changes
22
+ - **Expiry:** When a cache entry expires, the associated file watcher is cleaned up
23
+ - **Deletion:** If the config file is deleted, the cache entry and watcher are removed
24
+ - Used internally by `ServiceContext.getConfig()` to load root and client config files
@@ -0,0 +1,83 @@
1
+ # HTTP Handlers
2
+
3
+ ## `handleHttpRequest`
4
+
5
+ Handles HTTP RPC requests. Supports both GET (with JSON query parameter) and POST (with JSON array body) methods.
6
+
7
+ ```typescript
8
+ export async function handleHttpRequest<TAuthInfo = unknown>(
9
+ req: FastifyRequest,
10
+ reply: FastifyReply,
11
+ jwtSecret: string | undefined,
12
+ runMethod: (def: {
13
+ serviceName: string;
14
+ methodName: string;
15
+ params: unknown[];
16
+ http: { clientName: string; authTokenPayload?: AuthTokenPayload<TAuthInfo> };
17
+ }) => Promise<unknown>,
18
+ ): Promise<void>;
19
+ ```
20
+
21
+ | Parameter | Type | Description |
22
+ |-----------|------|-------------|
23
+ | `req` | `FastifyRequest` | Fastify request (expects `/:service/:method` route params) |
24
+ | `reply` | `FastifyReply` | Fastify reply |
25
+ | `jwtSecret` | `string \| undefined` | JWT secret for token verification |
26
+ | `runMethod` | callback | Service method executor |
27
+
28
+ Request requirements:
29
+ - Header `x-sd-client-name` is required
30
+ - GET: requires `?json=<encoded-params>` query parameter
31
+ - POST: requires JSON array body
32
+ - Authorization header (optional): `Bearer <token>`
33
+
34
+ ## `handleUpload`
35
+
36
+ Handles multipart file uploads. Saves files to `{rootPath}/www/uploads/` with UUID-based filenames.
37
+
38
+ ```typescript
39
+ export async function handleUpload(
40
+ req: FastifyRequest,
41
+ reply: FastifyReply,
42
+ rootPath: string,
43
+ jwtSecret: string | undefined,
44
+ ): Promise<void>;
45
+ ```
46
+
47
+ | Parameter | Type | Description |
48
+ |-----------|------|-------------|
49
+ | `req` | `FastifyRequest` | Fastify multipart request |
50
+ | `reply` | `FastifyReply` | Fastify reply |
51
+ | `rootPath` | `string` | Server root path |
52
+ | `jwtSecret` | `string \| undefined` | JWT secret for authentication |
53
+
54
+ Behavior:
55
+ - Requires multipart request and valid Authorization header
56
+ - Saves each file with a UUID filename preserving the original extension
57
+ - Returns `ServiceUploadResult[]` on success
58
+ - Cleans up all files on error (both partially written and already saved)
59
+
60
+ ## `handleStaticFile`
61
+
62
+ Serves static files from `{rootPath}/www/` with security guards.
63
+
64
+ ```typescript
65
+ export async function handleStaticFile(
66
+ req: FastifyRequest,
67
+ reply: FastifyReply,
68
+ rootPath: string,
69
+ urlPath: string,
70
+ ): Promise<void>;
71
+ ```
72
+
73
+ | Parameter | Type | Description |
74
+ |-----------|------|-------------|
75
+ | `req` | `FastifyRequest` | Fastify request |
76
+ | `reply` | `FastifyReply` | Fastify reply |
77
+ | `rootPath` | `string` | Server root path |
78
+ | `urlPath` | `string` | Decoded URL path (without leading slash) |
79
+
80
+ Security:
81
+ - Path traversal attack prevention (rejects paths outside `{rootPath}/www/`)
82
+ - Hidden file access denied (files starting with `.` return 403)
83
+ - Directory requests redirect to add trailing slash, then serve `index.html`
@@ -0,0 +1,25 @@
1
+ # Legacy V1
2
+
3
+ ## `handleV1Connection`
4
+
5
+ Handles V1 legacy WebSocket connections. Only supports the `SdAutoUpdateService.getLastVersion` command. All other requests return an upgrade-required error.
6
+
7
+ ```typescript
8
+ export function handleV1Connection(
9
+ socket: WebSocket,
10
+ autoUpdateMethods: { getLastVersion: (platform: string) => Promise<any> },
11
+ clientNameSetter?: (clientName: string | undefined) => void,
12
+ ): void;
13
+ ```
14
+
15
+ | Parameter | Type | Description |
16
+ |-----------|------|-------------|
17
+ | `socket` | `WebSocket` (from `ws`) | Raw WebSocket connection |
18
+ | `autoUpdateMethods` | `{ getLastVersion: (platform: string) => Promise<any> }` | Auto-update method implementations |
19
+ | `clientNameSetter` | `((clientName: string \| undefined) => void)?` | Callback to set the legacy client name on the context |
20
+
21
+ V1 protocol:
22
+ - Sends `{ name: "connected" }` on connection
23
+ - Expects JSON messages with `{ uuid, command, params, clientName? }` format
24
+ - Responds with `{ name: "response", reqUuid, state: "success"|"error", body }` format
25
+ - Only `SdAutoUpdateService.getLastVersion` is supported; all other commands return `UPGRADE_REQUIRED` error
@@ -0,0 +1,37 @@
1
+ # Protocol Wrapper
2
+
3
+ ## `ServerProtocolWrapper`
4
+
5
+ Server-side protocol wrapper that automatically offloads heavy message encoding/decoding to a worker thread. Light operations are processed on the main thread.
6
+
7
+ ```typescript
8
+ export interface ServerProtocolWrapper {
9
+ encode(uuid: string, message: ServiceMessage): Promise<{ chunks: Bytes[]; totalSize: number }>;
10
+ decode(bytes: Bytes): Promise<ServiceMessageDecodeResult<ServiceMessage>>;
11
+ dispose(): void;
12
+ }
13
+ ```
14
+
15
+ | Method | Parameters | Return | Description |
16
+ |--------|-----------|--------|-------------|
17
+ | `encode` | `uuid: string, message: ServiceMessage` | `Promise<{ chunks: Bytes[]; totalSize: number }>` | Encodes a message. Offloads to worker for messages with `Uint8Array` bodies |
18
+ | `decode` | `bytes: Bytes` | `Promise<ServiceMessageDecodeResult<ServiceMessage>>` | Decodes binary data. Offloads to worker for payloads > 30KB |
19
+ | `dispose` | none | `void` | Disposes the underlying protocol's GC timer |
20
+
21
+ ## `createServerProtocolWrapper`
22
+
23
+ Creates a `ServerProtocolWrapper` instance.
24
+
25
+ ```typescript
26
+ export function createServerProtocolWrapper(): ServerProtocolWrapper;
27
+ ```
28
+
29
+ **Returns:** `ServerProtocolWrapper`
30
+
31
+ Worker thread details:
32
+ - Uses `@simplysm/core-node` `Worker` (Node.js `worker_threads`)
33
+ - Shared singleton worker instance across all protocol wrappers
34
+ - Worker memory limit: 4096 MB (old generation)
35
+ - Size threshold for worker offloading: 30KB
36
+ - Encode uses worker when body contains `Uint8Array` elements
37
+ - Decode uses worker when total bytes exceed 30KB
@@ -0,0 +1,31 @@
1
+ # Server Options
2
+
3
+ ## `ServiceServerOptions`
4
+
5
+ Server configuration options.
6
+
7
+ ```typescript
8
+ export interface ServiceServerOptions {
9
+ rootPath: string;
10
+ port: number;
11
+ ssl?: {
12
+ pfxBytes: Uint8Array;
13
+ passphrase: string;
14
+ };
15
+ auth?: {
16
+ jwtSecret: string;
17
+ } | false;
18
+ services: ServiceDefinition[];
19
+ }
20
+ ```
21
+
22
+ | Field | Type | Description |
23
+ |-------|------|-------------|
24
+ | `rootPath` | `string` | Root directory path. Static files are served from `{rootPath}/www/`, config loaded from `{rootPath}/.config.json` |
25
+ | `port` | `number` | Server listen port |
26
+ | `ssl` | `{ pfxBytes: Uint8Array; passphrase: string }?` | SSL/TLS configuration using PFX certificate |
27
+ | `ssl.pfxBytes` | `Uint8Array` | PFX certificate file contents |
28
+ | `ssl.passphrase` | `string` | PFX certificate passphrase |
29
+ | `auth` | `{ jwtSecret: string } \| false` | Authentication configuration. `undefined` = auto-detect (error if auth-wrapped services exist). `false` = explicitly disable auth checks. `{ jwtSecret }` = enable JWT auth |
30
+ | `auth.jwtSecret` | `string` | JWT signing/verification secret (HS256) |
31
+ | `services` | `ServiceDefinition[]` | Array of service definitions to register |