@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
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { createServer, resolveServices } from './core/createServer';
2
2
  export { closeOnSignals } from './core/server/closeOnSignals';
3
+ export { loadFunctions, readFunctionsDir } from './modules/functions/load';
3
4
  export { registerHealthCheck, buildHealthPayload } from './core/health';
4
- export { consoleLogger, renderLogEvent } from './helpers/serverLog';
5
+ export { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from './helpers/serverLog';
5
6
  export type { HealthCheckApp, HealthIdentity } from './core/health';
6
7
  export { createCloudAdapters } from './adapters/cloudAdapters';
7
8
  export { createJsonAdapters } from './adapters/jsonAdapters';
@@ -9,6 +10,8 @@ export { createAuthAdapters } from './adapters/authAdapters';
9
10
  export { authoringPreview, createMemoryCache, createSpaceAdapters, fixedSpace, presentsCredential, refuse, verifiedDomain, wildcardSubdomain } from './adapters/space';
10
11
  export { createLocalFontStore, hostedPathsOf } from './core/fontStore';
11
12
  export { createMemoryDraftStore, takeDraftOverride } from './modules/ssr/preview';
13
+ export { createMemoryPubSub } from './modules/realtime/memoryPubSub';
14
+ export { createRedisPubSub } from './modules/realtime/redisPubSub';
12
15
  export { PREVIEW_TOKEN_PARAM } from './core/previewToken';
13
16
  export { resolveRscData } from './modules/rsc/resolveRscData';
14
17
  export { fetchConnectorRecords, rebaseMedia, writeConnectorRecord, createConnectorResolver } from './modules/connectors';
@@ -19,6 +22,8 @@ export type { AuthoringPreviewOptions, DeploymentRow, FrameAncestorsConfig, Spac
19
22
  export type { RscElementResolver, RscResolveContext, ResolveRscDataOptions } from './modules/rsc/resolveRscData';
20
23
  export type { ConnectorAuth, ConnectorCredential, ConnectorEndpoints, ConnectorFilter, ConnectorLookups, ConnectorManifest, ConnectorManifestDraft, ConnectorPageInfo, ConnectorPagination, ConnectorQuery, ConnectorReadEndpoint, ConnectorRecord, ConnectorResponseMapping, ConnectorResult, ProviderPagination } from './modules/connectors';
21
24
  export type { FontStore, StoredFont } from './core/fontStore';
25
+ export type { PubSubAdapter, SSRRealtimeConfig } from '@plitzi/sdk-shared';
26
+ export type { RedisPubSubClients } from './modules/realtime/redisPubSub';
22
27
  export type { ResolvedServices } from './core/createServer';
23
28
  export type { Closable, CloseOnSignalsOptions } from './core/server/closeOnSignals';
24
29
  export type { BaseContext, PipelineExtensions, SSRContext, Stage } from './core/http/types';
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
+ import { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from "./helpers/serverLog.js";
1
2
  import { fetchConnectorRecords, rebaseMedia, writeConnectorRecord } from "./modules/connectors/engine.js";
3
+ import { createMemoryPubSub } from "./modules/realtime/memoryPubSub.js";
2
4
  import { createConnectorResolver } from "./modules/connectors/resolver.js";
3
5
  import { resolveRscData } from "./modules/rsc/resolveRscData.js";
4
6
  import { PREVIEW_TOKEN_PARAM } from "./core/previewToken.js";
@@ -7,7 +9,7 @@ import { resolveServices } from "./core/services/resolve.js";
7
9
  import { buildHealthPayload, registerHealthCheck } from "./core/health.js";
8
10
  import { createServer } from "./core/createServer.js";
9
11
  import { closeOnSignals } from "./core/server/closeOnSignals.js";
10
- import { consoleLogger, renderLogEvent } from "./helpers/serverLog.js";
12
+ import { loadFunctions, readFunctionsDir } from "./modules/functions/load.js";
11
13
  import { createCloudAdapters } from "./adapters/cloudAdapters.js";
12
14
  import { createJsonAdapters } from "./adapters/jsonAdapters.js";
13
15
  import { createAuthAdapters } from "./adapters/authAdapters.js";
@@ -15,4 +17,5 @@ import { createMemoryCache, refuse } from "./adapters/space/types.js";
15
17
  import { authoringPreview, fixedSpace, presentsCredential, verifiedDomain, wildcardSubdomain } from "./adapters/space/resolvers.js";
16
18
  import { createSpaceAdapters } from "./adapters/space/index.js";
17
19
  import { createLocalFontStore, hostedPathsOf } from "./core/fontStore.js";
18
- export { PREVIEW_TOKEN_PARAM, authoringPreview, buildHealthPayload, closeOnSignals, consoleLogger, createAuthAdapters, createCloudAdapters, createConnectorResolver, createJsonAdapters, createLocalFontStore, createMemoryCache, createMemoryDraftStore, createServer, createSpaceAdapters, fetchConnectorRecords, fixedSpace, hostedPathsOf, presentsCredential, rebaseMedia, refuse, registerHealthCheck, renderLogEvent, resolveRscData, resolveServices, takeDraftOverride, verifiedDomain, wildcardSubdomain, writeConnectorRecord };
20
+ import { createRedisPubSub } from "./modules/realtime/redisPubSub.js";
21
+ export { PREVIEW_TOKEN_PARAM, authoringPreview, buildHealthPayload, closeOnSignals, consoleLogger, createAuthAdapters, createCloudAdapters, createConnectorResolver, createJsonAdapters, createLocalFontStore, createMemoryCache, createMemoryDraftStore, createMemoryPubSub, createRedisPubSub, createServer, createSpaceAdapters, fetchConnectorRecords, fixedSpace, hostedPathsOf, isLogged, loadFunctions, logLevelOf, presentsCredential, readFunctionsDir, rebaseMedia, refuse, registerHealthCheck, renderLogEvent, resolveRscData, resolveServices, serverLog, takeDraftOverride, verifiedDomain, wildcardSubdomain, writeConnectorRecord };
package/dist/kernel.d.ts CHANGED
@@ -16,8 +16,9 @@ export { healthStage } from './core/http/stages/health';
16
16
  export { configStaticStage, publicDirStage, wellKnownStage } from './core/http/stages/static';
17
17
  export { buildHealthPayload, registerHealthCheck } from './core/health';
18
18
  export { clientIp, parseRequest, readRawBody, requestOrigin } from './core/requestParser';
19
- export { consoleLogger, renderLogEvent } from './helpers/serverLog';
19
+ export { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from './helpers/serverLog';
20
20
  export { PREVIEW_TOKEN_PARAM } from './core/previewToken';
21
+ export { assertOutboundAllowed, isBlockedHost } from './helpers/outboundGuard';
21
22
  export type { HttpServerParts } from './core/server/baseServer';
22
23
  export type { BuildContext } from './core/http/dispatcher';
23
24
  export type { HealthCheckApp, HealthIdentity } from './core/health';
package/dist/kernel.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from "./helpers/serverLog.js";
2
+ import { assertOutboundAllowed, isBlockedHost } from "./helpers/outboundGuard.js";
1
3
  import { clientIp, parseRequest, readRawBody, requestOrigin } from "./core/requestParser.js";
2
4
  import { createHttpServer } from "./core/server/baseServer.js";
3
5
  import { PREVIEW_TOKEN_PARAM } from "./core/previewToken.js";
@@ -5,5 +7,4 @@ import { makeHandler } from "./core/http/dispatcher.js";
5
7
  import { buildHealthPayload, registerHealthCheck } from "./core/health.js";
6
8
  import { healthStage } from "./core/http/stages/health.js";
7
9
  import { configStaticStage, publicDirStage, wellKnownStage } from "./core/http/stages/static.js";
8
- import { consoleLogger, renderLogEvent } from "./helpers/serverLog.js";
9
- export { PREVIEW_TOKEN_PARAM, buildHealthPayload, clientIp, configStaticStage, consoleLogger, createHttpServer, healthStage, makeHandler, parseRequest, publicDirStage, readRawBody, registerHealthCheck, renderLogEvent, requestOrigin, wellKnownStage };
10
+ export { PREVIEW_TOKEN_PARAM, assertOutboundAllowed, buildHealthPayload, clientIp, configStaticStage, consoleLogger, createHttpServer, healthStage, isBlockedHost, isLogged, logLevelOf, makeHandler, parseRequest, publicDirStage, readRawBody, registerHealthCheck, renderLogEvent, requestOrigin, serverLog, wellKnownStage };
@@ -1,3 +1,4 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
1
2
  import { writeConnectorRecord } from "../connectors/engine.js";
2
3
  //#region src/modules/actions/connectorWrite.ts
3
4
  var parseBody = (body) => {
@@ -72,7 +73,7 @@ var handleAction = async (req, res, config, lookups) => {
72
73
  res.setHeader("Cache-Control", "no-store");
73
74
  res.send(JSON.stringify({ record: record ?? null }));
74
75
  } catch (err) {
75
- console.error("[Action] connector write failed:", err);
76
+ serverLog.error("Action", "connector write failed", err);
76
77
  fail(res, 502, "Connector write failed");
77
78
  }
78
79
  };
@@ -1,10 +1,35 @@
1
1
  import { ActionJobs } from './jobs';
2
2
  import { RunGuards } from './runtime/guards';
3
3
  import { ActionRunner } from './runtime/runAction';
4
- import { ActionKvStore, ActionsConfig, ActionTaskRegistry, ResolvedActionLimits } from './types';
4
+ import { ActionKvStore, ActionsConfig, ActionTaskRegistry, ResolvedActionLimits, SpaceRevision } from './types';
5
+ import { FunctionsSource } from '../functions/build';
6
+ import { ManifestReading } from '../functions/manifest';
7
+ import { RouteHandler, RouteVisit } from '../functions/routes';
8
+ import { PreparedFunctions } from '../functions/space';
5
9
  import { ActionDocument } from '@plitzi/sdk-shared';
6
10
  export type ActionsModule = ActionRunner & {
11
+ /** The deployment's own tasks: shipped, and its native functions. */
7
12
  registry: ActionTaskRegistry;
13
+ /**
14
+ * What a space's actions can use as of that revision: the deployment's tasks and the space's own functions — what
15
+ * its catalog offers, what a check checks against and what its runs run.
16
+ */
17
+ registryFor: (spaceId: number, at?: SpaceRevision) => Promise<ActionTaskRegistry>;
18
+ /**
19
+ * A space's functions source, built, read and checked — ready to store, or the problems to show where they are. The
20
+ * one way a space's functions become storable; refused when this server has no runner.
21
+ */
22
+ prepareFunctions: (source: FunctionsSource) => Promise<PreparedFunctions>;
23
+ /**
24
+ * What a space's code declares, read by every rule a saved space's functions meet — for code that is not built here:
25
+ * a space runtime's, described by the runtime itself when it starts. The manifest, and the problems that refuse it.
26
+ */
27
+ readManifest: (declared: unknown) => ManifestReading;
28
+ /**
29
+ * The function that answers `method path` under `/api/` for this visit — the deployment's own routes, then the space's
30
+ * — or none, and the page server answers as it would have.
31
+ */
32
+ routeFor: (visit: RouteVisit, method: string, path: string) => Promise<RouteHandler | undefined>;
8
33
  guards: RunGuards;
9
34
  /** The key/value store, namespaced to one space — the same one the `kv` tasks write through, so a rate limit the
10
35
  * transport keeps and a counter a flow keeps cannot end up in different places. */
@@ -20,16 +45,10 @@ export type ActionsModule = ActionRunner & {
20
45
  */
21
46
  jobs?: ActionJobs;
22
47
  };
23
- /**
24
- * The module's whole public surface: build it once from the deployment's config, then run actions through it.
25
- *
26
- * Constructed rather than imported piecemeal so the task registry is validated ONCE, at boot, and so the guards
27
- * are a single set for the process — two instances would each think they were the only run in flight, which is
28
- * the same as having no single-flight at all. Nothing outside this folder needs to know how a run is assembled.
29
- */
30
- export declare const createActionsModule: (config: ActionsConfig) => ActionsModule;
31
- export { ActionRunError } from './runtime/errors';
48
+ export declare const createActionsModule: (given: ActionsConfig) => ActionsModule;
49
+ export { ActionRefusal, ActionRunError } from './runtime/errors';
32
50
  export { precheckRun } from './runtime/precheck';
51
+ export { spaceKvPatterns } from './runtime/namespaceKv';
33
52
  export { checkAction } from './runtime/check';
34
53
  export { DEFAULT_LIMITS, resolveLimits } from './runtime/limits';
35
54
  export { createRunGuards, deriveRunKey } from './runtime/guards';
@@ -2,15 +2,19 @@ import "./jobs/memoryQueue.js";
2
2
  import "./jobs/scheduler.js";
3
3
  import "./runtime/errors.js";
4
4
  import "./jobs/worker.js";
5
+ import { fleetStore } from "../../core/server/fleet/link.js";
5
6
  import { createActionJobs } from "./jobs/index.js";
6
7
  import { createRunGuards } from "./runtime/guards.js";
7
8
  import { createKvStore } from "./runtime/kvStore.js";
8
9
  import { resolveLimits } from "./runtime/limits.js";
9
- import { createMemoryKv } from "./runtime/memoryKv.js";
10
- import { namespaceKv } from "./runtime/namespaceKv.js";
10
+ import { KV_METHODS, createMemoryKv } from "./runtime/memoryKv.js";
11
+ import { namespaceKv, spaceKvPatterns } from "./runtime/namespaceKv.js";
11
12
  import "./runtime/precheck.js";
12
13
  import { createActionRunner } from "./runtime/runAction.js";
13
14
  import { createTaskRegistry } from "./tasks/registry.js";
15
+ import { readManifest } from "../functions/manifest.js";
16
+ import { createRoutes } from "../functions/routes.js";
17
+ import { createSpaceRegistries, prepareFunctions } from "../functions/space.js";
14
18
  import "./runtime/check.js";
15
19
  import "./runtime/runLogger.js";
16
20
  import "./taskCatalog.js";
@@ -27,9 +31,32 @@ import { handleActionCancel } from "./transport/cancelHandler.js";
27
31
  * are a single set for the process — two instances would each think they were the only run in flight, which is
28
32
  * the same as having no single-flight at all. Nothing outside this folder needs to know how a run is assembled.
29
33
  */
30
- var createActionsModule = (config) => {
31
- const registry = createTaskRegistry(config.tasks, { db: (config.dbDrivers?.length ?? 0) > 0 });
32
- const { runAction } = createActionRunner(config, registry, config.fetchImpl);
34
+ /**
35
+ * The workers of one server are one replica, so with no `kv` configured they share the primary's: a flow's counter,
36
+ * a webhook's rate limit, a run's single-flight key, a cancel and a replayed answer then mean the same whichever
37
+ * worker the request lands on — the path a deployment with its own shared store already takes. One process keeps
38
+ * its own map.
39
+ */
40
+ var withFleetKv = (config) => {
41
+ if (config.kv) return config;
42
+ return {
43
+ ...config,
44
+ kv: fleetStore("actions.kv", KV_METHODS) ?? createMemoryKv()
45
+ };
46
+ };
47
+ var createActionsModule = (given) => {
48
+ const config = withFleetKv(given);
49
+ const registry = createTaskRegistry(config.functions?.native, { db: (config.dbDrivers?.length ?? 0) > 0 });
50
+ const spaceRegistries = createSpaceRegistries(registry, config.functions);
51
+ const reserved = new Set(registry.list().map((task) => task.namespace));
52
+ const registryFor = async (spaceId, at) => spaceRegistries.registryFor(await config.lookups.getFunctions?.(spaceId, at));
53
+ const registryForRun = (request) => Object.values(request.entry.document.nodes).every((node) => node.type !== "task" || !node.action || registry.get(node.action)) ? registry : registryFor(request.spaceId, request.at);
54
+ const { runAction, taskContext } = createActionRunner(config, registryForRun, config.fetchImpl);
55
+ const routes = createRoutes({
56
+ config: config.functions ?? {},
57
+ ...config.lookups.getFunctions ? { getFunctions: config.lookups.getFunctions } : {},
58
+ taskContext
59
+ });
33
60
  /**
34
61
  * Single-flight over the store the deployment already gave the `kv` tasks — its own Redis, table or whatever it
35
62
  * runs — because per process it is not a guarantee: the same double-click behind a load balancer lands on two
@@ -41,6 +68,16 @@ var createActionsModule = (config) => {
41
68
  const module = {
42
69
  runAction,
43
70
  registry,
71
+ registryFor,
72
+ routeFor: routes.routeFor,
73
+ prepareFunctions: (source) => {
74
+ const runner = config.functions?.runner;
75
+ return runner ? prepareFunctions(source, runner, reserved) : Promise.resolve({
76
+ ok: false,
77
+ problems: [{ message: "This server runs no space functions" }]
78
+ });
79
+ },
80
+ readManifest: (declared) => readManifest(declared, reserved),
44
81
  guards,
45
82
  kv: (spaceId) => namespaceKv(kv, spaceId),
46
83
  limitsFor
@@ -49,4 +86,4 @@ var createActionsModule = (config) => {
49
86
  return module;
50
87
  };
51
88
  //#endregion
52
- export { createActionsModule, handleActionCall, handleActionCancel, handleActionCatalog, handleActionWebhook };
89
+ export { createActionsModule, handleActionCall, handleActionCancel, handleActionCatalog, handleActionWebhook, spaceKvPatterns };
@@ -0,0 +1,17 @@
1
+ /** How long a pass may keep failing before it is reported as the error it has become. */
2
+ export declare const FAILURE_STREAK_ESCALATION_MS = 60000;
3
+ export type FailureStreak = {
4
+ failed: (error: unknown) => void;
5
+ succeeded: () => void;
6
+ };
7
+ /**
8
+ * How a pass that runs again by itself reports failing: a schedule sweep, a claim, a heartbeat.
9
+ *
10
+ * A store that drops its connections for a moment — a failover, a driver resetting its pool because the host stalled
11
+ * — fails one pass, and the next, seconds later, works. Nothing is lost: every pass is safe to repeat. Reported as an
12
+ * error with a stack, each of those read as an incident, and the ones that are an incident read the same.
13
+ *
14
+ * So the first failure of a streak is a warning with its reason; a streak still going after `escalateAfterMs` is the
15
+ * error, with the whole cause, once; and the pass that ends a streak that got that far says so.
16
+ */
17
+ export declare const createFailureStreak: (scope: string, what: string, escalateAfterMs?: number, now?: () => number) => FailureStreak;
@@ -0,0 +1,47 @@
1
+ import { serverLog } from "../../../helpers/serverLog.js";
2
+ //#region src/modules/actions/jobs/failureStreak.ts
3
+ /** How long a pass may keep failing before it is reported as the error it has become. */
4
+ var FAILURE_STREAK_ESCALATION_MS = 6e4;
5
+ var reasonOf = (error) => error instanceof Error ? error.message : String(error);
6
+ /**
7
+ * How a pass that runs again by itself reports failing: a schedule sweep, a claim, a heartbeat.
8
+ *
9
+ * A store that drops its connections for a moment — a failover, a driver resetting its pool because the host stalled
10
+ * — fails one pass, and the next, seconds later, works. Nothing is lost: every pass is safe to repeat. Reported as an
11
+ * error with a stack, each of those read as an incident, and the ones that are an incident read the same.
12
+ *
13
+ * So the first failure of a streak is a warning with its reason; a streak still going after `escalateAfterMs` is the
14
+ * error, with the whole cause, once; and the pass that ends a streak that got that far says so.
15
+ */
16
+ var createFailureStreak = (scope, what, escalateAfterMs = FAILURE_STREAK_ESCALATION_MS, now = Date.now) => {
17
+ let since;
18
+ let failures = 0;
19
+ let escalated = false;
20
+ return {
21
+ failed: (error) => {
22
+ failures += 1;
23
+ if (since === void 0) {
24
+ since = now();
25
+ serverLog.warn(scope, `${what} failed, trying again`, reasonOf(error));
26
+ return;
27
+ }
28
+ const elapsed = now() - since;
29
+ if (!escalated && elapsed >= escalateAfterMs) {
30
+ escalated = true;
31
+ serverLog.error(scope, `${what} has been failing for ${String(Math.round(elapsed / 1e3))}s`, error);
32
+ }
33
+ },
34
+ succeeded: () => {
35
+ if (since === void 0) return;
36
+ if (escalated) {
37
+ const seconds = Math.round((now() - since) / 1e3);
38
+ serverLog.info(scope, `${what} is working again, after ${String(failures)} failures over ${String(seconds)}s`);
39
+ }
40
+ since = void 0;
41
+ failures = 0;
42
+ escalated = false;
43
+ }
44
+ };
45
+ };
46
+ //#endregion
47
+ export { FAILURE_STREAK_ESCALATION_MS, createFailureStreak };
@@ -0,0 +1 @@
1
+ export {};
@@ -20,7 +20,8 @@ export type ActionJobs = {
20
20
  *
21
21
  * With no `queue` supplied this is one process's memory, which is right for a single replica and wrong the moment
22
22
  * there are two. That is a sentence rather than a silent behaviour because the failure is invisible: everything
23
- * works, and the nightly email goes out once per replica.
23
+ * works, and the nightly email goes out once per replica. The workers of one server are one replica: they share
24
+ * the primary's queue, and only one of them runs the scheduler and the jobs (`runsFleetJobs`).
24
25
  */
25
26
  export declare const createActionJobs: (config: ActionJobsConfig, module: ActionsModule, lookups: ActionLookups) => ActionJobs;
26
27
  export { createMemoryJobQueue } from './memoryQueue';
@@ -1,7 +1,8 @@
1
- import { createMemoryJobQueue } from "./memoryQueue.js";
1
+ import { JOB_QUEUE_METHODS, createMemoryJobQueue } from "./memoryQueue.js";
2
2
  import { DEFAULT_MAX_ATTEMPTS, scheduleFor, scheduleJobId, schedulesFor } from "./schedules.js";
3
3
  import { createScheduler } from "./scheduler.js";
4
4
  import { createJobWorker } from "./worker.js";
5
+ import { fleetStore } from "../../../core/server/fleet/link.js";
5
6
  //#region src/modules/actions/jobs/index.ts
6
7
  /**
7
8
  * The scheduling half of actions: a producer, a consumer and the store they meet in.
@@ -13,10 +14,11 @@ import { createJobWorker } from "./worker.js";
13
14
  *
14
15
  * With no `queue` supplied this is one process's memory, which is right for a single replica and wrong the moment
15
16
  * there are two. That is a sentence rather than a silent behaviour because the failure is invisible: everything
16
- * works, and the nightly email goes out once per replica.
17
+ * works, and the nightly email goes out once per replica. The workers of one server are one replica: they share
18
+ * the primary's queue, and only one of them runs the scheduler and the jobs (`runsFleetJobs`).
17
19
  */
18
20
  var createActionJobs = (config, module, lookups) => {
19
- const queue = config.queue ?? createMemoryJobQueue();
21
+ const queue = config.queue ?? fleetStore("actions.jobs", JOB_QUEUE_METHODS) ?? createMemoryJobQueue();
20
22
  const { produce = true, workers = 4 } = config;
21
23
  const scheduler = createScheduler({
22
24
  queue,
@@ -1,3 +1,4 @@
1
+ import { StoreMethods } from '../../../core/server/fleet/channel';
1
2
  import { ActionJobQueue } from '@plitzi/sdk-shared';
2
3
  export type MemoryJobQueueOptions = {
3
4
  /**
@@ -16,6 +17,8 @@ export type MemoryJobQueueOptions = {
16
17
  */
17
18
  clock?: () => number;
18
19
  };
20
+ /** Every method of the queue, for the copy a server's workers share (see `fleet/stores.ts`). */
21
+ export declare const JOB_QUEUE_METHODS: StoreMethods<ActionJobQueue>;
19
22
  /**
20
23
  * The default queue: one process's Maps.
21
24
  *
@@ -5,6 +5,22 @@ var TERMINAL = /* @__PURE__ */ new Set([
5
5
  "dead",
6
6
  "cancelled"
7
7
  ]);
8
+ /** Every method of the queue, for the copy a server's workers share (see `fleet/stores.ts`). */
9
+ var JOB_QUEUE_METHODS = {
10
+ now: true,
11
+ enqueue: true,
12
+ claim: true,
13
+ heartbeat: true,
14
+ settle: true,
15
+ dueSchedules: true,
16
+ advanceSchedule: true,
17
+ putSchedules: true,
18
+ listJobs: true,
19
+ getJob: true,
20
+ listSchedules: true,
21
+ requeue: true,
22
+ cancel: true
23
+ };
8
24
  /**
9
25
  * The default queue: one process's Maps.
10
26
  *
@@ -175,4 +191,4 @@ var createMemoryJobQueue = ({ retainFinished = 500, clock = Date.now } = {}) =>
175
191
  };
176
192
  };
177
193
  //#endregion
178
- export { createMemoryJobQueue };
194
+ export { JOB_QUEUE_METHODS, createMemoryJobQueue };
@@ -16,6 +16,8 @@ export type SchedulerOptions = {
16
16
  reconcileMs?: number;
17
17
  /** The spaces to reconcile, for a server that serves a known few. `listScheduledSpaces` wins over it. */
18
18
  spaces?: number[];
19
+ /** Every failed pass, in place of the default report — a warning, then an error once a pass has kept failing for a
20
+ * minute (see `createFailureStreak`). */
19
21
  onError?: (error: unknown) => void;
20
22
  };
21
23
  export type SweepResult = {
@@ -1,3 +1,5 @@
1
+ import { serverLog } from "../../../helpers/serverLog.js";
2
+ import { createFailureStreak } from "./failureStreak.js";
1
3
  import { scheduleJobId, schedulesFor } from "./schedules.js";
2
4
  import { cronFiresBetween, cronNextFire } from "@plitzi/sdk-shared/actions";
3
5
  //#region src/modules/actions/jobs/scheduler.ts
@@ -25,7 +27,7 @@ var PARK_MS = 2108160 * MINUTE_MS;
25
27
  * first occurrence after now, recording how many went by. A digest missed for a day sends once and says it missed
26
28
  * 23 — rather than sending 23 times, which is how a scheduler that "catches up" turns an outage into an incident.
27
29
  */
28
- var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, batch = 200, maxAttempts = 3, reconcileMs = 15 * MINUTE_MS, spaces, onError = (error) => console.error("[Actions] schedule sweep failed:", error) }) => {
30
+ var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, batch = 200, maxAttempts = 3, reconcileMs = 15 * MINUTE_MS, spaces, onError }) => {
29
31
  let timer;
30
32
  let reconcileTimer;
31
33
  let running = false;
@@ -86,14 +88,17 @@ var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, ba
86
88
  const reconcileAll = async () => {
87
89
  for (const spaceId of await scheduledSpaces()) await reconcile(spaceId);
88
90
  };
91
+ const sweepFailures = createFailureStreak("Actions", "schedule sweep");
92
+ const reconcileFailures = createFailureStreak("Actions", "schedule reconcile");
89
93
  /** One pass at a time per replica: a sweep that outlives its interval must not have a second one land on top. */
90
- const guarded = async (pass) => {
94
+ const guarded = async (pass, failures) => {
91
95
  if (running) return;
92
96
  running = true;
93
97
  try {
94
98
  await pass();
99
+ failures.succeeded();
95
100
  } catch (error) {
96
- onError(error);
101
+ (onError ?? failures.failed)(error);
97
102
  } finally {
98
103
  running = false;
99
104
  }
@@ -103,14 +108,14 @@ var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, ba
103
108
  reconcile,
104
109
  start: () => {
105
110
  if (timer) return;
106
- timer = setInterval(() => void guarded(sweep), pollMs + Math.floor(Math.random() * 1e3));
111
+ timer = setInterval(() => void guarded(sweep, sweepFailures), pollMs + Math.floor(Math.random() * 1e3));
107
112
  timer.unref();
108
113
  if (!lookups.listScheduledSpaces && !spaces?.length) {
109
- console.warn("[Actions] schedules are running but nothing says which spaces to watch. Name them as `action.jobs.spaces`, or answer `action.lookups.listScheduledSpaces`.");
114
+ serverLog.warn("Actions", "schedules are running but nothing says which spaces to watch. Name them as `action.jobs.spaces`, or answer `action.lookups.listScheduledSpaces`.");
110
115
  return;
111
116
  }
112
- guarded(reconcileAll);
113
- reconcileTimer = setInterval(() => void guarded(reconcileAll), reconcileMs);
117
+ guarded(reconcileAll, reconcileFailures);
118
+ reconcileTimer = setInterval(() => void guarded(reconcileAll, reconcileFailures), reconcileMs);
114
119
  reconcileTimer.unref();
115
120
  },
116
121
  stop: () => {
@@ -35,6 +35,8 @@ export type JobWorkerOptions = {
35
35
  };
36
36
  /** Names this replica in the job history, so a bad one is identifiable. Defaults to the process and a random id. */
37
37
  workerId?: string;
38
+ /** Every failure, in place of the default report. By default a claim or a heartbeat that fails is a warning, and an
39
+ * error once it has kept failing for a minute (see `createFailureStreak`); anything else is an error at once. */
38
40
  onError?: (error: unknown) => void;
39
41
  };
40
42
  export type JobWorker = {
@@ -59,4 +61,4 @@ export type JobWorker = {
59
61
  stop: () => Promise<void>;
60
62
  inFlight: () => number;
61
63
  };
62
- export declare const createJobWorker: ({ queue, lookups, module, workers, pollMs, leaseMs, backoff, workerId, onError }: JobWorkerOptions) => JobWorker;
64
+ export declare const createJobWorker: ({ queue, lookups, module, workers, pollMs, leaseMs, backoff, workerId, onError: customOnError }: JobWorkerOptions) => JobWorker;
@@ -1,3 +1,5 @@
1
+ import { serverLog } from "../../../helpers/serverLog.js";
2
+ import { createFailureStreak } from "./failureStreak.js";
1
3
  import { ActionRunError } from "../runtime/errors.js";
2
4
  import { randomUUID } from "node:crypto";
3
5
  //#region src/modules/actions/jobs/worker.ts
@@ -31,7 +33,10 @@ var GIVE_UP = /* @__PURE__ */ new Set([
31
33
  "forbidden",
32
34
  "recursion"
33
35
  ]);
34
- var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leaseMs = 3e4, backoff = {}, workerId = `${process.pid}-${randomUUID().slice(0, 8)}`, onError = (error) => console.error("[Actions] job worker failed:", error) }) => {
36
+ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leaseMs = 3e4, backoff = {}, workerId = `${process.pid}-${randomUUID().slice(0, 8)}`, onError: customOnError }) => {
37
+ const onError = customOnError ?? ((error) => serverLog.error("Actions", "job worker failed", error));
38
+ const claimFailures = createFailureStreak("Actions", "job claim");
39
+ const heartbeatFailures = createFailureStreak("Actions", "job heartbeat");
35
40
  const { baseMs = 3e4, maxMs = 9e5 } = backoff;
36
41
  const active = /* @__PURE__ */ new Map();
37
42
  /** Every job this worker started, until it has settled — what `stop()` waits for. */
@@ -223,7 +228,7 @@ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leas
223
228
  /** One pass at a time, and the one under way is kept so `stop()` can wait for the claim it may be making. */
224
229
  const guarded = async () => {
225
230
  if (pass) return;
226
- pass = poll().then(() => void 0).catch(onError).finally(() => {
231
+ pass = poll().then(() => claimFailures.succeeded()).catch(customOnError ?? claimFailures.failed).finally(() => {
227
232
  pass = void 0;
228
233
  });
229
234
  await pass;
@@ -236,7 +241,7 @@ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leas
236
241
  if (timer || workers <= 0) return;
237
242
  timer = setInterval(() => void guarded(), pollMs);
238
243
  timer.unref();
239
- heart = setInterval(() => void beat().catch(onError), Math.max(1e3, Math.floor(leaseMs / 3)));
244
+ heart = setInterval(() => void beat().then(() => heartbeatFailures.succeeded()).catch(customOnError ?? heartbeatFailures.failed), Math.max(1e3, Math.floor(leaseMs / 3)));
240
245
  heart.unref();
241
246
  },
242
247
  stop: async () => {
@@ -244,7 +249,7 @@ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leas
244
249
  clearInterval(timer);
245
250
  timer = void 0;
246
251
  await pass;
247
- if (inFlight.size > 0) console.info(`[Actions] waiting for ${inFlight.size} running job(s) to finish before stopping`);
252
+ if (inFlight.size > 0) serverLog.info("Actions", `waiting for ${inFlight.size} running job(s) to finish before stopping`);
248
253
  /**
249
254
  * Drained rather than abandoned: a deploy finishes the jobs it started instead of leaving them to be retried.
250
255
  *
@@ -1,4 +1,5 @@
1
1
  import { createActionsModule } from "./index.js";
2
+ import { realtimeModuleFor } from "../realtime/index.js";
2
3
  //#region src/modules/actions/moduleFor.ts
3
4
  /**
4
5
  * The one actions module for a server, whoever asks first.
@@ -19,16 +20,18 @@ var actionsModuleFor = (config) => {
19
20
  if (existing) return existing;
20
21
  const module = createActionsModule({
21
22
  lookups,
22
- tasks: config.action?.tasks,
23
+ functions: config.functions,
23
24
  limits: config.action?.limits,
24
25
  concurrency: config.action?.concurrency,
25
26
  kv: config.action?.kv,
26
27
  jobs: config.action?.jobs,
27
28
  rateLimit: config.action?.rateLimit,
28
29
  idempotency: config.action?.idempotency,
30
+ signingSecret: config.action?.signingSecret,
29
31
  dbDrivers: config.action?.dbDrivers,
30
32
  email: config.action?.email,
31
- onRun: config.action?.onRun
33
+ onRun: config.action?.onRun,
34
+ realtime: realtimeModuleFor(config)
32
35
  });
33
36
  modules.set(config, module);
34
37
  return module;
@@ -14,3 +14,15 @@ export declare class ActionRunError extends Error {
14
14
  steps?: ActionRunStep[];
15
15
  constructor(reason: ActionErrorReason, message: string);
16
16
  }
17
+ /**
18
+ * A step refusing to go on, with a reason written for whoever called — a password too easy to guess, a board that is
19
+ * read-only, a quota reached.
20
+ *
21
+ * What any other step throws stays in the run's record and never reaches the caller: an error can carry a query, a
22
+ * URL, a credential's name, and a page is shown to anybody. This one says, by its type, that its message was written
23
+ * to be read. A run that ends on it answers `status: 'failed'` with the message as `error`, which a page's flow reads
24
+ * as `{{ step.error }}` — the same place a refusal before the run began puts its own.
25
+ */
26
+ export declare class ActionRefusal extends Error {
27
+ constructor(message: string);
28
+ }
@@ -18,5 +18,20 @@ var ActionRunError = class extends Error {
18
18
  this.reason = reason;
19
19
  }
20
20
  };
21
+ /**
22
+ * A step refusing to go on, with a reason written for whoever called — a password too easy to guess, a board that is
23
+ * read-only, a quota reached.
24
+ *
25
+ * What any other step throws stays in the run's record and never reaches the caller: an error can carry a query, a
26
+ * URL, a credential's name, and a page is shown to anybody. This one says, by its type, that its message was written
27
+ * to be read. A run that ends on it answers `status: 'failed'` with the message as `error`, which a page's flow reads
28
+ * as `{{ step.error }}` — the same place a refusal before the run began puts its own.
29
+ */
30
+ var ActionRefusal = class extends Error {
31
+ constructor(message) {
32
+ super(message);
33
+ this.name = "ActionRefusal";
34
+ }
35
+ };
21
36
  //#endregion
22
- export { ActionRunError };
37
+ export { ActionRefusal, ActionRunError };
@@ -0,0 +1,27 @@
1
+ /** What a change needs of a store: read a key, and write it only if it still holds what was read. */
2
+ export type KvChangeStore<V> = {
3
+ get: (key: string) => Promise<V | undefined>;
4
+ swap: (key: string, expected: V | undefined, next: V, ttlSeconds?: number) => Promise<boolean>;
5
+ };
6
+ /**
7
+ * The lifetime a change writes with: a number of seconds, one worked out from the value written, or none.
8
+ */
9
+ export type KvChangeLifetime<T> = number | ((next: T) => number | undefined);
10
+ export type KvChangeOptions<T> = {
11
+ lifetime?: KvChangeLifetime<T> | undefined;
12
+ /**
13
+ * The error a change that kept losing ends with — an `ActionRefusal` where there is one to make: being too busy is
14
+ * something to tell whoever asked, not a fault. Handed in because this function may import nothing.
15
+ */
16
+ refusal: (message: string) => Error;
17
+ };
18
+ /**
19
+ * Reads `key`, hands its value to `change`, and writes back what that answers — unless somebody wrote in between, and
20
+ * then it reads again and asks again. `change` answering `undefined` writes nothing. Answers what was written, or
21
+ * `undefined` when nothing was. Losing every time ends in `refusal`, whose message names no key: it is for a visitor.
22
+ *
23
+ * The one read-change-write there is: `ctx.kv.change`, a list's writes, and the sandbox's `ctx.kv.change` too — its
24
+ * guest is handed THIS function's source (`isolate.ts`), so it must stay self-contained: no import, nothing of this
25
+ * module's, only what the guest's globals also have (`setTimeout`, `Math`).
26
+ */
27
+ export declare const changeKv: <V, T extends V>(store: KvChangeStore<V>, key: string, change: (current: V | undefined) => T | undefined | Promise<T | undefined>, { lifetime, refusal }: KvChangeOptions<T>) => Promise<T | undefined>;
@@ -0,0 +1,23 @@
1
+ //#region src/modules/actions/runtime/kvChange.ts
2
+ /**
3
+ * Reads `key`, hands its value to `change`, and writes back what that answers — unless somebody wrote in between, and
4
+ * then it reads again and asks again. `change` answering `undefined` writes nothing. Answers what was written, or
5
+ * `undefined` when nothing was. Losing every time ends in `refusal`, whose message names no key: it is for a visitor.
6
+ *
7
+ * The one read-change-write there is: `ctx.kv.change`, a list's writes, and the sandbox's `ctx.kv.change` too — its
8
+ * guest is handed THIS function's source (`isolate.ts`), so it must stay self-contained: no import, nothing of this
9
+ * module's, only what the guest's globals also have (`setTimeout`, `Math`).
10
+ */
11
+ var changeKv = async (store, key, change, { lifetime, refusal }) => {
12
+ const attempts = 25;
13
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
14
+ const current = await store.get(key);
15
+ const next = await change(current);
16
+ if (next === void 0) return;
17
+ if (await store.swap(key, current, next, typeof lifetime === "function" ? lifetime(next) : lifetime)) return next;
18
+ await new Promise((resolve) => setTimeout(resolve, Math.random() * Math.min(5 + attempt * 5, 50)));
19
+ }
20
+ throw refusal("Many people are changing this at once — try again in a moment");
21
+ };
22
+ //#endregion
23
+ export { changeKv };