@simplysm/service-server 13.0.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +587 -0
  2. package/dist/auth/auth-token-payload.js +1 -0
  3. package/dist/auth/auth-token-payload.js.map +7 -0
  4. package/dist/auth/auth.decorators.js +46 -0
  5. package/dist/auth/auth.decorators.js.map +7 -0
  6. package/dist/auth/jwt-manager.js +35 -0
  7. package/dist/auth/jwt-manager.js.map +7 -0
  8. package/dist/core/service-base.js +47 -0
  9. package/dist/core/service-base.js.map +7 -0
  10. package/dist/core/service-executor.js +46 -0
  11. package/dist/core/service-executor.js.map +7 -0
  12. package/dist/core-common/src/common.types.d.ts +74 -0
  13. package/dist/core-common/src/common.types.d.ts.map +1 -0
  14. package/dist/core-common/src/env.d.ts +6 -0
  15. package/dist/core-common/src/env.d.ts.map +1 -0
  16. package/dist/core-common/src/errors/argument-error.d.ts +25 -0
  17. package/dist/core-common/src/errors/argument-error.d.ts.map +1 -0
  18. package/dist/core-common/src/errors/not-implemented-error.d.ts +29 -0
  19. package/dist/core-common/src/errors/not-implemented-error.d.ts.map +1 -0
  20. package/dist/core-common/src/errors/sd-error.d.ts +27 -0
  21. package/dist/core-common/src/errors/sd-error.d.ts.map +1 -0
  22. package/dist/core-common/src/errors/timeout-error.d.ts +31 -0
  23. package/dist/core-common/src/errors/timeout-error.d.ts.map +1 -0
  24. package/dist/core-common/src/extensions/arr-ext.d.ts +15 -0
  25. package/dist/core-common/src/extensions/arr-ext.d.ts.map +1 -0
  26. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +19 -0
  27. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +1 -0
  28. package/dist/core-common/src/extensions/arr-ext.types.d.ts +215 -0
  29. package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +1 -0
  30. package/dist/core-common/src/extensions/map-ext.d.ts +57 -0
  31. package/dist/core-common/src/extensions/map-ext.d.ts.map +1 -0
  32. package/dist/core-common/src/extensions/set-ext.d.ts +36 -0
  33. package/dist/core-common/src/extensions/set-ext.d.ts.map +1 -0
  34. package/dist/core-common/src/features/debounce-queue.d.ts +53 -0
  35. package/dist/core-common/src/features/debounce-queue.d.ts.map +1 -0
  36. package/dist/core-common/src/features/event-emitter.d.ts +66 -0
  37. package/dist/core-common/src/features/event-emitter.d.ts.map +1 -0
  38. package/dist/core-common/src/features/serial-queue.d.ts +47 -0
  39. package/dist/core-common/src/features/serial-queue.d.ts.map +1 -0
  40. package/dist/core-common/src/index.d.ts +32 -0
  41. package/dist/core-common/src/index.d.ts.map +1 -0
  42. package/dist/core-common/src/types/date-only.d.ts +152 -0
  43. package/dist/core-common/src/types/date-only.d.ts.map +1 -0
  44. package/dist/core-common/src/types/date-time.d.ts +96 -0
  45. package/dist/core-common/src/types/date-time.d.ts.map +1 -0
  46. package/dist/core-common/src/types/lazy-gc-map.d.ts +80 -0
  47. package/dist/core-common/src/types/lazy-gc-map.d.ts.map +1 -0
  48. package/dist/core-common/src/types/time.d.ts +68 -0
  49. package/dist/core-common/src/types/time.d.ts.map +1 -0
  50. package/dist/core-common/src/types/uuid.d.ts +35 -0
  51. package/dist/core-common/src/types/uuid.d.ts.map +1 -0
  52. package/dist/core-common/src/utils/bytes.d.ts +51 -0
  53. package/dist/core-common/src/utils/bytes.d.ts.map +1 -0
  54. package/dist/core-common/src/utils/date-format.d.ts +90 -0
  55. package/dist/core-common/src/utils/date-format.d.ts.map +1 -0
  56. package/dist/core-common/src/utils/json.d.ts +34 -0
  57. package/dist/core-common/src/utils/json.d.ts.map +1 -0
  58. package/dist/core-common/src/utils/num.d.ts +60 -0
  59. package/dist/core-common/src/utils/num.d.ts.map +1 -0
  60. package/dist/core-common/src/utils/obj.d.ts +258 -0
  61. package/dist/core-common/src/utils/obj.d.ts.map +1 -0
  62. package/dist/core-common/src/utils/path.d.ts +23 -0
  63. package/dist/core-common/src/utils/path.d.ts.map +1 -0
  64. package/dist/core-common/src/utils/primitive.d.ts +18 -0
  65. package/dist/core-common/src/utils/primitive.d.ts.map +1 -0
  66. package/dist/core-common/src/utils/str.d.ts +103 -0
  67. package/dist/core-common/src/utils/str.d.ts.map +1 -0
  68. package/dist/core-common/src/utils/template-strings.d.ts +84 -0
  69. package/dist/core-common/src/utils/template-strings.d.ts.map +1 -0
  70. package/dist/core-common/src/utils/transferable.d.ts +47 -0
  71. package/dist/core-common/src/utils/transferable.d.ts.map +1 -0
  72. package/dist/core-common/src/utils/wait.d.ts +19 -0
  73. package/dist/core-common/src/utils/wait.d.ts.map +1 -0
  74. package/dist/core-common/src/utils/xml.d.ts +36 -0
  75. package/dist/core-common/src/utils/xml.d.ts.map +1 -0
  76. package/dist/core-common/src/zip/sd-zip.d.ts +80 -0
  77. package/dist/core-common/src/zip/sd-zip.d.ts.map +1 -0
  78. package/dist/core-node/src/features/fs-watcher.d.ts +70 -0
  79. package/dist/core-node/src/features/fs-watcher.d.ts.map +1 -0
  80. package/dist/core-node/src/index.d.ts +7 -0
  81. package/dist/core-node/src/index.d.ts.map +1 -0
  82. package/dist/core-node/src/utils/fs.d.ts +197 -0
  83. package/dist/core-node/src/utils/fs.d.ts.map +1 -0
  84. package/dist/core-node/src/utils/path.d.ts +75 -0
  85. package/dist/core-node/src/utils/path.d.ts.map +1 -0
  86. package/dist/core-node/src/worker/create-worker.d.ts +23 -0
  87. package/dist/core-node/src/worker/create-worker.d.ts.map +1 -0
  88. package/dist/core-node/src/worker/types.d.ts +67 -0
  89. package/dist/core-node/src/worker/types.d.ts.map +1 -0
  90. package/dist/core-node/src/worker/worker.d.ts +27 -0
  91. package/dist/core-node/src/worker/worker.d.ts.map +1 -0
  92. package/dist/index.js +20 -0
  93. package/dist/index.js.map +7 -0
  94. package/dist/legacy/v1-auto-update-handler.js +38 -0
  95. package/dist/legacy/v1-auto-update-handler.js.map +7 -0
  96. package/dist/orm-common/src/db-context.d.ts +669 -0
  97. package/dist/orm-common/src/db-context.d.ts.map +1 -0
  98. package/dist/orm-common/src/errors/db-transaction-error.d.ts +51 -0
  99. package/dist/orm-common/src/errors/db-transaction-error.d.ts.map +1 -0
  100. package/dist/orm-common/src/exec/executable.d.ts +79 -0
  101. package/dist/orm-common/src/exec/executable.d.ts.map +1 -0
  102. package/dist/orm-common/src/exec/queryable.d.ts +708 -0
  103. package/dist/orm-common/src/exec/queryable.d.ts.map +1 -0
  104. package/dist/orm-common/src/exec/search-parser.d.ts +72 -0
  105. package/dist/orm-common/src/exec/search-parser.d.ts.map +1 -0
  106. package/dist/orm-common/src/expr/expr-unit.d.ts +25 -0
  107. package/dist/orm-common/src/expr/expr-unit.d.ts.map +1 -0
  108. package/dist/orm-common/src/expr/expr.d.ts +1369 -0
  109. package/dist/orm-common/src/expr/expr.d.ts.map +1 -0
  110. package/dist/orm-common/src/index.d.ts +32 -0
  111. package/dist/orm-common/src/index.d.ts.map +1 -0
  112. package/dist/orm-common/src/models/system-migration.d.ts +10 -0
  113. package/dist/orm-common/src/models/system-migration.d.ts.map +1 -0
  114. package/dist/orm-common/src/query-builder/base/expr-renderer-base.d.ts +95 -0
  115. package/dist/orm-common/src/query-builder/base/expr-renderer-base.d.ts.map +1 -0
  116. package/dist/orm-common/src/query-builder/base/query-builder-base.d.ts +66 -0
  117. package/dist/orm-common/src/query-builder/base/query-builder-base.d.ts.map +1 -0
  118. package/dist/orm-common/src/query-builder/mssql/mssql-expr-renderer.d.ts +84 -0
  119. package/dist/orm-common/src/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -0
  120. package/dist/orm-common/src/query-builder/mssql/mssql-query-builder.d.ts +45 -0
  121. package/dist/orm-common/src/query-builder/mssql/mssql-query-builder.d.ts.map +1 -0
  122. package/dist/orm-common/src/query-builder/mysql/mysql-expr-renderer.d.ts +84 -0
  123. package/dist/orm-common/src/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -0
  124. package/dist/orm-common/src/query-builder/mysql/mysql-query-builder.d.ts +54 -0
  125. package/dist/orm-common/src/query-builder/mysql/mysql-query-builder.d.ts.map +1 -0
  126. package/dist/orm-common/src/query-builder/postgresql/postgresql-expr-renderer.d.ts +84 -0
  127. package/dist/orm-common/src/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -0
  128. package/dist/orm-common/src/query-builder/postgresql/postgresql-query-builder.d.ts +52 -0
  129. package/dist/orm-common/src/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -0
  130. package/dist/orm-common/src/query-builder/query-builder.d.ts +7 -0
  131. package/dist/orm-common/src/query-builder/query-builder.d.ts.map +1 -0
  132. package/dist/orm-common/src/schema/factory/column-builder.d.ts +394 -0
  133. package/dist/orm-common/src/schema/factory/column-builder.d.ts.map +1 -0
  134. package/dist/orm-common/src/schema/factory/index-builder.d.ts +151 -0
  135. package/dist/orm-common/src/schema/factory/index-builder.d.ts.map +1 -0
  136. package/dist/orm-common/src/schema/factory/relation-builder.d.ts +337 -0
  137. package/dist/orm-common/src/schema/factory/relation-builder.d.ts.map +1 -0
  138. package/dist/orm-common/src/schema/procedure-builder.d.ts +202 -0
  139. package/dist/orm-common/src/schema/procedure-builder.d.ts.map +1 -0
  140. package/dist/orm-common/src/schema/table-builder.d.ts +259 -0
  141. package/dist/orm-common/src/schema/table-builder.d.ts.map +1 -0
  142. package/dist/orm-common/src/schema/view-builder.d.ts +183 -0
  143. package/dist/orm-common/src/schema/view-builder.d.ts.map +1 -0
  144. package/dist/orm-common/src/types/column.d.ts +172 -0
  145. package/dist/orm-common/src/types/column.d.ts.map +1 -0
  146. package/dist/orm-common/src/types/db.d.ts +175 -0
  147. package/dist/orm-common/src/types/db.d.ts.map +1 -0
  148. package/dist/orm-common/src/types/expr.d.ts +474 -0
  149. package/dist/orm-common/src/types/expr.d.ts.map +1 -0
  150. package/dist/orm-common/src/types/query-def.d.ts +351 -0
  151. package/dist/orm-common/src/types/query-def.d.ts.map +1 -0
  152. package/dist/orm-common/src/utils/result-parser.d.ts +38 -0
  153. package/dist/orm-common/src/utils/result-parser.d.ts.map +1 -0
  154. package/dist/orm-node/src/connections/mssql-db-conn.d.ts +44 -0
  155. package/dist/orm-node/src/connections/mssql-db-conn.d.ts.map +1 -0
  156. package/dist/orm-node/src/connections/mysql-db-conn.d.ts +38 -0
  157. package/dist/orm-node/src/connections/mysql-db-conn.d.ts.map +1 -0
  158. package/dist/orm-node/src/connections/postgresql-db-conn.d.ts +39 -0
  159. package/dist/orm-node/src/connections/postgresql-db-conn.d.ts.map +1 -0
  160. package/dist/orm-node/src/db-conn-factory.d.ts +25 -0
  161. package/dist/orm-node/src/db-conn-factory.d.ts.map +1 -0
  162. package/dist/orm-node/src/index.d.ts +9 -0
  163. package/dist/orm-node/src/index.d.ts.map +1 -0
  164. package/dist/orm-node/src/node-db-context-executor.d.ts +77 -0
  165. package/dist/orm-node/src/node-db-context-executor.d.ts.map +1 -0
  166. package/dist/orm-node/src/pooled-db-conn.d.ts +79 -0
  167. package/dist/orm-node/src/pooled-db-conn.d.ts.map +1 -0
  168. package/dist/orm-node/src/sd-orm.d.ts +78 -0
  169. package/dist/orm-node/src/sd-orm.d.ts.map +1 -0
  170. package/dist/orm-node/src/types/db-conn.d.ts +159 -0
  171. package/dist/orm-node/src/types/db-conn.d.ts.map +1 -0
  172. package/dist/protocol/protocol-wrapper.js +64 -0
  173. package/dist/protocol/protocol-wrapper.js.map +7 -0
  174. package/dist/service-common/src/index.d.ts +8 -0
  175. package/dist/service-common/src/index.d.ts.map +1 -0
  176. package/dist/service-common/src/protocol/protocol.types.d.ts +100 -0
  177. package/dist/service-common/src/protocol/protocol.types.d.ts.map +1 -0
  178. package/dist/service-common/src/protocol/service-protocol.d.ts +63 -0
  179. package/dist/service-common/src/protocol/service-protocol.d.ts.map +1 -0
  180. package/dist/service-common/src/service-types/auto-update-service.types.d.ts +17 -0
  181. package/dist/service-common/src/service-types/auto-update-service.types.d.ts.map +1 -0
  182. package/dist/service-common/src/service-types/crypto-service.types.d.ts +22 -0
  183. package/dist/service-common/src/service-types/crypto-service.types.d.ts.map +1 -0
  184. package/dist/service-common/src/service-types/orm-service.types.d.ts +30 -0
  185. package/dist/service-common/src/service-types/orm-service.types.d.ts.map +1 -0
  186. package/dist/service-common/src/service-types/smtp-service.types.d.ts +55 -0
  187. package/dist/service-common/src/service-types/smtp-service.types.d.ts.map +1 -0
  188. package/dist/service-common/src/types.d.ts +43 -0
  189. package/dist/service-common/src/types.d.ts.map +1 -0
  190. package/dist/service-server/src/auth/auth-token-payload.d.ts +6 -0
  191. package/dist/service-server/src/auth/auth-token-payload.d.ts.map +1 -0
  192. package/dist/service-server/src/auth/auth.decorators.d.ts +19 -0
  193. package/dist/service-server/src/auth/auth.decorators.d.ts.map +1 -0
  194. package/dist/service-server/src/auth/jwt-manager.d.ts +10 -0
  195. package/dist/service-server/src/auth/jwt-manager.d.ts.map +1 -0
  196. package/dist/service-server/src/core/service-base.d.ts +19 -0
  197. package/dist/service-server/src/core/service-base.d.ts.map +1 -0
  198. package/dist/service-server/src/core/service-executor.d.ts +18 -0
  199. package/dist/service-server/src/core/service-executor.d.ts.map +1 -0
  200. package/dist/service-server/src/index.d.ts +20 -0
  201. package/dist/service-server/src/index.d.ts.map +1 -0
  202. package/dist/service-server/src/legacy/v1-auto-update-handler.d.ts +8 -0
  203. package/dist/service-server/src/legacy/v1-auto-update-handler.d.ts.map +1 -0
  204. package/dist/service-server/src/protocol/protocol-wrapper.d.ts +25 -0
  205. package/dist/service-server/src/protocol/protocol-wrapper.d.ts.map +1 -0
  206. package/dist/service-server/src/service-server.d.ts +29 -0
  207. package/dist/service-server/src/service-server.d.ts.map +1 -0
  208. package/dist/service-server/src/services/auto-update-service.d.ts +9 -0
  209. package/dist/service-server/src/services/auto-update-service.d.ts.map +1 -0
  210. package/dist/service-server/src/services/crypto-service.d.ts +10 -0
  211. package/dist/service-server/src/services/crypto-service.d.ts.map +1 -0
  212. package/dist/service-server/src/services/orm-service.d.ts +28 -0
  213. package/dist/service-server/src/services/orm-service.d.ts.map +1 -0
  214. package/dist/service-server/src/services/smtp-service.d.ts +7 -0
  215. package/dist/service-server/src/services/smtp-service.d.ts.map +1 -0
  216. package/dist/service-server/src/transport/http/http-request-handler.d.ts +12 -0
  217. package/dist/service-server/src/transport/http/http-request-handler.d.ts.map +1 -0
  218. package/dist/service-server/src/transport/http/static-file-handler.d.ts +9 -0
  219. package/dist/service-server/src/transport/http/static-file-handler.d.ts.map +1 -0
  220. package/dist/service-server/src/transport/http/upload-handler.d.ts +10 -0
  221. package/dist/service-server/src/transport/http/upload-handler.d.ts.map +1 -0
  222. package/dist/service-server/src/transport/socket/service-socket.d.ts +41 -0
  223. package/dist/service-server/src/transport/socket/service-socket.d.ts.map +1 -0
  224. package/dist/service-server/src/transport/socket/websocket-handler.d.ts +18 -0
  225. package/dist/service-server/src/transport/socket/websocket-handler.d.ts.map +1 -0
  226. package/dist/service-server/src/types/server-options.d.ts +15 -0
  227. package/dist/service-server/src/types/server-options.d.ts.map +1 -0
  228. package/dist/service-server/src/utils/config-manager.d.ts +7 -0
  229. package/dist/service-server/src/utils/config-manager.d.ts.map +1 -0
  230. package/dist/service-server/src/workers/service-protocol.worker.d.ts +15 -0
  231. package/dist/service-server/src/workers/service-protocol.worker.d.ts.map +1 -0
  232. package/dist/service-server.js +165 -0
  233. package/dist/service-server.js.map +7 -0
  234. package/dist/services/auto-update-service.js +39 -0
  235. package/dist/services/auto-update-service.js.map +7 -0
  236. package/dist/services/crypto-service.js +32 -0
  237. package/dist/services/crypto-service.js.map +7 -0
  238. package/dist/services/orm-service.js +186 -0
  239. package/dist/services/orm-service.js.map +7 -0
  240. package/dist/services/smtp-service.js +47 -0
  241. package/dist/services/smtp-service.js.map +7 -0
  242. package/dist/transport/http/http-request-handler.js +57 -0
  243. package/dist/transport/http/http-request-handler.js.map +7 -0
  244. package/dist/transport/http/static-file-handler.js +57 -0
  245. package/dist/transport/http/static-file-handler.js.map +7 -0
  246. package/dist/transport/http/upload-handler.js +71 -0
  247. package/dist/transport/http/upload-handler.js.map +7 -0
  248. package/dist/transport/socket/service-socket.js +105 -0
  249. package/dist/transport/socket/service-socket.js.map +7 -0
  250. package/dist/transport/socket/websocket-handler.js +144 -0
  251. package/dist/transport/socket/websocket-handler.js.map +7 -0
  252. package/dist/types/server-options.js +1 -0
  253. package/dist/types/server-options.js.map +7 -0
  254. package/dist/utils/config-manager.js +62 -0
  255. package/dist/utils/config-manager.js.map +7 -0
  256. package/dist/workers/service-protocol.worker.js +15 -0
  257. package/dist/workers/service-protocol.worker.js.map +7 -0
  258. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,587 @@
1
+ # @simplysm/service-server
2
+
3
+ A Fastify-based HTTP/WebSocket server package. Provides server features needed for full-stack applications, including RPC-style service invocation, JWT authentication, file upload, static file serving, and real-time events.
4
+
5
+ Used together with `@simplysm/service-client` to configure WebSocket/HTTP communication between client and server.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @simplysm/service-server
11
+ # or
12
+ pnpm add @simplysm/service-server
13
+ ```
14
+
15
+ ## Main Modules
16
+
17
+ ### Core Classes
18
+
19
+ | Module | Path | Description |
20
+ |------|------|------|
21
+ | `ServiceServer` | `service-server.ts` | Main server class. Creates Fastify instance and configures routes/plugins |
22
+ | `ServiceBase` | `core/service-base.ts` | Service base abstract class. All custom services must inherit from this |
23
+ | `ServiceExecutor` | `core/service-executor.ts` | Internal executor that handles service method discovery, auth checks, and execution |
24
+
25
+ ### Authentication
26
+
27
+ | Module | Path | Description |
28
+ |------|------|------|
29
+ | `JwtManager` | `auth/jwt-manager.ts` | JWT token generation/verification/decoding based on jose library (HS256, 12-hour expiration) |
30
+ | `Authorize` | `auth/auth.decorators.ts` | Stage 3 decorator. Sets authentication permissions at class or method level |
31
+ | `AuthTokenPayload` | `auth/auth-token-payload.ts` | JWT payload interface (includes `roles`, `data`) |
32
+
33
+ ### Transport Layer - WebSocket
34
+
35
+ | Module | Path | Description |
36
+ |------|------|------|
37
+ | `WebSocketHandler` | `transport/socket/websocket-handler.ts` | Handles WebSocket connection management, message routing, and event distribution |
38
+ | `ServiceSocket` | `transport/socket/service-socket.ts` | Wraps individual WebSocket connections. Manages ping/pong, protocol encoding/decoding, event listener management |
39
+
40
+ ### Transport Layer - HTTP
41
+
42
+ | Module | Path | Description |
43
+ |------|------|------|
44
+ | `HttpRequestHandler` | `transport/http/http-request-handler.ts` | Calls service methods via HTTP at `/api/:service/:method` route |
45
+ | `UploadHandler` | `transport/http/upload-handler.ts` | Handles multipart file upload at `/upload` route (auth required) |
46
+ | `StaticFileHandler` | `transport/http/static-file-handler.ts` | Serves static files. Prevents path traversal and blocks hidden files |
47
+
48
+ ### Protocol
49
+
50
+ | Module | Path | Description |
51
+ |------|------|------|
52
+ | `ProtocolWrapper` | `protocol/protocol-wrapper.ts` | Message encoding/decoding wrapper. Messages over 30KB are processed in worker threads |
53
+
54
+ ### Built-in Services
55
+
56
+ | Module | Path | Description |
57
+ |------|------|------|
58
+ | `OrmService` | `services/orm-service.ts` | DB connection/transaction/query execution (WebSocket only, auth required) |
59
+ | `CryptoService` | `services/crypto-service.ts` | SHA256 hash and AES-256-CBC encryption/decryption |
60
+ | `SmtpService` | `services/smtp-service.ts` | nodemailer-based email sending |
61
+ | `AutoUpdateService` | `services/auto-update-service.ts` | App auto-update (provides latest version query and download path) |
62
+
63
+ ### Utilities
64
+
65
+ | Module | Path | Description |
66
+ |------|------|------|
67
+ | `ConfigManager` | `utils/config-manager.ts` | JSON config file loading/caching/real-time monitoring (auto expiration based on LazyGcMap) |
68
+
69
+ ### Legacy
70
+
71
+ | Module | Path | Description |
72
+ |------|------|------|
73
+ | `handleV1Connection` | `legacy/v1-auto-update-handler.ts` | V1 protocol client compatibility handling (supports auto-update only) |
74
+
75
+ ## Usage
76
+
77
+ ### Basic Server Configuration
78
+
79
+ ```typescript
80
+ import { ServiceServer } from "@simplysm/service-server";
81
+
82
+ const server = new ServiceServer({
83
+ port: 8080,
84
+ rootPath: "/app/data",
85
+ services: [MyService],
86
+ });
87
+
88
+ // Start server
89
+ await server.listen();
90
+
91
+ // Receive events
92
+ server.on("ready", () => {
93
+ console.log("Server ready");
94
+ });
95
+
96
+ server.on("close", () => {
97
+ console.log("Server closed");
98
+ });
99
+
100
+ // Close server
101
+ await server.close();
102
+ ```
103
+
104
+ ### Server Options (`ServiceServerOptions`)
105
+
106
+ ```typescript
107
+ interface ServiceServerOptions {
108
+ /** Server root path (base directory for static files and config files) */
109
+ rootPath: string;
110
+ /** Listen port */
111
+ port: number;
112
+ /** SSL/TLS config (enables HTTPS) */
113
+ ssl?: {
114
+ pfxBytes: Uint8Array;
115
+ passphrase: string;
116
+ };
117
+ /** JWT authentication config */
118
+ auth?: {
119
+ jwtSecret: string;
120
+ };
121
+ /** List of service classes to register */
122
+ services: Type<ServiceBase>[];
123
+ }
124
+ ```
125
+
126
+ The following structure is expected under `rootPath`:
127
+
128
+ ```
129
+ rootPath/
130
+ .config.json # Root config file
131
+ www/ # Static file root
132
+ uploads/ # Upload file storage directory
133
+ {clientName}/ # Per-client directory
134
+ .config.json # Per-client config file
135
+ index.html
136
+ ```
137
+
138
+ ### SSL/HTTPS Server
139
+
140
+ ```typescript
141
+ import { fsReadFile } from "@simplysm/core-node";
142
+
143
+ const pfxBytes = await fsReadFile("/path/to/cert.pfx");
144
+
145
+ const server = new ServiceServer({
146
+ port: 443,
147
+ rootPath: "/app/data",
148
+ ssl: {
149
+ pfxBytes,
150
+ passphrase: "certificate-password",
151
+ },
152
+ auth: { jwtSecret: "my-secret-key" },
153
+ services: [],
154
+ });
155
+
156
+ await server.listen();
157
+ ```
158
+
159
+ ### Custom Service Definition
160
+
161
+ Define services by inheriting from `ServiceBase`. Service methods are called via RPC from the client.
162
+
163
+ ```typescript
164
+ import { ServiceBase } from "@simplysm/service-server";
165
+
166
+ class MyService extends ServiceBase {
167
+ async hello(name: string): Promise<string> {
168
+ return `Hello, ${name}!`;
169
+ }
170
+
171
+ async getServerTime(): Promise<Date> {
172
+ return new Date();
173
+ }
174
+ }
175
+ ```
176
+
177
+ Context accessible within services:
178
+
179
+ | Property | Type | Description |
180
+ |------|------|------|
181
+ | `this.server` | `ServiceServer` | Server instance reference |
182
+ | `this.socket` | `ServiceSocket \| undefined` | WebSocket connection (`undefined` for HTTP calls) |
183
+ | `this.http` | `{ clientName, authTokenPayload? }` | HTTP request context |
184
+ | `this.authInfo` | `TAuthInfo \| undefined` | Authenticated user info |
185
+ | `this.clientName` | `string \| undefined` | Client app name |
186
+ | `this.clientPath` | `string \| undefined` | Per-client directory path |
187
+
188
+ ### Config File Reference
189
+
190
+ Read sections from `.config.json` files using `ServiceBase.getConfig()`. Root and per-client configs are automatically merged.
191
+
192
+ ```typescript
193
+ class MyService extends ServiceBase {
194
+ async getDbHost(): Promise<string> {
195
+ // Read "mySection" key from rootPath/.config.json or clientPath/.config.json
196
+ const config = await this.getConfig<{ host: string }>("mySection");
197
+ return config.host;
198
+ }
199
+ }
200
+ ```
201
+
202
+ `.config.json` example:
203
+
204
+ ```json
205
+ {
206
+ "mySection": {
207
+ "host": "localhost"
208
+ },
209
+ "orm": {
210
+ "default": {
211
+ "dialect": "mysql",
212
+ "host": "localhost",
213
+ "port": 3306,
214
+ "database": "mydb",
215
+ "user": "root",
216
+ "password": "password"
217
+ }
218
+ }
219
+ }
220
+ ```
221
+
222
+ `ConfigManager` caches config files and automatically refreshes the cache on file changes (LazyGcMap-based, auto expires after 1 hour).
223
+
224
+ ### Authentication (`Authorize` Decorator)
225
+
226
+ Use Stage 3 decorators to set authentication requirements on services or methods. Only works when `ServiceServerOptions.auth` is configured.
227
+
228
+ ```typescript
229
+ import { ServiceBase, Authorize } from "@simplysm/service-server";
230
+
231
+ // Class level: all methods require login
232
+ @Authorize()
233
+ class UserService extends ServiceBase<{ userId: number; role: string }> {
234
+ // Login only required (inherits from class level)
235
+ async getProfile(): Promise<unknown> {
236
+ const userId = this.authInfo?.userId;
237
+ // ...
238
+ }
239
+
240
+ // Method level: specific role required (overrides class level)
241
+ @Authorize(["admin"])
242
+ async deleteUser(targetId: number): Promise<void> {
243
+ // Only users with admin role can call
244
+ }
245
+ }
246
+
247
+ // No authentication required (no decorator)
248
+ class PublicService extends ServiceBase {
249
+ async healthCheck(): Promise<string> {
250
+ return "OK";
251
+ }
252
+ }
253
+ ```
254
+
255
+ Decorator behavior:
256
+
257
+ | Target | `@Authorize()` | `@Authorize(["admin"])` |
258
+ |-----------|----------------|-------------------------|
259
+ | Class | All methods require login | All methods require admin role |
260
+ | Method | Method requires login | Method requires admin role |
261
+ | None | No auth required (Public) | - |
262
+
263
+ Method-level decorators override class-level settings.
264
+
265
+ ### JWT Token Management
266
+
267
+ Generate and verify JWT tokens through the `ServiceServer` instance.
268
+
269
+ ```typescript
270
+ // Generate token (12-hour expiration, HS256 algorithm)
271
+ const token = await server.generateAuthToken({
272
+ roles: ["admin", "user"],
273
+ data: { userId: 1, name: "홍길동" },
274
+ });
275
+
276
+ // Verify token
277
+ const payload = await server.verifyAuthToken(token);
278
+ // payload.roles: ["admin", "user"]
279
+ // payload.data: { userId: 1, name: "홍길동" }
280
+ ```
281
+
282
+ `AuthTokenPayload` interface:
283
+
284
+ ```typescript
285
+ interface AuthTokenPayload<TAuthInfo = unknown> extends JWTPayload {
286
+ /** User role list (used for permission check in Authorize decorator) */
287
+ roles: string[];
288
+ /** Custom auth info (generic type) */
289
+ data: TAuthInfo;
290
+ }
291
+ ```
292
+
293
+ ### HTTP API Call
294
+
295
+ Service methods can also be called via HTTP through the `/api/:service/:method` path.
296
+
297
+ **GET Request:**
298
+
299
+ ```
300
+ GET /api/MyService/hello?json=["World"]
301
+ Header: x-sd-client-name: my-app
302
+ Header: Authorization: Bearer <token> (optional)
303
+ ```
304
+
305
+ **POST Request:**
306
+
307
+ ```
308
+ POST /api/MyService/hello
309
+ Header: Content-Type: application/json
310
+ Header: x-sd-client-name: my-app
311
+ Header: Authorization: Bearer <token> (optional)
312
+ Body: ["World"]
313
+ ```
314
+
315
+ - The `x-sd-client-name` header is required.
316
+ - Parameters are passed in array form (in the order of method arguments).
317
+ - For GET requests, pass a JSON-serialized array in the `json` query parameter.
318
+
319
+ ### File Upload
320
+
321
+ Upload files via multipart request to the `/upload` endpoint. Auth token is required.
322
+
323
+ ```typescript
324
+ // Client-side example
325
+ const formData = new FormData();
326
+ formData.append("file", file);
327
+
328
+ const response = await fetch("/upload", {
329
+ method: "POST",
330
+ headers: {
331
+ Authorization: `Bearer ${token}`,
332
+ },
333
+ body: formData,
334
+ });
335
+
336
+ // Response: ServiceUploadResult[]
337
+ const results = await response.json();
338
+ // [{ path: "uploads/uuid.ext", filename: "original-filename.ext", size: 12345 }]
339
+ ```
340
+
341
+ Uploaded files are stored in the `rootPath/www/uploads/` directory with UUID-based filenames.
342
+
343
+ ### Real-time Event Publishing
344
+
345
+ Publish events to connected clients from the server.
346
+
347
+ ```typescript
348
+ import { ServiceEventListener } from "@simplysm/service-common";
349
+
350
+ // Event definition (from service-common)
351
+ class OrderUpdatedEvent extends ServiceEventListener<
352
+ { orderId: number },
353
+ { status: string }
354
+ > {
355
+ readonly eventName = "OrderUpdatedEvent";
356
+ }
357
+
358
+ // Publish event from server
359
+ await server.emitEvent(
360
+ OrderUpdatedEvent,
361
+ (info) => info.orderId === 123, // Target filter
362
+ { status: "completed" }, // Data to send
363
+ );
364
+
365
+ // Send reload command to all clients
366
+ await server.broadcastReload("my-app", new Set(["main.js"]));
367
+ ```
368
+
369
+ ### Built-in Service: OrmService
370
+
371
+ Provides database connection/query/transaction via WebSocket. `@Authorize()` decorator is applied, requiring login.
372
+
373
+ ```typescript
374
+ const server = new ServiceServer({
375
+ port: 8080,
376
+ rootPath: "/app/data",
377
+ auth: { jwtSecret: "secret" },
378
+ services: [OrmService],
379
+ });
380
+ ```
381
+
382
+ Define ORM config in `.config.json`:
383
+
384
+ ```json
385
+ {
386
+ "orm": {
387
+ "default": {
388
+ "dialect": "mysql",
389
+ "host": "localhost",
390
+ "port": 3306,
391
+ "database": "mydb",
392
+ "user": "root",
393
+ "password": "password"
394
+ }
395
+ }
396
+ }
397
+ ```
398
+
399
+ Methods provided by `OrmService`:
400
+
401
+ | Method | Description |
402
+ |--------|------|
403
+ | `getInfo(opt)` | Query DB connection info (dialect, database, schema) |
404
+ | `connect(opt)` | Create DB connection. Returns connection ID |
405
+ | `close(connId)` | Close DB connection |
406
+ | `beginTransaction(connId, isolationLevel?)` | Begin transaction |
407
+ | `commitTransaction(connId)` | Commit transaction |
408
+ | `rollbackTransaction(connId)` | Rollback transaction |
409
+ | `executeParametrized(connId, query, params?)` | Execute parameterized query |
410
+ | `executeDefs(connId, defs, options?)` | Execute QueryDef-based queries |
411
+ | `bulkInsert(connId, tableName, columnDefs, records)` | Bulk INSERT |
412
+
413
+ When a WebSocket connection is closed, all DB connections opened from that socket are automatically cleaned up.
414
+
415
+ ### Built-in Service: CryptoService
416
+
417
+ Provides SHA256 hash and AES-256-CBC symmetric key encryption/decryption.
418
+
419
+ ```typescript
420
+ const server = new ServiceServer({
421
+ port: 8080,
422
+ rootPath: "/app/data",
423
+ services: [CryptoService],
424
+ });
425
+ ```
426
+
427
+ `.config.json` config:
428
+
429
+ ```json
430
+ {
431
+ "crypto": {
432
+ "key": "your-32-byte-secret-key-here!!"
433
+ }
434
+ }
435
+ ```
436
+
437
+ | Method | Description |
438
+ |--------|------|
439
+ | `encrypt(data)` | Generate SHA256 HMAC hash (one-way) |
440
+ | `encryptAes(data)` | AES-256-CBC encryption. Returns hex string in `iv:encrypted` format |
441
+ | `decryptAes(encText)` | AES-256-CBC decryption. Returns original binary |
442
+
443
+ ### Built-in Service: SmtpService
444
+
445
+ A nodemailer-based email sending service. Can pass SMTP config directly or reference server config file.
446
+
447
+ ```typescript
448
+ const server = new ServiceServer({
449
+ port: 8080,
450
+ rootPath: "/app/data",
451
+ services: [SmtpService],
452
+ });
453
+ ```
454
+
455
+ `.config.json` config (when using config reference method):
456
+
457
+ ```json
458
+ {
459
+ "smtp": {
460
+ "default": {
461
+ "host": "smtp.example.com",
462
+ "port": 587,
463
+ "secure": false,
464
+ "user": "user@example.com",
465
+ "pass": "password",
466
+ "senderName": "My App",
467
+ "senderEmail": "noreply@example.com"
468
+ }
469
+ }
470
+ }
471
+ ```
472
+
473
+ | Method | Description |
474
+ |--------|------|
475
+ | `send(options)` | Send email by directly passing SMTP config |
476
+ | `sendByConfig(configName, options)` | Send email by referencing SMTP config in config file |
477
+
478
+ `send()` options:
479
+
480
+ ```typescript
481
+ interface SmtpSendOption {
482
+ host: string;
483
+ port?: number;
484
+ secure?: boolean;
485
+ user?: string;
486
+ pass?: string;
487
+ from: string;
488
+ to: string;
489
+ cc?: string;
490
+ bcc?: string;
491
+ subject: string;
492
+ html: string;
493
+ attachments?: SmtpSendAttachment[];
494
+ }
495
+ ```
496
+
497
+ ### Built-in Service: AutoUpdateService
498
+
499
+ Supports auto-update for client apps. Searches for latest version files by platform in the client directory.
500
+
501
+ ```typescript
502
+ const server = new ServiceServer({
503
+ port: 8080,
504
+ rootPath: "/app/data",
505
+ services: [AutoUpdateService],
506
+ });
507
+ ```
508
+
509
+ Update file structure:
510
+
511
+ ```
512
+ rootPath/www/{clientName}/{platform}/updates/
513
+ 1.0.0.exe (Windows)
514
+ 1.0.1.exe
515
+ 1.0.0.apk (Android)
516
+ 1.0.1.apk
517
+ ```
518
+
519
+ | Method | Description |
520
+ |--------|------|
521
+ | `getLastVersion(platform)` | Returns latest version and download path for the platform. Returns `undefined` if no update |
522
+
523
+ Return value:
524
+
525
+ ```typescript
526
+ {
527
+ version: string; // e.g., "1.0.1"
528
+ downloadPath: string; // e.g., "/my-app/android/updates/1.0.1.apk"
529
+ }
530
+ ```
531
+
532
+ ### ConfigManager
533
+
534
+ A static utility class that manages loading, caching, and real-time monitoring of JSON config files. Used internally by `ServiceBase.getConfig()`.
535
+
536
+ ```typescript
537
+ import { ConfigManager } from "@simplysm/service-server";
538
+
539
+ const config = await ConfigManager.getConfig<MyConfig>("/path/to/.config.json");
540
+ ```
541
+
542
+ Behavior:
543
+ - Caches file in `LazyGcMap` on first load.
544
+ - Registers file change watch (`FsWatcher`) to auto-refresh cache on changes.
545
+ - Cache auto-expires after 1 hour of no access, and associated watch is released.
546
+
547
+ ### ProtocolWrapper
548
+
549
+ Handles encoding/decoding of WebSocket messages. Automatically branches between main thread and worker thread based on message size.
550
+
551
+ | Condition | Processing Method |
552
+ |------|-----------|
553
+ | 30KB or less | Processed directly in main thread |
554
+ | Over 30KB | Processed in worker thread (max 4GB memory allocation) |
555
+
556
+ Messages containing large binary data (Uint8Array) also branch to worker thread.
557
+
558
+ ## Server Route Structure
559
+
560
+ The following routes are automatically registered when `ServiceServer.listen()` is called:
561
+
562
+ | Route | Method | Description |
563
+ |--------|--------|------|
564
+ | `/api/:service/:method` | GET, POST | Service method call via HTTP |
565
+ | `/upload` | POST | Multipart file upload (auth required) |
566
+ | `/` | WebSocket | WebSocket connection endpoint |
567
+ | `/ws` | WebSocket | WebSocket connection endpoint (alias) |
568
+ | `/*` | GET, etc. | Static file serving (based on `rootPath/www/`) |
569
+
570
+ ## Security
571
+
572
+ - **Helmet**: `@fastify/helmet` plugin automatically sets security headers like CSP, HSTS.
573
+ - **CORS**: `@fastify/cors` plugin configures CORS.
574
+ - **Path Traversal Prevention**: Static file handler and client name validation block `..`, `/`, `\` characters.
575
+ - **Hidden File Blocking**: Files starting with `.` return a 403 response.
576
+ - **Graceful Shutdown**: Detects `SIGINT`/`SIGTERM` signals to safely close open WebSocket connections and server (10-second timeout).
577
+
578
+ ## Caveats
579
+
580
+ - `OrmService` is WebSocket-only. Cannot be used via HTTP requests.
581
+ - Config files (`.config.json`) contain sensitive information (DB passwords, JWT secrets, etc.), so hidden files (starting with `.`) are automatically blocked by the static file handler.
582
+ - WebSocket connection requires query parameters `ver=2`, `clientId`, `clientName`. Without these parameters, it operates in V1 legacy mode.
583
+ - If SSL is not configured, the `upgrade-insecure-requests` CSP directive is disabled.
584
+
585
+ ## License
586
+
587
+ Apache-2.0
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=auth-token-payload.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,46 @@
1
+ const classAuthMap = /* @__PURE__ */ new WeakMap();
2
+ const methodAuthMap = /* @__PURE__ */ new WeakMap();
3
+ const pendingMethodAuth = /* @__PURE__ */ new Map();
4
+ function Authorize(permissions = []) {
5
+ return function(target, context) {
6
+ if (context.kind === "class") {
7
+ classAuthMap.set(target, permissions);
8
+ const className = context.name ?? "";
9
+ const pending = pendingMethodAuth.get(className);
10
+ if (pending != null) {
11
+ let methodMap = methodAuthMap.get(target);
12
+ if (methodMap == null) {
13
+ methodMap = /* @__PURE__ */ new Map();
14
+ methodAuthMap.set(target, methodMap);
15
+ }
16
+ for (const { permissions: perms, methodName } of pending) {
17
+ methodMap.set(methodName, perms);
18
+ }
19
+ pendingMethodAuth.delete(className);
20
+ }
21
+ } else {
22
+ const methodName = String(context.name);
23
+ context.addInitializer(function() {
24
+ const ctor = this.constructor;
25
+ let methodMap = methodAuthMap.get(ctor);
26
+ if (methodMap == null) {
27
+ methodMap = /* @__PURE__ */ new Map();
28
+ methodAuthMap.set(ctor, methodMap);
29
+ }
30
+ methodMap.set(methodName, permissions);
31
+ });
32
+ }
33
+ };
34
+ }
35
+ function getAuthPermissions(ctor, methodName) {
36
+ if (methodName != null) {
37
+ const perms = methodAuthMap.get(ctor)?.get(methodName);
38
+ if (perms != null) return perms;
39
+ }
40
+ return classAuthMap.get(ctor);
41
+ }
42
+ export {
43
+ Authorize,
44
+ getAuthPermissions
45
+ };
46
+ //# sourceMappingURL=auth.decorators.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/auth/auth.decorators.ts"],
4
+ "sourcesContent": ["// WeakMap \uAE30\uBC18 \uBA54\uD0C0\uB370\uC774\uD130 \uC800\uC7A5 (reflect-metadata \uBBF8\uC0AC\uC6A9)\nconst classAuthMap = new WeakMap<Function, string[]>();\nconst methodAuthMap = new WeakMap<Function, Map<string, string[]>>();\n\n// \uBA54\uC18C\uB4DC \uB370\uCF54\uB808\uC774\uD130\uC5D0\uC11C \uD074\uB798\uC2A4 \uC0DD\uC131\uC790\uB97C \uB098\uC911\uC5D0 \uC5F0\uACB0\uD558\uAE30 \uC704\uD55C \uC784\uC2DC \uC800\uC7A5\uC18C\nconst pendingMethodAuth = new Map<string, { permissions: string[]; methodName: string }[]>();\n\n/**\n * \uC778\uC99D \uAD8C\uD55C\uC744 \uC124\uC815\uD558\uB294 \uB370\uCF54\uB808\uC774\uD130 (Stage 3 Decorators)\n * - \uD074\uB798\uC2A4 \uB808\uBCA8: \uBAA8\uB4E0 \uBA54\uC18C\uB4DC\uC5D0 \uAE30\uBCF8 \uAD8C\uD55C \uC801\uC6A9\n * - \uBA54\uC18C\uB4DC \uB808\uBCA8: \uD574\uB2F9 \uBA54\uC18C\uB4DC\uC5D0\uB9CC \uAD8C\uD55C \uC801\uC6A9 (\uD074\uB798\uC2A4 \uB808\uBCA8 \uC624\uBC84\uB77C\uC774\uB4DC)\n *\n * @param permissions \uD544\uC694\uD55C \uAD8C\uD55C \uBAA9\uB85D (\uBE48 \uBC30\uC5F4: \uB85C\uADF8\uC778\uB9CC \uD544\uC694)\n */\nexport function Authorize(permissions: string[] = []) {\n return function <T extends Function | ((...args: unknown[]) => unknown)>(\n target: T,\n context: ClassDecoratorContext | ClassMethodDecoratorContext,\n ): T | void {\n if (context.kind === \"class\") {\n // \uD074\uB798\uC2A4 \uB808\uBCA8\n classAuthMap.set(target as Function, permissions);\n\n // \uB300\uAE30 \uC911\uC778 \uBA54\uC18C\uB4DC \uAD8C\uD55C \uC5F0\uACB0\n const className = context.name ?? \"\";\n const pending = pendingMethodAuth.get(className);\n if (pending != null) {\n let methodMap = methodAuthMap.get(target as Function);\n if (methodMap == null) {\n methodMap = new Map();\n methodAuthMap.set(target as Function, methodMap);\n }\n for (const { permissions: perms, methodName } of pending) {\n methodMap.set(methodName, perms);\n }\n pendingMethodAuth.delete(className);\n }\n } else {\n // \uBA54\uC18C\uB4DC \uB808\uBCA8 - \uD074\uB798\uC2A4 \uB370\uCF54\uB808\uC774\uD130\uAC00 \uB098\uC911\uC5D0 \uC2E4\uD589\uB418\uBBC0\uB85C \uC784\uC2DC \uC800\uC7A5\n const methodName = String(context.name);\n\n // addInitializer\uB97C \uD1B5\uD574 \uD074\uB798\uC2A4 \uC0DD\uC131\uC790\uC5D0 \uC811\uADFC\n context.addInitializer(function (this: unknown) {\n const ctor = (this as object).constructor;\n let methodMap = methodAuthMap.get(ctor);\n if (methodMap == null) {\n methodMap = new Map();\n methodAuthMap.set(ctor, methodMap);\n }\n methodMap.set(methodName, permissions);\n });\n }\n };\n}\n\n/**\n * \uC778\uC99D \uAD8C\uD55C \uC870\uD68C\n * - \uBA54\uC18C\uB4DC \uB808\uBCA8 \uAD8C\uD55C \uC6B0\uC120\n * - \uC5C6\uC73C\uBA74 \uD074\uB798\uC2A4 \uB808\uBCA8 \uAD8C\uD55C \uBC18\uD658\n *\n * @param ctor \uC11C\uBE44\uC2A4 \uD074\uB798\uC2A4 \uC0DD\uC131\uC790\n * @param methodName \uBA54\uC18C\uB4DC \uC774\uB984 (\uC120\uD0DD)\n * @returns \uAD8C\uD55C \uBAA9\uB85D \uB610\uB294 undefined (Public API)\n */\nexport function getAuthPermissions(ctor: Function, methodName?: string): string[] | undefined {\n if (methodName != null) {\n const perms = methodAuthMap.get(ctor)?.get(methodName);\n if (perms != null) return perms;\n }\n return classAuthMap.get(ctor);\n}\n"],
5
+ "mappings": "AACA,MAAM,eAAe,oBAAI,QAA4B;AACrD,MAAM,gBAAgB,oBAAI,QAAyC;AAGnE,MAAM,oBAAoB,oBAAI,IAA6D;AASpF,SAAS,UAAU,cAAwB,CAAC,GAAG;AACpD,SAAO,SACL,QACA,SACU;AACV,QAAI,QAAQ,SAAS,SAAS;AAE5B,mBAAa,IAAI,QAAoB,WAAW;AAGhD,YAAM,YAAY,QAAQ,QAAQ;AAClC,YAAM,UAAU,kBAAkB,IAAI,SAAS;AAC/C,UAAI,WAAW,MAAM;AACnB,YAAI,YAAY,cAAc,IAAI,MAAkB;AACpD,YAAI,aAAa,MAAM;AACrB,sBAAY,oBAAI,IAAI;AACpB,wBAAc,IAAI,QAAoB,SAAS;AAAA,QACjD;AACA,mBAAW,EAAE,aAAa,OAAO,WAAW,KAAK,SAAS;AACxD,oBAAU,IAAI,YAAY,KAAK;AAAA,QACjC;AACA,0BAAkB,OAAO,SAAS;AAAA,MACpC;AAAA,IACF,OAAO;AAEL,YAAM,aAAa,OAAO,QAAQ,IAAI;AAGtC,cAAQ,eAAe,WAAyB;AAC9C,cAAM,OAAQ,KAAgB;AAC9B,YAAI,YAAY,cAAc,IAAI,IAAI;AACtC,YAAI,aAAa,MAAM;AACrB,sBAAY,oBAAI,IAAI;AACpB,wBAAc,IAAI,MAAM,SAAS;AAAA,QACnC;AACA,kBAAU,IAAI,YAAY,WAAW;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAWO,SAAS,mBAAmB,MAAgB,YAA2C;AAC5F,MAAI,cAAc,MAAM;AACtB,UAAM,QAAQ,cAAc,IAAI,IAAI,GAAG,IAAI,UAAU;AACrD,QAAI,SAAS,KAAM,QAAO;AAAA,EAC5B;AACA,SAAO,aAAa,IAAI,IAAI;AAC9B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,35 @@
1
+ import * as jose from "jose";
2
+ class JwtManager {
3
+ constructor(_server) {
4
+ this._server = _server;
5
+ }
6
+ async sign(payload) {
7
+ const jwtSecret = this._server.options.auth?.jwtSecret;
8
+ if (jwtSecret == null) throw new Error("JWT Secret\uC774 \uC815\uC758\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
9
+ const secret = new TextEncoder().encode(jwtSecret);
10
+ return new jose.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime("12h").sign(secret);
11
+ }
12
+ async verify(token) {
13
+ const jwtSecret = this._server.options.auth?.jwtSecret;
14
+ if (jwtSecret == null) throw new Error("JWT Secret\uC774 \uC815\uC758\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
15
+ const secret = new TextEncoder().encode(jwtSecret);
16
+ try {
17
+ const { payload } = await jose.jwtVerify(token, secret);
18
+ return payload;
19
+ } catch (err) {
20
+ if (err != null && typeof err === "object" && "code" in err && err.code === "ERR_JWT_EXPIRED") {
21
+ throw new Error("\uD1A0\uD070\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
22
+ }
23
+ throw new Error("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD1A0\uD070\uC785\uB2C8\uB2E4.");
24
+ }
25
+ }
26
+ decode(token) {
27
+ const jwtSecret = this._server.options.auth?.jwtSecret;
28
+ if (jwtSecret == null) throw new Error("JWT Secret\uC774 \uC815\uC758\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
29
+ return jose.decodeJwt(token);
30
+ }
31
+ }
32
+ export {
33
+ JwtManager
34
+ };
35
+ //# sourceMappingURL=jwt-manager.js.map