@plitzi/sdk-server 0.37.2 → 0.37.4

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 (359) hide show
  1. package/CHANGELOG.md +1170 -0
  2. package/README.md +100 -7
  3. package/dist/actions.d.ts +6 -2
  4. package/dist/actions.js +5 -2
  5. package/dist/adapters/cloudAdapters.js +4 -3
  6. package/dist/adapters/jsonAdapters.js +28 -6
  7. package/dist/adapters/jsonAdapters.test.d.ts +1 -0
  8. package/dist/auth.d.ts +7 -4
  9. package/dist/auth.js +8 -6
  10. package/dist/core/auth/api.d.ts +29 -1
  11. package/dist/core/auth/api.js +47 -13
  12. package/dist/core/auth/createAuth.d.ts +4 -0
  13. package/dist/core/auth/createAuth.js +3 -3
  14. package/dist/core/auth/credentials.d.ts +3 -0
  15. package/dist/core/auth/credentials.js +1 -1
  16. package/dist/core/auth/csrf.d.ts +25 -1
  17. package/dist/core/auth/csrf.js +29 -4
  18. package/dist/core/auth/renewal.d.ts +26 -0
  19. package/dist/core/auth/renewal.js +24 -0
  20. package/dist/core/auth/routes.js +8 -6
  21. package/dist/core/auth/session.d.ts +45 -0
  22. package/dist/core/auth/session.js +47 -1
  23. package/dist/core/auth/sessionActivity.d.ts +11 -0
  24. package/dist/core/auth/sessionActivity.js +14 -0
  25. package/dist/core/auth/throttle.d.ts +15 -0
  26. package/dist/core/auth/throttle.js +29 -1
  27. package/dist/core/auth/totp.d.ts +9 -1
  28. package/dist/core/auth/totp.js +11 -6
  29. package/dist/core/createServer.actions.test.d.ts +1 -0
  30. package/dist/core/createServer.d.ts +14 -1
  31. package/dist/core/createServer.functions.test.d.ts +1 -0
  32. package/dist/core/createServer.js +22 -12
  33. package/dist/core/fontStore.js +1 -1
  34. package/dist/core/handlers/authRouteHandlers.d.ts +1 -1
  35. package/dist/core/handlers/authRouteHandlers.js +57 -21
  36. package/dist/core/handlers/csrfMiddleware.d.ts +23 -0
  37. package/dist/core/handlers/csrfMiddleware.js +31 -7
  38. package/dist/core/handlers/csrfMiddleware.test.d.ts +1 -0
  39. package/dist/core/handlers/oauthRouteHandlers.js +5 -3
  40. package/dist/core/handlers/socialRouteHandlers.d.ts +1 -1
  41. package/dist/core/handlers/socialRouteHandlers.js +2 -1
  42. package/dist/core/http/dispatcher.d.ts +9 -1
  43. package/dist/core/http/dispatcher.js +38 -11
  44. package/dist/core/http/navigation.d.ts +5 -2
  45. package/dist/core/http/navigation.js +7 -4
  46. package/dist/core/http/socketResponse.d.ts +18 -0
  47. package/dist/core/http/socketResponse.js +59 -0
  48. package/dist/core/http/sse.d.ts +26 -0
  49. package/dist/core/http/sse.js +78 -0
  50. package/dist/core/http/stages/authRoutes.js +3 -1
  51. package/dist/core/http/stages/exchangeRoute.test.d.ts +1 -0
  52. package/dist/core/http/stages/middlewares.d.ts +1 -1
  53. package/dist/core/http/stages/middlewares.js +16 -10
  54. package/dist/core/http/stages/middlewares.test.d.ts +1 -0
  55. package/dist/core/http/stages/oauth.js +2 -2
  56. package/dist/core/http/stages/sessionRenewal.d.ts +16 -0
  57. package/dist/core/http/stages/sessionRenewal.js +81 -0
  58. package/dist/core/http/stages/sessionRenewal.test.d.ts +1 -0
  59. package/dist/core/http/stages/signInRoute.d.ts +2 -0
  60. package/dist/core/http/stages/signInRoute.js +139 -0
  61. package/dist/core/http/stages/signInRoute.test.d.ts +1 -0
  62. package/dist/core/http/types.d.ts +9 -0
  63. package/dist/core/http/webExchange.d.ts +18 -0
  64. package/dist/core/http/webExchange.js +53 -0
  65. package/dist/core/oauth/authorize.js +37 -13
  66. package/dist/core/oauth/consentPage.js +11 -0
  67. package/dist/core/oauth/issueContext.d.ts +14 -0
  68. package/dist/core/oauth/issueContext.js +32 -0
  69. package/dist/core/oauth/records.d.ts +7 -0
  70. package/dist/core/oauth/register.d.ts +2 -0
  71. package/dist/core/oauth/register.js +32 -11
  72. package/dist/core/oauth/register.test.d.ts +1 -0
  73. package/dist/core/oauth/token.js +21 -6
  74. package/dist/core/oauth/token.test.d.ts +1 -0
  75. package/dist/core/requestParser.d.ts +4 -0
  76. package/dist/core/requestParser.js +14 -7
  77. package/dist/core/sdkAssets.js +1 -1
  78. package/dist/core/server/baseServer.d.ts +10 -0
  79. package/dist/core/server/baseServer.js +42 -11
  80. package/dist/core/server/closeOnSignals.js +4 -3
  81. package/dist/core/server/drain.d.ts +18 -0
  82. package/dist/core/server/drain.js +62 -0
  83. package/dist/core/server/drain.test.d.ts +1 -0
  84. package/dist/core/server/fleet/channel.d.ts +103 -0
  85. package/dist/core/server/fleet/channel.js +191 -0
  86. package/dist/core/server/fleet/channel.test.d.ts +1 -0
  87. package/dist/core/server/fleet/fixtures/fleetServer.d.ts +1 -0
  88. package/dist/core/server/fleet/fleet.integration.test.d.ts +1 -0
  89. package/dist/core/server/fleet/link.d.ts +23 -0
  90. package/dist/core/server/fleet/link.js +70 -0
  91. package/dist/core/server/fleet/relay.d.ts +11 -0
  92. package/dist/core/server/fleet/relay.js +104 -0
  93. package/dist/core/server/fleet/relay.test.d.ts +1 -0
  94. package/dist/core/server/fleet/role.d.ts +46 -0
  95. package/dist/core/server/fleet/role.js +59 -0
  96. package/dist/core/server/fleet/role.test.d.ts +1 -0
  97. package/dist/core/server/fleet/stores.d.ts +7 -0
  98. package/dist/core/server/fleet/stores.js +19 -0
  99. package/dist/core/server/fleet/supervisor.d.ts +26 -0
  100. package/dist/core/server/fleet/supervisor.js +108 -0
  101. package/dist/core/server/fleet/supervisor.test.d.ts +1 -0
  102. package/dist/core/server/pageServer.js +34 -5
  103. package/dist/core/services/action.js +10 -2
  104. package/dist/core/services/functionRoutes.d.ts +9 -0
  105. package/dist/core/services/functionRoutes.js +47 -0
  106. package/dist/core/services/realtime.d.ts +8 -0
  107. package/dist/core/services/realtime.js +57 -0
  108. package/dist/core/services/registry.js +6 -2
  109. package/dist/core/staticFiles.js +12 -4
  110. package/dist/core/staticFiles.test.d.ts +1 -0
  111. package/dist/core/transports.d.ts +13 -3
  112. package/dist/core/transports.js +14 -5
  113. package/dist/functions-api.d.ts +281 -0
  114. package/dist/functions.d.ts +19 -0
  115. package/dist/functions.js +5 -0
  116. package/dist/functionsRunner.d.ts +15 -0
  117. package/dist/functionsRunner.js +6 -0
  118. package/dist/handlers.d.ts +2 -2
  119. package/dist/handlers.js +2 -2
  120. package/dist/helpers/atomicFile.d.ts +10 -0
  121. package/dist/helpers/atomicFile.js +33 -0
  122. package/dist/helpers/atomicFile.test.d.ts +1 -0
  123. package/dist/helpers/buildResponseHelpers.js +35 -11
  124. package/dist/helpers/buildServerInfo.js +4 -2
  125. package/dist/helpers/buildServerInfo.test.d.ts +1 -0
  126. package/dist/helpers/cache/CompressedFileCache.d.ts +18 -0
  127. package/dist/helpers/cache/CompressedFileCache.js +44 -0
  128. package/dist/helpers/cache/CompressedFileCache.test.d.ts +1 -0
  129. package/dist/helpers/cache/cacheManager.d.ts +1 -1
  130. package/dist/helpers/cache/cacheManager.js +2 -1
  131. package/dist/helpers/cache/cacheManager.test.d.ts +1 -0
  132. package/dist/helpers/cache/index.d.ts +1 -1
  133. package/dist/helpers/cache/keys.d.ts +15 -1
  134. package/dist/helpers/cache/keys.js +47 -5
  135. package/dist/helpers/cache/serverCaches.d.ts +7 -1
  136. package/dist/helpers/compress.d.ts +3 -1
  137. package/dist/helpers/compress.js +11 -3
  138. package/dist/helpers/hydrationPayload.d.ts +11 -0
  139. package/dist/helpers/hydrationPayload.js +51 -0
  140. package/dist/helpers/hydrationPayload.test.d.ts +1 -0
  141. package/dist/helpers/metrics.d.ts +1 -1
  142. package/dist/helpers/metrics.js +3 -2
  143. package/dist/helpers/outboundGuard.d.ts +14 -6
  144. package/dist/helpers/outboundGuard.js +132 -8
  145. package/dist/helpers/paintedCookie.d.ts +8 -0
  146. package/dist/helpers/paintedCookie.js +13 -0
  147. package/dist/helpers/reportReactBuild.d.ts +9 -0
  148. package/dist/helpers/reportReactBuild.js +18 -0
  149. package/dist/helpers/reportReactBuild.test.d.ts +1 -0
  150. package/dist/helpers/serverLog.d.ts +25 -1
  151. package/dist/helpers/serverLog.js +68 -3
  152. package/dist/helpers/serverLog.test.d.ts +1 -0
  153. package/dist/helpers/wsFrame.d.ts +3 -0
  154. package/dist/helpers/wsFrame.js +5 -0
  155. package/dist/index.d.ts +6 -1
  156. package/dist/index.js +5 -2
  157. package/dist/kernel.d.ts +2 -1
  158. package/dist/kernel.js +3 -2
  159. package/dist/modules/actions/connectorWrite.js +2 -1
  160. package/dist/modules/actions/index.d.ts +29 -10
  161. package/dist/modules/actions/index.js +43 -6
  162. package/dist/modules/actions/jobs/failureStreak.d.ts +17 -0
  163. package/dist/modules/actions/jobs/failureStreak.js +47 -0
  164. package/dist/modules/actions/jobs/failureStreak.test.d.ts +1 -0
  165. package/dist/modules/actions/jobs/index.d.ts +2 -1
  166. package/dist/modules/actions/jobs/index.js +5 -3
  167. package/dist/modules/actions/jobs/memoryQueue.d.ts +3 -0
  168. package/dist/modules/actions/jobs/memoryQueue.js +17 -1
  169. package/dist/modules/actions/jobs/scheduler.d.ts +2 -0
  170. package/dist/modules/actions/jobs/scheduler.js +12 -7
  171. package/dist/modules/actions/jobs/worker.d.ts +3 -1
  172. package/dist/modules/actions/jobs/worker.js +9 -4
  173. package/dist/modules/actions/moduleFor.js +5 -2
  174. package/dist/modules/actions/runtime/errors.d.ts +12 -0
  175. package/dist/modules/actions/runtime/errors.js +16 -1
  176. package/dist/modules/actions/runtime/kvChange.d.ts +27 -0
  177. package/dist/modules/actions/runtime/kvChange.js +23 -0
  178. package/dist/modules/actions/runtime/kvList.d.ts +51 -0
  179. package/dist/modules/actions/runtime/kvList.js +52 -0
  180. package/dist/modules/actions/runtime/kvStore.d.ts +8 -0
  181. package/dist/modules/actions/runtime/kvStore.js +46 -20
  182. package/dist/modules/actions/runtime/memoryKv.d.ts +3 -0
  183. package/dist/modules/actions/runtime/memoryKv.js +19 -1
  184. package/dist/modules/actions/runtime/namespaceKv.d.ts +4 -6
  185. package/dist/modules/actions/runtime/namespaceKv.js +15 -3
  186. package/dist/modules/actions/runtime/namespaceKv.test.d.ts +1 -0
  187. package/dist/modules/actions/runtime/precheck.js +4 -8
  188. package/dist/modules/actions/runtime/rateLimit.d.ts +19 -0
  189. package/dist/modules/actions/runtime/rateLimit.js +19 -0
  190. package/dist/modules/actions/runtime/redisKv.d.ts +27 -0
  191. package/dist/modules/actions/runtime/redisKv.integration.test.d.ts +1 -0
  192. package/dist/modules/actions/runtime/redisKv.js +46 -0
  193. package/dist/modules/actions/runtime/report.js +2 -1
  194. package/dist/modules/actions/runtime/runAction.d.ts +10 -2
  195. package/dist/modules/actions/runtime/runAction.js +52 -116
  196. package/dist/modules/actions/runtime/runLogger.d.ts +5 -0
  197. package/dist/modules/actions/runtime/runLogger.js +8 -2
  198. package/dist/modules/actions/runtime/signing.d.ts +20 -0
  199. package/dist/modules/actions/runtime/signing.js +25 -0
  200. package/dist/modules/actions/runtime/signing.test.d.ts +1 -0
  201. package/dist/modules/actions/runtime/taskContext.d.ts +33 -0
  202. package/dist/modules/actions/runtime/taskContext.js +124 -0
  203. package/dist/modules/actions/tasks/builtins.js +5 -1
  204. package/dist/modules/actions/tasks/flow.js +81 -10
  205. package/dist/modules/actions/tasks/helpers.js +2 -2
  206. package/dist/modules/actions/tasks/http.js +2 -3
  207. package/dist/modules/actions/tasks/kv.js +39 -0
  208. package/dist/modules/actions/tasks/list.d.ts +2 -0
  209. package/dist/modules/actions/tasks/list.js +145 -0
  210. package/dist/modules/actions/tasks/realtime.d.ts +2 -0
  211. package/dist/modules/actions/tasks/realtime.js +104 -0
  212. package/dist/modules/actions/tasks/registry.d.ts +10 -1
  213. package/dist/modules/actions/tasks/registry.js +17 -6
  214. package/dist/modules/actions/transport/callHandler.js +5 -2
  215. package/dist/modules/actions/transport/catalogHandler.d.ts +5 -2
  216. package/dist/modules/actions/transport/catalogHandler.js +3 -2
  217. package/dist/modules/actions/transport/stream.d.ts +4 -5
  218. package/dist/modules/actions/transport/stream.js +12 -76
  219. package/dist/modules/actions/transport/webhookHandler.js +4 -3
  220. package/dist/modules/actions/types.d.ts +86 -3
  221. package/dist/modules/connectors/engine.js +3 -5
  222. package/dist/modules/functions/build.d.ts +22 -0
  223. package/dist/modules/functions/build.js +122 -0
  224. package/dist/modules/functions/build.test.d.ts +1 -0
  225. package/dist/modules/functions/capabilities.d.ts +22 -0
  226. package/dist/modules/functions/capabilities.js +228 -0
  227. package/dist/modules/functions/config.d.ts +34 -0
  228. package/dist/modules/functions/config.js +24 -0
  229. package/dist/modules/functions/context.d.ts +17 -0
  230. package/dist/modules/functions/context.js +88 -0
  231. package/dist/modules/functions/contract.d.ts +121 -0
  232. package/dist/modules/functions/contract.js +9 -0
  233. package/dist/modules/functions/driver.d.ts +36 -0
  234. package/dist/modules/functions/driver.js +150 -0
  235. package/dist/modules/functions/load.d.ts +15 -0
  236. package/dist/modules/functions/load.js +45 -0
  237. package/dist/modules/functions/load.test.d.ts +1 -0
  238. package/dist/modules/functions/local.d.ts +29 -0
  239. package/dist/modules/functions/local.js +61 -0
  240. package/dist/modules/functions/local.test.d.ts +1 -0
  241. package/dist/modules/functions/manifest.d.ts +24 -0
  242. package/dist/modules/functions/manifest.js +163 -0
  243. package/dist/modules/functions/manifest.test.d.ts +1 -0
  244. package/dist/modules/functions/native.d.ts +8 -0
  245. package/dist/modules/functions/native.js +21 -0
  246. package/dist/modules/functions/native.test.d.ts +1 -0
  247. package/dist/modules/functions/protocol.d.ts +216 -0
  248. package/dist/modules/functions/protocol.js +18 -0
  249. package/dist/modules/functions/routes.d.ts +36 -0
  250. package/dist/modules/functions/routes.js +181 -0
  251. package/dist/modules/functions/routes.test.d.ts +1 -0
  252. package/dist/modules/functions/runner/messages.d.ts +5 -0
  253. package/dist/modules/functions/runner/messages.js +188 -0
  254. package/dist/modules/functions/runner/remote.d.ts +19 -0
  255. package/dist/modules/functions/runner/remote.js +116 -0
  256. package/dist/modules/functions/runner/remote.test.d.ts +1 -0
  257. package/dist/modules/functions/runner/service.d.ts +32 -0
  258. package/dist/modules/functions/runner/service.js +209 -0
  259. package/dist/modules/functions/sandbox/guest.d.ts +45 -0
  260. package/dist/modules/functions/sandbox/guest.js +660 -0
  261. package/dist/modules/functions/sandbox/isolate.d.ts +37 -0
  262. package/dist/modules/functions/sandbox/isolate.js +347 -0
  263. package/dist/modules/functions/sandbox/isolate.test.d.ts +1 -0
  264. package/dist/modules/functions/sandbox/prelude.d.ts +2 -0
  265. package/dist/modules/functions/sandbox/prelude.js +49 -0
  266. package/dist/modules/functions/space.d.ts +40 -0
  267. package/dist/modules/functions/space.js +162 -0
  268. package/dist/modules/functions/testing/tasksOf.d.ts +4 -0
  269. package/dist/modules/functions/tryEntry.d.ts +9 -0
  270. package/dist/modules/functions/tryEntry.js +49 -0
  271. package/dist/modules/mongo/kv.js +31 -0
  272. package/dist/modules/mysql/accounts.js +19 -9
  273. package/dist/modules/mysql/index.d.ts +2 -1
  274. package/dist/modules/mysql/jobs/index.d.ts +1 -1
  275. package/dist/modules/mysql/jobs/kv.js +30 -0
  276. package/dist/modules/mysql/jobs/schema.d.ts +9 -0
  277. package/dist/modules/mysql/jobs/schema.js +21 -4
  278. package/dist/modules/mysql/schema.js +25 -0
  279. package/dist/modules/mysql/sessions.d.ts +1 -11
  280. package/dist/modules/mysql/sessions.js +6 -1
  281. package/dist/modules/realtime/declarations.d.ts +11 -0
  282. package/dist/modules/realtime/declarations.js +26 -0
  283. package/dist/modules/realtime/grants.d.ts +23 -0
  284. package/dist/modules/realtime/grants.js +61 -0
  285. package/dist/modules/realtime/handlers.d.ts +74 -0
  286. package/dist/modules/realtime/handlers.js +224 -0
  287. package/dist/modules/realtime/hub.d.ts +62 -0
  288. package/dist/modules/realtime/hub.js +141 -0
  289. package/dist/modules/realtime/index.d.ts +51 -0
  290. package/dist/modules/realtime/index.js +62 -0
  291. package/dist/modules/realtime/memoryPubSub.d.ts +10 -0
  292. package/dist/modules/realtime/memoryPubSub.js +43 -0
  293. package/dist/modules/realtime/realtime.test.d.ts +1 -0
  294. package/dist/modules/realtime/redisPubSub.d.ts +24 -0
  295. package/dist/modules/realtime/redisPubSub.js +36 -0
  296. package/dist/modules/realtime/redisPubSub.test.d.ts +1 -0
  297. package/dist/modules/realtime/socket.d.ts +25 -0
  298. package/dist/modules/realtime/socket.js +122 -0
  299. package/dist/modules/realtime/socket.test.d.ts +1 -0
  300. package/dist/modules/rsc/handler.d.ts +16 -0
  301. package/dist/modules/rsc/handler.js +17 -10
  302. package/dist/modules/rsc/handler.test.d.ts +1 -0
  303. package/dist/modules/rsc/resolveRscData.js +2 -1
  304. package/dist/modules/runtime/bundle.d.ts +24 -0
  305. package/dist/modules/runtime/bundle.js +102 -0
  306. package/dist/modules/runtime/contract.d.ts +37 -0
  307. package/dist/modules/runtime/contract.js +21 -0
  308. package/dist/modules/runtime/entry.test.d.ts +1 -0
  309. package/dist/modules/runtime/host.d.ts +38 -0
  310. package/dist/modules/runtime/host.js +68 -0
  311. package/dist/modules/runtime/inside.d.ts +15 -0
  312. package/dist/modules/runtime/inside.js +47 -0
  313. package/dist/modules/runtime/inside.test.d.ts +1 -0
  314. package/dist/modules/runtime/runner.d.ts +11 -0
  315. package/dist/modules/runtime/runner.js +38 -0
  316. package/dist/modules/runtime/runtime.test.d.ts +1 -0
  317. package/dist/modules/runtime/stages.d.ts +50 -0
  318. package/dist/modules/runtime/stages.js +117 -0
  319. package/dist/modules/ssr/Component.d.ts +3 -1
  320. package/dist/modules/ssr/Component.js +2 -1
  321. package/dist/modules/ssr/handler.js +10 -2
  322. package/dist/modules/ssr/loadPluginComponents.js +2 -1
  323. package/dist/modules/ssr/prepareRender.js +39 -10
  324. package/dist/modules/ssr/preview.d.ts +3 -0
  325. package/dist/modules/ssr/preview.js +17 -7
  326. package/dist/modules/ssr/redirect.test.d.ts +1 -0
  327. package/dist/modules/ssr/registerExternalPlugins.d.ts +6 -1
  328. package/dist/modules/ssr/registerExternalPlugins.js +19 -16
  329. package/dist/modules/ssr/registerExternalPlugins.test.d.ts +1 -0
  330. package/dist/modules/ssr/reportMissingPlugins.d.ts +9 -0
  331. package/dist/modules/ssr/reportMissingPlugins.js +24 -0
  332. package/dist/modules/ssr/reportMissingPlugins.test.d.ts +1 -0
  333. package/dist/modules/ssr/streamBody.d.ts +2 -2
  334. package/dist/modules/ssr/streamBody.js +4 -1
  335. package/dist/modules/ssr/template.js +1 -1
  336. package/dist/modules/ssr/views/template.ejs +8 -5
  337. package/dist/mysql.d.ts +1 -1
  338. package/dist/mysql.js +2 -2
  339. package/dist/oauth.js +2 -2
  340. package/dist/plugins/compile.js +9 -4
  341. package/dist/plugins/copy.js +3 -3
  342. package/dist/plugins/manager.d.ts +35 -3
  343. package/dist/plugins/manager.js +109 -38
  344. package/dist/runtime.d.ts +15 -0
  345. package/dist/runtime.js +7 -0
  346. package/package.json +39 -8
  347. package/skills/plitzi-authoring/SKILL.md +98 -14
  348. package/skills/plitzi-authoring/reference/accessibility.md +111 -0
  349. package/skills/plitzi-authoring/reference/authoring-errors.md +70 -0
  350. package/skills/plitzi-authoring/reference/data-and-visibility.md +84 -18
  351. package/skills/plitzi-authoring/reference/elements-and-styles.md +61 -7
  352. package/skills/plitzi-authoring/reference/flows.md +108 -17
  353. package/skills/plitzi-authoring/reference/lists.md +74 -0
  354. package/skills/plitzi-authoring/reference/performance.md +67 -0
  355. package/skills/plitzi-authoring/reference/plugins.md +167 -0
  356. package/skills/plitzi-authoring/reference/review-checklist.md +19 -2
  357. package/skills/plitzi-authoring/reference/templates.md +67 -27
  358. package/skills/plitzi-authoring/reference/testing.md +72 -5
  359. package/skills/plitzi-authoring/reference/validation.md +73 -0
@@ -1,21 +1,38 @@
1
- import { randomId } from "./pkce.js";
2
1
  import { getClientByFingerprint, putClient, putClientFingerprint } from "./records.js";
2
+ import { randomId } from "./pkce.js";
3
3
  import { sendErrorJson, sendJson } from "./respond.js";
4
4
  import { createHash } from "node:crypto";
5
5
  //#region src/core/oauth/register.ts
6
- var isUsableRedirectUri = (value) => {
7
- let url;
6
+ var parseUri = (value) => {
8
7
  try {
9
- url = new URL(value);
8
+ return new URL(value);
10
9
  } catch {
11
- return false;
10
+ return;
12
11
  }
13
- if (url.protocol === "https:") return true;
14
- return url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1");
15
12
  };
13
+ /** Plain http on the loopback interface — the exception RFC 8252 carves out for a native app listening on a port. */
14
+ var isLoopbackRedirectUri = (value) => {
15
+ const url = parseUri(value);
16
+ return url?.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1");
17
+ };
18
+ /**
19
+ * A redirect target must be one the user's browser can be sent to safely: https anywhere, or loopback. A deployment
20
+ * whose clients are all native apps narrows that to loopback alone (see `OAuthConfig.loopbackRedirectsOnly`).
21
+ */
22
+ var isUsableRedirectUri = (value, loopbackOnly) => isLoopbackRedirectUri(value) || !loopbackOnly && parseUri(value)?.protocol === "https:";
16
23
  var stringList = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
17
24
  var nowSeconds = () => Math.floor(Date.now() / 1e3);
18
25
  var fingerprintOf = (clientName, redirectUris) => createHash("sha256").update(JSON.stringify([clientName, [...redirectUris].sort()])).digest("base64url");
26
+ /**
27
+ * What a client calls itself is shown to the person it acts for — on the grant screen and in their list of devices — so
28
+ * it is bounded: a name is a line of text, not a document a client can fill the screen with.
29
+ */
30
+ var CLIENT_NAME_MAX = 120;
31
+ var SOFTWARE_ID_MAX = 64;
32
+ var textField = (value, max) => {
33
+ if (typeof value !== "string") return;
34
+ return value.trim().slice(0, max) || void 0;
35
+ };
19
36
  /** RFC 7591 dynamic client registration. A remote host has no way to be configured into this server ahead of
20
37
  * time, so it registers itself on first connect; the record it gets back is only ever used to pin the redirect
21
38
  * target, since a public client authenticates with PKCE rather than with credentials. */
@@ -25,17 +42,20 @@ var handleRegister = async (config, res, body) => {
25
42
  return;
26
43
  }
27
44
  const metadata = body;
28
- const redirectUris = stringList(metadata["redirect_uris"]).filter(isUsableRedirectUri);
45
+ const loopbackOnly = config.loopbackRedirectsOnly === true;
46
+ const redirectUris = stringList(metadata["redirect_uris"]).filter((uri) => isUsableRedirectUri(uri, loopbackOnly));
29
47
  if (redirectUris.length === 0) {
30
- sendErrorJson(res, 400, "invalid_request", "redirect_uris must list at least one https (or loopback) URI.");
48
+ sendErrorJson(res, 400, "invalid_request", loopbackOnly ? "redirect_uris must list at least one loopback URI (http://127.0.0.1:<port>/…)." : "redirect_uris must list at least one https (or loopback) URI.");
31
49
  return;
32
50
  }
33
- const clientName = typeof metadata["client_name"] === "string" ? metadata["client_name"] : "MCP client";
51
+ const clientName = textField(metadata["client_name"], CLIENT_NAME_MAX) ?? "MCP client";
52
+ const softwareId = textField(metadata["software_id"], SOFTWARE_ID_MAX);
34
53
  const { store } = config.adapters;
35
54
  const fingerprint = fingerprintOf(clientName, redirectUris);
36
55
  const client = await getClientByFingerprint(store, fingerprint) ?? {
37
56
  clientId: randomId(),
38
57
  clientName,
58
+ ...softwareId ? { softwareId } : {},
39
59
  redirectUris,
40
60
  issuedAt: nowSeconds()
41
61
  };
@@ -45,6 +65,7 @@ var handleRegister = async (config, res, body) => {
45
65
  client_id: client.clientId,
46
66
  client_id_issued_at: client.issuedAt,
47
67
  client_name: clientName,
68
+ ...client.softwareId ? { software_id: client.softwareId } : {},
48
69
  redirect_uris: redirectUris,
49
70
  grant_types: config.refreshTtlSeconds === 0 ? ["authorization_code"] : ["authorization_code", "refresh_token"],
50
71
  response_types: ["code"],
@@ -52,4 +73,4 @@ var handleRegister = async (config, res, body) => {
52
73
  });
53
74
  };
54
75
  //#endregion
55
- export { handleRegister };
76
+ export { handleRegister, isLoopbackRedirectUri };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,8 @@
1
+ import { dropAccess, dropCode, dropRefresh, getAccess, getCode, getRefresh, putAccess, putRefresh } from "./records.js";
2
+ import { issueContextFor } from "./issueContext.js";
1
3
  import { scopesOf } from "./metadata.js";
2
4
  import { field, optionalField } from "./params.js";
3
5
  import { randomId, verifyChallenge } from "./pkce.js";
4
- import { dropAccess, dropCode, dropRefresh, getCode, getRefresh, putAccess, putRefresh } from "./records.js";
5
6
  import { sendErrorJson, sendJson } from "./respond.js";
6
7
  //#region src/core/oauth/token.ts
7
8
  var DEFAULT_REFRESH_TTL_SECONDS = 2592e3;
@@ -35,12 +36,21 @@ var sendTokens = async (config, res, credential, expiresInSeconds, grant) => {
35
36
  const body = {
36
37
  access_token: bearer,
37
38
  token_type: "Bearer",
38
- scope: scopeOf(config, grant.scope)
39
+ scope: scopeOf(config, grant.scope),
40
+ /**
41
+ * What the person chose on the grant screen — a space, the account. RFC 6749 §5.1 lets a token response carry
42
+ * parameters of its own, and this one is what a client that asked to CHOOSE needs back: without it, a native
43
+ * client granted "work in this space" would hold a credential and not know which space it was for.
44
+ */
45
+ target: grant.target.value
39
46
  };
40
47
  if (expiresInSeconds !== void 0) body["expires_in"] = expiresInSeconds;
41
48
  if (ttl > 0) {
42
49
  const refreshToken = randomId();
43
- await putRefresh(config.adapters.store, refreshToken, grant, ttl);
50
+ await putRefresh(config.adapters.store, refreshToken, {
51
+ ...grant,
52
+ credential
53
+ }, ttl);
44
54
  body["refresh_token"] = refreshToken;
45
55
  }
46
56
  sendJson(res, 200, body);
@@ -89,7 +99,7 @@ var exchangeRefresh = async (config, res, params) => {
89
99
  sendErrorJson(res, 400, "invalid_grant", "The refresh token was issued to another client.");
90
100
  return;
91
101
  }
92
- const issued = await config.adapters.issueToken(record.user, record.target);
102
+ const issued = await config.adapters.issueToken(record.user, record.target, await issueContextFor(config, record.clientId, { replaces: record.credential }));
93
103
  if (!issued) {
94
104
  sendErrorJson(res, 400, "invalid_grant", "The account no longer has access to this resource.");
95
105
  return;
@@ -107,8 +117,13 @@ var exchangeRefresh = async (config, res, params) => {
107
117
  var handleRevoke = async (config, res, params) => {
108
118
  const token = optionalField(params, "token");
109
119
  if (token) {
110
- await dropRefresh(config.adapters.store, token);
111
- await dropAccess(config.adapters.store, token);
120
+ const { store, revokeToken } = config.adapters;
121
+ const refresh = await getRefresh(store, token);
122
+ const access = await getAccess(store, token);
123
+ await dropRefresh(store, token);
124
+ await dropAccess(store, token);
125
+ const credential = refresh?.credential ?? (access ? access.credential ?? token : void 0);
126
+ if (credential && revokeToken) await revokeToken(credential);
112
127
  }
113
128
  res.setStatus(200);
114
129
  res.end();
@@ -0,0 +1 @@
1
+ export {};
@@ -9,4 +9,8 @@ export declare const requestOrigin: (req: SSRRequest) => string;
9
9
  * the original client first. All three are plain headers a direct client can forge, so this is log/diagnostic
10
10
  * material — never an authorisation input. Falls back to the socket peer, which no client controls. */
11
11
  export declare const clientIp: (raw: IncomingMessage, req: SSRRequest) => string;
12
+ /** The proxies' account of the client address, without the socket — for a caller that has headers and nothing else. */
13
+ export declare const forwardedIp: (headers: Record<string, string | string[] | undefined>) => string;
14
+ /** A request's body as it arrived, byte for byte — what a binary upload to a function's route needs. */
15
+ export declare const readRawBytes: (raw: IncomingMessage) => Promise<Buffer>;
12
16
  export declare const readRawBody: (raw: IncomingMessage) => Promise<string>;
@@ -18,8 +18,10 @@ var parseRequest = (raw) => {
18
18
  const sp = new URLSearchParams(search.slice(1));
19
19
  for (const [k, v] of sp.entries()) query[k] = v;
20
20
  }
21
+ const method = (headers[":method"] ?? raw.method ?? "GET").toUpperCase();
22
+ const ip = forwardedIp(headers) || unmapIpv4(raw.socket.remoteAddress ?? "");
21
23
  return {
22
- method: (headers[":method"] ?? raw.method ?? "GET").toUpperCase(),
24
+ method,
23
25
  path,
24
26
  search,
25
27
  url: rawUrl,
@@ -27,6 +29,7 @@ var parseRequest = (raw) => {
27
29
  protocol,
28
30
  headers,
29
31
  query,
32
+ ...ip ? { ip } : {},
30
33
  ctx: {}
31
34
  };
32
35
  };
@@ -43,12 +46,15 @@ var unmapIpv4 = (address) => address.startsWith("::ffff:") && address.includes("
43
46
  * peer it accepted in `cf-connecting-ip`, the ingress in `x-real-ip`, and `x-forwarded-for` lists the chain with
44
47
  * the original client first. All three are plain headers a direct client can forge, so this is log/diagnostic
45
48
  * material — never an authorisation input. Falls back to the socket peer, which no client controls. */
46
- var clientIp = (raw, req) => {
47
- const forwardedFor = headerValue(req.headers["x-forwarded-for"]).split(",")[0] ?? "";
48
- return unmapIpv4(headerValue(req.headers["cf-connecting-ip"]) || headerValue(req.headers["x-real-ip"]) || forwardedFor.trim() || raw.socket.remoteAddress || "");
49
+ var clientIp = (raw, req) => forwardedIp(req.headers) || unmapIpv4(raw.socket.remoteAddress ?? "");
50
+ /** The proxies' account of the client address, without the socket — for a caller that has headers and nothing else. */
51
+ var forwardedIp = (headers) => {
52
+ const forwardedFor = headerValue(headers["x-forwarded-for"]).split(",")[0] ?? "";
53
+ return unmapIpv4(headerValue(headers["cf-connecting-ip"]) || headerValue(headers["x-real-ip"]) || forwardedFor.trim());
49
54
  };
50
55
  var MAX_BODY_BYTES = 1048576;
51
- var readRawBody = (raw) => new Promise((resolve, reject) => {
56
+ /** A request's body as it arrived, byte for byte — what a binary upload to a function's route needs. */
57
+ var readRawBytes = (raw) => new Promise((resolve, reject) => {
52
58
  const chunks = [];
53
59
  let size = 0;
54
60
  raw.on("data", (chunk) => {
@@ -59,8 +65,9 @@ var readRawBody = (raw) => new Promise((resolve, reject) => {
59
65
  }
60
66
  chunks.push(chunk);
61
67
  });
62
- raw.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
68
+ raw.on("end", () => resolve(Buffer.concat(chunks)));
63
69
  raw.on("error", reject);
64
70
  });
71
+ var readRawBody = async (raw) => (await readRawBytes(raw)).toString("utf8");
65
72
  //#endregion
66
- export { clientIp, parseRequest, readRawBody, requestOrigin };
73
+ export { clientIp, forwardedIp, parseRequest, readRawBody, readRawBytes, requestOrigin };
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
- import { statSync } from "node:fs";
3
2
  import path from "node:path";
3
+ import { statSync } from "node:fs";
4
4
  //#region src/core/sdkAssets.ts
5
5
  /** Where the rendered page is told to fetch the SDK bundle from. Emitted by the render, so it is also served. */
6
6
  var SDK_ASSETS_PREFIX = "/sdk-assets";
@@ -6,7 +6,17 @@ export interface HttpServerParts {
6
6
  plugins: PluginRegistry;
7
7
  /** Started once the transport is bound: background work that should not run in a server nobody listened on. */
8
8
  onListen?: () => void;
9
+ /**
10
+ * The server has stopped taking connections and is shutting down: what holds connections open for good — realtime
11
+ * sockets and streams — lets them go now, rather than being cut when the grace runs out.
12
+ */
13
+ onClosing?: () => void;
9
14
  /** Awaited, so a server that holds work in flight — jobs, drains — can finish it before the sockets close. */
10
15
  onDestroy?: () => void | Promise<void>;
16
+ /** What a plugin invalidated in another process of the fleet leaves to do here: forget it, in memory only. */
17
+ forgetPlugins?: (name?: string, version?: string) => void;
18
+ /** What the primary does once, before it starts the workers — work each of them would otherwise repeat, or race
19
+ * the others to do. */
20
+ beforeFork?: () => Promise<void>;
11
21
  }
12
22
  export declare const createHttpServer: (config: SSRServerConfig, makeHandlerForPort: (port: number) => Handler, parts: HttpServerParts) => SSRServer;
@@ -1,4 +1,9 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
2
+ import { fleetRole, resolveWorkers } from "./fleet/role.js";
3
+ import { channelName } from "./fleet/link.js";
1
4
  import { buildTransport, protoLabel } from "../transports.js";
5
+ import { watchConnections } from "./drain.js";
6
+ import { relayCache, relayPlugins } from "./fleet/relay.js";
2
7
  //#region src/core/server/baseServer.ts
3
8
  /**
4
9
  * What went wrong taking the port, and what to do about it.
@@ -19,13 +24,33 @@ var createHttpServer = (config, makeHandlerForPort, parts) => {
19
24
  const version = config.httpVersion ?? (config.tls ? 2 : 1);
20
25
  if (version >= 3 && !config.tls) throw new Error(`[${label}] httpVersion: ${version} requires a tls config with key and cert`);
21
26
  let primary;
27
+ let connections;
22
28
  let h3;
29
+ let fleet;
30
+ let closed = false;
31
+ const plan = resolveWorkers(config.workers);
32
+ const role = fleetRole(plan);
33
+ const channel = role === "single" ? void 0 : channelName(label);
23
34
  return {
24
- cache: parts.cache,
25
- plugins: parts.plugins,
35
+ cache: channel && parts.cache ? relayCache(parts.cache, `${channel}.cache`) : parts.cache,
36
+ plugins: channel && parts.forgetPlugins ? relayPlugins(parts.plugins, parts.forgetPlugins, `${channel}.plugins`, label) : parts.plugins,
26
37
  listen(port, host = "0.0.0.0") {
38
+ if (plan.requested !== void 0 && role !== "worker") serverLog.warn(label, `${plan.requested} workers asked for, ${plan.count} cores to run them on: starting ${plan.count}`);
39
+ if (role === "primary") {
40
+ (parts.beforeFork?.() ?? Promise.resolve()).catch((error) => serverLog.error(label, "preparing for the workers failed", error)).then(async () => {
41
+ const { startFleet } = await import("./fleet/supervisor.js");
42
+ if (closed) return;
43
+ fleet = startFleet(plan.count, label);
44
+ serverLog.info(label, `${plan.count} workers on ${host}:${port}`);
45
+ }).catch((error) => {
46
+ serverLog.error(label, "the workers could not start", error);
47
+ process.exitCode = 1;
48
+ });
49
+ return;
50
+ }
27
51
  const handler = makeHandlerForPort(port);
28
52
  ({primary, h3} = buildTransport(config, handler, port, label));
53
+ connections = watchConnections(primary);
29
54
  primary.on("error", (error) => {
30
55
  if (config.onListenError) {
31
56
  config.onListenError(error, {
@@ -35,29 +60,35 @@ var createHttpServer = (config, makeHandlerForPort, parts) => {
35
60
  });
36
61
  return;
37
62
  }
38
- console.error(bindFailure(error, port, label));
63
+ serverLog.error(label, bindFailure(error, port, label));
39
64
  process.exitCode = 1;
40
65
  process.exit(1);
41
66
  });
42
67
  primary.listen(port, host, () => {
43
- console.log(`[${label}] ${protoLabel(version, !!config.tls)} - listening on ${host}:${port}`);
68
+ serverLog.info(label, `${protoLabel(version, !!config.tls)} - listening on ${host}:${port}`);
44
69
  parts.onListen?.();
45
70
  });
46
71
  },
47
72
  async close() {
48
- await parts.onDestroy?.();
49
- const open = [primary, h3].filter((srv) => srv !== void 0);
73
+ closed = true;
74
+ await fleet?.stop();
75
+ fleet = void 0;
76
+ const draining = connections?.drain(label);
77
+ const quic = h3;
50
78
  primary = void 0;
79
+ connections = void 0;
51
80
  h3 = void 0;
52
- await Promise.all(open.map((srv) => new Promise((resolve, reject) => {
53
- srv.close((err) => {
54
- if (err && err.code !== "ERR_SERVER_NOT_RUNNING") {
55
- reject(err);
81
+ parts.onClosing?.();
82
+ await parts.onDestroy?.();
83
+ await Promise.all([draining, quic && new Promise((resolve, reject) => {
84
+ quic.close((error) => {
85
+ if (error && !("code" in error && error.code === "ERR_SERVER_NOT_RUNNING")) {
86
+ reject(error);
56
87
  return;
57
88
  }
58
89
  resolve();
59
90
  });
60
- })));
91
+ })]);
61
92
  }
62
93
  };
63
94
  };
@@ -1,3 +1,4 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
1
2
  //#region src/core/server/closeOnSignals.ts
2
3
  /**
3
4
  * Closes the server when the process is told to stop, and only then lets the process exit.
@@ -20,19 +21,19 @@ var closeOnSignals = (server, { signals = ["SIGTERM", "SIGINT"], afterClose } =
20
21
  let closing = false;
21
22
  const onSignal = (signal) => {
22
23
  if (closing) {
23
- console.warn(`[server] ${signal} again: exiting without waiting`);
24
+ serverLog.warn("server", `${signal} again: exiting without waiting`);
24
25
  process.exit(1);
25
26
  return;
26
27
  }
27
28
  closing = true;
28
- console.info(`[server] ${signal}: finishing what is running, then exiting`);
29
+ serverLog.info("server", `${signal}: finishing what is running, then exiting`);
29
30
  (async () => {
30
31
  try {
31
32
  await server.close();
32
33
  await afterClose?.();
33
34
  process.exit(0);
34
35
  } catch (error) {
35
- console.error("[server] could not close cleanly:", error);
36
+ serverLog.error("server", "could not close cleanly", error);
36
37
  process.exit(1);
37
38
  }
38
39
  })();
@@ -0,0 +1,18 @@
1
+ import { PrimaryServer } from '../transports';
2
+ /**
3
+ * How long a server shutting down lets what it is answering finish before it cuts it: a render, an upload, an action
4
+ * called a moment ago. Well under the 30 seconds a cluster gives a pod between SIGTERM and SIGKILL.
5
+ */
6
+ export declare const SHUTDOWN_GRACE_MS = 10000;
7
+ /**
8
+ * The connections a server holds, watched from the moment it is built, so it can be shut down.
9
+ *
10
+ * Node's `server.close()` stops taking connections and then waits for every open one to end. A request ends; a
11
+ * WebSocket or an event stream does not — a board open in a tab, an agent's app listening — so a server with one open
12
+ * waited for ever, and a Ctrl+C or a SIGTERM hung until something killed it. `drain` stops taking connections, closes
13
+ * the idle ones, ends every event stream at once (a stream has nothing left to finish), gives what is still being
14
+ * answered `graceMs`, and then cuts what remains.
15
+ */
16
+ export declare const watchConnections: (server: PrimaryServer) => {
17
+ drain: (label: string, graceMs?: number) => Promise<void>;
18
+ };
@@ -0,0 +1,62 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
2
+ //#region src/core/server/drain.ts
3
+ /**
4
+ * How long a server shutting down lets what it is answering finish before it cuts it: a render, an upload, an action
5
+ * called a moment ago. Well under the 30 seconds a cluster gives a pod between SIGTERM and SIGKILL.
6
+ */
7
+ var SHUTDOWN_GRACE_MS = 1e4;
8
+ /**
9
+ * Whether a response is an event stream: said by its content type — or, since headers written with `writeHead(status,
10
+ * headers)` are not kept where `getHeader` looks, by what it answers: a GET that asked for one, as an EventSource and
11
+ * an MCP client's listening stream do.
12
+ */
13
+ var isEventStream = (asking, answering) => {
14
+ const type = answering.getHeader("content-type");
15
+ const accept = asking.headers.accept;
16
+ return typeof type === "string" && type.startsWith("text/event-stream") || asking.method === "GET" && [accept].flat().some((value) => value?.includes("text/event-stream"));
17
+ };
18
+ /**
19
+ * The connections a server holds, watched from the moment it is built, so it can be shut down.
20
+ *
21
+ * Node's `server.close()` stops taking connections and then waits for every open one to end. A request ends; a
22
+ * WebSocket or an event stream does not — a board open in a tab, an agent's app listening — so a server with one open
23
+ * waited for ever, and a Ctrl+C or a SIGTERM hung until something killed it. `drain` stops taking connections, closes
24
+ * the idle ones, ends every event stream at once (a stream has nothing left to finish), gives what is still being
25
+ * answered `graceMs`, and then cuts what remains.
26
+ */
27
+ var watchConnections = (server) => {
28
+ const sockets = /* @__PURE__ */ new Set();
29
+ const answering = /* @__PURE__ */ new Map();
30
+ server.on("connection", (socket) => {
31
+ sockets.add(socket);
32
+ socket.once("close", () => sockets.delete(socket));
33
+ });
34
+ server.on("request", (request, response) => {
35
+ answering.set(response, request);
36
+ response.once("close", () => answering.delete(response));
37
+ });
38
+ return { drain: (label, graceMs = SHUTDOWN_GRACE_MS) => new Promise((resolve, reject) => {
39
+ const cut = setTimeout(() => {
40
+ if (sockets.size) serverLog.warn(label, `${sockets.size} connection(s) still open after ${graceMs} ms: closing them`);
41
+ sockets.forEach((socket) => socket.destroy());
42
+ }, graceMs);
43
+ cut.unref();
44
+ server.close((error) => {
45
+ clearTimeout(cut);
46
+ if (error && !("code" in error && error.code === "ERR_SERVER_NOT_RUNNING")) {
47
+ reject(error);
48
+ return;
49
+ }
50
+ resolve();
51
+ });
52
+ const closeIdle = () => {
53
+ if ("closeIdleConnections" in server) server.closeIdleConnections();
54
+ };
55
+ closeIdle();
56
+ answering.forEach((request, response) => {
57
+ if (isEventStream(request, response)) response.end(closeIdle);
58
+ });
59
+ }) };
60
+ };
61
+ //#endregion
62
+ export { SHUTDOWN_GRACE_MS, watchConnections };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,103 @@
1
+ /**
2
+ * What the workers of one server say to their primary, and it to them — with nothing here that knows about
3
+ * `node:cluster`, so the rules can be held by tests in one process.
4
+ *
5
+ * Two things cross it:
6
+ *
7
+ * - **Calls to a store the primary holds.** A default kept in memory — an action's `kv`, the job queue, the drafts a
8
+ * preview reads, the sign-in rate limit — is right for one process and wrong for several: a counter that counts
9
+ * one worker's requests, a schedule every worker fires. With workers, the primary keeps the one copy and each
10
+ * worker calls it. One process answering them in turn is what makes `increment` atomic across the fleet.
11
+ * - **Broadcasts.** What one process is told — invalidate this page, forget that plugin — reaches every other.
12
+ * Nothing answers a broadcast, so what is sent must be safe to apply twice.
13
+ */
14
+ export type FleetCall = {
15
+ sdkFleet: 'call';
16
+ id: number;
17
+ store: string;
18
+ method: string;
19
+ args: unknown[];
20
+ };
21
+ export type FleetReply = {
22
+ sdkFleet: 'reply';
23
+ id: number;
24
+ ok: true;
25
+ value: unknown;
26
+ } | {
27
+ sdkFleet: 'reply';
28
+ id: number;
29
+ ok: false;
30
+ error: string;
31
+ };
32
+ export type FleetBroadcast = {
33
+ sdkFleet: 'broadcast';
34
+ channel: string;
35
+ payload: unknown;
36
+ };
37
+ export type FleetMessage = FleetCall | FleetReply | FleetBroadcast;
38
+ /** The channel is shared with `node:cluster` and anything else the deployment sends: only these are ours. */
39
+ export declare const isFleetMessage: (value: unknown) => value is FleetMessage;
40
+ /** A store as a worker sees it: every method answers later, since the answer comes from another process. */
41
+ export type Remote<T> = {
42
+ [K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<Awaited<R>> : never;
43
+ };
44
+ /** Every method of a store, named: the key set is checked, so a method added to the store is not left unreachable. */
45
+ export type StoreMethods<T> = {
46
+ [K in keyof T]-?: true;
47
+ };
48
+ /** How the primary makes a store the first time a worker asks for it, and the methods a worker may call on it. */
49
+ export type HostedStore = {
50
+ create: () => object;
51
+ methods: ReadonlySet<string>;
52
+ };
53
+ export declare const hostable: <T extends object>(create: () => T, methods: StoreMethods<T>) => HostedStore;
54
+ /**
55
+ * The primary's side: the stores it keeps for its workers, answering their calls.
56
+ *
57
+ * A worker names a store `<kind>#<n>` — the n-th of that kind its code built, the same in every worker since they
58
+ * all run the same code — and the primary makes it from the catalogue the first time it is asked. Nothing is made
59
+ * that no worker uses. A call names a method the kind was registered with and nothing else: the channel is not a way
60
+ * to reach whatever the object happens to carry.
61
+ */
62
+ export declare const createStoreHost: (catalogue: Readonly<Record<string, HostedStore>>) => {
63
+ answer: (call: FleetCall) => Promise<FleetReply>;
64
+ };
65
+ export type StoreHost = ReturnType<typeof createStoreHost>;
66
+ /** Who in this process hears a broadcast, by channel. A listener that throws is the caller's to report. */
67
+ export declare const createListeners: (onError: (channel: string, error: unknown) => void) => {
68
+ listen: (channel: string, listener: (payload: unknown) => void) => (() => void);
69
+ deliver: (channel: string, payload: unknown) => void;
70
+ };
71
+ /**
72
+ * A worker's side: calls to the primary's stores, and broadcasts both ways.
73
+ *
74
+ * `send` may throw — a value that cannot cross the channel, a primary already gone — and the call then fails
75
+ * rather than waiting for an answer that will not come. The same when the channel closes with calls in flight.
76
+ */
77
+ export declare const createFleetClient: (send: (message: FleetMessage) => void, deliver: (channel: string, payload: unknown) => void) => {
78
+ call: (store: string, method: string, args: unknown[]) => Promise<unknown>;
79
+ remote: <T extends object>(store: string, methods: StoreMethods<T>) => Remote<T>;
80
+ broadcast: (channel: string, payload: unknown) => void;
81
+ receive: (message: FleetMessage) => void;
82
+ close: () => void;
83
+ };
84
+ export type FleetClient = ReturnType<typeof createFleetClient>;
85
+ export type FleetPeer = {
86
+ id: number;
87
+ send: (message: FleetMessage) => void;
88
+ };
89
+ /**
90
+ * The primary's side of the channel: it answers its workers' calls from the stores it holds, and passes each
91
+ * broadcast on to every process that did not send it — itself included, so a server in the primary hears it too.
92
+ *
93
+ * A peer that went away between a call and its answer is simply not answered: it is not waiting any more.
94
+ */
95
+ export declare const createFleetHub: ({ host, deliver, peers }: {
96
+ host: StoreHost;
97
+ deliver: (channel: string, payload: unknown) => void;
98
+ peers: () => FleetPeer[];
99
+ }) => {
100
+ receive: (from: number, message: FleetMessage) => Promise<void>;
101
+ broadcast: (channel: string, payload: unknown, except?: number) => void;
102
+ };
103
+ export type FleetHub = ReturnType<typeof createFleetHub>;