@simplysm/service-server 13.0.0-beta.45 → 13.0.0-beta.47
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 +84 -32
- package/dist/auth/auth-token-payload.js.map +0 -1
- package/dist/auth/jwt-manager.js.map +0 -1
- package/dist/core/define-service.d.ts +67 -0
- package/dist/core/define-service.d.ts.map +1 -0
- package/dist/core/define-service.js +70 -0
- package/dist/core/define-service.js.map +6 -0
- package/dist/core/service-executor.d.ts.map +1 -1
- package/dist/core/service-executor.js +12 -13
- package/dist/core/service-executor.js.map +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -2
- package/dist/legacy/v1-auto-update-handler.d.ts +3 -2
- package/dist/legacy/v1-auto-update-handler.d.ts.map +1 -1
- package/dist/legacy/v1-auto-update-handler.js +3 -3
- package/dist/legacy/v1-auto-update-handler.js.map +1 -2
- package/dist/protocol/protocol-wrapper.js.map +0 -1
- package/dist/service-server.d.ts +3 -3
- package/dist/service-server.d.ts.map +1 -1
- package/dist/service-server.js +18 -7
- package/dist/service-server.js.map +1 -2
- package/dist/services/auto-update-service.d.ts +4 -4
- package/dist/services/auto-update-service.d.ts.map +1 -1
- package/dist/services/auto-update-service.js +5 -5
- package/dist/services/auto-update-service.js.map +1 -2
- package/dist/services/crypto-service.d.ts +4 -5
- package/dist/services/crypto-service.d.ts.map +1 -1
- package/dist/services/crypto-service.js +8 -11
- package/dist/services/crypto-service.js.map +1 -2
- package/dist/services/orm-service.d.ts +5 -9
- package/dist/services/orm-service.d.ts.map +1 -1
- package/dist/services/orm-service.js +122 -171
- package/dist/services/orm-service.js.map +1 -2
- package/dist/services/smtp-service.d.ts +6 -5
- package/dist/services/smtp-service.d.ts.map +1 -1
- package/dist/services/smtp-service.js +22 -19
- package/dist/services/smtp-service.js.map +1 -2
- package/dist/transport/http/http-request-handler.js.map +0 -1
- package/dist/transport/http/static-file-handler.js.map +0 -1
- package/dist/transport/http/upload-handler.js.map +0 -1
- package/dist/transport/socket/service-socket.js.map +0 -1
- package/dist/transport/socket/websocket-handler.d.ts +2 -3
- package/dist/transport/socket/websocket-handler.d.ts.map +1 -1
- package/dist/transport/socket/websocket-handler.js +2 -2
- package/dist/transport/socket/websocket-handler.js.map +1 -2
- package/dist/types/server-options.d.ts +2 -3
- package/dist/types/server-options.d.ts.map +1 -1
- package/dist/types/server-options.js.map +0 -1
- package/dist/utils/config-manager.js.map +0 -1
- package/dist/workers/service-protocol.worker.js.map +0 -1
- package/docs/authentication.md +35 -39
- package/docs/built-in-services.md +9 -9
- package/docs/server.md +68 -54
- package/docs/transport.md +7 -9
- package/package.json +7 -6
- package/src/auth/auth-token-payload.ts +6 -0
- package/src/auth/jwt-manager.ts +44 -0
- package/src/core/define-service.ts +159 -0
- package/src/core/service-executor.ts +68 -0
- package/src/index.ts +37 -0
- package/src/legacy/v1-auto-update-handler.ts +67 -0
- package/src/protocol/protocol-wrapper.ts +75 -0
- package/src/service-server.ts +249 -0
- package/src/services/auto-update-service.ts +53 -0
- package/src/services/crypto-service.ts +36 -0
- package/src/services/orm-service.ts +176 -0
- package/src/services/smtp-service.ts +59 -0
- package/src/transport/http/http-request-handler.ts +69 -0
- package/src/transport/http/static-file-handler.ts +66 -0
- package/src/transport/http/upload-handler.ts +87 -0
- package/src/transport/socket/service-socket.ts +136 -0
- package/src/transport/socket/websocket-handler.ts +180 -0
- package/src/types/server-options.ts +14 -0
- package/src/utils/config-manager.ts +70 -0
- package/src/workers/service-protocol.worker.ts +15 -0
- package/dist/auth/auth.decorators.d.ts +0 -19
- package/dist/auth/auth.decorators.d.ts.map +0 -1
- package/dist/auth/auth.decorators.js +0 -46
- package/dist/auth/auth.decorators.js.map +0 -7
- package/dist/core/service-base.d.ts +0 -19
- package/dist/core/service-base.d.ts.map +0 -1
- package/dist/core/service-base.js +0 -47
- package/dist/core/service-base.js.map +0 -7
package/README.md
CHANGED
|
@@ -14,17 +14,18 @@ pnpm add @simplysm/service-server
|
|
|
14
14
|
|
|
15
15
|
## Main Modules
|
|
16
16
|
|
|
17
|
-
### Core Classes
|
|
17
|
+
### Core Functions and Classes
|
|
18
18
|
|
|
19
|
+
- [`createServiceServer`](#basic-server-configuration) - Factory function for creating a ServiceServer instance
|
|
19
20
|
- [`ServiceServer`](docs/server.md#serviceserver) - Main server class. Creates Fastify instance and configures routes/plugins
|
|
20
|
-
- [`
|
|
21
|
+
- [`defineService`](#custom-services) - Defines a service with a factory function pattern
|
|
21
22
|
- `ServiceExecutor` - Internal executor that handles service method discovery, auth checks, and execution
|
|
22
23
|
|
|
23
24
|
### Authentication
|
|
24
25
|
|
|
25
|
-
- [`
|
|
26
|
+
- [`auth`](#authentication) - Function wrapper that sets authentication permissions at service or method level
|
|
27
|
+
- [`getServiceAuthPermissions`](#authentication) - Queries auth permissions for a service or method (used internally by `ServiceExecutor`)
|
|
26
28
|
- [`JwtManager`](docs/authentication.md#jwtmanager) - JWT token generation/verification/decoding based on jose library (HS256, 12-hour expiration)
|
|
27
|
-
- [`getAuthPermissions`](docs/authentication.md#getauthpermissions) - Queries auth permissions for a service class/method (used internally by `ServiceExecutor`)
|
|
28
29
|
- [`AuthTokenPayload`](docs/authentication.md#authtokenpayload) - JWT payload interface (includes `roles`, `data`)
|
|
29
30
|
|
|
30
31
|
### Transport Layer - WebSocket
|
|
@@ -62,9 +63,9 @@ pnpm add @simplysm/service-server
|
|
|
62
63
|
### Basic Server Configuration
|
|
63
64
|
|
|
64
65
|
```typescript
|
|
65
|
-
import {
|
|
66
|
+
import { createServiceServer } from "@simplysm/service-server";
|
|
66
67
|
|
|
67
|
-
const server =
|
|
68
|
+
const server = createServiceServer({
|
|
68
69
|
port: 8080,
|
|
69
70
|
rootPath: "/app/data",
|
|
70
71
|
services: [MyService],
|
|
@@ -92,43 +93,94 @@ See [`ServiceServerOptions`](docs/server.md#server-options-serviceserveroptions)
|
|
|
92
93
|
|
|
93
94
|
### Custom Services
|
|
94
95
|
|
|
95
|
-
Services are defined
|
|
96
|
+
Services are defined using the `defineService` function. Service methods are called via RPC from the client.
|
|
96
97
|
|
|
97
98
|
```typescript
|
|
98
|
-
import {
|
|
99
|
+
import { defineService } from "@simplysm/service-server";
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
async
|
|
101
|
+
export const MyService = defineService("MyService", (ctx) => ({
|
|
102
|
+
hello: async (name: string): Promise<string> => {
|
|
102
103
|
return `Hello, ${name}!`;
|
|
103
|
-
}
|
|
104
|
+
},
|
|
104
105
|
|
|
105
|
-
async
|
|
106
|
+
getServerTime: async (): Promise<Date> => {
|
|
106
107
|
return new Date();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
108
|
+
},
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
// Export type for client-side type sharing
|
|
112
|
+
export type MyServiceMethods = import("@simplysm/service-server").ServiceMethods<typeof MyService>;
|
|
109
113
|
```
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
#### ServiceContext
|
|
116
|
+
|
|
117
|
+
The `ctx` parameter provides access to server resources:
|
|
118
|
+
|
|
119
|
+
- `ctx.server` - ServiceServer instance
|
|
120
|
+
- `ctx.socket` - ServiceSocket instance (WebSocket only, undefined for HTTP)
|
|
121
|
+
- `ctx.http` - HTTP request/reply objects (HTTP only, undefined for WebSocket)
|
|
122
|
+
- `ctx.authInfo` - Authentication info (set via JWT token)
|
|
123
|
+
- `ctx.clientName` - Client identifier
|
|
124
|
+
- `ctx.getConfig(name)` - Get server config by name
|
|
112
125
|
|
|
113
126
|
### Authentication
|
|
114
127
|
|
|
115
|
-
Use the
|
|
128
|
+
Use the `auth()` wrapper to set authentication requirements at service or method level:
|
|
116
129
|
|
|
117
130
|
```typescript
|
|
118
|
-
import {
|
|
131
|
+
import { defineService, auth } from "@simplysm/service-server";
|
|
119
132
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
interface UserAuthInfo {
|
|
134
|
+
userId: number;
|
|
135
|
+
role: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Service-level auth: all methods require authentication
|
|
139
|
+
export const UserService = defineService("UserService", auth((ctx) => ({
|
|
140
|
+
getProfile: async (): Promise<unknown> => {
|
|
141
|
+
const userId = (ctx.authInfo as UserAuthInfo)?.userId;
|
|
124
142
|
// ...
|
|
125
|
-
}
|
|
143
|
+
},
|
|
126
144
|
|
|
127
|
-
|
|
128
|
-
async deleteUser(targetId: number): Promise<void> {
|
|
145
|
+
deleteUser: auth(["admin"], async (targetId: number): Promise<void> => {
|
|
129
146
|
// Only users with admin role can call
|
|
130
|
-
}
|
|
131
|
-
}
|
|
147
|
+
}),
|
|
148
|
+
})));
|
|
149
|
+
|
|
150
|
+
export type UserServiceMethods = import("@simplysm/service-server").ServiceMethods<typeof UserService>;
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Auth Patterns
|
|
154
|
+
|
|
155
|
+
**Method-level auth only:**
|
|
156
|
+
```typescript
|
|
157
|
+
export const MyService = defineService("MyService", (ctx) => ({
|
|
158
|
+
publicMethod: async (): Promise<void> => {
|
|
159
|
+
// No auth required
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
protectedMethod: auth(async (): Promise<void> => {
|
|
163
|
+
// Auth required
|
|
164
|
+
}),
|
|
165
|
+
|
|
166
|
+
adminMethod: auth(["admin"], async (): Promise<void> => {
|
|
167
|
+
// Auth + admin role required
|
|
168
|
+
}),
|
|
169
|
+
}));
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Service-level auth with method override:**
|
|
173
|
+
```typescript
|
|
174
|
+
// All methods require authentication by default
|
|
175
|
+
export const SecureService = defineService("SecureService", auth((ctx) => ({
|
|
176
|
+
normalMethod: async (): Promise<void> => {
|
|
177
|
+
// Auth required (inherited from service level)
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
adminMethod: auth(["admin"], async (): Promise<void> => {
|
|
181
|
+
// Auth + admin role required
|
|
182
|
+
}),
|
|
183
|
+
})));
|
|
132
184
|
```
|
|
133
185
|
|
|
134
186
|
See [Authentication](docs/authentication.md) for JWT token management and permission handling.
|
|
@@ -166,14 +218,12 @@ See [File Upload](docs/transport.md#file-upload) for more details.
|
|
|
166
218
|
Publish real-time events to connected WebSocket clients:
|
|
167
219
|
|
|
168
220
|
```typescript
|
|
169
|
-
import {
|
|
221
|
+
import { defineEvent } from "@simplysm/service-common";
|
|
170
222
|
|
|
171
|
-
|
|
223
|
+
export const OrderUpdatedEvent = defineEvent<
|
|
172
224
|
{ orderId: number },
|
|
173
225
|
{ status: string }
|
|
174
|
-
>
|
|
175
|
-
readonly eventName = "OrderUpdatedEvent";
|
|
176
|
-
}
|
|
226
|
+
>("OrderUpdatedEvent");
|
|
177
227
|
|
|
178
228
|
await server.emitEvent(
|
|
179
229
|
OrderUpdatedEvent,
|
|
@@ -196,7 +246,9 @@ The package provides several built-in services:
|
|
|
196
246
|
Register them like any other service:
|
|
197
247
|
|
|
198
248
|
```typescript
|
|
199
|
-
|
|
249
|
+
import { createServiceServer, OrmService, CryptoService, SmtpService } from "@simplysm/service-server";
|
|
250
|
+
|
|
251
|
+
const server = createServiceServer({
|
|
200
252
|
port: 8080,
|
|
201
253
|
rootPath: "/app/data",
|
|
202
254
|
auth: { jwtSecret: "secret" },
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/auth/jwt-manager.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ServiceServer } from \"../service-server\";\nimport * as jose from \"jose\";\nimport type { AuthTokenPayload } from \"./auth-token-payload\";\n\nexport class JwtManager<TAuthInfo = unknown> {\n constructor(private readonly _server: ServiceServer<TAuthInfo>) {}\n\n async sign(payload: AuthTokenPayload<TAuthInfo>): Promise<string> {\n const jwtSecret = this._server.options.auth?.jwtSecret;\n if (jwtSecret == null) throw new Error(\"JWT Secret\uC774 \uC815\uC758\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.\");\n\n const secret = new TextEncoder().encode(jwtSecret);\n\n return new jose.SignJWT(payload)\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"12h\")\n .sign(secret);\n }\n\n async verify(token: string): Promise<AuthTokenPayload<TAuthInfo>> {\n const jwtSecret = this._server.options.auth?.jwtSecret;\n if (jwtSecret == null) throw new Error(\"JWT Secret\uC774 \uC815\uC758\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.\");\n\n const secret = new TextEncoder().encode(jwtSecret);\n\n try {\n const { payload } = await jose.jwtVerify(token, secret);\n return payload as AuthTokenPayload<TAuthInfo>;\n } catch (err) {\n if (err != null && typeof err === \"object\" && \"code\" in err && err.code === \"ERR_JWT_EXPIRED\") {\n throw new Error(\"\uD1A0\uD070\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\");\n }\n throw new Error(\"\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD1A0\uD070\uC785\uB2C8\uB2E4.\");\n }\n }\n\n decode(token: string): AuthTokenPayload<TAuthInfo> {\n const jwtSecret = this._server.options.auth?.jwtSecret;\n if (jwtSecret == null) throw new Error(\"JWT Secret\uC774 \uC815\uC758\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.\");\n\n return jose.decodeJwt(token) as AuthTokenPayload<TAuthInfo>;\n }\n}\n"],
|
|
5
4
|
"mappings": "AACA,YAAY,UAAU;AAGf,MAAM,WAAgC;AAAA,EAC3C,YAA6B,SAAmC;AAAnC;AAAA,EAAoC;AAAA,EAEjE,MAAM,KAAK,SAAuD;AAChE,UAAM,YAAY,KAAK,QAAQ,QAAQ,MAAM;AAC7C,QAAI,aAAa,KAAM,OAAM,IAAI,MAAM,2EAAyB;AAEhE,UAAM,SAAS,IAAI,YAAY,EAAE,OAAO,SAAS;AAEjD,WAAO,IAAI,KAAK,QAAQ,OAAO,EAC5B,mBAAmB,EAAE,KAAK,QAAQ,CAAC,EACnC,YAAY,EACZ,kBAAkB,KAAK,EACvB,KAAK,MAAM;AAAA,EAChB;AAAA,EAEA,MAAM,OAAO,OAAqD;AAChE,UAAM,YAAY,KAAK,QAAQ,QAAQ,MAAM;AAC7C,QAAI,aAAa,KAAM,OAAM,IAAI,MAAM,2EAAyB;AAEhE,UAAM,SAAS,IAAI,YAAY,EAAE,OAAO,SAAS;AAEjD,QAAI;AACF,YAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,UAAU,OAAO,MAAM;AACtD,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,OAAO,QAAQ,OAAO,QAAQ,YAAY,UAAU,OAAO,IAAI,SAAS,mBAAmB;AAC7F,cAAM,IAAI,MAAM,gEAAc;AAAA,MAChC;AACA,YAAM,IAAI,MAAM,uEAAgB;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,OAAO,OAA4C;AACjD,UAAM,YAAY,KAAK,QAAQ,QAAQ,MAAM;AAC7C,QAAI,aAAa,KAAM,OAAM,IAAI,MAAM,2EAAyB;AAEhE,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AACF;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ServiceServer } from "../service-server";
|
|
2
|
+
import type { ServiceSocket } from "../transport/socket/service-socket";
|
|
3
|
+
import type { AuthTokenPayload } from "../auth/auth-token-payload";
|
|
4
|
+
export interface ServiceContext<TAuthInfo = unknown> {
|
|
5
|
+
server: ServiceServer<TAuthInfo>;
|
|
6
|
+
socket?: ServiceSocket;
|
|
7
|
+
http?: {
|
|
8
|
+
clientName: string;
|
|
9
|
+
authTokenPayload?: AuthTokenPayload<TAuthInfo>;
|
|
10
|
+
};
|
|
11
|
+
/** V1 legacy context (auto-update only) */
|
|
12
|
+
legacy?: {
|
|
13
|
+
clientName?: string;
|
|
14
|
+
};
|
|
15
|
+
get authInfo(): TAuthInfo | undefined;
|
|
16
|
+
get clientName(): string | undefined;
|
|
17
|
+
get clientPath(): string | undefined;
|
|
18
|
+
getConfig<T>(section: string): Promise<T>;
|
|
19
|
+
}
|
|
20
|
+
export declare function createServiceContext<TAuthInfo = unknown>(server: ServiceServer<TAuthInfo>, socket?: ServiceSocket, http?: {
|
|
21
|
+
clientName: string;
|
|
22
|
+
authTokenPayload?: AuthTokenPayload<TAuthInfo>;
|
|
23
|
+
}, legacy?: {
|
|
24
|
+
clientName?: string;
|
|
25
|
+
}): ServiceContext<TAuthInfo>;
|
|
26
|
+
/** Read auth permissions from an auth()-wrapped function. Returns undefined if not wrapped. */
|
|
27
|
+
export declare function getServiceAuthPermissions(fn: Function): string[] | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Auth wrapper for service factories and methods.
|
|
30
|
+
*
|
|
31
|
+
* - Service-level: `auth((ctx) => ({ ... }))` — all methods require login
|
|
32
|
+
* - Service-level with roles: `auth(["admin"], (ctx) => ({ ... }))`
|
|
33
|
+
* - Method-level: `auth(() => result)` — this method requires login
|
|
34
|
+
* - Method-level with roles: `auth(["admin"], () => result)`
|
|
35
|
+
*/
|
|
36
|
+
export declare function auth<T extends (...args: any[]) => any>(fn: T): T;
|
|
37
|
+
export declare function auth<T extends (...args: any[]) => any>(permissions: string[], fn: T): T;
|
|
38
|
+
export interface ServiceDefinition<TMethods = Record<string, (...args: any[]) => any>> {
|
|
39
|
+
name: string;
|
|
40
|
+
factory: (ctx: ServiceContext) => TMethods;
|
|
41
|
+
authPermissions?: string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Define a service with a name and factory function.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Basic service
|
|
48
|
+
* const HealthService = defineService("Health", (ctx) => ({
|
|
49
|
+
* check: () => ({ status: "ok" }),
|
|
50
|
+
* }));
|
|
51
|
+
*
|
|
52
|
+
* // Service with auth
|
|
53
|
+
* const UserService = defineService("User", auth((ctx) => ({
|
|
54
|
+
* getProfile: () => ctx.authInfo,
|
|
55
|
+
* adminOnly: auth(["admin"], () => "admin"),
|
|
56
|
+
* })));
|
|
57
|
+
*/
|
|
58
|
+
export declare function defineService<TMethods extends Record<string, (...args: any[]) => any>>(name: string, factory: (ctx: ServiceContext) => TMethods): ServiceDefinition<TMethods>;
|
|
59
|
+
/**
|
|
60
|
+
* Extract method signatures from a ServiceDefinition for client-side type sharing.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* export type UserServiceType = ServiceMethods<typeof UserService>;
|
|
64
|
+
* // Client: client.getService<UserServiceType>("User");
|
|
65
|
+
*/
|
|
66
|
+
export type ServiceMethods<T> = T extends ServiceDefinition<infer M> ? M : never;
|
|
67
|
+
//# sourceMappingURL=define-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-service.d.ts","sourceRoot":"","sources":["../../src/core/define-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAOnE,MAAM,WAAW,cAAc,CAAC,SAAS,GAAG,OAAO;IACjD,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,IAAI,CAAC,EAAE;QACL,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;KAChD,CAAC;IAEF,2CAA2C;IAC3C,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IAEF,IAAI,QAAQ,IAAI,SAAS,GAAG,SAAS,CAAC;IACtC,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAAC;IACrC,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAAC;IACrC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3C;AAED,wBAAgB,oBAAoB,CAAC,SAAS,GAAG,OAAO,EACtD,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,EAChC,MAAM,CAAC,EAAE,aAAa,EACtB,IAAI,CAAC,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAA;CAAE,EAC7E,MAAM,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,cAAc,CAAC,SAAS,CAAC,CAkD3B;AAMD,+FAA+F;AAC/F,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,SAAS,CAE5E;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAClE,wBAAgB,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAczF,MAAM,WAAW,iBAAiB,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,QAAQ,CAAC;IAC3C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,EACpF,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,QAAQ,GACzC,iBAAiB,CAAC,QAAQ,CAAC,CAM7B;AAID;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { objMerge } from "@simplysm/core-common";
|
|
2
|
+
import { ConfigManager } from "../utils/config-manager.js";
|
|
3
|
+
import path from "path";
|
|
4
|
+
function createServiceContext(server, socket, http, legacy) {
|
|
5
|
+
return {
|
|
6
|
+
server,
|
|
7
|
+
socket,
|
|
8
|
+
http,
|
|
9
|
+
legacy,
|
|
10
|
+
get authInfo() {
|
|
11
|
+
return socket?.authTokenPayload?.data ?? http?.authTokenPayload?.data;
|
|
12
|
+
},
|
|
13
|
+
get clientName() {
|
|
14
|
+
const name = socket?.clientName ?? http?.clientName ?? legacy?.clientName;
|
|
15
|
+
if (name == null) return void 0;
|
|
16
|
+
if (name === "" || name.includes("..") || name.includes("/") || name.includes("\\")) {
|
|
17
|
+
throw new Error(`\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD074\uB77C\uC774\uC5B8\uD2B8 \uBA85\uC785\uB2C8\uB2E4: ${name}`);
|
|
18
|
+
}
|
|
19
|
+
return name;
|
|
20
|
+
},
|
|
21
|
+
get clientPath() {
|
|
22
|
+
const name = this.clientName;
|
|
23
|
+
return name == null ? void 0 : path.resolve(server.options.rootPath, "www", name);
|
|
24
|
+
},
|
|
25
|
+
async getConfig(section) {
|
|
26
|
+
let configParent = {};
|
|
27
|
+
const rootFilePath = path.resolve(server.options.rootPath, ".config.json");
|
|
28
|
+
const rootConfig = await ConfigManager.getConfig(rootFilePath);
|
|
29
|
+
if (rootConfig != null) {
|
|
30
|
+
configParent = rootConfig;
|
|
31
|
+
}
|
|
32
|
+
const targetPath = this.clientPath;
|
|
33
|
+
if (targetPath != null) {
|
|
34
|
+
const clientFilePath = path.resolve(targetPath, ".config.json");
|
|
35
|
+
const clientConfig = await ConfigManager.getConfig(clientFilePath);
|
|
36
|
+
if (clientConfig != null) {
|
|
37
|
+
configParent = objMerge(configParent, clientConfig);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const config = configParent[section];
|
|
41
|
+
if (config == null) throw new Error(`\uC124\uC815 \uC139\uC158\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${section}`);
|
|
42
|
+
return config;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const AUTH_PERMISSIONS = /* @__PURE__ */ Symbol("authPermissions");
|
|
47
|
+
function getServiceAuthPermissions(fn) {
|
|
48
|
+
return fn[AUTH_PERMISSIONS];
|
|
49
|
+
}
|
|
50
|
+
function auth(permissionsOrFn, maybeFn) {
|
|
51
|
+
const permissions = Array.isArray(permissionsOrFn) ? permissionsOrFn : [];
|
|
52
|
+
const fn = Array.isArray(permissionsOrFn) ? maybeFn : permissionsOrFn;
|
|
53
|
+
const wrapper = (...args) => fn(...args);
|
|
54
|
+
wrapper[AUTH_PERMISSIONS] = permissions;
|
|
55
|
+
return wrapper;
|
|
56
|
+
}
|
|
57
|
+
function defineService(name, factory) {
|
|
58
|
+
return {
|
|
59
|
+
name,
|
|
60
|
+
factory,
|
|
61
|
+
authPermissions: getServiceAuthPermissions(factory)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
auth,
|
|
66
|
+
createServiceContext,
|
|
67
|
+
defineService,
|
|
68
|
+
getServiceAuthPermissions
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=define-service.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/define-service.ts"],
|
|
4
|
+
"mappings": "AAGA,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AAuBV,SAAS,qBACd,QACA,QACA,MACA,QAC2B;AAC3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IAEA,IAAI,WAAkC;AACpC,aAAQ,QAAQ,kBAAkB,QAAQ,MAAM,kBAAkB;AAAA,IACpE;AAAA,IAEA,IAAI,aAAiC;AACnC,YAAM,OAAO,QAAQ,cAAc,MAAM,cAAc,QAAQ;AAC/D,UAAI,QAAQ,KAAM,QAAO;AAEzB,UAAI,SAAS,MAAM,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,GAAG;AACnF,cAAM,IAAI,MAAM,kGAAuB,IAAI,EAAE;AAAA,MAC/C;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,IAAI,aAAiC;AACnC,YAAM,OAAO,KAAK;AAClB,aAAO,QAAQ,OAAO,SAAY,KAAK,QAAQ,OAAO,QAAQ,UAAU,OAAO,IAAI;AAAA,IACrF;AAAA,IAEA,MAAM,UAAa,SAA6B;AAC9C,UAAI,eAA8C,CAAC;AAEnD,YAAM,eAAe,KAAK,QAAQ,OAAO,QAAQ,UAAU,cAAc;AACzE,YAAM,aAAa,MAAM,cAAc,UAA6B,YAAY;AAChF,UAAI,cAAc,MAAM;AACtB,uBAAe;AAAA,MACjB;AAEA,YAAM,aAAa,KAAK;AACxB,UAAI,cAAc,MAAM;AACtB,cAAM,iBAAiB,KAAK,QAAQ,YAAY,cAAc;AAC9D,cAAM,eAAe,MAAM,cAAc,UAA6B,cAAc;AACpF,YAAI,gBAAgB,MAAM;AACxB,yBAAe,SAAS,cAAc,YAAY;AAAA,QACpD;AAAA,MACF;AAEA,YAAM,SAAS,aAAa,OAAO;AACnC,UAAI,UAAU,KAAM,OAAM,IAAI,MAAM,iFAAqB,OAAO,EAAE;AAClE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAIA,MAAM,mBAAmB,uBAAO,iBAAiB;AAG1C,SAAS,0BAA0B,IAAoC;AAC5E,SAAQ,GAA0C,gBAAgB;AACpE;AAYO,SAAS,KAAK,iBAAsC,SAA8B;AACvF,QAAM,cAAc,MAAM,QAAQ,eAAe,IAAI,kBAAkB,CAAC;AACxE,QAAM,KAAK,MAAM,QAAQ,eAAe,IAAI,UAAW;AAGvD,QAAM,UAAU,IAAI,SAAoB,GAAG,GAAG,IAAI;AAClD,EAAC,QAA+C,gBAAgB,IAAI;AAEpE,SAAO;AACT;AAyBO,SAAS,cACd,MACA,SAC6B;AAC7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,iBAAiB,0BAA0B,OAAO;AAAA,EACpD;AACF;",
|
|
5
|
+
"names": []
|
|
6
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-executor.d.ts","sourceRoot":"","sources":["../../src/core/service-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE7C,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,EAAE,CAAC;QAClB,MAAM,CAAC,EAAE,aAAa,CAAC;QACvB,IAAI,CAAC,EAAE;YAAE,UAAU,EAAE,MAAM,CAAC;YAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;SAAE,CAAC;KACpE,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"service-executor.d.ts","sourceRoot":"","sources":["../../src/core/service-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE7C,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,EAAE,CAAC;QAClB,MAAM,CAAC,EAAE,aAAa,CAAC;QACvB,IAAI,CAAC,EAAE;YAAE,UAAU,EAAE,MAAM,CAAC;YAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;SAAE,CAAC;KACpE,GAAG,OAAO,CAAC,OAAO,CAAC;CAqDrB"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createServiceContext, getServiceAuthPermissions } from "./define-service.js";
|
|
2
2
|
class ServiceExecutor {
|
|
3
3
|
constructor(_server) {
|
|
4
4
|
this._server = _server;
|
|
5
5
|
}
|
|
6
6
|
async runMethod(def) {
|
|
7
|
-
const
|
|
8
|
-
if (
|
|
7
|
+
const serviceDef = this._server.options.services.find((item) => item.name === def.serviceName);
|
|
8
|
+
if (serviceDef == null) {
|
|
9
9
|
throw new Error(`\uC11C\uBE44\uC2A4[${def.serviceName}]\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`);
|
|
10
10
|
}
|
|
11
11
|
const clientName = def.socket?.clientName ?? def.http?.clientName;
|
|
@@ -14,8 +14,15 @@ class ServiceExecutor {
|
|
|
14
14
|
throw new Error(`[Security] \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD074\uB77C\uC774\uC5B8\uD2B8\uBA85\uC785\uB2C8\uB2E4: ${clientName}`);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
+
const ctx = createServiceContext(this._server, def.socket, def.http);
|
|
18
|
+
const methods = serviceDef.factory(ctx);
|
|
19
|
+
const method = methods[def.methodName];
|
|
20
|
+
if (typeof method !== "function") {
|
|
21
|
+
throw new Error(`\uBA54\uC18C\uB4DC[${def.serviceName}.${def.methodName}]\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`);
|
|
22
|
+
}
|
|
17
23
|
if (this._server.options.auth != null) {
|
|
18
|
-
const
|
|
24
|
+
const methodPerms = getServiceAuthPermissions(method);
|
|
25
|
+
const requiredPerms = methodPerms ?? serviceDef.authPermissions;
|
|
19
26
|
if (requiredPerms != null) {
|
|
20
27
|
const authTokenPayload = def.socket?.authTokenPayload ?? def.http?.authTokenPayload;
|
|
21
28
|
if (authTokenPayload == null) {
|
|
@@ -29,15 +36,7 @@ class ServiceExecutor {
|
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
service.server = this._server;
|
|
34
|
-
service.socket = def.socket;
|
|
35
|
-
service.http = def.http;
|
|
36
|
-
const method = service[def.methodName];
|
|
37
|
-
if (typeof method !== "function") {
|
|
38
|
-
throw new Error(`\uBA54\uC18C\uB4DC[${def.serviceName}.${def.methodName}]\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`);
|
|
39
|
-
}
|
|
40
|
-
return await method.apply(service, def.params);
|
|
39
|
+
return await method(...def.params);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
42
|
export {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/core/service-executor.ts"],
|
|
4
|
-
"
|
|
5
|
-
"mappings": "AAGA,SAAS,0BAA0B;AAE5B,MAAM,gBAAgB;AAAA,EAC3B,YAA6B,SAAwB;AAAxB;AAAA,EAAyB;AAAA,EAEtD,MAAM,UAAU,KAMK;AAEnB,UAAM,eAAe,KAAK,QAAQ,QAAQ,SAAS,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,WAAW;AAE/F,QAAI,gBAAgB,MAAM;AACxB,YAAM,IAAI,MAAM,sBAAO,IAAI,WAAW,uDAAe;AAAA,IACvD;AAGA,UAAM,aAAa,IAAI,QAAQ,cAAc,IAAI,MAAM;AACvD,QAAI,cAAc,MAAM;AACtB,UAAI,WAAW,SAAS,IAAI,KAAK,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,IAAI,GAAG;AACtF,cAAM,IAAI,MAAM,4GAAiC,UAAU,EAAE;AAAA,MAC/D;AAAA,IACF;AAGA,QAAI,KAAK,QAAQ,QAAQ,QAAQ,MAAM;AAErC,YAAM,gBAAgB,mBAAmB,cAAc,IAAI,UAAU;AAGrE,UAAI,iBAAiB,MAAM;AACzB,cAAM,mBAAmB,IAAI,QAAQ,oBAAoB,IAAI,MAAM;AAGnE,YAAI,oBAAoB,MAAM;AAC5B,gBAAM,IAAI,MAAM,0DAAa;AAAA,QAC/B;AAGA,YAAI,cAAc,SAAS,GAAG;AAC5B,gBAAM,UAAU,cAAc,KAAK,CAAC,SAAS,iBAAiB,MAAM,SAAS,IAAI,CAAC;AAClF,cAAI,CAAC,SAAS;AACZ,kBAAM,IAAI,MAAM,oDAAY;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAAU,IAAI,aAAa;AACjC,YAAQ,SAAS,KAAK;AACtB,YAAQ,SAAS,IAAI;AACrB,YAAQ,OAAO,IAAI;AAGnB,UAAM,SAAU,QAA+C,IAAI,UAAU;AAC7E,QAAI,OAAO,WAAW,YAAY;AAChC,YAAM,IAAI,MAAM,sBAAO,IAAI,WAAW,IAAI,IAAI,UAAU,uDAAe;AAAA,IACzE;AAGA,WAAO,MAAM,OAAO,MAAM,SAAS,IAAI,MAAM;AAAA,EAC/C;AACF;",
|
|
4
|
+
"mappings": "AAGA,SAAS,sBAAsB,iCAAiC;AAEzD,MAAM,gBAAgB;AAAA,EAC3B,YAA6B,SAAwB;AAAxB;AAAA,EAAyB;AAAA,EAEtD,MAAM,UAAU,KAMK;AAEnB,UAAM,aAAa,KAAK,QAAQ,QAAQ,SAAS,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,WAAW;AAE7F,QAAI,cAAc,MAAM;AACtB,YAAM,IAAI,MAAM,sBAAO,IAAI,WAAW,uDAAe;AAAA,IACvD;AAGA,UAAM,aAAa,IAAI,QAAQ,cAAc,IAAI,MAAM;AACvD,QAAI,cAAc,MAAM;AACtB,UAAI,WAAW,SAAS,IAAI,KAAK,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,IAAI,GAAG;AACtF,cAAM,IAAI,MAAM,4GAAiC,UAAU,EAAE;AAAA,MAC/D;AAAA,IACF;AAGA,UAAM,MAAM,qBAAqB,KAAK,SAAS,IAAI,QAAQ,IAAI,IAAI;AAGnE,UAAM,UAAU,WAAW,QAAQ,GAAG;AAGtC,UAAM,SAAU,QAAoC,IAAI,UAAU;AAClE,QAAI,OAAO,WAAW,YAAY;AAChC,YAAM,IAAI,MAAM,sBAAO,IAAI,WAAW,IAAI,IAAI,UAAU,uDAAe;AAAA,IACzE;AAGA,QAAI,KAAK,QAAQ,QAAQ,QAAQ,MAAM;AAErC,YAAM,cAAc,0BAA0B,MAAM;AACpD,YAAM,gBAAgB,eAAe,WAAW;AAEhD,UAAI,iBAAiB,MAAM;AACzB,cAAM,mBAAmB,IAAI,QAAQ,oBAAoB,IAAI,MAAM;AAEnE,YAAI,oBAAoB,MAAM;AAC5B,gBAAM,IAAI,MAAM,0DAAa;AAAA,QAC/B;AAEA,YAAI,cAAc,SAAS,GAAG;AAC5B,gBAAM,UAAU,cAAc,KAAK,CAAC,SAAS,iBAAiB,MAAM,SAAS,IAAI,CAAC;AAClF,cAAI,CAAC,SAAS;AACZ,kBAAM,IAAI,MAAM,oDAAY;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,WAAO,MAAM,OAAO,GAAG,IAAI,MAAM;AAAA,EACnC;AACF;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export * from "./types/server-options";
|
|
2
|
-
export * from "./auth/auth.decorators";
|
|
3
2
|
export * from "./auth/auth-token-payload";
|
|
4
3
|
export * from "./auth/jwt-manager";
|
|
5
|
-
export * from "./core/service
|
|
4
|
+
export * from "./core/define-service";
|
|
6
5
|
export * from "./core/service-executor";
|
|
7
6
|
export * from "./transport/socket/websocket-handler";
|
|
8
7
|
export * from "./transport/socket/service-socket";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAGlD,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AAGrD,cAAc,6BAA6B,CAAC;AAG5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAG/C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,iCAAiC,CAAC;AAGhD,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export * from "./types/server-options.js";
|
|
2
|
-
export * from "./auth/auth.decorators.js";
|
|
3
2
|
export * from "./auth/auth-token-payload.js";
|
|
4
3
|
export * from "./auth/jwt-manager.js";
|
|
5
|
-
export * from "./core/service
|
|
4
|
+
export * from "./core/define-service.js";
|
|
6
5
|
export * from "./core/service-executor.js";
|
|
7
6
|
export * from "./transport/socket/websocket-handler.js";
|
|
8
7
|
export * from "./transport/socket/service-socket.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"
|
|
5
|
-
"mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AAGd,cAAc;",
|
|
4
|
+
"mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AAGd,cAAc;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { WebSocket } from "ws";
|
|
2
|
-
import type { AutoUpdateService } from "../services/auto-update-service";
|
|
3
2
|
/**
|
|
4
3
|
* V1 레거시 클라이언트 처리 (auto-update만 지원)
|
|
5
4
|
* 다른 모든 요청은 업그레이드 유도 에러를 반환합니다.
|
|
6
5
|
*/
|
|
7
|
-
export declare function handleV1Connection(socket: WebSocket,
|
|
6
|
+
export declare function handleV1Connection(socket: WebSocket, autoUpdateMethods: {
|
|
7
|
+
getLastVersion: (platform: string) => Promise<any>;
|
|
8
|
+
}, clientNameSetter?: (clientName: string | undefined) => void): void;
|
|
8
9
|
//# sourceMappingURL=v1-auto-update-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1-auto-update-handler.d.ts","sourceRoot":"","sources":["../../src/legacy/v1-auto-update-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"v1-auto-update-handler.d.ts","sourceRoot":"","sources":["../../src/legacy/v1-auto-update-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAmBpC;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,iBAAiB,EAAE;IAAE,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;CAAE,EACzE,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,QAwC5D"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import consola from "consola";
|
|
2
2
|
const logger = consola.withTag("service-server:V1AutoUpdateHandler");
|
|
3
|
-
function handleV1Connection(socket,
|
|
3
|
+
function handleV1Connection(socket, autoUpdateMethods, clientNameSetter) {
|
|
4
4
|
socket.send(JSON.stringify({ name: "connected" }));
|
|
5
5
|
socket.on("message", (data) => {
|
|
6
6
|
try {
|
|
7
7
|
const msg = JSON.parse(data.toString());
|
|
8
8
|
if (msg.command === "SdAutoUpdateService.getLastVersion") {
|
|
9
|
-
|
|
10
|
-
const result =
|
|
9
|
+
clientNameSetter?.(msg.clientName);
|
|
10
|
+
const result = autoUpdateMethods.getLastVersion(msg.params[0]);
|
|
11
11
|
const response = {
|
|
12
12
|
name: "response",
|
|
13
13
|
reqUuid: msg.uuid,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/legacy/v1-auto-update-handler.ts"],
|
|
4
|
-
"
|
|
5
|
-
"mappings": "AAEA,OAAO,aAAa;AAEpB,MAAM,SAAS,QAAQ,QAAQ,oCAAoC;AAoB5D,SAAS,mBAAmB,QAAmB,mBAAsC;AAE1F,SAAO,KAAK,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC,CAAC;AAEjD,SAAO,GAAG,WAAW,CAAC,SAAS;AAC7B,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC;AAGtC,UAAI,IAAI,YAAY,sCAAsC;AAExD,0BAAkB,SAAS,EAAE,YAAY,IAAI,WAAW;AAExD,cAAM,SAAS,kBAAkB,eAAe,IAAI,OAAO,CAAC,CAAW;AAEvE,cAAM,WAAwB;AAAA,UAC5B,MAAM;AAAA,UACN,SAAS,IAAI;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AACA,eAAO,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,MACtC,OAAO;AAEL,cAAM,WAAwB;AAAA,UAC5B,MAAM;AAAA,UACN,SAAS,IAAI;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,YACJ,SAAS;AAAA,YACT,MAAM;AAAA,UACR;AAAA,QACF;AACA,eAAO,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,MACtC;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,KAAK,mDAAgB,GAAG;AAAA,IACjC;AAAA,EACF,CAAC;AACH;",
|
|
4
|
+
"mappings": "AACA,OAAO,aAAa;AAEpB,MAAM,SAAS,QAAQ,QAAQ,oCAAoC;AAoB5D,SAAS,mBACd,QACA,mBACA,kBACA;AAEA,SAAO,KAAK,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC,CAAC;AAEjD,SAAO,GAAG,WAAW,CAAC,SAAS;AAC7B,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,KAAK,SAAS,CAAC;AAGtC,UAAI,IAAI,YAAY,sCAAsC;AAExD,2BAAmB,IAAI,UAAU;AAEjC,cAAM,SAAS,kBAAkB,eAAe,IAAI,OAAO,CAAC,CAAW;AAEvE,cAAM,WAAwB;AAAA,UAC5B,MAAM;AAAA,UACN,SAAS,IAAI;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AACA,eAAO,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,MACtC,OAAO;AAEL,cAAM,WAAwB;AAAA,UAC5B,MAAM;AAAA,UACN,SAAS,IAAI;AAAA,UACb,OAAO;AAAA,UACP,MAAM;AAAA,YACJ,SAAS;AAAA,YACT,MAAM;AAAA,UACR;AAAA,QACF;AACA,eAAO,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,MACtC;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,KAAK,mDAAgB,GAAG;AAAA,IACjC;AAAA,EACF,CAAC;AACH;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/protocol/protocol-wrapper.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Bytes } from \"@simplysm/core-common\";\nimport { Worker, type WorkerProxy } from \"@simplysm/core-node\";\nimport type { ServiceMessageDecodeResult, ServiceMessage } from \"@simplysm/service-common\";\nimport { ServiceProtocol } from \"@simplysm/service-common\";\nimport type * as ServiceProtocolWorkerModule from \"../workers/service-protocol.worker\";\n\nexport class ProtocolWrapper {\n // \uC6CC\uCEE4 \uC2A4\uB808\uB4DC (\uBB34\uAC70\uC6B4 \uC791\uC5C5\uC6A9, Static Lazy Singleton)\n private static _worker?: WorkerProxy<typeof ServiceProtocolWorkerModule>;\n private static get worker() {\n if (this._worker == null) {\n this._worker = Worker.create<typeof ServiceProtocolWorkerModule>(\n import.meta.resolve(\"../workers/service-protocol.worker\"),\n {\n resourceLimits: { maxOldGenerationSizeMb: 4096 },\n },\n );\n }\n return this._worker;\n }\n\n // \uBA54\uC778 \uC2A4\uB808\uB4DC\uC6A9 \uD504\uB85C\uD1A0\uCF5C \uC778\uC2A4\uD134\uC2A4 (\uAC00\uBCBC\uC6B4 \uC791\uC5C5\uC6A9)\n private readonly _protocol = new ServiceProtocol();\n\n // \uAE30\uC900\uAC12 \uC124\uC815\n private readonly _SIZE_THRESHOLD = 30 * 1024; // 30KB\n\n /**\n * \uBA54\uC2DC\uC9C0 \uC778\uCF54\uB529 (\uC790\uB3D9 \uBD84\uAE30 \uCC98\uB9AC)\n */\n async encode(uuid: string, message: ServiceMessage): Promise<{ chunks: Bytes[]; totalSize: number }> {\n if (this._shouldUseWorkerForEncode(message)) {\n return ProtocolWrapper.worker.encode(uuid, message);\n } else {\n return this._protocol.encode(uuid, message);\n }\n }\n\n /**\n * \uBA54\uC2DC\uC9C0 \uB514\uCF54\uB529 (\uC790\uB3D9 \uBD84\uAE30 \uCC98\uB9AC)\n */\n async decode(bytes: Bytes): Promise<ServiceMessageDecodeResult<ServiceMessage>> {\n const totalSize = bytes.length;\n if (totalSize > this._SIZE_THRESHOLD) {\n return ProtocolWrapper.worker.decode(bytes);\n } else {\n return this._protocol.decode(bytes);\n }\n }\n\n /**\n * \uC6CC\uCEE4 \uC0AC\uC6A9 \uC5EC\uBD80 \uD310\uB2E8 \uB85C\uC9C1 (Encode)\n */\n private _shouldUseWorkerForEncode(msg: ServiceMessage): boolean {\n if (!(\"body\" in msg)) return false;\n\n const body = msg.body;\n\n // Uint8Array: \uD06C\uAE30 \uD655\uC778\n if (body instanceof Uint8Array) {\n return true;\n }\n\n // Array: \uAE38\uC774 \uD655\uC778 (ORM \uACB0\uACFC \uB4F1)\n if (Array.isArray(body)) {\n return body.length > 0 && body.some((item) => item instanceof Uint8Array);\n }\n\n return false;\n }\n\n dispose() {\n this._protocol.dispose();\n }\n}\n"],
|
|
5
4
|
"mappings": "AACA,SAAS,cAAgC;AAEzC,SAAS,uBAAuB;AAGzB,MAAM,gBAAgB;AAAA;AAAA,EAE3B,OAAe;AAAA,EACf,WAAmB,SAAS;AAC1B,QAAI,KAAK,WAAW,MAAM;AACxB,WAAK,UAAU,OAAO;AAAA,QACpB,YAAY,QAAQ,oCAAoC;AAAA,QACxD;AAAA,UACE,gBAAgB,EAAE,wBAAwB,KAAK;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGiB,YAAY,IAAI,gBAAgB;AAAA;AAAA,EAGhC,kBAAkB,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,MAAM,OAAO,MAAc,SAA0E;AACnG,QAAI,KAAK,0BAA0B,OAAO,GAAG;AAC3C,aAAO,gBAAgB,OAAO,OAAO,MAAM,OAAO;AAAA,IACpD,OAAO;AACL,aAAO,KAAK,UAAU,OAAO,MAAM,OAAO;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,OAAmE;AAC9E,UAAM,YAAY,MAAM;AACxB,QAAI,YAAY,KAAK,iBAAiB;AACpC,aAAO,gBAAgB,OAAO,OAAO,KAAK;AAAA,IAC5C,OAAO;AACL,aAAO,KAAK,UAAU,OAAO,KAAK;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAA0B,KAA8B;AAC9D,QAAI,EAAE,UAAU,KAAM,QAAO;AAE7B,UAAM,OAAO,IAAI;AAGjB,QAAI,gBAAgB,YAAY;AAC9B,aAAO;AAAA,IACT;AAGA,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAO,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,SAAS,gBAAgB,UAAU;AAAA,IAC1E;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU;AACR,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
package/dist/service-server.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Type } from "@simplysm/core-common";
|
|
1
|
+
import type { ServiceEventDef } from "@simplysm/service-common";
|
|
3
2
|
import { EventEmitter } from "@simplysm/core-common";
|
|
4
3
|
import type { FastifyInstance } from "fastify";
|
|
5
4
|
import type { AuthTokenPayload } from "./auth/auth-token-payload";
|
|
@@ -21,9 +20,10 @@ export declare class ServiceServer<TAuthInfo = unknown> extends EventEmitter<{
|
|
|
21
20
|
listen(): Promise<void>;
|
|
22
21
|
close(): Promise<void>;
|
|
23
22
|
broadcastReload(clientName: string | undefined, changedFileSet: Set<string>): Promise<void>;
|
|
24
|
-
emitEvent<
|
|
23
|
+
emitEvent<TInfo, TData>(eventDef: ServiceEventDef<TInfo, TData>, infoSelector: (item: TInfo) => boolean, data: TData): Promise<void>;
|
|
25
24
|
generateAuthToken(payload: AuthTokenPayload<TAuthInfo>): Promise<string>;
|
|
26
25
|
verifyAuthToken(token: string): Promise<AuthTokenPayload<TAuthInfo>>;
|
|
27
26
|
private _registerGracefulShutdown;
|
|
28
27
|
}
|
|
28
|
+
export declare function createServiceServer<TAuthInfo = unknown>(options: ServiceServerOptions): ServiceServer<TAuthInfo>;
|
|
29
29
|
//# sourceMappingURL=service-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-server.d.ts","sourceRoot":"","sources":["../src/service-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"service-server.d.ts","sourceRoot":"","sources":["../src/service-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAIhE,OAAO,EAA4B,YAAY,EAAO,MAAM,uBAAuB,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAa/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAOnE,qBAAa,aAAa,CAAC,SAAS,GAAG,OAAO,CAAE,SAAQ,YAAY,CAAC;IACnE,KAAK,EAAE,IAAI,CAAC;IACZ,KAAK,EAAE,IAAI,CAAC;CACb,CAAC;IAcY,QAAQ,CAAC,OAAO,EAAE,oBAAoB;IAblD,MAAM,UAAS;IAEf,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAC9D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IAExD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkE;IACtG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA+B;IAClE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsC;IAErE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0D;IAErF,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;gBAEb,OAAO,EAAE,oBAAoB;IAY5C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAsIvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC;IAK3E,SAAS,CAAC,KAAK,EAAE,KAAK,EAC1B,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,EACvC,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,EACtC,IAAI,EAAE,KAAK;IAKP,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC;IAItD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAI1E,OAAO,CAAC,yBAAyB;CAyBlC;AAED,wBAAgB,mBAAmB,CAAC,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAAC,SAAS,CAAC,CAEhH"}
|
package/dist/service-server.js
CHANGED
|
@@ -14,7 +14,7 @@ import { UploadHandler } from "./transport/http/upload-handler.js";
|
|
|
14
14
|
import { WebSocketHandler } from "./transport/socket/websocket-handler.js";
|
|
15
15
|
import { JwtManager } from "./auth/jwt-manager.js";
|
|
16
16
|
import { handleV1Connection } from "./legacy/v1-auto-update-handler.js";
|
|
17
|
-
import {
|
|
17
|
+
import { createServiceContext } from "./core/define-service.js";
|
|
18
18
|
import consola from "consola";
|
|
19
19
|
const logger = consola.withTag("service-server:ServiceServer");
|
|
20
20
|
class ServiceServer extends EventEmitter {
|
|
@@ -91,9 +91,16 @@ class ServiceServer extends EventEmitter {
|
|
|
91
91
|
}
|
|
92
92
|
this._wsHandler.addSocket(socket, clientId, clientName, req);
|
|
93
93
|
} else {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const autoUpdateDef = this.options.services.find((s) => s.name === "AutoUpdate");
|
|
95
|
+
if (autoUpdateDef == null) {
|
|
96
|
+
socket.close(1008, "AutoUpdate service not configured");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const legacyCtx = createServiceContext(this, void 0, void 0, {});
|
|
100
|
+
const autoUpdateMethods = autoUpdateDef.factory(legacyCtx);
|
|
101
|
+
handleV1Connection(socket, autoUpdateMethods, (name) => {
|
|
102
|
+
legacyCtx.legacy = { clientName: name };
|
|
103
|
+
});
|
|
97
104
|
}
|
|
98
105
|
};
|
|
99
106
|
this.fastify.get("/", { websocket: true }, onWebSocketConnected.bind(this));
|
|
@@ -127,8 +134,8 @@ class ServiceServer extends EventEmitter {
|
|
|
127
134
|
logger.debug("\uC11C\uBC84\uB0B4 \uBAA8\uB4E0 \uD074\uB77C\uC774\uC5B8\uD2B8 RELOAD \uBA85\uB839 \uC804\uC1A1");
|
|
128
135
|
await this._wsHandler.broadcastReload(clientName, changedFileSet);
|
|
129
136
|
}
|
|
130
|
-
async emitEvent(
|
|
131
|
-
await this._wsHandler.emitToServer(
|
|
137
|
+
async emitEvent(eventDef, infoSelector, data) {
|
|
138
|
+
await this._wsHandler.emitToServer(eventDef, infoSelector, data);
|
|
132
139
|
}
|
|
133
140
|
async generateAuthToken(payload) {
|
|
134
141
|
return this._jwt.sign(payload);
|
|
@@ -159,7 +166,11 @@ class ServiceServer extends EventEmitter {
|
|
|
159
166
|
process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
|
|
160
167
|
}
|
|
161
168
|
}
|
|
169
|
+
function createServiceServer(options) {
|
|
170
|
+
return new ServiceServer(options);
|
|
171
|
+
}
|
|
162
172
|
export {
|
|
163
|
-
ServiceServer
|
|
173
|
+
ServiceServer,
|
|
174
|
+
createServiceServer
|
|
164
175
|
};
|
|
165
176
|
//# sourceMappingURL=service-server.js.map
|