@simplysm/service-server 13.0.99 → 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/auth-token-payload.js +2 -1
- package/dist/auth/auth-token-payload.js.map +1 -6
- package/dist/auth/jwt-manager.js +21 -21
- package/dist/auth/jwt-manager.js.map +1 -6
- package/dist/core/define-service.d.ts +12 -12
- package/dist/core/define-service.d.ts.map +1 -1
- package/dist/core/define-service.js +77 -63
- package/dist/core/define-service.js.map +1 -6
- package/dist/core/service-executor.d.ts.map +1 -1
- package/dist/core/service-executor.js +42 -32
- package/dist/core/service-executor.js.map +1 -6
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -6
- package/dist/legacy/v1-auto-update-handler.d.ts +2 -2
- package/dist/legacy/v1-auto-update-handler.js +42 -35
- package/dist/legacy/v1-auto-update-handler.js.map +1 -6
- package/dist/protocol/protocol-wrapper.d.ts +9 -9
- package/dist/protocol/protocol-wrapper.js +64 -46
- package/dist/protocol/protocol-wrapper.js.map +1 -6
- package/dist/service-server.d.ts +2 -0
- package/dist/service-server.d.ts.map +1 -1
- package/dist/service-server.js +187 -165
- package/dist/service-server.js.map +1 -6
- package/dist/services/auto-update-service.js +35 -34
- package/dist/services/auto-update-service.js.map +1 -6
- package/dist/services/orm-service.js +114 -120
- package/dist/services/orm-service.js.map +1 -6
- package/dist/transport/http/http-request-handler.d.ts.map +1 -1
- package/dist/transport/http/http-request-handler.js +58 -46
- package/dist/transport/http/http-request-handler.js.map +1 -6
- package/dist/transport/http/static-file-handler.js +42 -39
- package/dist/transport/http/static-file-handler.js.map +1 -6
- package/dist/transport/http/upload-handler.d.ts.map +1 -1
- package/dist/transport/http/upload-handler.js +60 -55
- package/dist/transport/http/upload-handler.js.map +1 -6
- package/dist/transport/socket/service-socket.d.ts +13 -13
- package/dist/transport/socket/service-socket.js +132 -108
- package/dist/transport/socket/service-socket.js.map +1 -6
- package/dist/transport/socket/websocket-handler.d.ts +10 -10
- package/dist/transport/socket/websocket-handler.d.ts.map +1 -1
- package/dist/transport/socket/websocket-handler.js +154 -139
- package/dist/transport/socket/websocket-handler.js.map +1 -6
- package/dist/types/server-options.d.ts +1 -1
- package/dist/types/server-options.d.ts.map +1 -1
- package/dist/types/server-options.js +2 -1
- package/dist/types/server-options.js.map +1 -6
- package/dist/utils/config-manager.js +48 -46
- package/dist/utils/config-manager.js.map +1 -6
- package/dist/workers/service-protocol.worker.js +8 -11
- package/dist/workers/service-protocol.worker.js.map +1 -6
- package/package.json +12 -14
- package/src/auth/jwt-manager.ts +2 -2
- package/src/core/define-service.ts +19 -19
- package/src/core/service-executor.ts +23 -17
- package/src/index.ts +10 -12
- package/src/legacy/v1-auto-update-handler.ts +10 -10
- package/src/protocol/protocol-wrapper.ts +16 -16
- package/src/service-server.ts +52 -39
- package/src/services/auto-update-service.ts +1 -1
- package/src/services/orm-service.ts +7 -7
- package/src/transport/http/http-request-handler.ts +16 -10
- package/src/transport/http/static-file-handler.ts +8 -8
- package/src/transport/http/upload-handler.ts +16 -9
- package/src/transport/socket/service-socket.ts +22 -22
- package/src/transport/socket/websocket-handler.ts +59 -60
- package/src/types/server-options.ts +1 -1
- package/src/utils/config-manager.ts +11 -11
- package/README.md +0 -163
- package/dist/services/smtp-client-service.d.ts +0 -8
- package/dist/services/smtp-client-service.d.ts.map +0 -1
- package/dist/services/smtp-client-service.js +0 -46
- package/dist/services/smtp-client-service.js.map +0 -6
- package/docs/auth.md +0 -59
- package/docs/core.md +0 -133
- package/docs/server.md +0 -126
- package/docs/services.md +0 -58
- package/docs/transport.md +0 -164
- package/src/services/smtp-client-service.ts +0 -59
- package/tests/define-service.spec.ts +0 -66
- package/tests/orm-service.spec.ts +0 -83
- package/tests/service-executor.spec.ts +0 -114
|
@@ -5,12 +5,12 @@ import consola from "consola";
|
|
|
5
5
|
|
|
6
6
|
const logger = consola.withTag("service-server:ConfigManager");
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// 값: 설정 객체, 키: 파일 경로
|
|
9
9
|
const _cache = new LazyGcMap<string, unknown>({
|
|
10
|
-
gcInterval: 10 * 60 * 1000, //
|
|
11
|
-
expireTime: 60 * 60 * 1000, //
|
|
10
|
+
gcInterval: 10 * 60 * 1000, // 10분마다
|
|
11
|
+
expireTime: 60 * 60 * 1000, // 1시간 후 만료
|
|
12
12
|
onExpire: async (filePath) => {
|
|
13
|
-
logger.debug(
|
|
13
|
+
logger.debug(`설정 캐시 만료 및 워처 해제됨: ${path.basename(filePath)}`);
|
|
14
14
|
await closeWatcher(filePath);
|
|
15
15
|
},
|
|
16
16
|
});
|
|
@@ -18,18 +18,18 @@ const _cache = new LazyGcMap<string, unknown>({
|
|
|
18
18
|
const _watchers = new Map<string, FsWatcher>();
|
|
19
19
|
|
|
20
20
|
export async function getConfig<TConfig>(filePath: string): Promise<TConfig | undefined> {
|
|
21
|
-
// 1.
|
|
21
|
+
// 1. 캐시 히트 (시간 자동 갱신)
|
|
22
22
|
if (_cache.has(filePath)) {
|
|
23
23
|
return _cache.get(filePath) as TConfig;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (!(await fsx.exists(filePath))) return undefined;
|
|
27
27
|
|
|
28
|
-
// 2.
|
|
28
|
+
// 2. 로드 및 캐시
|
|
29
29
|
const config = await fsx.readJson(filePath);
|
|
30
30
|
_cache.set(filePath, config);
|
|
31
31
|
|
|
32
|
-
// 3.
|
|
32
|
+
// 3. 워처 등록
|
|
33
33
|
if (!_watchers.has(filePath)) {
|
|
34
34
|
try {
|
|
35
35
|
const watcher = await FsWatcher.watch([filePath]);
|
|
@@ -39,20 +39,20 @@ export async function getConfig<TConfig>(filePath: string): Promise<TConfig | un
|
|
|
39
39
|
if (!(await fsx.exists(filePath))) {
|
|
40
40
|
_cache.delete(filePath);
|
|
41
41
|
await closeWatcher(filePath);
|
|
42
|
-
logger.debug(
|
|
42
|
+
logger.debug(`설정 파일 삭제됨: ${path.basename(filePath)}`);
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
try {
|
|
47
47
|
const newConfig = await fsx.readJson(filePath);
|
|
48
48
|
_cache.set(filePath, newConfig);
|
|
49
|
-
logger.debug(
|
|
49
|
+
logger.debug(`설정 파일 실시간 리로드됨: ${path.basename(filePath)}`);
|
|
50
50
|
} catch (err) {
|
|
51
|
-
logger.warn(
|
|
51
|
+
logger.warn(`설정 파일 리로드 실패: ${filePath}`, err);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
} catch (err) {
|
|
55
|
-
logger.error(
|
|
55
|
+
logger.error(`워치 실패: ${filePath}`, err);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
package/README.md
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# @simplysm/service-server
|
|
2
|
-
|
|
3
|
-
Simplysm package - service module (server)
|
|
4
|
-
|
|
5
|
-
Fastify-based service server with WebSocket support, JWT authentication, and built-in ORM/SMTP/auto-update services. Works with `@simplysm/service-client` for client-server communication.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @simplysm/service-server
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## API Overview
|
|
14
|
-
|
|
15
|
-
### Types
|
|
16
|
-
| API | Type | Description |
|
|
17
|
-
|-----|------|-------------|
|
|
18
|
-
| `ServiceServerOptions` | interface | Server config (rootPath, port, ssl, auth, services) |
|
|
19
|
-
|
|
20
|
-
-> See [docs/server.md](./docs/server.md) for details.
|
|
21
|
-
|
|
22
|
-
### Auth
|
|
23
|
-
| API | Type | Description |
|
|
24
|
-
|-----|------|-------------|
|
|
25
|
-
| `AuthTokenPayload` | interface | JWT payload with roles and custom data |
|
|
26
|
-
| `signJwt` | function | Sign a JWT token (HS256, 12h expiry) |
|
|
27
|
-
| `verifyJwt` | function | Verify and decode a JWT token |
|
|
28
|
-
| `decodeJwt` | function | Decode JWT without verification |
|
|
29
|
-
|
|
30
|
-
-> See [docs/auth.md](./docs/auth.md) for details.
|
|
31
|
-
|
|
32
|
-
### Core
|
|
33
|
-
| API | Type | Description |
|
|
34
|
-
|-----|------|-------------|
|
|
35
|
-
| `ServiceContext` | interface | Context with server, socket, auth, config access |
|
|
36
|
-
| `createServiceContext` | function | Create a service context |
|
|
37
|
-
| `ServiceDefinition` | interface | Service definition (name, factory, auth) |
|
|
38
|
-
| `defineService` | function | Define a service with name and factory |
|
|
39
|
-
| `auth` | function | Auth wrapper for services/methods (login/roles) |
|
|
40
|
-
| `getServiceAuthPermissions` | function | Read auth permissions from wrapped function |
|
|
41
|
-
| `ServiceMethods` | type | Extract method types from ServiceDefinition |
|
|
42
|
-
| `executeServiceMethod` | function | Execute service method with auth checks |
|
|
43
|
-
|
|
44
|
-
-> See [docs/core.md](./docs/core.md) for details.
|
|
45
|
-
|
|
46
|
-
### Transport - Socket
|
|
47
|
-
| API | Type | Description |
|
|
48
|
-
|-----|------|-------------|
|
|
49
|
-
| `WebSocketHandler` | interface | Multi-connection WebSocket manager |
|
|
50
|
-
| `createWebSocketHandler` | function | Create WebSocket handler |
|
|
51
|
-
| `ServiceSocket` | interface | Single WebSocket connection manager |
|
|
52
|
-
| `createServiceSocket` | function | Create service socket |
|
|
53
|
-
|
|
54
|
-
-> See [docs/transport.md](./docs/transport.md) for details.
|
|
55
|
-
|
|
56
|
-
### Transport - HTTP
|
|
57
|
-
| API | Type | Description |
|
|
58
|
-
|-----|------|-------------|
|
|
59
|
-
| `handleHttpRequest` | function | Handle HTTP API requests |
|
|
60
|
-
| `handleUpload` | function | Handle file upload (multipart) |
|
|
61
|
-
| `handleStaticFile` | function | Serve static files from www/ |
|
|
62
|
-
|
|
63
|
-
-> See [docs/transport.md](./docs/transport.md) for details.
|
|
64
|
-
|
|
65
|
-
### Protocol
|
|
66
|
-
| API | Type | Description |
|
|
67
|
-
|-----|------|-------------|
|
|
68
|
-
| `ServerProtocolWrapper` | interface | Server protocol with worker thread offloading |
|
|
69
|
-
| `createServerProtocolWrapper` | function | Create server protocol wrapper |
|
|
70
|
-
|
|
71
|
-
-> See [docs/transport.md](./docs/transport.md) for details.
|
|
72
|
-
|
|
73
|
-
### Services
|
|
74
|
-
| API | Type | Description |
|
|
75
|
-
|-----|------|-------------|
|
|
76
|
-
| `OrmService` | const | Built-in ORM service (DB connection, queries) |
|
|
77
|
-
| `AutoUpdateService` | const | Built-in auto-update service |
|
|
78
|
-
| `SmtpClientService` | const | Built-in SMTP email service |
|
|
79
|
-
|
|
80
|
-
-> See [docs/services.md](./docs/services.md) for details.
|
|
81
|
-
|
|
82
|
-
### Utils
|
|
83
|
-
| API | Type | Description |
|
|
84
|
-
|-----|------|-------------|
|
|
85
|
-
| `getConfig` | function | Read JSON config with caching and live-reload |
|
|
86
|
-
|
|
87
|
-
-> See [docs/server.md](./docs/server.md) for details.
|
|
88
|
-
|
|
89
|
-
### Main
|
|
90
|
-
| API | Type | Description |
|
|
91
|
-
|-----|------|-------------|
|
|
92
|
-
| `ServiceServer` | class | Main server (Fastify, WebSocket, auth, events) |
|
|
93
|
-
| `createServiceServer` | function | Factory to create ServiceServer |
|
|
94
|
-
|
|
95
|
-
-> See [docs/server.md](./docs/server.md) for details.
|
|
96
|
-
|
|
97
|
-
### Legacy
|
|
98
|
-
| API | Type | Description |
|
|
99
|
-
|-----|------|-------------|
|
|
100
|
-
| `handleV1Connection` | function | V1 legacy client handler (auto-update only) |
|
|
101
|
-
|
|
102
|
-
-> See [docs/server.md](./docs/server.md) for details.
|
|
103
|
-
|
|
104
|
-
## Usage Examples
|
|
105
|
-
|
|
106
|
-
### Basic Server Setup
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
import { createServiceServer, defineService, auth } from "@simplysm/service-server";
|
|
110
|
-
import { OrmService, AutoUpdateService } from "@simplysm/service-server";
|
|
111
|
-
|
|
112
|
-
// Define a custom service
|
|
113
|
-
const HealthService = defineService("Health", (ctx) => ({
|
|
114
|
-
check: () => ({ status: "ok", time: new Date().toISOString() }),
|
|
115
|
-
}));
|
|
116
|
-
|
|
117
|
-
// Define an authenticated service
|
|
118
|
-
const UserService = defineService("User", auth((ctx) => ({
|
|
119
|
-
getProfile: () => ctx.authInfo,
|
|
120
|
-
adminOnly: auth(["admin"], () => "admin-only data"),
|
|
121
|
-
})));
|
|
122
|
-
|
|
123
|
-
// Create and start server
|
|
124
|
-
const server = createServiceServer({
|
|
125
|
-
rootPath: "/app",
|
|
126
|
-
port: 3000,
|
|
127
|
-
auth: { jwtSecret: "my-secret" },
|
|
128
|
-
services: [HealthService, UserService, OrmService, AutoUpdateService],
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
await server.listen();
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### JWT Authentication
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
import { signJwt, verifyJwt } from "@simplysm/service-server";
|
|
138
|
-
|
|
139
|
-
// Sign token (in login handler)
|
|
140
|
-
const token = await server.signAuthToken({
|
|
141
|
-
roles: ["user", "admin"],
|
|
142
|
-
data: { userId: 123, name: "John" },
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// Verify token
|
|
146
|
-
const payload = await server.verifyAuthToken(token);
|
|
147
|
-
console.log(payload.data.name); // "John"
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Server-Side Event Emission
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
import { defineEvent } from "@simplysm/service-common";
|
|
154
|
-
|
|
155
|
-
const OrderUpdated = defineEvent<{ orderId: number }, { status: string }>("OrderUpdated");
|
|
156
|
-
|
|
157
|
-
// Emit to all listeners with matching orderId
|
|
158
|
-
await server.emitEvent(
|
|
159
|
-
OrderUpdated,
|
|
160
|
-
(info) => info.orderId === 123,
|
|
161
|
-
{ status: "shipped" },
|
|
162
|
-
);
|
|
163
|
-
```
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type ServiceMethods } from "../core/define-service";
|
|
2
|
-
import type { SmtpClientSendByDefaultOption, SmtpClientSendOption } from "@simplysm/service-common";
|
|
3
|
-
export declare const SmtpClientService: import("..").ServiceDefinition<{
|
|
4
|
-
send(options: SmtpClientSendOption): Promise<string>;
|
|
5
|
-
sendByConfig(configName: string, options: SmtpClientSendByDefaultOption): Promise<string>;
|
|
6
|
-
}>;
|
|
7
|
-
export type SmtpClientServiceType = ServiceMethods<typeof SmtpClientService>;
|
|
8
|
-
//# sourceMappingURL=smtp-client-service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"smtp-client-service.d.ts","sourceRoot":"","sources":["..\\..\\src\\services\\smtp-client-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EAEV,6BAA6B,EAC7B,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,eAAO,MAAM,iBAAiB;kBACR,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;6BA6B3B,MAAM,WAAW,6BAA6B,GAAG,OAAO,CAAC,MAAM,CAAC;EAkB9F,CAAC;AAEJ,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import nodemailer from "nodemailer";
|
|
2
|
-
import { defineService } from "../core/define-service.js";
|
|
3
|
-
const SmtpClientService = defineService("SmtpClient", (ctx) => ({
|
|
4
|
-
async send(options) {
|
|
5
|
-
return new Promise((resolve, reject) => {
|
|
6
|
-
const transport = nodemailer.createTransport({
|
|
7
|
-
host: options.host,
|
|
8
|
-
port: options.port,
|
|
9
|
-
secure: options.secure,
|
|
10
|
-
auth: options.user != null ? {
|
|
11
|
-
user: options.user,
|
|
12
|
-
pass: options.pass
|
|
13
|
-
} : void 0,
|
|
14
|
-
tls: {
|
|
15
|
-
rejectUnauthorized: false
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
transport.sendMail(options, (err, info) => {
|
|
19
|
-
if (err) {
|
|
20
|
-
reject(err);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
resolve(info.messageId);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
},
|
|
27
|
-
async sendByConfig(configName, options) {
|
|
28
|
-
const config = (await ctx.getConfig("smtp"))[configName];
|
|
29
|
-
if (config == null) {
|
|
30
|
-
throw new Error(`SMTP config not found: ${configName}`);
|
|
31
|
-
}
|
|
32
|
-
return this.send({
|
|
33
|
-
user: config.user,
|
|
34
|
-
pass: config.pass,
|
|
35
|
-
host: config.host,
|
|
36
|
-
port: config.port,
|
|
37
|
-
secure: config.secure,
|
|
38
|
-
from: `"${config.senderName}" <${config.senderEmail ?? config.user}>`,
|
|
39
|
-
...options
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}));
|
|
43
|
-
export {
|
|
44
|
-
SmtpClientService
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=smtp-client-service.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/services/smtp-client-service.ts"],
|
|
4
|
-
"mappings": "AAAA,OAAO,gBAAgB;AACvB,SAAS,qBAA0C;AAO5C,MAAM,oBAAoB,cAAc,cAAc,CAAC,SAAS;AAAA,EACrE,MAAM,KAAK,SAAgD;AACzD,WAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,YAAM,YAAY,WAAW,gBAAgB;AAAA,QAC3C,MAAM,QAAQ;AAAA,QACd,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ;AAAA,QAChB,MACE,QAAQ,QAAQ,OACZ;AAAA,UACE,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ;AAAA,QAChB,IACA;AAAA,QACN,KAAK;AAAA,UACH,oBAAoB;AAAA,QACtB;AAAA,MACF,CAAC;AAED,gBAAU,SAAS,SAAuC,CAAC,KAAK,SAAS;AACvE,YAAI,KAAK;AACP,iBAAO,GAAG;AACV;AAAA,QACF;AAEA,gBAAQ,KAAK,SAAS;AAAA,MACxB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,YAAoB,SAAyD;AAC9F,UAAM,UACJ,MAAM,IAAI,UAAgE,MAAM,GAChF,UAAU;AACZ,QAAI,UAAU,MAAM;AAClB,YAAM,IAAI,MAAM,0BAA0B,UAAU,EAAE;AAAA,IACxD;AAEA,WAAO,KAAK,KAAK;AAAA,MACf,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO;AAAA,MACf,MAAM,IAAI,OAAO,UAAU,MAAM,OAAO,eAAe,OAAO,IAAI;AAAA,MAClE,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AACF,EAAE;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
package/docs/auth.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# Auth
|
|
2
|
-
|
|
3
|
-
JWT-based authentication utilities using the `jose` library (HS256 algorithm).
|
|
4
|
-
|
|
5
|
-
## `AuthTokenPayload`
|
|
6
|
-
|
|
7
|
-
JWT token payload with roles and custom data. Extends `JWTPayload` from `jose`.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
interface AuthTokenPayload<TAuthInfo = unknown> extends JWTPayload {
|
|
11
|
-
roles: string[];
|
|
12
|
-
data: TAuthInfo;
|
|
13
|
-
}
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
| Field | Type | Description |
|
|
17
|
-
|-------|------|-------------|
|
|
18
|
-
| `roles` | `string[]` | User roles for permission checking |
|
|
19
|
-
| `data` | `TAuthInfo` | Custom auth data (user info, etc.) |
|
|
20
|
-
|
|
21
|
-
## `signJwt`
|
|
22
|
-
|
|
23
|
-
Sign a JWT token with HS256 algorithm. Token expires in 12 hours.
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
async function signJwt<TAuthInfo = unknown>(
|
|
27
|
-
jwtSecret: string,
|
|
28
|
-
payload: AuthTokenPayload<TAuthInfo>,
|
|
29
|
-
): Promise<string>;
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
| Parameter | Type | Description |
|
|
33
|
-
|-----------|------|-------------|
|
|
34
|
-
| `jwtSecret` | `string` | Secret key for signing |
|
|
35
|
-
| `payload` | `AuthTokenPayload<TAuthInfo>` | Token payload |
|
|
36
|
-
|
|
37
|
-
## `verifyJwt`
|
|
38
|
-
|
|
39
|
-
Verify and decode a JWT token. Throws on expired or invalid tokens.
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
async function verifyJwt<TAuthInfo = unknown>(
|
|
43
|
-
jwtSecret: string,
|
|
44
|
-
token: string,
|
|
45
|
-
): Promise<AuthTokenPayload<TAuthInfo>>;
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
| Parameter | Type | Description |
|
|
49
|
-
|-----------|------|-------------|
|
|
50
|
-
| `jwtSecret` | `string` | Secret key for verification |
|
|
51
|
-
| `token` | `string` | JWT token string |
|
|
52
|
-
|
|
53
|
-
## `decodeJwt`
|
|
54
|
-
|
|
55
|
-
Decode a JWT token without verification (for reading payload only).
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
function decodeJwt<TAuthInfo = unknown>(token: string): AuthTokenPayload<TAuthInfo>;
|
|
59
|
-
```
|
package/docs/core.md
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
# Core
|
|
2
|
-
|
|
3
|
-
## `ServiceContext`
|
|
4
|
-
|
|
5
|
-
Context object passed to service factory functions. Provides access to server, socket, auth info, and configuration.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
interface ServiceContext<TAuthInfo = unknown> {
|
|
9
|
-
server: ServiceServer<TAuthInfo>;
|
|
10
|
-
socket?: ServiceSocket;
|
|
11
|
-
http?: {
|
|
12
|
-
clientName: string;
|
|
13
|
-
authTokenPayload?: AuthTokenPayload<TAuthInfo>;
|
|
14
|
-
};
|
|
15
|
-
legacy?: {
|
|
16
|
-
clientName?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
get authInfo(): TAuthInfo | undefined;
|
|
20
|
-
get clientName(): string | undefined;
|
|
21
|
-
get clientPath(): string | undefined;
|
|
22
|
-
getConfig<T>(section: string): Promise<T>;
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
| Property | Type | Description |
|
|
27
|
-
|----------|------|-------------|
|
|
28
|
-
| `server` | `ServiceServer<TAuthInfo>` | Server instance |
|
|
29
|
-
| `socket` | `ServiceSocket` | WebSocket connection (if via WebSocket) |
|
|
30
|
-
| `http` | `object` | HTTP request info (if via HTTP) |
|
|
31
|
-
| `legacy` | `object` | V1 legacy context (auto-update only) |
|
|
32
|
-
| `authInfo` | `TAuthInfo \| undefined` | Authenticated user data |
|
|
33
|
-
| `clientName` | `string \| undefined` | Client name |
|
|
34
|
-
| `clientPath` | `string \| undefined` | Resolved client path on disk |
|
|
35
|
-
| `getConfig()` | `<T>(section) => Promise<T>` | Read config from `.config.json` files |
|
|
36
|
-
|
|
37
|
-
## `createServiceContext`
|
|
38
|
-
|
|
39
|
-
Create a service context instance.
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
function createServiceContext<TAuthInfo = unknown>(
|
|
43
|
-
server: ServiceServer<TAuthInfo>,
|
|
44
|
-
socket?: ServiceSocket,
|
|
45
|
-
http?: { clientName: string; authTokenPayload?: AuthTokenPayload<TAuthInfo> },
|
|
46
|
-
legacy?: { clientName?: string },
|
|
47
|
-
): ServiceContext<TAuthInfo>;
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## `ServiceDefinition`
|
|
51
|
-
|
|
52
|
-
Service definition object. Contains name, factory function, and optional auth permissions.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
interface ServiceDefinition<TMethods = Record<string, (...args: any[]) => any>> {
|
|
56
|
-
name: string;
|
|
57
|
-
factory: (ctx: ServiceContext) => TMethods;
|
|
58
|
-
authPermissions?: string[];
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
| Field | Type | Description |
|
|
63
|
-
|-------|------|-------------|
|
|
64
|
-
| `name` | `string` | Service name |
|
|
65
|
-
| `factory` | `(ctx: ServiceContext) => TMethods` | Factory function that creates method object |
|
|
66
|
-
| `authPermissions` | `string[]` | Required permissions (from `auth()` wrapper) |
|
|
67
|
-
|
|
68
|
-
## `defineService`
|
|
69
|
-
|
|
70
|
-
Define a service with a name and factory function.
|
|
71
|
-
|
|
72
|
-
```typescript
|
|
73
|
-
function defineService<TMethods extends Record<string, (...args: any[]) => any>>(
|
|
74
|
-
name: string,
|
|
75
|
-
factory: (ctx: ServiceContext) => TMethods,
|
|
76
|
-
): ServiceDefinition<TMethods>;
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
| Parameter | Type | Description |
|
|
80
|
-
|-----------|------|-------------|
|
|
81
|
-
| `name` | `string` | Service name |
|
|
82
|
-
| `factory` | `(ctx: ServiceContext) => TMethods` | Factory function |
|
|
83
|
-
|
|
84
|
-
## `auth`
|
|
85
|
-
|
|
86
|
-
Auth wrapper for service factories and methods. Can be applied at service-level or method-level with optional role requirements.
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
function auth<TFunction extends (...args: any[]) => any>(fn: TFunction): TFunction;
|
|
90
|
-
function auth<TFunction extends (...args: any[]) => any>(
|
|
91
|
-
permissions: string[],
|
|
92
|
-
fn: TFunction,
|
|
93
|
-
): TFunction;
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
| Overload | Description |
|
|
97
|
-
|----------|-------------|
|
|
98
|
-
| `auth(fn)` | Require login (any authenticated user) |
|
|
99
|
-
| `auth(["admin"], fn)` | Require specific roles |
|
|
100
|
-
|
|
101
|
-
## `getServiceAuthPermissions`
|
|
102
|
-
|
|
103
|
-
Read auth permissions from an `auth()`-wrapped function. Returns `undefined` if not wrapped.
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
function getServiceAuthPermissions(fn: Function): string[] | undefined;
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## `ServiceMethods`
|
|
110
|
-
|
|
111
|
-
Extract method signatures from a `ServiceDefinition` for client-side type sharing.
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
type ServiceMethods<TDefinition> =
|
|
115
|
-
TDefinition extends ServiceDefinition<infer M> ? M : never;
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## `executeServiceMethod`
|
|
119
|
-
|
|
120
|
-
Execute a service method with authentication and authorization checks.
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
async function executeServiceMethod(
|
|
124
|
-
server: ServiceServer,
|
|
125
|
-
def: {
|
|
126
|
-
serviceName: string;
|
|
127
|
-
methodName: string;
|
|
128
|
-
params: unknown[];
|
|
129
|
-
socket?: ServiceSocket;
|
|
130
|
-
http?: { clientName: string; authTokenPayload?: AuthTokenPayload };
|
|
131
|
-
},
|
|
132
|
-
): Promise<unknown>;
|
|
133
|
-
```
|
package/docs/server.md
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# Server
|
|
2
|
-
|
|
3
|
-
## `ServiceServerOptions`
|
|
4
|
-
|
|
5
|
-
Configuration options for `ServiceServer`.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
interface ServiceServerOptions {
|
|
9
|
-
rootPath: string;
|
|
10
|
-
port: number;
|
|
11
|
-
ssl?: {
|
|
12
|
-
pfxBytes: Uint8Array;
|
|
13
|
-
passphrase: string;
|
|
14
|
-
};
|
|
15
|
-
auth?: {
|
|
16
|
-
jwtSecret: string;
|
|
17
|
-
};
|
|
18
|
-
services: ServiceDefinition[];
|
|
19
|
-
}
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
| Field | Type | Description |
|
|
23
|
-
|-------|------|-------------|
|
|
24
|
-
| `rootPath` | `string` | Root path for static files, uploads, and config |
|
|
25
|
-
| `port` | `number` | Server port |
|
|
26
|
-
| `ssl` | `object` | SSL/TLS config (PFX certificate) |
|
|
27
|
-
| `ssl.pfxBytes` | `Uint8Array` | PFX certificate bytes |
|
|
28
|
-
| `ssl.passphrase` | `string` | Certificate passphrase |
|
|
29
|
-
| `auth` | `object` | Authentication config |
|
|
30
|
-
| `auth.jwtSecret` | `string` | JWT signing secret |
|
|
31
|
-
| `services` | `ServiceDefinition[]` | Service definitions to register |
|
|
32
|
-
|
|
33
|
-
## `ServiceServer`
|
|
34
|
-
|
|
35
|
-
Fastify-based service server with WebSocket support, JWT authentication, and built-in services. Extends `EventEmitter`.
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
class ServiceServer<TAuthInfo = unknown> extends EventEmitter<{
|
|
39
|
-
ready: void;
|
|
40
|
-
close: void;
|
|
41
|
-
}> {
|
|
42
|
-
isOpen: boolean;
|
|
43
|
-
readonly fastify: FastifyInstance;
|
|
44
|
-
readonly options: ServiceServerOptions;
|
|
45
|
-
|
|
46
|
-
constructor(options: ServiceServerOptions);
|
|
47
|
-
|
|
48
|
-
listen(): Promise<void>;
|
|
49
|
-
close(): Promise<void>;
|
|
50
|
-
broadcastReload(clientName: string | undefined, changedFileSet: Set<string>): Promise<void>;
|
|
51
|
-
emitEvent<TInfo, TData>(
|
|
52
|
-
eventDef: ServiceEventDef<TInfo, TData>,
|
|
53
|
-
infoSelector: (item: TInfo) => boolean,
|
|
54
|
-
data: TData,
|
|
55
|
-
): Promise<void>;
|
|
56
|
-
signAuthToken(payload: AuthTokenPayload<TAuthInfo>): Promise<string>;
|
|
57
|
-
verifyAuthToken(token: string): Promise<AuthTokenPayload<TAuthInfo>>;
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
| Property | Type | Description |
|
|
62
|
-
|----------|------|-------------|
|
|
63
|
-
| `isOpen` | `boolean` | Whether server is listening |
|
|
64
|
-
| `fastify` | `FastifyInstance` | Underlying Fastify instance |
|
|
65
|
-
| `options` | `ServiceServerOptions` | Server options |
|
|
66
|
-
|
|
67
|
-
| Method | Description |
|
|
68
|
-
|--------|-------------|
|
|
69
|
-
| `listen()` | Start the server (registers plugins, routes, WebSocket, graceful shutdown) |
|
|
70
|
-
| `close()` | Stop the server (close all connections) |
|
|
71
|
-
| `broadcastReload()` | Broadcast reload to all connected clients |
|
|
72
|
-
| `emitEvent()` | Emit event to matching clients |
|
|
73
|
-
| `signAuthToken()` | Sign a JWT token |
|
|
74
|
-
| `verifyAuthToken()` | Verify and decode a JWT token |
|
|
75
|
-
|
|
76
|
-
### Registered Routes
|
|
77
|
-
|
|
78
|
-
| Route | Method | Description |
|
|
79
|
-
|-------|--------|-------------|
|
|
80
|
-
| `/api/:service/:method` | GET/POST | HTTP service method endpoint |
|
|
81
|
-
| `/upload` | POST | File upload endpoint (multipart) |
|
|
82
|
-
| `/ws` | WebSocket | WebSocket service endpoint (Protocol V2) |
|
|
83
|
-
| `/` | WebSocket | WebSocket endpoint (V1 legacy + V2) |
|
|
84
|
-
| `/*` | GET | Static file serving from `www/` |
|
|
85
|
-
|
|
86
|
-
### Registered Plugins
|
|
87
|
-
|
|
88
|
-
- `@fastify/websocket` - WebSocket support
|
|
89
|
-
- `@fastify/helmet` - Security headers (CSP, HSTS)
|
|
90
|
-
- `@fastify/multipart` - File upload
|
|
91
|
-
- `@fastify/static` - Static file serving
|
|
92
|
-
- `@fastify/cors` - CORS support
|
|
93
|
-
|
|
94
|
-
## `createServiceServer`
|
|
95
|
-
|
|
96
|
-
Factory function to create a `ServiceServer` instance.
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
function createServiceServer<TAuthInfo = unknown>(
|
|
100
|
-
options: ServiceServerOptions,
|
|
101
|
-
): ServiceServer<TAuthInfo>;
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Utils
|
|
105
|
-
|
|
106
|
-
### `getConfig`
|
|
107
|
-
|
|
108
|
-
Read JSON configuration from file with caching and live-reload via file watcher. Cache expires after 1 hour.
|
|
109
|
-
|
|
110
|
-
```typescript
|
|
111
|
-
async function getConfig<TConfig>(filePath: string): Promise<TConfig | undefined>;
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Legacy
|
|
115
|
-
|
|
116
|
-
### `handleV1Connection`
|
|
117
|
-
|
|
118
|
-
V1 legacy client handler. Only auto-update is supported; all other requests return an upgrade-required error.
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
function handleV1Connection(
|
|
122
|
-
socket: WebSocket,
|
|
123
|
-
autoUpdateMethods: { getLastVersion: (platform: string) => Promise<any> },
|
|
124
|
-
clientNameSetter?: (clientName: string | undefined) => void,
|
|
125
|
-
): void;
|
|
126
|
-
```
|
package/docs/services.md
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Built-in Services
|
|
2
|
-
|
|
3
|
-
Pre-defined service definitions ready to use with `ServiceServer`.
|
|
4
|
-
|
|
5
|
-
## `OrmService`
|
|
6
|
-
|
|
7
|
-
Server-side ORM service implementation. Requires authentication. Manages database connections per WebSocket socket (using `WeakMap`). Supports MySQL, MSSQL, and PostgreSQL via `@simplysm/orm-node`.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
const OrmService: ServiceDefinition;
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Implements the `OrmService` interface from `@simplysm/service-common`:
|
|
14
|
-
|
|
15
|
-
| Method | Description |
|
|
16
|
-
|--------|-------------|
|
|
17
|
-
| `getInfo()` | Get database dialect and connection info from config |
|
|
18
|
-
| `connect()` | Open a new database connection, returns connection ID |
|
|
19
|
-
| `close()` | Close a database connection |
|
|
20
|
-
| `beginTransaction()` | Begin transaction |
|
|
21
|
-
| `commitTransaction()` | Commit transaction |
|
|
22
|
-
| `rollbackTransaction()` | Rollback transaction |
|
|
23
|
-
| `executeParametrized()` | Execute parameterized SQL |
|
|
24
|
-
| `executeDefs()` | Execute QueryDef array (builds SQL via QueryBuilder) |
|
|
25
|
-
| `bulkInsert()` | Bulk insert records |
|
|
26
|
-
|
|
27
|
-
**Note:** ORM service requires WebSocket connection (cannot be used over HTTP).
|
|
28
|
-
|
|
29
|
-
## `AutoUpdateService`
|
|
30
|
-
|
|
31
|
-
Server-side auto-update service implementation. Scans the client's platform-specific `updates/` directory for version files.
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
const AutoUpdateService: ServiceDefinition;
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Implements the `AutoUpdateService` interface from `@simplysm/service-common`:
|
|
38
|
-
|
|
39
|
-
| Method | Description |
|
|
40
|
-
|--------|-------------|
|
|
41
|
-
| `getLastVersion(platform)` | Find latest version file for platform (win32, android, etc.) |
|
|
42
|
-
|
|
43
|
-
Supported platforms and file extensions:
|
|
44
|
-
- `android`: `.apk` files
|
|
45
|
-
- Other platforms: `.exe` files
|
|
46
|
-
|
|
47
|
-
## `SmtpClientService`
|
|
48
|
-
|
|
49
|
-
Server-side SMTP email sending service. Uses `nodemailer` under the hood.
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
const SmtpClientService: ServiceDefinition;
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
| Method | Description |
|
|
56
|
-
|--------|-------------|
|
|
57
|
-
| `send(options)` | Send email with full SMTP options |
|
|
58
|
-
| `sendByDefault(options)` | Send email using server's default SMTP config |
|