@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
@@ -0,0 +1,38 @@
1
+ import { ActionRefusal } from "../actions/runtime/errors.js";
2
+ import { changeKv } from "../actions/runtime/kvChange.js";
3
+ import { requestFromWire, responseOf, wireResponseFrom, wireResponseOf } from "../functions/capabilities.js";
4
+ import { FunctionFailure } from "../functions/protocol.js";
5
+ import { createFunctionsDriver, describeFunctions } from "../functions/driver.js";
6
+ //#region src/modules/runtime/runner.ts
7
+ /** A refusal, however it was made: the platform's class, or a bundle's own copy of it — known by its name. */
8
+ var isRefusal = (error) => error instanceof Error && error.name === "ActionRefusal";
9
+ /**
10
+ * A runtime's functions as a runner: the same protocol as the sandbox's, answered by code loaded in this process. The
11
+ * driver is the sandbox's own (`createFunctionsDriver`), so a task behaves the same in both — its `ctx` is calls to the
12
+ * platform, `ctx.kv.change` the same loop, a refusal the same answer. What it does not share is the isolate: there are
13
+ * no limits here but the platform's clock, since this process is the space's alone.
14
+ *
15
+ * The bundle a request names is not asked for: the code is the one this runtime was started with.
16
+ */
17
+ var createRuntimeRunner = (definition = {}) => ({
18
+ describe: () => Promise.resolve(describeFunctions(definition)),
19
+ invoke: async ({ invocation, answer, signal }) => {
20
+ const driver = createFunctionsDriver({
21
+ call: answer,
22
+ signal,
23
+ responseOf: (wire) => responseOf(wireResponseFrom(wire)),
24
+ requestOf: requestFromWire,
25
+ wireOfResponse: async (response) => response instanceof Response ? wireResponseOf(response) : void 0,
26
+ changeKv,
27
+ refusal: (message) => new ActionRefusal(message)
28
+ });
29
+ try {
30
+ return await driver.invoke(definition, invocation);
31
+ } catch (error) {
32
+ if (isRefusal(error)) throw new FunctionFailure("refused", error.message);
33
+ throw error;
34
+ }
35
+ }
36
+ });
37
+ //#endregion
38
+ export { createRuntimeRunner };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import { SpaceRuntime, SpaceRuntimeContext, SpaceRuntimeEndpoint } from './contract';
2
+ import { SSRContext, Stage } from '../../core/http/types';
3
+ import { FunctionsDefinition } from '../functions/contract';
4
+ /** A runtime's endpoints answered in this process — self-hosting — exactly as the platform forwards them to its own. */
5
+ export declare const runtimeEndpointsStage: (endpoints: Record<string, SpaceRuntimeEndpoint>) => Stage<SSRContext>;
6
+ /** A runtime on a server of its own: what `createServer` is handed of it, and how to stop it. */
7
+ export type ServedRuntime = {
8
+ /** Its tasks and routes, for `functions.native`. */
9
+ native: FunctionsDefinition[];
10
+ /** Its endpoints, for `preAuth` — they gate themselves, as the platform's forwarding does. */
11
+ stage: Stage<SSRContext>;
12
+ close: () => Promise<void>;
13
+ };
14
+ /**
15
+ * A space runtime served by a self-hosted server instead of the platform: started here, its functions loaded natively
16
+ * and its endpoints answered by a stage — the same module the platform runs as a runtime of the space.
17
+ */
18
+ export declare const serveRuntime: (runtime: SpaceRuntime, context: SpaceRuntimeContext) => Promise<ServedRuntime>;
19
+ /** Where a space's runtime is, for the page server to forward its endpoints to. */
20
+ export type RuntimeTarget = {
21
+ /** Its base URL — `http://10.0.4.7:8791`. */
22
+ url: string;
23
+ /** What it is presented, as `Authorization: Bearer <secret>`. */
24
+ secret: string;
25
+ /** The paths it answers — what it described when it started. */
26
+ endpoints: readonly string[];
27
+ };
28
+ export type RuntimeProxyConfig = {
29
+ /** The runtime serving a space and environment — or none, for a space the platform serves alone. */
30
+ lookup: (space: {
31
+ spaceId: number;
32
+ environment: string;
33
+ }) => Promise<RuntimeTarget | undefined>;
34
+ /**
35
+ * Told each time a request is forwarded to a space's runtime — not for every request of the space, most of which are
36
+ * its pages: what counts as a runtime being used, for a deployment that stops the ones nobody uses.
37
+ */
38
+ onForward?: (space: {
39
+ spaceId: number;
40
+ environment: string;
41
+ endpoint: string;
42
+ }) => void;
43
+ };
44
+ /**
45
+ * The page server forwarding a space's endpoints to its runtime: the request as it came, streamed both ways — an agent's
46
+ * event stream included — without the visitor's cookies or `Authorization`, and with who asked in `X-Forwarded-*`.
47
+ *
48
+ * A data stage: after the auth chain, so the space is known, and before the space's `/api/` routes and its pages.
49
+ */
50
+ export declare const createRuntimeProxyStage: ({ lookup, onForward }: RuntimeProxyConfig) => Stage<SSRContext>;
@@ -0,0 +1,117 @@
1
+ import { clientIp, requestOrigin } from "../../core/requestParser.js";
2
+ import { endpointFor, endpointProblem } from "./contract.js";
3
+ import { webRequestOf, writeWebResponse } from "../../core/http/webExchange.js";
4
+ import { PLATFORM_HEADERS } from "./host.js";
5
+ import http from "node:http";
6
+ import https from "node:https";
7
+ //#region src/modules/runtime/stages.ts
8
+ var originOf = (ctx) => requestOrigin(ctx.req) || `${ctx.req.protocol}://${ctx.req.hostname}`;
9
+ /** A runtime's endpoints answered in this process — self-hosting — exactly as the platform forwards them to its own. */
10
+ var runtimeEndpointsStage = (endpoints) => {
11
+ const paths = Object.keys(endpoints);
12
+ const problems = paths.flatMap((path) => endpointProblem(path) ?? []);
13
+ if (problems.length > 0) throw new Error(problems.join("; "));
14
+ return async (ctx) => {
15
+ const endpoint = endpointFor(paths, ctx.req.path);
16
+ const answer = endpoint ? endpoints[endpoint] : void 0;
17
+ if (!endpoint || !answer) return false;
18
+ ctx.operation = `endpoint ${endpoint}`;
19
+ const request = await webRequestOf(ctx.raw, `${originOf(ctx)}${ctx.raw.url ?? ctx.req.path}`, PLATFORM_HEADERS);
20
+ await writeWebResponse(ctx.rawRes, await answer(request), ctx.signal);
21
+ return true;
22
+ };
23
+ };
24
+ /**
25
+ * A space runtime served by a self-hosted server instead of the platform: started here, its functions loaded natively
26
+ * and its endpoints answered by a stage — the same module the platform runs as a runtime of the space.
27
+ */
28
+ var serveRuntime = async (runtime, context) => {
29
+ const parts = await runtime.start(context);
30
+ return {
31
+ native: parts.functions ? [parts.functions] : [],
32
+ stage: runtimeEndpointsStage(parts.endpoints ?? {}),
33
+ close: async () => {
34
+ await parts.close?.();
35
+ }
36
+ };
37
+ };
38
+ var HOP_BY_HOP = [
39
+ "connection",
40
+ "keep-alive",
41
+ "transfer-encoding",
42
+ "upgrade"
43
+ ];
44
+ /** The query parameter a platform credential rides in (`credentials.ts`): never forwarded either. */
45
+ var PLATFORM_QUERY_CREDENTIAL = "access-token";
46
+ /** Never forwarded to a runtime: one hop's, and the platform's — the visitor's session is not the runtime's to hold. */
47
+ var NOT_FORWARDED = /* @__PURE__ */ new Set([
48
+ ...HOP_BY_HOP,
49
+ ...PLATFORM_HEADERS,
50
+ "host"
51
+ ]);
52
+ /** Never answered from one: the host's cookies are the platform's, as a function route's are. */
53
+ var NOT_ANSWERED = /* @__PURE__ */ new Set([...HOP_BY_HOP, "set-cookie"]);
54
+ /**
55
+ * The page server forwarding a space's endpoints to its runtime: the request as it came, streamed both ways — an agent's
56
+ * event stream included — without the visitor's cookies or `Authorization`, and with who asked in `X-Forwarded-*`.
57
+ *
58
+ * A data stage: after the auth chain, so the space is known, and before the space's `/api/` routes and its pages.
59
+ */
60
+ var createRuntimeProxyStage = ({ lookup, onForward }) => async (ctx) => {
61
+ const { spaceId, environment = "main" } = ctx.req.ctx.spaceDeployment ?? {};
62
+ if (typeof spaceId !== "number") return false;
63
+ const target = await lookup({
64
+ spaceId,
65
+ environment
66
+ });
67
+ const endpoint = target ? endpointFor(target.endpoints, ctx.req.path) : void 0;
68
+ if (!target || !endpoint) return false;
69
+ ctx.operation = `runtime ${endpoint}`;
70
+ onForward?.({
71
+ spaceId,
72
+ environment,
73
+ endpoint
74
+ });
75
+ const headers = {};
76
+ Object.entries(ctx.raw.headers).forEach(([name, value]) => {
77
+ if (!name.startsWith(":") && !NOT_FORWARDED.has(name) && value !== void 0) headers[name] = value;
78
+ });
79
+ headers.authorization = `Bearer ${target.secret}`;
80
+ headers["x-forwarded-host"] = ctx.req.hostname;
81
+ headers["x-forwarded-proto"] = ctx.req.protocol;
82
+ headers["x-forwarded-for"] = clientIp(ctx.raw, ctx.req);
83
+ const url = new URL(ctx.raw.url ?? ctx.req.path, target.url);
84
+ url.searchParams.delete(PLATFORM_QUERY_CREDENTIAL);
85
+ await new Promise((resolve) => {
86
+ const upstream = (url.protocol === "https:" ? https : http).request(url, {
87
+ method: ctx.raw.method,
88
+ headers
89
+ });
90
+ const unreachable = () => {
91
+ if (!ctx.rawRes.headersSent) {
92
+ ctx.rawRes.writeHead(502, { "content-type": "application/json" });
93
+ ctx.rawRes.end(JSON.stringify({ error: "This space’s runtime is not answering" }));
94
+ } else ctx.rawRes.end();
95
+ resolve();
96
+ };
97
+ ctx.signal.addEventListener("abort", () => upstream.destroy(), { once: true });
98
+ upstream.on("error", unreachable);
99
+ upstream.on("response", (answer) => {
100
+ const answered = {};
101
+ Object.entries(answer.headers).forEach(([name, value]) => {
102
+ if (!NOT_ANSWERED.has(name) && value !== void 0) answered[name] = value;
103
+ });
104
+ ctx.rawRes.writeHead(answer.statusCode ?? 502, answered);
105
+ answer.on("data", (chunk) => ctx.rawRes.write(chunk));
106
+ answer.on("end", () => {
107
+ ctx.rawRes.end();
108
+ resolve();
109
+ });
110
+ answer.on("error", unreachable);
111
+ });
112
+ ctx.raw.pipe(upstream);
113
+ });
114
+ return true;
115
+ };
116
+ //#endregion
117
+ export { createRuntimeProxyStage, runtimeEndpointsStage, serveRuntime };
@@ -13,6 +13,8 @@ export type ComponentProps = {
13
13
  overQuota?: boolean;
14
14
  /** The theme this document was rendered with, from the visitor's cookie. See `prepareRender`. */
15
15
  theme?: Theme;
16
+ /** The kept state the first paint depends on (`settings.paintedState`), from the visitor's cookie. */
17
+ state?: Record<string, unknown>;
16
18
  };
17
- declare const Component: ({ server, renderMode, previewMode, offlineData, environment, plugins, ssrResult, sdkDevToolsStylePath, debugMode, overQuota, theme }: ComponentProps) => import('react').JSX.Element;
19
+ declare const Component: ({ server, renderMode, previewMode, offlineData, environment, plugins, ssrResult, sdkDevToolsStylePath, debugMode, overQuota, theme, state }: ComponentProps) => import('react').JSX.Element;
18
20
  export default Component;
@@ -1,7 +1,7 @@
1
1
  import PlitziSdk from "@plitzi/plitzi-sdk";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  //#region src/modules/ssr/Component.tsx
4
- var Component = ({ server, renderMode = "raw", previewMode = true, offlineData, environment = "main", plugins, ssrResult, sdkDevToolsStylePath, debugMode = false, overQuota, theme }) => {
4
+ var Component = ({ server, renderMode = "raw", previewMode = true, offlineData, environment = "main", plugins, ssrResult, sdkDevToolsStylePath, debugMode = false, overQuota, theme, state }) => {
5
5
  const serverWithResult = {
6
6
  ...server,
7
7
  ssr: {
@@ -20,6 +20,7 @@ var Component = ({ server, renderMode = "raw", previewMode = true, offlineData,
20
20
  debugMode,
21
21
  ...overQuota === void 0 ? {} : { overQuota },
22
22
  ...theme === void 0 ? {} : { theme },
23
+ ...state === void 0 ? {} : { state },
23
24
  children: plugins && Object.keys(plugins).map((key) => /* @__PURE__ */ jsx(PlitziSdk.Plugin, {
24
25
  renderType: key,
25
26
  component: plugins[key].component,
@@ -46,7 +46,7 @@ var renderSSR = async (req, res, config, renderFn, pluginManager, caches) => {
46
46
  res.setHeader("X-Cache", "HIT");
47
47
  if (devMode) res.setHeader("Server-Timing", "html;desc=\"cache-hit\";dur=0");
48
48
  await meterPage(req, config, spaceId, environment, revision, true);
49
- res.send(cached);
49
+ res.send(cached.html, { compressed: cached.compressed });
50
50
  return;
51
51
  }
52
52
  }
@@ -63,7 +63,15 @@ var renderSSR = async (req, res, config, renderFn, pluginManager, caches) => {
63
63
  metrics.log(`${req.method} ${req.path}`);
64
64
  }
65
65
  if (applySSRResult(res, result)) return;
66
- if (htmlCache && cacheKey && body !== void 0 && cacheable) htmlCache.set(cacheKey, body);
66
+ if (htmlCache && cacheKey && body !== void 0 && cacheable) {
67
+ const page = {
68
+ html: body,
69
+ compressed: {}
70
+ };
71
+ htmlCache.set(cacheKey, page);
72
+ res.send(body, { compressed: page.compressed });
73
+ return;
74
+ }
67
75
  res.send(body ?? "");
68
76
  };
69
77
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
1
2
  import { pathToFileURL } from "node:url";
2
3
  //#region src/modules/ssr/loadPluginComponents.ts
3
4
  /** Module-level cache: the bundle's stamped identity → loaded React component. */
@@ -56,7 +57,7 @@ var loadPluginComponents = async (entries, inlineComponents) => {
56
57
  component = mod.default ?? mod;
57
58
  componentCache.set(cacheKey, component);
58
59
  } catch (err) {
59
- console.warn(`[SSR] Plugin "${e.keyName}" cannot be imported server-side, falling back to client rendering:`, err.message);
60
+ serverLog.warn("SSR", `Plugin "${e.keyName}" cannot be imported server-side, falling back to client rendering`, err);
60
61
  failedImports.add(filePath);
61
62
  return;
62
63
  }
@@ -1,5 +1,7 @@
1
1
  import { authorizesDebugging } from "../../helpers/debugAuthorization.js";
2
+ import { realtimeModuleFor } from "../realtime/index.js";
2
3
  import { matchRscPage } from "../rsc/matchRscPage.js";
4
+ import { ssrPaintedCookieName } from "../../helpers/paintedCookie.js";
3
5
  import { readCookie } from "../../helpers/readCookie.js";
4
6
  import { buildOfflineDataCacheKey } from "../../helpers/cache/keys.js";
5
7
  import { loadPluginComponents } from "./loadPluginComponents.js";
@@ -7,18 +9,30 @@ import "../../core/previewToken.js";
7
9
  import { resolveActionEndpoint, resolveRscEndpoint } from "../../core/services/resolve.js";
8
10
  import { createOfflineDataLoader } from "../../helpers/offlineDataLoader.js";
9
11
  import { registerExternalPlugins } from "./registerExternalPlugins.js";
12
+ import { reportMissingPlugins } from "./reportMissingPlugins.js";
10
13
  import { resolvePageSeo } from "./resolvePageSeo.js";
11
14
  import { sdkAssetVersion } from "../../core/sdkAssets.js";
12
15
  import { buildServerInfo } from "../../helpers/buildServerInfo.js";
13
- import { escapeJson } from "../../helpers/escapeJson.js";
16
+ import { hydrationPayload } from "../../helpers/hydrationPayload.js";
14
17
  import { resolveDebugMode } from "../../helpers/resolveDebugMode.js";
15
18
  import { hasServerElements } from "@plitzi/sdk-shared/schema/serverElements";
16
19
  import { debugCookieName } from "@plitzi/sdk-shared/devTools";
17
20
  import { themeFromCookies } from "@plitzi/sdk-shared/theme";
21
+ import { paintedKeys, paintedStateFor } from "@plitzi/sdk-shared/state/paintedState";
18
22
  import { fontUrlResolver, fontsToHead } from "@plitzi/sdk-shared/style";
19
23
  //#region src/modules/ssr/prepareRender.tsx
20
24
  /** Last resort only: used for a page that declares no SEO title and a deployment that supplies none either. */
21
25
  var DEFAULT_TITLE = "Plitzi App";
26
+ /**
27
+ * The theme a space declares a first visit starts in, when it declares one other than `system`.
28
+ *
29
+ * `Partial`, because a style document written before themes existed has no `theme` at all, and a published space
30
+ * is rendered from whatever document it was published with.
31
+ */
32
+ var declaredTheme = (style) => {
33
+ const declared = style?.theme?.default;
34
+ return declared && declared !== "system" ? declared : void 0;
35
+ };
22
36
  var prepareRender = async (req, config, spaceId, environment, revision, pluginManager, offlineDataCache, metrics, offlineDataOverride) => {
23
37
  const m = (name, fn) => metrics ? metrics.measure(name, fn) : Promise.resolve(fn());
24
38
  const offlineCacheKey = environment !== "main" ? buildOfflineDataCacheKey(spaceId, environment, revision) : void 0;
@@ -44,7 +58,9 @@ var prepareRender = async (req, config, spaceId, environment, revision, pluginMa
44
58
  const server = buildServerInfo(req, config, {
45
59
  rscPath,
46
60
  rscData,
47
- actionPath: resolveActionEndpoint(config)
61
+ actionPath: resolveActionEndpoint(config),
62
+ realtimePath: realtimeModuleFor(config)?.path,
63
+ realtimeTransport: realtimeModuleFor(config)?.transport
48
64
  });
49
65
  if (offlineDataOverride === void 0 && !cachedOfflineStr && offlineCacheKey && offlineData !== void 0) offlineDataCache?.set(offlineCacheKey, JSON.stringify(offlineData));
50
66
  const version = config.assetVersion ?? sdkAssetVersion();
@@ -92,22 +108,33 @@ var prepareRender = async (req, config, spaceId, environment, revision, pluginMa
92
108
  * `{{ theme.resolved }}` or gate a rule on the scheme, and a client that started at `system` while the server
93
109
  * rendered `dark` would hydrate different markup and throw away the tree.
94
110
  *
95
- * Absent — a first visit — is not a problem to solve: nothing is stamped, `system` is what the provider starts
96
- * at, and the stylesheet's media queries answer, which is exactly right.
111
+ * Absent — a first visit — the space's own default applies (`style.theme.default`), painted by the server like a
112
+ * choice would be. A default of `system` stamps nothing and the stylesheet's media queries answer, which is exactly
113
+ * right for a space that did not pick.
114
+ */
115
+ const theme = themeFromCookies(req.headers.cookie) ?? declaredTheme(offlineData?.style);
116
+ /**
117
+ * The kept state the first paint depends on, from the cookie the SDK writes the space's `settings.paintedState` to.
118
+ *
119
+ * The theme's reasoning, for the space's own state: web storage is the browser's alone, so what a visitor chose — the
120
+ * tool a toolbar shows, their name in an avatar — would reach the page only after hydration, and be swapped in over
121
+ * the defaults the server drew. Read here, the server draws with it, and the page starts from the same values: it
122
+ * travels as the SDK's `state`, the starting `runtime.state`, in the render and in the payload alike, or the client
123
+ * would hydrate other markup. Only the keys the space declares, and only with `keepState` on.
97
124
  */
98
- const theme = themeFromCookies(req.headers.cookie);
99
- const offlineDataStr = escapeJson(JSON.stringify({
100
- offlineData,
125
+ const paintedState = schema?.settings.keepState ? paintedStateFor(req.headers.cookie, ssrPaintedCookieName(req.headers.host), paintedKeys(schema.settings)) : void 0;
126
+ const offlineDataStr = hydrationPayload(offlineData, {
101
127
  offlineMode: true,
102
128
  environment,
103
129
  renderMode: "raw",
104
130
  server,
105
131
  sdkDevToolsStylePath,
106
132
  ...theme ? { theme } : {},
133
+ ...paintedState ? { state: paintedState } : {},
107
134
  ...clientAnalytics ? { analytics: clientAnalytics } : {},
108
135
  ...overQuota ? { overQuota } : {},
109
136
  ...actionRuns ? { actionRuns } : {}
110
- }));
137
+ });
111
138
  const pluginNames = req.ctx.spaceDeployment?.pluginNames ?? [];
112
139
  const pluginSources = req.ctx.spaceDeployment?.pluginSources;
113
140
  const pluginBaseNames = new Set(pluginNames.map((n) => n.replace(/@[^@]*$/, "")));
@@ -116,7 +143,7 @@ var prepareRender = async (req, config, spaceId, environment, revision, pluginMa
116
143
  const key = pluginManager.ensure(pluginName, pluginSource);
117
144
  if (!pluginBaseNames.has(pluginName)) dynamicNames.push(key);
118
145
  }
119
- const externalNamesFiltered = (config.autoLoadSchemaPlugins !== false ? await m("extPlugins", () => registerExternalPlugins(pluginManager, offlineData)) : []).filter((k) => !pluginBaseNames.has(k.replace(/@[^@]*$/, "")));
146
+ const externalNamesFiltered = (config.autoLoadSchemaPlugins !== false ? await m("extPlugins", () => registerExternalPlugins(pluginManager, offlineData, { allowPrivateHosts: config.allowPrivatePluginHosts === true })) : []).filter((k) => !pluginBaseNames.has(k.replace(/@[^@]*$/, "")));
120
147
  const allPluginNames = [
121
148
  ...pluginNames,
122
149
  ...dynamicNames,
@@ -124,6 +151,7 @@ var prepareRender = async (req, config, spaceId, environment, revision, pluginMa
124
151
  ];
125
152
  const entries = allPluginNames.length > 0 ? await pluginManager.getEntries(allPluginNames) : [];
126
153
  const pluginComponents = await m("plugins", () => loadPluginComponents(entries, pluginManager.getComponents()));
154
+ reportMissingPlugins(spaceId, schema, /* @__PURE__ */ new Set([...Object.keys(pluginComponents), ...entries.map((entry) => entry.keyName)]));
127
155
  const templatePlugins = (entries.length > 0 ? entries : req.ctx.spaceDeployment?.templateProps?.plugins)?.map((entry) => ({
128
156
  ...entry,
129
157
  ssr: entry.keyName in pluginComponents
@@ -138,7 +166,8 @@ var prepareRender = async (req, config, spaceId, environment, revision, pluginMa
138
166
  debugMode: debugRendered,
139
167
  sdkDevToolsStylePath,
140
168
  overQuota,
141
- theme
169
+ theme,
170
+ ...paintedState ? { state: paintedState } : {}
142
171
  },
143
172
  entries,
144
173
  templateParams: {
@@ -1,7 +1,10 @@
1
+ import { StoreMethods } from '../../core/server/fleet/channel';
1
2
  import { DraftStore, OfflineDataRaw, SSRRequest, SSRServerConfig } from '@plitzi/sdk-shared';
2
3
  /** The READ side of draft-preview: a render resolving a stashed draft from its token. The write side — applying
3
4
  * unsaved operations and rendering the result — lives in `@plitzi/sdk-mcp`, which is what knows how to interpret an
4
5
  * operation; a page-only deployment keeps this much and never loads that. */
6
+ /** Every method of the store, for the copy a server's workers share (see `fleet/stores.ts`). */
7
+ export declare const DRAFT_STORE_METHODS: StoreMethods<DraftStore>;
5
8
  /** In-memory draft store — the default when the consumer injects none. Fine for a single replica; a multi-replica
6
9
  * deployment must inject a shared store so a preview URL resolves on any replica. */
7
10
  export declare const createMemoryDraftStore: () => DraftStore;
@@ -3,16 +3,23 @@ import { PREVIEW_COOKIE, readDraftToken } from "../../core/previewToken.js";
3
3
  /** The READ side of draft-preview: a render resolving a stashed draft from its token. The write side — applying
4
4
  * unsaved operations and rendering the result — lives in `@plitzi/sdk-mcp`, which is what knows how to interpret an
5
5
  * operation; a page-only deployment keeps this much and never loads that. */
6
+ /** Every method of the store, for the copy a server's workers share (see `fleet/stores.ts`). */
7
+ var DRAFT_STORE_METHODS = {
8
+ put: true,
9
+ take: true,
10
+ drop: true
11
+ };
6
12
  /** In-memory draft store — the default when the consumer injects none. Fine for a single replica; a multi-replica
7
13
  * deployment must inject a shared store so a preview URL resolves on any replica. */
8
14
  var createMemoryDraftStore = () => {
9
15
  const store = /* @__PURE__ */ new Map();
10
16
  return {
11
- put(token, data, { ttlMs, reusable = false }) {
17
+ put(token, data, { ttlMs, reusable = false, spaceId }) {
12
18
  store.set(token, {
13
19
  data,
14
20
  expiresAt: Date.now() + ttlMs,
15
- reusable
21
+ reusable,
22
+ spaceId
16
23
  });
17
24
  },
18
25
  take(token) {
@@ -21,7 +28,8 @@ var createMemoryDraftStore = () => {
21
28
  if (!hit.reusable || hit.expiresAt <= Date.now()) store.delete(token);
22
29
  return hit.expiresAt > Date.now() ? {
23
30
  data: hit.data,
24
- reusable: hit.reusable
31
+ reusable: hit.reusable,
32
+ spaceId: hit.spaceId
25
33
  } : void 0;
26
34
  },
27
35
  drop(token) {
@@ -39,10 +47,12 @@ var takeDraftOverride = async (req, config) => {
39
47
  const token = readDraftToken(req);
40
48
  if (!token || !config.draftStore) return;
41
49
  const entry = await config.draftStore.take(token);
42
- return entry ? {
43
- ...entry,
50
+ if (!entry || entry.spaceId !== req.ctx.spaceDeployment?.spaceId) return;
51
+ return {
52
+ data: entry.data,
53
+ reusable: entry.reusable,
44
54
  token
45
- } : void 0;
55
+ };
46
56
  };
47
57
  /** The `Set-Cookie` that carries a draft session through the rest of the visit. */
48
58
  var draftSessionCookie = (req, token, ttlMs) => [
@@ -54,4 +64,4 @@ var draftSessionCookie = (req, token, ttlMs) => [
54
64
  ...req.protocol === "https" ? ["Secure"] : []
55
65
  ].join("; ");
56
66
  //#endregion
57
- export { createMemoryDraftStore, draftSessionCookie, takeDraftOverride };
67
+ export { DRAFT_STORE_METHODS, createMemoryDraftStore, draftSessionCookie, takeDraftOverride };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,12 @@
1
1
  import { PluginManager } from '../../plugins/manager';
2
2
  import { OfflineDataRaw } from '@plitzi/sdk-shared';
3
+ /** Where a plugin may be read from: anywhere public, and — on a development machine only — a private address too. */
4
+ type ManifestReach = {
5
+ allowPrivateHosts: boolean;
6
+ };
3
7
  /**
4
8
  * Reads plugins listed in offlineData.plugins, fetches their manifests, downloads and caches
5
9
  * JS/CSS via the PluginManager, and returns the effective plugin keys to pass to getEntries().
6
10
  */
7
- export declare const registerExternalPlugins: (pluginManager: PluginManager, offlineData: OfflineDataRaw | undefined) => Promise<string[]>;
11
+ export declare const registerExternalPlugins: (pluginManager: PluginManager, offlineData: OfflineDataRaw | undefined, reach?: ManifestReach) => Promise<string[]>;
12
+ export {};
@@ -1,3 +1,6 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
2
+ import { fetchOutbound } from "../../helpers/outboundGuard.js";
3
+ import { writeFileAtomic } from "../../helpers/atomicFile.js";
1
4
  import crypto from "node:crypto";
2
5
  import path from "node:path";
3
6
  import fs from "node:fs/promises";
@@ -22,17 +25,17 @@ var readDiskEntry = async (dir, resource) => {
22
25
  var writeDiskEntry = async (dir, resource, entry) => {
23
26
  try {
24
27
  await fs.mkdir(dir, { recursive: true });
25
- await fs.writeFile(cacheFilePath(dir, resource), JSON.stringify(entry), "utf-8");
28
+ await writeFileAtomic(cacheFilePath(dir, resource), JSON.stringify(entry));
26
29
  } catch (err) {
27
- console.warn(`[SSR] Failed to persist plugin manifest cache for ${resource}:`, err);
30
+ serverLog.warn("SSR", `Failed to persist plugin manifest cache for ${resource}`, err);
28
31
  }
29
32
  };
30
- var fetchAndStore = async (dir, resource) => {
33
+ var fetchAndStore = async (dir, resource, reach) => {
31
34
  try {
32
35
  const url = `${resource}/plugin-manifest.json`;
33
- const res = await fetch(url);
36
+ const res = reach.allowPrivateHosts ? await fetch(url) : await fetchOutbound(fetch, new URL(url));
34
37
  if (!res.ok) {
35
- console.warn(`[SSR] Failed to fetch plugin manifest from ${url}: HTTP ${res.status}`);
38
+ serverLog.warn("SSR", `Failed to fetch plugin manifest from ${url}: HTTP ${res.status}`);
36
39
  return null;
37
40
  }
38
41
  const manifest = await res.json();
@@ -44,24 +47,24 @@ var fetchAndStore = async (dir, resource) => {
44
47
  await writeDiskEntry(dir, resource, entry);
45
48
  return manifest;
46
49
  } catch (err) {
47
- console.warn(`[SSR] Error fetching plugin manifest from ${resource}:`, err);
50
+ serverLog.warn("SSR", `Error fetching plugin manifest from ${resource}`, err);
48
51
  return null;
49
52
  }
50
53
  };
51
- var revalidate = (dir, resource) => {
54
+ var revalidate = (dir, resource, reach) => {
52
55
  if (refreshing.has(resource)) return;
53
56
  refreshing.add(resource);
54
- fetchAndStore(dir, resource).finally(() => refreshing.delete(resource));
57
+ fetchAndStore(dir, resource, reach).finally(() => refreshing.delete(resource));
55
58
  };
56
- var fetchManifest = async (pluginManager, resource) => {
59
+ var fetchManifest = async (pluginManager, resource, reach) => {
57
60
  const dir = manifestCacheDir(pluginManager);
58
61
  const cached = manifestCache.get(resource) ?? await readDiskEntry(dir, resource) ?? void 0;
59
62
  if (cached) {
60
63
  manifestCache.set(resource, cached);
61
- if (cached.expiresAt <= Date.now()) revalidate(dir, resource);
64
+ if (cached.expiresAt <= Date.now()) revalidate(dir, resource, reach);
62
65
  return cached.manifest;
63
66
  }
64
- return fetchAndStore(dir, resource);
67
+ return fetchAndStore(dir, resource, reach);
65
68
  };
66
69
  var resolveAssetUrl = (resource, asset) => {
67
70
  if (asset.url) return asset.url;
@@ -74,13 +77,13 @@ var findAsset = (manifest, type, resource) => {
74
77
  return main ? resolveAssetUrl(resource, main) ?? void 0 : void 0;
75
78
  };
76
79
  var isAbsoluteUrl = (url) => url.startsWith("http://") || url.startsWith("https://");
77
- var registerPlugin = async (pluginManager, plugin) => {
80
+ var registerPlugin = async (pluginManager, plugin, reach) => {
78
81
  if (!plugin.resource || !isAbsoluteUrl(plugin.resource)) return null;
79
- const manifest = await fetchManifest(pluginManager, plugin.resource);
82
+ const manifest = await fetchManifest(pluginManager, plugin.resource, reach);
80
83
  if (!manifest) return null;
81
84
  const jsUrl = findAsset(manifest, "script", plugin.resource);
82
85
  if (!jsUrl) {
83
- console.warn(`[SSR] Plugin "${plugin.type}" has no JS asset in manifest, skipping`);
86
+ serverLog.warn("SSR", `Plugin "${plugin.type}" has no JS asset in manifest, skipping`);
84
87
  return null;
85
88
  }
86
89
  const source = {
@@ -95,10 +98,10 @@ var registerPlugin = async (pluginManager, plugin) => {
95
98
  * Reads plugins listed in offlineData.plugins, fetches their manifests, downloads and caches
96
99
  * JS/CSS via the PluginManager, and returns the effective plugin keys to pass to getEntries().
97
100
  */
98
- var registerExternalPlugins = async (pluginManager, offlineData) => {
101
+ var registerExternalPlugins = async (pluginManager, offlineData, reach = { allowPrivateHosts: false }) => {
99
102
  const plugins = offlineData?.plugins;
100
103
  if (!plugins || plugins.length === 0) return [];
101
- return (await Promise.all(plugins.map((p) => registerPlugin(pluginManager, p)))).filter((k) => k !== null);
104
+ return (await Promise.all(plugins.map((p) => registerPlugin(pluginManager, p, reach)))).filter((k) => k !== null);
102
105
  };
103
106
  //#endregion
104
107
  export { registerExternalPlugins };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Schema } from '@plitzi/sdk-shared';
2
+ /**
3
+ * The plugin types a space renders that this server has nothing for — neither a component in the render nor a bundle
4
+ * for the browser. Each prints "Custom Component … Not Found" where the plugin should be, and nothing else anywhere
5
+ * says why, so it is said here: once per space and type, at `error`, because a visitor is looking at the placeholder.
6
+ *
7
+ * A `custom` element carrying its own `scriptUrl` loads itself in the browser and is not this server's to supply.
8
+ */
9
+ export declare const reportMissingPlugins: (spaceId: number, schema: Schema | undefined, available: ReadonlySet<string>) => void;
@@ -0,0 +1,24 @@
1
+ import { serverLog } from "../../helpers/serverLog.js";
2
+ //#region src/modules/ssr/reportMissingPlugins.ts
3
+ var reported = /* @__PURE__ */ new Set();
4
+ /**
5
+ * The plugin types a space renders that this server has nothing for — neither a component in the render nor a bundle
6
+ * for the browser. Each prints "Custom Component … Not Found" where the plugin should be, and nothing else anywhere
7
+ * says why, so it is said here: once per space and type, at `error`, because a visitor is looking at the placeholder.
8
+ *
9
+ * A `custom` element carrying its own `scriptUrl` loads itself in the browser and is not this server's to supply.
10
+ */
11
+ var reportMissingPlugins = (spaceId, schema, available) => {
12
+ if (!schema || !serverLog.enabled("error")) return;
13
+ for (const element of Object.values(schema.flat)) {
14
+ const { renderType, isPlugin, scriptUrl } = element.attributes;
15
+ const loadsItself = isPlugin === true && typeof scriptUrl === "string" && scriptUrl !== "";
16
+ if (element.definition.type !== "custom" || typeof renderType !== "string" || renderType === "" || loadsItself) continue;
17
+ const key = `${spaceId}:${renderType}`;
18
+ if (available.has(renderType) || reported.has(key)) continue;
19
+ reported.add(key);
20
+ serverLog.error("SSR", `Space ${String(spaceId)} renders the plugin "${renderType}" (element "${element.id}"), and this server has none by that name, so the page shows "Custom Component ${renderType} Not Found". Register it in \`plugins\` and name it in the deployment's \`pluginNames\`.`);
21
+ }
22
+ };
23
+ //#endregion
24
+ export { reportMissingPlugins };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
- import { TtlCache } from '../../helpers/cache';
1
+ import { CachedPage, TtlCache } from '../../helpers/cache';
2
2
  import { RequestMetrics } from '../../helpers/metrics';
3
3
  import { PluginManager } from '../../plugins/manager';
4
4
  import { Environment, OfflineDataRaw, SSRPageServerConfig, SSRRequest, SSRResponseHelpers, SSRTemplateFn } from '@plitzi/sdk-shared';
5
- export declare const streamBody: (req: SSRRequest, res: SSRResponseHelpers, config: SSRPageServerConfig, spaceId: number, environment: Environment, revision: number, renderFn: SSRTemplateFn, pluginManager: PluginManager, offlineDataCache?: TtlCache<string>, htmlCache?: TtlCache<string>, cacheKey?: string, metrics?: RequestMetrics, offlineDataOverride?: OfflineDataRaw) => Promise<void>;
5
+ export declare const streamBody: (req: SSRRequest, res: SSRResponseHelpers, config: SSRPageServerConfig, spaceId: number, environment: Environment, revision: number, renderFn: SSRTemplateFn, pluginManager: PluginManager, offlineDataCache?: TtlCache<string>, htmlCache?: TtlCache<CachedPage>, cacheKey?: string, metrics?: RequestMetrics, offlineDataOverride?: OfflineDataRaw) => Promise<void>;
@@ -30,7 +30,10 @@ var streamBody = async (req, res, config, spaceId, environment, revision, render
30
30
  const tailBuf = Buffer.from(tail, "utf-8");
31
31
  res.write(tailBuf);
32
32
  res.end();
33
- if (chunks && cacheKey && htmlCache) htmlCache.set(cacheKey, head + Buffer.concat(chunks).toString("utf-8") + tail);
33
+ if (chunks && cacheKey && htmlCache) htmlCache.set(cacheKey, {
34
+ html: head + Buffer.concat(chunks).toString("utf-8") + tail,
35
+ compressed: {}
36
+ });
34
37
  resolve();
35
38
  cb();
36
39
  }