mega-framework 0.1.5 β†’ 0.1.7

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 (236) hide show
  1. package/bin/mega-ws-hub.js +2 -2
  2. package/package.json +32 -8
  3. package/sample/crud/.env +156 -8
  4. package/sample/crud/.env.example +153 -28
  5. package/sample/crud/.mega/journal/history/20260612092543-create-users.json +261 -0
  6. package/sample/crud/.mega/journal/snapshot.json +261 -0
  7. package/sample/crud/apps/main/controllers/auth-controller.js +22 -14
  8. package/sample/crud/apps/main/controllers/web-controller.js +7 -5
  9. package/sample/crud/apps/main/migrations/20260606000001-create-users.js +91 -13
  10. package/sample/crud/apps/main/migrations/20260606000002-create-boards.js +165 -0
  11. package/sample/crud/apps/main/migrations/20260606000003-create-logs.js +107 -0
  12. package/sample/crud/apps/main/models/log-partition-model.js +105 -0
  13. package/sample/crud/apps/main/models/note-model.js +79 -0
  14. package/sample/crud/apps/main/models/user-level-model.js +24 -0
  15. package/sample/crud/apps/main/models/user-model.js +146 -0
  16. package/sample/crud/apps/main/models/user-type-model.js +21 -0
  17. package/sample/crud/apps/main/models/wallet-model.js +24 -0
  18. package/sample/crud/apps/main/routes/users.js +55 -10
  19. package/sample/crud/apps/main/schedules/log-partition-schedule.js +33 -0
  20. package/sample/crud/apps/main/services/auth-service.js +39 -24
  21. package/sample/crud/apps/main/services/log-partition-service.js +101 -0
  22. package/sample/crud/apps/main/services/note-service.js +6 -6
  23. package/sample/crud/apps/main/services/redis-demo-service.js +3 -3
  24. package/sample/crud/apps/main/services/user-service.js +62 -21
  25. package/sample/crud/apps/main/views/auth/login.ejs +6 -6
  26. package/sample/crud/apps/main/views/auth/register.ejs +46 -5
  27. package/sample/crud/apps/main/views/users/edit.ejs +42 -5
  28. package/sample/crud/apps/main/views/users/list.ejs +6 -2
  29. package/sample/crud/apps/main/views/users/new.ejs +56 -4
  30. package/sample/crud/docs/log_partition_design.mm.md +23 -0
  31. package/sample/crud/mega.config.js +63 -3
  32. package/sample/crud/package.json +3 -3
  33. package/sample/crud/scripts/start-ws-hub.sh +2 -2
  34. package/sample/simple/package.json +2 -2
  35. package/src/adapters/adapter-manager.js +2 -1
  36. package/src/adapters/adapter-options.js +30 -0
  37. package/src/adapters/maria-adapter.js +26 -3
  38. package/src/adapters/mega-db-adapter.js +7 -1
  39. package/src/adapters/mongo-adapter.js +19 -1
  40. package/src/adapters/postgres-adapter.js +25 -2
  41. package/src/adapters/sqlite-adapter.js +20 -1
  42. package/src/cli/commands/new.js +13 -3
  43. package/src/cli/commands/scaffold.js +137 -33
  44. package/src/cli/generators/index.js +82 -2
  45. package/src/cli/index.js +478 -104
  46. package/src/core/ajv-mapper.js +27 -2
  47. package/src/core/boot.js +485 -237
  48. package/src/core/cluster-metrics.js +13 -4
  49. package/src/core/config-validator.js +25 -0
  50. package/src/core/ctx-builder.js +6 -2
  51. package/src/core/envelope.js +112 -12
  52. package/src/core/hub-link.js +65 -4
  53. package/src/core/i18n.js +11 -1
  54. package/src/core/index.js +6 -2
  55. package/src/core/mega-app.js +223 -481
  56. package/src/core/mega-cluster.js +54 -13
  57. package/src/core/mega-server.js +40 -9
  58. package/src/core/migration/dialect-registry.js +107 -0
  59. package/src/core/migration/dialects/README.md +62 -0
  60. package/src/core/migration/dialects/maria.js +496 -0
  61. package/src/core/migration/dialects/mongo.js +824 -0
  62. package/src/core/migration/dialects/postgres.js +563 -0
  63. package/src/core/migration/dialects/sqlite.js +476 -0
  64. package/src/core/migration/differ.js +456 -0
  65. package/src/core/migration/generate.js +508 -0
  66. package/src/core/migration/journal.js +167 -0
  67. package/src/core/migration/model-scan.js +84 -0
  68. package/src/core/migration/mongo-migration-db.js +97 -0
  69. package/src/core/migration/schema-builder.js +400 -0
  70. package/src/core/migration/schema-validator.js +315 -0
  71. package/src/core/migration-lock.js +205 -0
  72. package/src/core/migration-runner.js +166 -38
  73. package/src/core/multipart.js +28 -5
  74. package/src/core/pipeline.js +129 -0
  75. package/src/core/router.js +70 -65
  76. package/src/core/scope-registry.js +0 -1
  77. package/src/core/security.js +67 -9
  78. package/src/core/workers-manager.js +12 -1
  79. package/src/core/ws-cluster.js +10 -3
  80. package/src/core/ws-message.js +48 -4
  81. package/src/core/ws-presence.js +624 -0
  82. package/src/core/ws-roster.js +4 -1
  83. package/src/core/ws-upgrade.js +118 -12
  84. package/src/index.js +1 -1
  85. package/src/lib/hub-protocol.js +29 -0
  86. package/src/lib/mega-health.js +25 -4
  87. package/src/lib/mega-job-queue.js +98 -21
  88. package/src/lib/mega-job.js +29 -0
  89. package/src/lib/mega-logger.js +1 -1
  90. package/src/lib/mega-metrics.js +3 -12
  91. package/src/lib/mega-plugin.js +34 -3
  92. package/src/lib/mega-schedule.js +40 -22
  93. package/src/lib/mega-shutdown.js +162 -49
  94. package/src/lib/mega-tracing.js +66 -19
  95. package/src/lib/mega-worker.js +5 -1
  96. package/src/lib/otel-resource.js +36 -0
  97. package/src/{cli β†’ lib}/ws-hub.js +51 -8
  98. package/src/models/crud-sql-builder.js +133 -0
  99. package/src/models/mega-model.js +82 -2
  100. package/src/models/model-crud.js +483 -0
  101. package/src/models/mongo-crud.js +285 -0
  102. package/templates/model/code-mongo.tpl +35 -0
  103. package/templates/model/code.tpl +15 -1
  104. package/templates/model/test-mongo.tpl +38 -0
  105. package/templates/model/test.tpl +4 -0
  106. package/types/adapters/adapter-manager.d.ts +95 -0
  107. package/types/adapters/adapter-options.d.ts +91 -0
  108. package/types/adapters/file-adapter.d.ts +94 -0
  109. package/types/adapters/file-session-adapter.d.ts +101 -0
  110. package/types/adapters/index.d.ts +20 -0
  111. package/types/adapters/maria-adapter.d.ts +115 -0
  112. package/types/adapters/mega-adapter.d.ts +215 -0
  113. package/types/adapters/mega-bus-adapter.d.ts +45 -0
  114. package/types/adapters/mega-cache-adapter.d.ts +47 -0
  115. package/types/adapters/mega-db-adapter.d.ts +47 -0
  116. package/types/adapters/mega-lock-adapter.d.ts +62 -0
  117. package/types/adapters/mega-log-sink-adapter.d.ts +15 -0
  118. package/types/adapters/mega-session-adapter.d.ts +32 -0
  119. package/types/adapters/mongo-adapter.d.ts +139 -0
  120. package/types/adapters/nats-adapter.d.ts +108 -0
  121. package/types/adapters/postgres-adapter.d.ts +139 -0
  122. package/types/adapters/redis-adapter.d.ts +70 -0
  123. package/types/adapters/redis-session-adapter.d.ts +82 -0
  124. package/types/adapters/redlock-adapter.d.ts +149 -0
  125. package/types/adapters/registry.d.ts +46 -0
  126. package/types/adapters/sqlite-adapter.d.ts +106 -0
  127. package/types/auth/index.d.ts +24 -0
  128. package/types/cli/commands/console-cmd.d.ts +37 -0
  129. package/types/cli/commands/new.d.ts +16 -0
  130. package/types/cli/commands/routes.d.ts +36 -0
  131. package/types/cli/commands/scaffold.d.ts +78 -0
  132. package/types/cli/commands/test-cmd.d.ts +14 -0
  133. package/types/cli/generators/index.d.ts +112 -0
  134. package/types/cli/index.d.ts +249 -0
  135. package/types/cli/template-engine.d.ts +40 -0
  136. package/types/core/ajv-mapper.d.ts +27 -0
  137. package/types/core/boot.d.ts +233 -0
  138. package/types/core/cluster-metrics.d.ts +52 -0
  139. package/types/core/config-loader.d.ts +13 -0
  140. package/types/core/config-validator.d.ts +30 -0
  141. package/types/core/ctx-builder.d.ts +80 -0
  142. package/types/core/envelope.d.ts +79 -0
  143. package/types/core/error-mapper.d.ts +17 -0
  144. package/types/core/formbody.d.ts +41 -0
  145. package/types/core/hub-link.d.ts +264 -0
  146. package/types/core/i18n.d.ts +178 -0
  147. package/types/core/index.d.ts +28 -0
  148. package/types/core/mega-app.d.ts +529 -0
  149. package/types/core/mega-cluster.d.ts +104 -0
  150. package/types/core/mega-server.d.ts +91 -0
  151. package/types/core/mega-service.d.ts +31 -0
  152. package/types/core/migration/dialect-registry.d.ts +22 -0
  153. package/types/core/migration/dialects/maria.d.ts +99 -0
  154. package/types/core/migration/dialects/mongo.d.ts +89 -0
  155. package/types/core/migration/dialects/postgres.d.ts +117 -0
  156. package/types/core/migration/dialects/sqlite.d.ts +111 -0
  157. package/types/core/migration/differ.d.ts +47 -0
  158. package/types/core/migration/generate.d.ts +56 -0
  159. package/types/core/migration/journal.d.ts +52 -0
  160. package/types/core/migration/model-scan.d.ts +19 -0
  161. package/types/core/migration/mongo-migration-db.d.ts +7 -0
  162. package/types/core/migration/schema-builder.d.ts +197 -0
  163. package/types/core/migration/schema-validator.d.ts +20 -0
  164. package/types/core/migration-lock.d.ts +33 -0
  165. package/types/core/migration-runner.d.ts +101 -0
  166. package/types/core/multipart.d.ts +86 -0
  167. package/types/core/openapi.d.ts +62 -0
  168. package/types/core/pipeline.d.ts +92 -0
  169. package/types/core/router.d.ts +159 -0
  170. package/types/core/routes-loader.d.ts +21 -0
  171. package/types/core/scope-registry.d.ts +14 -0
  172. package/types/core/security.d.ts +77 -0
  173. package/types/core/services-loader.d.ts +27 -0
  174. package/types/core/session-cleanup-schedule.d.ts +19 -0
  175. package/types/core/session-store.d.ts +18 -0
  176. package/types/core/session.d.ts +77 -0
  177. package/types/core/static-assets.d.ts +73 -0
  178. package/types/core/template.d.ts +106 -0
  179. package/types/core/workers-manager.d.ts +79 -0
  180. package/types/core/ws-cluster.d.ts +208 -0
  181. package/types/core/ws-compression.d.ts +112 -0
  182. package/types/core/ws-controller.d.ts +65 -0
  183. package/types/core/ws-message.d.ts +106 -0
  184. package/types/core/ws-presence.d.ts +273 -0
  185. package/types/core/ws-roster.d.ts +96 -0
  186. package/types/core/ws-upgrade.d.ts +231 -0
  187. package/types/errors/config-error.d.ts +10 -0
  188. package/types/errors/http-errors.d.ts +120 -0
  189. package/types/errors/index.d.ts +3 -0
  190. package/types/errors/mega-error.d.ts +32 -0
  191. package/types/index.d.ts +39 -0
  192. package/types/lib/asp/config.d.ts +49 -0
  193. package/types/lib/asp/crypto.d.ts +43 -0
  194. package/types/lib/asp/errors.d.ts +30 -0
  195. package/types/lib/asp/nonce-cache.d.ts +52 -0
  196. package/types/lib/asp/plugin.d.ts +30 -0
  197. package/types/lib/asp/ws-terminator.d.ts +45 -0
  198. package/types/lib/env-mapper.d.ts +14 -0
  199. package/types/lib/hub-protocol.d.ts +106 -0
  200. package/types/lib/index.d.ts +22 -0
  201. package/types/lib/logger/telegram-core.d.ts +104 -0
  202. package/types/lib/logger/telegram-transport.d.ts +45 -0
  203. package/types/lib/mega-brute-force.d.ts +66 -0
  204. package/types/lib/mega-circuit-breaker.d.ts +241 -0
  205. package/types/lib/mega-cron.d.ts +66 -0
  206. package/types/lib/mega-hash.d.ts +32 -0
  207. package/types/lib/mega-health.d.ts +41 -0
  208. package/types/lib/mega-job-queue.d.ts +176 -0
  209. package/types/lib/mega-job-worker.d.ts +130 -0
  210. package/types/lib/mega-job.d.ts +138 -0
  211. package/types/lib/mega-logger.d.ts +45 -0
  212. package/types/lib/mega-metrics.d.ts +285 -0
  213. package/types/lib/mega-plugin.d.ts +245 -0
  214. package/types/lib/mega-retry.d.ts +85 -0
  215. package/types/lib/mega-schedule.d.ts +260 -0
  216. package/types/lib/mega-shutdown.d.ts +135 -0
  217. package/types/lib/mega-tracing.d.ts +224 -0
  218. package/types/lib/mega-worker.d.ts +127 -0
  219. package/types/lib/otel-resource.d.ts +16 -0
  220. package/types/lib/worker-runner/process-entry.d.ts +1 -0
  221. package/types/lib/worker-runner/task-dispatch.d.ts +28 -0
  222. package/types/lib/worker-runner/thread-entry.d.ts +1 -0
  223. package/types/lib/ws-hub.d.ts +234 -0
  224. package/types/models/crud-sql-builder.d.ts +48 -0
  225. package/types/models/index.d.ts +1 -0
  226. package/types/models/mega-model.d.ts +138 -0
  227. package/types/models/model-crud.d.ts +82 -0
  228. package/types/models/mongo-crud.d.ts +59 -0
  229. package/types/test/index.d.ts +84 -0
  230. package/.env +0 -127
  231. package/sample/crud/apps/main/migrations/20260606000002-add-auth-to-users.js +0 -30
  232. package/sample/crud/apps/main/models/note.js +0 -71
  233. package/sample/crud/apps/main/models/user.js +0 -86
  234. package/sample/crud/package-lock.json +0 -5665
  235. package/sample/crud/yarn.lock +0 -2142
  236. package/sample/simple/package-lock.json +0 -1851
@@ -0,0 +1,106 @@
1
+ /**
2
+ * μ•± `views` config λ₯Ό μ •κ·œν™”ν•œλ‹€. `dir` 이 μ—†μœΌλ©΄ null(옡트인 λ―Έν™œμ„± β€” i18n normalizeI18n νŒ¨ν„΄ μ •ν•©).
3
+ *
4
+ * @param {unknown} views - μ•± config 의 `views` ν‚€.
5
+ * @returns {{ dir: string, layoutDir: string, partialsDir: string, defaultLayout: string|null, cache: boolean }|null}
6
+ */
7
+ export function normalizeViews(views: unknown): {
8
+ dir: string;
9
+ layoutDir: string;
10
+ partialsDir: string;
11
+ defaultLayout: string | null;
12
+ cache: boolean;
13
+ } | null;
14
+ /**
15
+ * view/layout 이름을 λ·° 루트 κΈ°μ€€ μ ˆλŒ€ 경둜둜 ν’€κ³ , κ·Έ κ²½λ‘œκ°€ **λ·° 루트 λ‚΄λΆ€**인지 κ²€μ¦ν•œλ‹€(경둜 탐색 차단).
16
+ * ν™•μž₯μžκ°€ μ—†μœΌλ©΄ `.ejs` λ₯Ό 뢙인닀. 루트λ₯Ό λ²—μ–΄λ‚˜λ©΄ 400 throw(LFI λ°©μ–΄ β€” multipart sanitize 이쀑 λ°©μ–΄ μ •ν•©).
17
+ *
18
+ * @param {string} dir - λ·° 루트(μ ˆλŒ€κ²½λ‘œ).
19
+ * @param {string} name - view λ˜λŠ” layout μƒλŒ€ 이름(예 'posts/show', 'layouts/main').
20
+ * @param {'view'|'layout'} kind - μ—λŸ¬ λ©”μ‹œμ§€ κ΅¬λΆ„μš©.
21
+ * @returns {string} κ²€μ¦λœ μ ˆλŒ€ 경둜.
22
+ * @throws {MegaValidationError} λ·° 루트λ₯Ό λ²—μ–΄λ‚˜λ©΄ `template.invalid_view`.
23
+ */
24
+ export function resolveViewPath(dir: string, name: string, kind?: "view" | "layout"): string;
25
+ /**
26
+ * 순수 λ Œλ” β€” λ·°λ₯Ό HTML λ¬Έμžμ—΄λ‘œ λ§Œλ“ λ‹€(send 없이). `MegaTemplate#render` 본체이자 reply.render 의 μ½”μ–΄.
27
+ * νŠΈλ ˆμ΄μ‹± span + λ©”νŠΈλ¦­μ„ μ—¬κΈ°μ„œ 1회 κΈ°λ‘ν•œλ‹€(reply.renderΒ·ctx.render κ°€ 곡유).
28
+ *
29
+ * @param {{ dir: string, layoutDir: string, partialsDir: string, defaultLayout: string|null, cache: boolean }} cfg
30
+ * @param {string} view - λ·° 루트 κΈ°μ€€ μƒλŒ€ 이름(예 'posts/show').
31
+ * @param {object} [data] - ν…œν”Œλ¦Ώ 둜컬(데이터). μ˜ˆμ•½ ν‚€ `t`/`lang`/`settings`/`cache` λŠ” ν”„λ ˆμž„μ›Œν¬κ°€ μ±„μš΄λ‹€.
32
+ * @param {{ layout?: string|false }} [opts] - `layout` 으둜 λ ˆμ΄μ•„μ›ƒ override(false λ©΄ λ ˆμ΄μ•„μ›ƒ κ°•μ œ ν•΄μ œ).
33
+ * @param {{ app?: string }} [meta] - λ©”νŠΈλ¦­ app 라벨.
34
+ * @returns {Promise<string>} λ Œλ”λœ HTML.
35
+ * @throws {MegaValidationError} 경둜 탐색 κ±°λΆ€(400). @throws {MegaInternalError} λ Œλ” μ‹€νŒ¨(500).
36
+ */
37
+ export function renderView(cfg: {
38
+ dir: string;
39
+ layoutDir: string;
40
+ partialsDir: string;
41
+ defaultLayout: string | null;
42
+ cache: boolean;
43
+ }, view: string, data?: object, opts?: {
44
+ layout?: string | false;
45
+ }, meta?: {
46
+ app?: string;
47
+ }): Promise<string>;
48
+ /**
49
+ * MegaApp 에 ν…œν”Œλ¦Ώμ„ 옡트인 λ“±λ‘ν•œλ‹€. `views.dir` 이 μžˆμ„ λ•Œλ§Œ `reply.render` λ°μ½”λ ˆμ΄ν„°λ₯Ό 단닀(μ—†μœΌλ©΄
50
+ * 미등둝 β€” render 호좜 μ‹œ Fastify κ°€ 'reply.render is not a function' 으둜 fail-fast, 옡트인 λͺ…μ‹œ).
51
+ *
52
+ * `reply.render` λŠ” μ •λ³Έ `res.render(view, data, { layout })`(docs/03 Β§618):
53
+ * - μš”μ²­λ³„ i18n `t`/`lang`(`req.t`/`req.lang`, i18n 미등둝이면 passthrough)을 data 에 μžλ™ 병합.
54
+ * - λ Œλ” ν›„ `Content-Type: text/html; charset=utf-8` 둜 send. μ²΄μ΄λ‹μš©μœΌλ‘œ reply λ°˜ν™˜.
55
+ *
56
+ * @param {import('fastify').FastifyInstance} fastify
57
+ * @param {object} args
58
+ * @param {unknown} [args.views] - μ•± `views` config(`{ dir, layoutDir, partialsDir, defaultLayout, cache }`).
59
+ * @param {string} [args.appName] - λ©”νŠΈλ¦­Β·λ‘œκ·Έ 라벨.
60
+ * @param {{ debug?: Function }} [args.logger]
61
+ * @returns {{ enabled: boolean, template: MegaTemplate|null }}
62
+ */
63
+ export function registerTemplate(fastify: import("fastify").FastifyInstance, { views, appName, logger }?: {
64
+ views?: unknown;
65
+ appName?: string;
66
+ logger?: {
67
+ debug?: Function;
68
+ };
69
+ }): {
70
+ enabled: boolean;
71
+ template: MegaTemplate | null;
72
+ };
73
+ /** κ³ μ • λ·° μ—”μ§„Β·ν™•μž₯자 (ADR-011 β€” EJS). ejs-mate `settings['view engine']` κ³Ό μΌμΉ˜μ‹œν‚¨λ‹€. */
74
+ export const VIEW_ENGINE: "ejs";
75
+ /** λ ˆμ΄μ•„μ›ƒ 디렉터리 κΈ°λ³Έ κ΄€λ‘€ (02-architecture Β§11 β€” `views/layouts/`). */
76
+ export const DEFAULT_LAYOUT_DIR: "layouts";
77
+ /** νŒŒμ…œ 디렉터리 κΈ°λ³Έ κ΄€λ‘€ (02-architecture Β§11 β€” `views/partials/`). */
78
+ export const DEFAULT_PARTIALS_DIR: "partials";
79
+ /**
80
+ * μ •λ³Έ `MegaTemplate`(docs/03 Β§892 / 06-class-diagrams) β€” 옡트인 λ·° config λ₯Ό 감싼 thin wrapper.
81
+ * registerTemplate κ°€ μ•±λ‹Ή 1개 λ§Œλ“€μ–΄ reply.render κ°€ μœ„μž„ν•œλ‹€. i18n/MegaTracing 처럼 λ³Έμ²΄λŠ” λͺ¨λ“ˆ ν•¨μˆ˜ν˜•.
82
+ */
83
+ export class MegaTemplate {
84
+ /** @param {unknown} views - μ•± `views` config. @param {string} [appName] - λ©”νŠΈλ¦­ app 라벨. */
85
+ constructor(views: unknown, appName?: string);
86
+ /** @type {{ dir: string, layoutDir: string, partialsDir: string, defaultLayout: string|null, cache: boolean }} */
87
+ _cfg: {
88
+ dir: string;
89
+ layoutDir: string;
90
+ partialsDir: string;
91
+ defaultLayout: string | null;
92
+ cache: boolean;
93
+ };
94
+ /** @type {string|undefined} */
95
+ _app: string | undefined;
96
+ /**
97
+ * λ·°λ₯Ό HTML λ¬Έμžμ—΄λ‘œ λ Œλ”(send 없이) β€” docs/03 Β§892.
98
+ * @param {string} viewPath - λ·° 루트 κΈ°μ€€ μƒλŒ€ 이름(예 'posts/show').
99
+ * @param {object} [data]
100
+ * @param {{ layout?: string|false }} [opts]
101
+ * @returns {Promise<string>}
102
+ */
103
+ render(viewPath: string, data?: object, opts?: {
104
+ layout?: string | false;
105
+ }): Promise<string>;
106
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `config.workers`(MegaWorker μ„œλΈŒν΄λž˜μŠ€ λ°°μ—΄)λ‘œλΆ€ν„° μ›Œμ»€ ν’€ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“ λ‹€(아직 start μ•ˆ 함).
3
+ * config-validator κ°€ λ°°μ—΄Β·ν΄λž˜μŠ€ shape λ₯Ό λ¨Όμ € κ²€μ¦ν•˜μ§€λ§Œ, μ—¬κΈ°μ„œλ„ MegaWorker μ„œλΈŒν΄λž˜μŠ€Β·μ΄λ¦„ 쀑볡을
4
+ * λΆ€νŒ… μ‹œμ μ— fail-fast(ν˜•μ œ register νŒ¨ν„΄).
5
+ *
6
+ * @param {{ workers?: Array<typeof MegaWorker> }} [globalConfig] - mega.config.js default export.
7
+ * @param {{ projectRoot?: string, registerShutdownHook?: boolean }} [opts]
8
+ * @returns {void}
9
+ * @throws {MegaConfigError} MegaWorker μ„œλΈŒν΄λž˜μŠ€κ°€ μ•„λ‹ˆκ±°λ‚˜ `static name` 쀑볡일 λ•Œ.
10
+ */
11
+ export function buildWorkers(globalConfig?: {
12
+ workers?: Array<typeof MegaWorker>;
13
+ }, { projectRoot, registerShutdownHook }?: {
14
+ projectRoot?: string;
15
+ registerShutdownHook?: boolean;
16
+ }): void;
17
+ /**
18
+ * λͺ¨λ“  μ›Œμ»€ 풀을 start ν•œλ‹€(μŠ€λ ˆλ“œ/ν”„λ‘œμ„ΈμŠ€ spawn). ν•˜λ‚˜λΌλ„ μ‹€νŒ¨ν•˜λ©΄ 이미 start 된 풀을 등둝 μ—­μˆœ(LIFO)으둜
19
+ * stop ν•œ λ’€ μ›λž˜ μ—λŸ¬λ₯Ό throw(fail-fast + leak λ°©μ§€ β€” adapter-manager connectAll νŒ¨ν„΄).
20
+ *
21
+ * @param {{ logger?: { debug?: Function, info?: Function, warn?: Function } }} [opts]
22
+ * @returns {Promise<void>}
23
+ */
24
+ export function startAll({ logger }?: {
25
+ logger?: {
26
+ debug?: Function;
27
+ info?: Function;
28
+ warn?: Function;
29
+ };
30
+ }): Promise<void>;
31
+ /**
32
+ * `static name` 으둜 μ›Œμ»€ ν’€ 쑰회. 미등둝이면 fail-fast(silent X β€” adapter-manager.get μ •ν•©).
33
+ * @param {string} name @returns {MegaWorker} @throws {MegaConfigError}
34
+ */
35
+ export function get(name: string): MegaWorker;
36
+ /**
37
+ * 등둝 μ—¬λΆ€(Boolean β€” has*, μ»¨λ²€μ…˜). @param {string} name @returns {boolean}
38
+ */
39
+ export function has(name: string): boolean;
40
+ /**
41
+ * λ“±λ‘λœ μ›Œμ»€ 메타 μŠ€λƒ…μƒ·(디버그/CLI). @returns {Array<{ name: string, mode: string, poolSize: number, started: boolean }>}
42
+ */
43
+ export function list(): Array<{
44
+ name: string;
45
+ mode: string;
46
+ poolSize: number;
47
+ started: boolean;
48
+ }>;
49
+ /**
50
+ * `ctx.workers` 둜 쀄 객체 β€” `ctx.workers.<name>.run(task)`. 미등둝 이름 접근은 fail-fast.
51
+ * 동일 Proxy λ₯Ό boot ctxΒ·μš”μ²­ ctx κ°€ κ³΅μœ ν•œλ‹€(μ›Œμ»€λŠ” κΈ€λ‘œλ²Œ μžμ›μ΄λΌ μš”μ²­Β·μ•± 무관).
52
+ * @returns {Record<string, MegaWorker>}
53
+ */
54
+ export function contextProxy(): Record<string, MegaWorker>;
55
+ /**
56
+ * λͺ¨λ“  μ›Œμ»€ 풀을 graceful stop ν•œλ‹€ β€” 등둝 **μ—­μˆœ(LIFO)**. κ°œλ³„ μ‹€νŒ¨λŠ” λΉ„μΉ˜λͺ…적(warn ν›„ 계속).
57
+ * @param {{ logger?: { debug?: Function, warn?: Function } }} [opts]
58
+ * @returns {Promise<void>}
59
+ */
60
+ export function stopAll({ logger }?: {
61
+ logger?: {
62
+ debug?: Function;
63
+ warn?: Function;
64
+ };
65
+ }): Promise<void>;
66
+ /**
67
+ * ν…ŒμŠ€νŠΈμš© reset β€” μΈμŠ€ν„΄μŠ€ λΉ„μš°κ³  shutdown hook ν•΄μ œ(μ›Œμ»€λŠ” stop μ•ˆ 함 β€” ν˜ΈμΆœμžκ°€ λ¨Όμ € stopAll).
68
+ * @returns {void}
69
+ */
70
+ export function _reset(): void;
71
+ /**
72
+ * Proxy get 트랩이 throw ν•˜λ©΄ μ•ˆ λ˜λŠ” "암묡 쑰회" string ν‚€ λͺ¨μŒ. `await`(then)Β·`JSON.stringify`(toJSON)Β·
73
+ * λ¬Έμžμ—΄/μ›μ‹œκ°’ λ³€ν™˜(toString/valueOf)Β·inspect λ₯˜(constructor/inspect)κ°€ 일반 객체에 으레 μ‘°νšŒν•˜λŠ” 킀라,
74
+ * 미등둝 fail-fast λŒ€μƒ(μ˜€νƒ€)κ³Ό ꡬ뢄해 undefined λ₯Ό λŒλ €μ€€λ‹€. 같은 이름이 μ‹€μ œλ‘œ 등둝돼 있으면 κ·ΈλŒ€λ‘œ
75
+ * ν•΄μ„ν•œλ‹€. `then` 은 Symbol 이 μ•„λ‹ˆλΌ **string ν‚€**λ‹€ β€” Promise resolution 이 string 'then' 을 μ‘°νšŒν•˜λ―€λ‘œ
76
+ * 이 κ°€λ“œκ°€ μ—†μœΌλ©΄ `await ctx.workers`/`await ctx.services` κ°€ not_registered 둜 μ£½λŠ”λ‹€.
77
+ */
78
+ export const PROXY_PROTOCOL_KEYS: Set<string>;
79
+ import { MegaWorker } from '../lib/mega-worker.js';
@@ -0,0 +1,208 @@
1
+ /**
2
+ * NATS 기반 WS ν΄λŸ¬μŠ€ν„° fan-out + roster.
3
+ *
4
+ * μ•± 1κ°œλ‹Ή 1 μΈμŠ€ν„΄μŠ€. boot κ°€ 생성·startΒ·shutdown 을 κ΄€λ¦¬ν•œλ‹€(μžλ™ λ°°μ„ ). subject λŠ” μ•± μ΄λ¦„μœΌλ‘œ
5
+ * κ²©λ¦¬λ˜μ–΄(`<prefix>.<appName>.*`) 닀쀑 앱이 ν•œ NATS λ₯Ό κ³΅μœ ν•΄λ„ μ„žμ΄μ§€ μ•ŠλŠ”λ‹€.
6
+ */
7
+ export class MegaWsCluster {
8
+ /**
9
+ * @param {Object} opts
10
+ * @param {import('../adapters/mega-bus-adapter.js').MegaBusAdapter} opts.bus - μ—°κ²°λœ NATS λ²„μŠ€ μ–΄λŒ‘ν„°.
11
+ * @param {string} opts.appName - μ•± 이름(subject 격리 + 둜그).
12
+ * @param {(payload: { ns: string, channel?: string, message: { type: string, payload?: Object }, exceptSessionIds?: string[] }) => void} opts.deliverBroadcast -
13
+ * μˆ˜μ‹ ν•œ broadcast λ₯Ό 둜컬 연결에 μ „λ‹¬ν•˜λŠ” 콜백(보톡 `app._deliverBroadcast`).
14
+ * @param {(payload: { userId: string, message: { type: string, payload?: Object } }) => void} opts.deliverDirect -
15
+ * μˆ˜μ‹ ν•œ direct λ₯Ό 둜컬 연결에 μ „λ‹¬ν•˜λŠ” 콜백(보톡 `app._deliverDirect`).
16
+ * @param {{ debug?: Function, info?: Function, warn?: Function, error?: Function }} [opts.logger]
17
+ * @param {string} [opts.subjectPrefix] - subject 접두(κΈ°λ³Έ 'mega.ws').
18
+ * @param {{ driver?: 'nats'|'none', ttlMs?: number }} [opts.roster] - roster 동기화 μ„€μ •.
19
+ */
20
+ constructor({ bus, appName, deliverBroadcast, deliverDirect, logger, subjectPrefix, roster }?: {
21
+ bus: import("../adapters/mega-bus-adapter.js").MegaBusAdapter;
22
+ appName: string;
23
+ deliverBroadcast: (payload: {
24
+ ns: string;
25
+ channel?: string;
26
+ message: {
27
+ type: string;
28
+ payload?: Object;
29
+ };
30
+ exceptSessionIds?: string[];
31
+ }) => void;
32
+ deliverDirect: (payload: {
33
+ userId: string;
34
+ message: {
35
+ type: string;
36
+ payload?: Object;
37
+ };
38
+ }) => void;
39
+ logger?: {
40
+ debug?: Function;
41
+ info?: Function;
42
+ warn?: Function;
43
+ error?: Function;
44
+ };
45
+ subjectPrefix?: string;
46
+ roster?: {
47
+ driver?: "nats" | "none";
48
+ ttlMs?: number;
49
+ };
50
+ });
51
+ /** @type {import('../adapters/mega-bus-adapter.js').MegaBusAdapter} */
52
+ _bus: import("../adapters/mega-bus-adapter.js").MegaBusAdapter;
53
+ _appName: string;
54
+ _deliverBroadcast: (payload: {
55
+ ns: string;
56
+ channel?: string;
57
+ message: {
58
+ type: string;
59
+ payload?: Object;
60
+ };
61
+ exceptSessionIds?: string[];
62
+ }) => void;
63
+ _deliverDirect: (payload: {
64
+ userId: string;
65
+ message: {
66
+ type: string;
67
+ payload?: Object;
68
+ };
69
+ }) => void;
70
+ _log: {
71
+ debug?: Function;
72
+ info?: Function;
73
+ warn?: Function;
74
+ error?: Function;
75
+ };
76
+ /** 이 ν”„λ‘œμ„ΈμŠ€μ˜ 고유 μ‹λ³„μž β€” echo ꡬ뢄. */
77
+ instanceId: string;
78
+ _subjBroadcast: string;
79
+ _subjDirect: string;
80
+ _subjRoster: string;
81
+ _rosterDriver: string;
82
+ _rosterTtlMs: number;
83
+ /** 이 μΈμŠ€ν„΄μŠ€κ°€ λ³΄μœ ν•œ 둜컬 멀버. sessionId β†’ RosterMember. */
84
+ _localMembers: Map<any, any>;
85
+ /** ν΄λŸ¬μŠ€ν„° μ „μ—­ view. sessionId β†’ RosterMember & { instanceId, expiresAt }. */
86
+ _view: Map<any, any>;
87
+ /** @type {Array<{ unsubscribe: () => Promise<void> }>} ν™œμ„± ꡬ독 ν•Έλ“€. */
88
+ _subs: Array<{
89
+ unsubscribe: () => Promise<void>;
90
+ }>;
91
+ /** @type {ReturnType<typeof setInterval>|null} */
92
+ _heartbeatTimer: ReturnType<typeof setInterval> | null;
93
+ /** @type {ReturnType<typeof setInterval>|null} */
94
+ _sweepTimer: ReturnType<typeof setInterval> | null;
95
+ _isStarted: boolean;
96
+ /** μ‹œμž‘λλŠ”μ§€. @returns {boolean} */
97
+ get isStarted(): boolean;
98
+ /**
99
+ * ꡬ독 μ‹œμž‘ β€” broadcast/direct subject + (roster:'nats' λ©΄) roster subject λ₯Ό subscribe ν•˜κ³ , roster
100
+ * 동기화 타이머(heartbeat/sweep)λ₯Ό 켜고, μ‹ κ·œ μΈμŠ€ν„΄μŠ€ sync_request λ₯Ό 보낸닀. λ©±λ“±(쀑볡 호좜 λ¬΄μ‹œ).
101
+ * @returns {Promise<void>}
102
+ */
103
+ start(): Promise<void>;
104
+ /**
105
+ * broadcast λ₯Ό ν΄λŸ¬μŠ€ν„°λ‘œ publish. 솑신츑은 이미 둜컬 μ „λ‹¬ν–ˆμœΌλ―€λ‘œ `o`(origin)둜 자기 echo λ₯Ό ν‘œμ‹œν•œλ‹€.
106
+ * @param {{ ns: string, channel?: string, message: { type: string, payload?: Object }, exceptSessionIds?: string[] }} payload
107
+ * @returns {Promise<void>}
108
+ */
109
+ publishBroadcast(payload: {
110
+ ns: string;
111
+ channel?: string;
112
+ message: {
113
+ type: string;
114
+ payload?: Object;
115
+ };
116
+ exceptSessionIds?: string[];
117
+ }): Promise<void>;
118
+ /**
119
+ * direct(νŠΉμ • userId)λ₯Ό ν΄λŸ¬μŠ€ν„°λ‘œ publish β€” λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€μ˜ 같은 userId μ„Έμ…˜κΉŒμ§€ λ‹Ώκ²Œ ν•œλ‹€.
120
+ * @param {string} userId
121
+ * @param {{ type: string, payload?: Object }} message
122
+ * @returns {Promise<void>}
123
+ */
124
+ publishDirect(userId: string, message: {
125
+ type: string;
126
+ payload?: Object;
127
+ }): Promise<void>;
128
+ /**
129
+ * roster 에 멀버 μΆ”κ°€(joinSession ν›…). 둜컬 보유 + μ „μ—­ view 반영 + 델타 publish. roster:'none' 이면
130
+ * 둜컬만 κ°±μ‹ ν•œλ‹€.
131
+ * @param {RosterMember} member
132
+ * @returns {void}
133
+ */
134
+ rosterAdd(member: RosterMember): void;
135
+ /**
136
+ * roster μ—μ„œ 멀버 제거(disconnect ν›…). 둜컬 제거 + μ „μ—­ view 제거 + 델타 publish.
137
+ * @param {string} sessionId
138
+ * @returns {void}
139
+ */
140
+ rosterRemove(sessionId: string): void;
141
+ /**
142
+ * ν•΄λ‹Ή ns 의 ν΄λŸ¬μŠ€ν„° μ „μ—­ μ ‘μ†μž λͺ©λ‘. roster:'none' 이면 둜컬 λ©€λ²„λ§Œ.
143
+ * @param {string} ns
144
+ * @returns {Array<{ sessionId: string, userId: string, metadata?: Object }>}
145
+ */
146
+ roster(ns: string): Array<{
147
+ sessionId: string;
148
+ userId: string;
149
+ metadata?: Object;
150
+ }>;
151
+ /**
152
+ * 정리 β€” 타이머 ν•΄μ œ + ꡬ독 ν•΄μ œ + 자기 멀버 LEAVE 곡지(graceful μ’…λ£Œ μ‹œ λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€ roster μ¦‰μ‹œ 정리).
153
+ * @returns {Promise<void>}
154
+ */
155
+ stop(): Promise<void>;
156
+ /**
157
+ * roster subject μˆ˜μ‹  처리. 자기 echo λŠ” κ±΄λ„ˆλ›°λ˜, sync_request λ§Œμ€ 자기 μš”μ²­μ΄μ–΄λ„ 무관(μƒλŒ€κ°€ 응닡).
158
+ * @param {any} msg
159
+ * @returns {void}
160
+ * @private
161
+ */
162
+ private _onRosterMessage;
163
+ /**
164
+ * view 에 멀버 upsert + λ§Œλ£Œμ‹œκ° κ°±μ‹ . 멀버 좜처 instanceId λ₯Ό ν•¨κ»˜ μ €μž₯(sweep νŒλ‹¨Β·μžκΈ°λ©€λ²„ ꡬ뢄).
165
+ * @param {RosterMember} member @param {string} instanceId @returns {void}
166
+ * @private
167
+ */
168
+ private _upsertView;
169
+ /**
170
+ * 만료(heartbeat 끊긴 crash μΈμŠ€ν„΄μŠ€) 멀버λ₯Ό view μ—μ„œ 제거. 자기 λ©€λ²„λŠ” 항상 fresh ν•˜λ―€λ‘œ 영ν–₯ μ—†μŒ.
171
+ * @returns {void}
172
+ * @private
173
+ */
174
+ private _sweepExpired;
175
+ /**
176
+ * 자기 둜컬 멀버 전체λ₯Ό heartbeat 둜 곡지(λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€μ˜ TTL κ°±μ‹ ) + 자기 view 도 fresh μœ μ§€.
177
+ * @returns {Promise<void>}
178
+ * @private
179
+ */
180
+ private _publishHeartbeat;
181
+ /**
182
+ * roster subject 둜 λ©”μ‹œμ§€ publish(자기 instanceId λ₯Ό origin 으둜).
183
+ * @param {Object} body @returns {Promise<void>}
184
+ * @private
185
+ */
186
+ private _publishRoster;
187
+ }
188
+ /**
189
+ * roster 멀버(ν΄λŸ¬μŠ€ν„° 곡유). sessionId λŠ” joinSession μ „μ—­ 유일 계약(ADR-098)으둜 ν‚€κ°€ λœλ‹€.
190
+ */
191
+ export type RosterMember = {
192
+ /**
193
+ * - WS namespace(채널 경둜, 예: '/ws/chat').
194
+ */
195
+ ns: string;
196
+ /**
197
+ * - μ„Έμ…˜ μ‹λ³„μž(μ „μ—­ 유일).
198
+ */
199
+ sessionId: string;
200
+ /**
201
+ * - μ‚¬μš©μž μ‹λ³„μž.
202
+ */
203
+ userId: string;
204
+ /**
205
+ * - presence 메타(λͺ…μ‹œ ν•„λ“œλ§Œ).
206
+ */
207
+ metadata?: Object;
208
+ };
@@ -0,0 +1,112 @@
1
+ /**
2
+ * μ••μΆ• μ„€μ • 검증 β€” μœ„λ°˜ μ‹œ μ‚¬λžŒμ΄ 읽을 μ—λŸ¬ λ©”μ‹œμ§€, 톡과 μ‹œ null λ°˜ν™˜(throw μ•ˆ 함).
3
+ *
4
+ * ν˜ΈμΆœλΆ€κ°€ μ»¨ν…μŠ€νŠΈ(MegaConfigError vs 일반 Error)에 맞게 wrap ν•œλ‹€ β€” config-validator λŠ”
5
+ * MegaConfigError 둜, MegaApp/MegaWsHub 직접 생성 κ²½λ‘œλŠ” 일반 Error 둜.
6
+ *
7
+ * @param {Partial<WsCompressionConfig>} [config] - MegaWebsocketCompressionConfig | MegaWsHubCompressionConfig.
8
+ * @param {string} [label='websocket.compression'] - μ—λŸ¬ λ©”μ‹œμ§€ prefix (예: 'wsHub.compression').
9
+ * @returns {string | null} μœ„λ°˜ λ©”μ‹œμ§€ λ˜λŠ” null.
10
+ */
11
+ export function checkCompressionConfig(config?: Partial<WsCompressionConfig>, label?: string): string | null;
12
+ /**
13
+ * μ••μΆ• μ„€μ • β†’ `ws` WebSocket(Server) 의 `perMessageDeflate` κ°’μœΌλ‘œ λ³€ν™˜.
14
+ *
15
+ * - `enabled !== true` β†’ `false` (μ••μΆ• λΉ„ν™œμ„±, ws κΈ°λ³Έκ°’κ³Ό 동일).
16
+ * - `enabled === true` β†’ 5 ν•„λ“œλ₯Ό λ””ν΄νŠΈλ‘œ μ±„μš΄ perMessageDeflate μ˜΅μ…˜ 객체.
17
+ *
18
+ * λΆ€νŒ…(config-validator)μ—μ„œ 이미 κ²€μ¦λ˜μ§€λ§Œ, 직접 생성 경둜(single λͺ¨λ“œΒ·ν…ŒμŠ€νŠΈ)λ₯Ό μœ„ν•΄ μ—¬κΈ°μ„œλ„
19
+ * λ°©μ–΄μ μœΌλ‘œ κ²€μ¦ν•œλ‹€ β€” μœ„λ°˜ μ‹œ throw(silent κΈˆμ§€).
20
+ *
21
+ * @param {Partial<WsCompressionConfig>} [config] - MegaWebsocketCompressionConfig | MegaWsHubCompressionConfig.
22
+ * @param {string} [label='websocket.compression'] - throw λ©”μ‹œμ§€ prefix.
23
+ * @returns {false | { threshold: number, serverNoContextTakeover: boolean, clientNoContextTakeover: boolean, serverMaxWindowBits: number, concurrencyLimit: number }}
24
+ * @throws {Error} threshold 음수 / serverMaxWindowBits λ²”μœ„ μœ„λ°˜.
25
+ */
26
+ export function buildPerMessageDeflate(config?: Partial<WsCompressionConfig>, label?: string): false | {
27
+ threshold: number;
28
+ serverNoContextTakeover: boolean;
29
+ clientNoContextTakeover: boolean;
30
+ serverMaxWindowBits: number;
31
+ concurrencyLimit: number;
32
+ };
33
+ /**
34
+ * WebSocket per-message deflate μ••μΆ• μ˜΅μ…˜ μ •κ·œν™” (ADR-078).
35
+ *
36
+ * 두 곳이 같은 μŠ€ν‚€λ§ˆλ₯Ό μ“΄λ‹€(04-data-models Β§1.1/Β§2.1):
37
+ * - App-only `websocket.compression` β€” λΈŒλΌμš°μ €β†”Bridge(embedded WS, MegaApp `_ensureWss`)
38
+ * - Global `wsHub.compression` β€” Bridge↔Hub link (MegaWsHub μ„œλ²„ + MegaHubLink 클라)
39
+ *
40
+ * 두 typedef(`MegaWebsocketCompressionConfig` / `MegaWsHubCompressionConfig`)의 6 ν•„λ“œλŠ”
41
+ * κ·ΈλŒ€λ‘œ `ws` νŒ¨ν‚€μ§€μ˜ `perMessageDeflate` μ˜΅μ…˜λͺ…κ³Ό 1:1 λ§€ν•‘λœλ‹€(검증: node_modules/ws/lib/
42
+ * permessage-deflate.js β€” threshold/serverNoContextTakeover/clientNoContextTakeover/
43
+ * serverMaxWindowBits/concurrencyLimit). `enabled` 만 우리 게이트 β€” false λ©΄ μ••μΆ• λΉ„ν™œμ„±
44
+ * (`perMessageDeflate: false`, ws κΈ°λ³Έκ°’).
45
+ *
46
+ * # threshold 의미 (ws μ†ŒμŠ€ 확인)
47
+ * threshold λŠ” **context takeover κ°€ λΉ„ν™œμ„±μΌ λ•Œλ§Œ** μ μš©λœλ‹€(sender.js: no_context_takeover
48
+ * negotiate μ‹œ `rsv1 = byteLength >= threshold`). ADR-078 이 두 NoContextTakeover λ””ν΄νŠΈλ₯Ό true 둜
49
+ * λ‘” 이유 β€” threshold κ°€ μ‹€μ œλ‘œ λ™μž‘ν•˜κ³  μ—°κ²°λ‹Ή λ©”λͺ¨λ¦¬λ„ 절감.
50
+ *
51
+ * # negotiate μ‹€νŒ¨ = μžλ™ raw fallback
52
+ * `permessage-deflate` ν™•μž₯은 μ–‘μͺ½μ΄ λͺ¨λ‘ ν˜‘μƒν•΄μ•Ό ν™œμ„±(RFC 7692). ν•œμͺ½μ΄ OFF(`false`)λ©΄ ν˜‘μƒλ˜μ§€
53
+ * μ•Šμ•„ μžλ™μœΌλ‘œ raw ν†΅μ‹ μœΌλ‘œ λ–¨μ–΄μ§„λ‹€ β€” 별도 fallback μ½”λ“œ λΆˆν•„μš”(ws λ‚΄μž₯ λ™μž‘).
54
+ *
55
+ * @module core/ws-compression
56
+ */
57
+ /**
58
+ * μ••μΆ• μ„€μ • β€” App `websocket.compression` κ³Ό Global `wsHub.compression` 곡톡 μŠ€ν‚€λ§ˆ (ADR-078).
59
+ * 04-data-models 의 `MegaWebsocketCompressionConfig` / `MegaWsHubCompressionConfig` 와 동일.
60
+ * @typedef {Object} WsCompressionConfig
61
+ * @property {boolean} enabled - λ””ν΄νŠΈ false. 옡트인 게이트.
62
+ * @property {number} [threshold] - byte. λ””ν΄νŠΈ 1024. λ―Έλ§Œμ€ μ••μΆ• 우회(NoContextTakeover μ‹œ).
63
+ * @property {boolean} [serverNoContextTakeover] - λ””ν΄νŠΈ true (μ—°κ²°λ‹Ή λ©”λͺ¨λ¦¬ 절감).
64
+ * @property {boolean} [clientNoContextTakeover] - λ””ν΄νŠΈ true.
65
+ * @property {number} [serverMaxWindowBits] - λ””ν΄νŠΈ 10. λ²”μœ„ 9~15 (λ²—μ–΄λ‚˜λ©΄ λΆ€νŒ… throw).
66
+ * @property {number} [concurrencyLimit] - λ””ν΄νŠΈ 10.
67
+ */
68
+ /**
69
+ * ADR-078 λ””ν΄νŠΈκ°’. `enabled` μ™Έ 5 ν•„λ“œλŠ” `ws` perMessageDeflate 에 κ·ΈλŒ€λ‘œ μ „λ‹¬λœλ‹€.
70
+ * @type {Readonly<{ enabled: boolean, threshold: number, serverNoContextTakeover: boolean, clientNoContextTakeover: boolean, serverMaxWindowBits: number, concurrencyLimit: number }>}
71
+ */
72
+ export const COMPRESSION_DEFAULTS: Readonly<{
73
+ enabled: boolean;
74
+ threshold: number;
75
+ serverNoContextTakeover: boolean;
76
+ clientNoContextTakeover: boolean;
77
+ serverMaxWindowBits: number;
78
+ concurrencyLimit: number;
79
+ }>;
80
+ /** serverMaxWindowBits ν—ˆμš© λ²”μœ„ (zlib windowBits μ΅œμ†Œ 9 ~ RFC 7692 μ΅œλŒ€ 15, ADR-078). */
81
+ export const SERVER_MAX_WINDOW_BITS_MIN: 9;
82
+ export const SERVER_MAX_WINDOW_BITS_MAX: 15;
83
+ /**
84
+ * μ••μΆ• μ„€μ • β€” App `websocket.compression` κ³Ό Global `wsHub.compression` 곡톡 μŠ€ν‚€λ§ˆ (ADR-078).
85
+ * 04-data-models 의 `MegaWebsocketCompressionConfig` / `MegaWsHubCompressionConfig` 와 동일.
86
+ */
87
+ export type WsCompressionConfig = {
88
+ /**
89
+ * - λ””ν΄νŠΈ false. 옡트인 게이트.
90
+ */
91
+ enabled: boolean;
92
+ /**
93
+ * - byte. λ””ν΄νŠΈ 1024. λ―Έλ§Œμ€ μ••μΆ• 우회(NoContextTakeover μ‹œ).
94
+ */
95
+ threshold?: number;
96
+ /**
97
+ * - λ””ν΄νŠΈ true (μ—°κ²°λ‹Ή λ©”λͺ¨λ¦¬ 절감).
98
+ */
99
+ serverNoContextTakeover?: boolean;
100
+ /**
101
+ * - λ””ν΄νŠΈ true.
102
+ */
103
+ clientNoContextTakeover?: boolean;
104
+ /**
105
+ * - λ””ν΄νŠΈ 10. λ²”μœ„ 9~15 (λ²—μ–΄λ‚˜λ©΄ λΆ€νŒ… throw).
106
+ */
107
+ serverMaxWindowBits?: number;
108
+ /**
109
+ * - λ””ν΄νŠΈ 10.
110
+ */
111
+ concurrencyLimit?: number;
112
+ };
@@ -0,0 +1,65 @@
1
+ export class MegaWebSocketController {
2
+ /** @type {any} */ _ctxRef: any;
3
+ /** @type {any} */ _appRef: any;
4
+ /** @type {any} */ _logRef: any;
5
+ /** @type {any} */ _servicesRef: any;
6
+ /**
7
+ * ν”„λ ˆμž„μ›Œν¬κ°€ 채널 μΈμŠ€ν„΄μŠ€μ— μ»¨ν…μŠ€νŠΈλ₯Ό λ°”μΈλ”©ν•œλ‹€ (후속 Step 의 upgrade μ²˜λ¦¬μ—μ„œ 호좜).
8
+ * **μ‚¬μš©μž μ½”λ“œλŠ” ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€** (framework-internal).
9
+ *
10
+ * @param {{ ctx?: any, app?: any, log?: any, services?: any }} [binding]
11
+ * @returns {void}
12
+ */
13
+ _bind(binding?: {
14
+ ctx?: any;
15
+ app?: any;
16
+ log?: any;
17
+ services?: any;
18
+ }): void;
19
+ /** ν˜„μž¬ 채널 μ»¨ν…μŠ€νŠΈ (미바인딩 μ‹œ null). */
20
+ get ctx(): any;
21
+ /** μ†Œμ† MegaApp (미바인딩 μ‹œ null). */
22
+ get app(): any;
23
+ /** request_id μžλ™ μ£Όμž… 둜거 (미바인딩 μ‹œ null). */
24
+ get log(): any;
25
+ /** μžλ™ DI ν•Έλ“€ β€” `ctx.services` 와 동일 (미바인딩 μ‹œ null). */
26
+ get services(): any;
27
+ /**
28
+ * μ—°κ²° 수립 μ‹œ 1회 호좜. κΈ°λ³Έ no-op β€” μ„œλΈŒν΄λž˜μŠ€κ°€ override.
29
+ * @param {any} _sock - WS μ†ŒμΌ“.
30
+ * @param {any} _ctx - 채널 μ»¨ν…μŠ€νŠΈ.
31
+ * @returns {Promise<void>}
32
+ */
33
+ onConnect(_sock: any, _ctx: any): Promise<void>;
34
+ /**
35
+ * λ””μŠ€νŒ¨μΉ˜λ˜μ§€ μ•Šμ€ λ©”μ‹œμ§€μ˜ 폴백 ν•Έλ“€λŸ¬. κΈ°λ³Έ no-op β€” μ„œλΈŒν΄λž˜μŠ€κ°€ override.
36
+ * @param {any} _sock - WS μ†ŒμΌ“.
37
+ * @param {Object} _msg - κ²€μ¦λœ WS envelope.
38
+ * @param {any} _ctx - 채널 μ»¨ν…μŠ€νŠΈ.
39
+ * @returns {Promise<any>}
40
+ */
41
+ onMessage(_sock: any, _msg: Object, _ctx: any): Promise<any>;
42
+ /**
43
+ * μ—°κ²° μ’…λ£Œ μ‹œ 호좜. κΈ°λ³Έ no-op β€” μ„œλΈŒν΄λž˜μŠ€κ°€ override.
44
+ * @param {any} _sock - WS μ†ŒμΌ“.
45
+ * @param {any} _ctx - 채널 μ»¨ν…μŠ€νŠΈ.
46
+ * @returns {Promise<void>}
47
+ */
48
+ onDisconnect(_sock: any, _ctx: any): Promise<void>;
49
+ /**
50
+ * μˆ˜μ‹  λ©”μ‹œμ§€ μžλ™ λ””μŠ€νŒ¨μΉ˜ (ADR-015). ν”„λ ˆμž„μ›Œν¬(후속 Step)κ°€ μ†ŒμΌ“ message λ§ˆλ‹€ ν˜ΈμΆœν•œλ‹€.
51
+ *
52
+ * `msg.type` 이 `domain.action` νŒ¨ν„΄({@link WS_TYPE_PATTERN}) 이고 동λͺ… λ©”μ„œλ“œκ°€ 있으면 κ·Έ
53
+ * λ©”μ„œλ“œλ₯Ό, μ•„λ‹ˆλ©΄ {@link MegaWebSocketController#onMessage} 폴백을 ν˜ΈμΆœν•œλ‹€. νŒ¨ν„΄μ΄ 점(`.`)을
54
+ * κ°•μ œν•˜λ―€λ‘œ `constructor` / `onMessage` 같은 베이슀 멀버λͺ…은 type 으둜 맀칭될 수 μ—†λ‹€ β€”
55
+ * prototype μ˜€μ—Ό / μ˜λ„μΉ˜ μ•Šμ€ 베이슀 ν˜ΈμΆœμ„ ꡬ쑰적으둜 차단.
56
+ *
57
+ * @param {any} sock - WS μ†ŒμΌ“.
58
+ * @param {{ type?: string }} msg - κ²€μ¦λœ WS envelope (ws-message.js).
59
+ * @param {any} ctx - 채널 μ»¨ν…μŠ€νŠΈ.
60
+ * @returns {Promise<any>} ν•Έλ“€λŸ¬ λ°˜ν™˜κ°’.
61
+ */
62
+ dispatch(sock: any, msg: {
63
+ type?: string;
64
+ }, ctx: any): Promise<any>;
65
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Sec-WebSocket-Protocol μ œμ•ˆ λͺ©λ‘μ—μ„œ envelope ν”„λ‘œν† μ½œ 버전을 ν˜‘μƒν•œλ‹€.
3
+ *
4
+ * κ·œμΉ™ (ꡬ버전 클라/μ„œλ²„ ν˜Όν•© 둀링 배포 μ•ˆμ „):
5
+ * - `mega.v<N>` 토큰이 ν•˜λ‚˜λ„ μ—†μœΌλ©΄ β†’ **λ ˆκ±°μ‹œ 폴백 v1** (`{ version: 1, subprotocol: undefined }`)
6
+ * β€” subprotocol λ―Έμ‚¬μš© 클라(ν˜„ WASM MegaSocketΒ·λΈŒλΌμš°μ € κΈ°λ³Έ)λŠ” μ „λΆ€ v1 둜 μ·¨κΈ‰ν•œλ‹€.
7
+ * - μƒν˜Έ 지원 버전이 있으면 졜고 버전 채택 β†’ `{ version: N, subprotocol: 'mega.v<N>' }`
8
+ * (μ„œλ²„κ°€ ν•Έλ“œμ…°μ΄ν¬ 응닡 `Sec-WebSocket-Protocol` 둜 ν™•μ • 톡지 β€” ν΄λΌλŠ” `WebSocket.protocol` 둜 μ½λŠ”λ‹€).
9
+ * - `mega.v*` λ₯Ό μ œμ•ˆν–ˆμ§€λ§Œ μƒν˜Έ 버전이 μ—†μœΌλ©΄(클라가 미래 λ²„μ „λ§Œ 지원) β†’ `null`
10
+ * β€” ν˜ΈμΆœλΆ€λŠ” subprotocol 없이 μˆ˜λ½ν•œλ‹€(클라 μž…μž₯에선 "μ„œλ²„κ°€ λ‚΄ 버전을 λͺ» 함" = v1 폴백 μ‹ ν˜Έ.
11
+ * v1 을 λͺ» ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλŠ” 슀슀둜 λ‹«λŠ”λ‹€). ν•Έλ“œμ…°μ΄ν¬λ₯Ό κ±°λΆ€ν•˜μ§€ μ•Šμ•„ ν•˜μœ„ν˜Έν™˜μ΄ μ ˆλŒ€ κΉ¨μ§€μ§€ μ•ŠλŠ”λ‹€.
12
+ *
13
+ * @param {Iterable<string>} offered - ν΄λΌμ΄μ–ΈνŠΈκ°€ μ œμ•ˆν•œ subprotocol 토큰듀(ws λŠ” Set 을 전달).
14
+ * @param {ReadonlyArray<number>} [supported] - μ„œλ²„ 지원 버전 λͺ©λ‘.
15
+ * @returns {{ version: number, subprotocol: string | undefined } | null} ν˜‘μƒ κ²°κ³Ό, μƒν˜Έ 버전 μ—†μœΌλ©΄ null.
16
+ */
17
+ export function negotiateWsProtocol(offered: Iterable<string>, supported?: ReadonlyArray<number>): {
18
+ version: number;
19
+ subprotocol: string | undefined;
20
+ } | null;
21
+ /**
22
+ * λ©”μ‹œμ§€ id 생성 β€” ULID (48-bit timestamp + 80-bit randomness = 26자 Crockford base32).
23
+ *
24
+ * 정식 `MegaIdGen` λΌμ΄λΈŒλŸ¬λ¦¬ν™”λŠ” OQ-014 둜 μ˜ˆμ•½ β€” λ³Έ helper λŠ” envelope μ „μš© zero-dep κ΅¬ν˜„.
25
+ *
26
+ * @param {number} [timestamp] - epoch ms (ν…ŒμŠ€νŠΈ μ£Όμž…μš©; λ―Έμ§€μ • μ‹œ `Date.now()`).
27
+ * @returns {string} 26자 ULID (μ•ž 10자 = μ‹œκ°„, λ’€ 16자 = 랜덀).
28
+ */
29
+ export function generateMessageId(timestamp?: number): string;
30
+ /**
31
+ * WS λ©”μ‹œμ§€ envelope 생성. `v` / `id` / `ts` μžλ™ 채움 (Β§6.2).
32
+ *
33
+ * @param {Object} [fields]
34
+ * @param {string} [fields.type] - `domain.action` νŒ¨ν„΄ (검증됨, μœ„λ°˜ μ‹œ throw). λˆ„λ½ μ‹œ throw.
35
+ * @param {string} [fields.ns] - 채널 namespace (예: `'chat'`).
36
+ * @param {Object} [fields.payload] - νŽ˜μ΄λ‘œλ“œ.
37
+ * @param {Object} [fields.error] - μ—λŸ¬ 객체 (Β§6.3 λͺ¨μ–‘ ꢌμž₯).
38
+ * @param {string} [fields.ref] - μš”μ²­-응닡 맀칭용. μ„œλ²„ ν‘Έμ‹œλŠ” μƒλž΅.
39
+ * @param {{ id?: string, ts?: number }} [opts] - ν…ŒμŠ€νŠΈ/μž¬ν˜„μš© μ£Όμž… (λ―Έμ§€μ • μ‹œ μžλ™).
40
+ * @returns {{ v: number, id: string, type: string, ts: number }} μ™„μ„±λœ envelope.
41
+ * @throws {Error} `type` 이 {@link WS_TYPE_PATTERN} μœ„λ°˜.
42
+ * @example
43
+ * createWsMessage({ type: 'chat.send', ns: 'chat', payload: { text: 'hi' } })
44
+ * // β†’ { v: 1, id: '01HV...', type: 'chat.send', ts: 1735..., ns: 'chat', payload: { text: 'hi' } }
45
+ */
46
+ export function createWsMessage({ type, ns, payload, error, ref }?: {
47
+ type?: string;
48
+ ns?: string;
49
+ payload?: Object;
50
+ error?: Object;
51
+ ref?: string;
52
+ }, opts?: {
53
+ id?: string;
54
+ ts?: number;
55
+ }): {
56
+ v: number;
57
+ id: string;
58
+ type: string;
59
+ ts: number;
60
+ };
61
+ /**
62
+ * WS λ©”μ‹œμ§€ envelope 검증 (Β§6.2 schema). μœ„λ°˜ μ‚¬μœ  배열을 λ°˜ν™˜ν•œλ‹€ (빈 λ°°μ—΄ = 유효).
63
+ *
64
+ * λ˜μ§€μ§€ μ•Šκ³  μ‚¬μœ  λͺ©λ‘μ„ λŒλ €μ£ΌλŠ” 이유: ν˜ΈμΆœλΆ€(λ””μŠ€νŒ¨μ²˜/hub)κ°€ μ‚¬μœ λ₯Ό ERROR envelope 의
65
+ * `details` 둜 κ·ΈλŒ€λ‘œ μ‹€μ–΄ 보낼 수 μžˆλ„λ‘ (ADR-075 λ°°μ—΄ ν‘œμ€€).
66
+ *
67
+ * @param {any} msg
68
+ * @param {{ version?: number }} [opts] - `version` = 이 μ—°κ²°μ—μ„œ ν˜‘μƒλœ envelope 버전
69
+ * ({@link negotiateWsProtocol}). λ―Έμ§€μ • μ‹œ v1 β€” ν˜‘μƒ μ—†λŠ” κΈ°μ‘΄ ν˜ΈμΆœλΆ€μ™€ ν•˜μœ„ν˜Έν™˜.
70
+ * @returns {string[]} μœ„λ°˜ λ©”μ‹œμ§€ λͺ©λ‘ (μ—†μœΌλ©΄ 빈 λ°°μ—΄).
71
+ */
72
+ export function validateWsMessage(msg: any, { version }?: {
73
+ version?: number;
74
+ }): string[];
75
+ /**
76
+ * JSON λ¬Έμžμ—΄ β†’ κ²€μ¦λœ WS λ©”μ‹œμ§€ envelope. νŒŒμ‹±/검증 μ‹€νŒ¨ μ‹œ throw (silent κΈˆμ§€).
77
+ *
78
+ * @param {string} json - wire 평문 JSON (ASP λ³΅ν˜Έν™” ν›„ λ˜λŠ” `P:` 평문).
79
+ * @param {{ version?: number }} [opts] - ν˜‘μƒλœ envelope 버전(λ―Έμ§€μ • μ‹œ v1, {@link validateWsMessage}).
80
+ * @returns {Object} 검증 ν†΅κ³Όν•œ envelope.
81
+ * @throws {Error} JSON νŒŒμ‹± μ‹€νŒ¨ λ˜λŠ” schema μœ„λ°˜ (λ©”μ‹œμ§€μ— μ‚¬μœ  포함).
82
+ */
83
+ export function parseWsMessage(json: string, opts?: {
84
+ version?: number;
85
+ }): Object;
86
+ /** ν˜„ ν”„λ‘œν† μ½œ 버전 (04-data-models Β§6.2 `v: { const: 1 }`). */
87
+ export const WS_PROTOCOL_VERSION: 1;
88
+ /**
89
+ * 이 μ„œλ²„κ°€ μ§€μ›ν•˜λŠ” WS envelope ν”„λ‘œν† μ½œ 버전 λͺ©λ‘. 버전은 μ„ ν˜• λˆ„μ  계약 β€” vN 지원 = v1..vN μ „λΆ€
90
+ * 지원. ν˜‘μƒμ€ ν΄λΌμ΄μ–ΈνŠΈ μ œμ•ˆκ³Όμ˜ **졜고 μƒν˜Έ 버전**을 μ±„νƒν•œλ‹€(v2 λ„μž… μ‹œ [1, 2] 둜 ν™•μž₯).
91
+ * @type {ReadonlyArray<number>}
92
+ */
93
+ export const SUPPORTED_WS_PROTOCOL_VERSIONS: ReadonlyArray<number>;
94
+ /** WS 버전 ν˜‘μƒ subprotocol 토큰 ν˜•μ‹ β€” `mega.v<μ–‘μ˜ μ •μˆ˜>` (예: 'mega.v1'). */
95
+ export const WS_SUBPROTOCOL_PATTERN: RegExp;
96
+ /**
97
+ * λ©”μ‹œμ§€ `type` / `error.code` νŒ¨ν„΄ β€” `domain.action[.result]` (ADR-016, Β§6.2/Β§6.3).
98
+ * 점(`.`)이 μ΅œμ†Œ 1개 κ°•μ œ β†’ 베이슀 λ©”μ„œλ“œλͺ…(`onMessage` λ“±, 점 μ—†μŒ) κ³Ό μ ˆλŒ€ μΆ©λŒν•˜μ§€ μ•ŠμŒ.
99
+ */
100
+ export const WS_TYPE_PATTERN: RegExp;
101
+ /**
102
+ * WS λ©”μ‹œμ§€ JSON Schema (04-data-models Β§6.2 μ •λ³Έ κ·ΈλŒ€λ‘œ).
103
+ * 후속 단계(bridge↔hub, AJV 컴파일)μ—μ„œ μž¬μ‚¬μš©ν•  수 μžˆλ„λ‘ export.
104
+ * @type {Object}
105
+ */
106
+ export const WS_MESSAGE_SCHEMA: Object;