@statewalker/cellb 0.0.0-stage → 0.1.1

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 (365) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -2
  3. package/dist/adapters/files-backup.d.ts +16 -0
  4. package/dist/adapters/files-backup.js +32 -0
  5. package/dist/adapters/files-backup.js.map +1 -0
  6. package/dist/adapters/files-changelog.d.ts +33 -0
  7. package/dist/adapters/files-changelog.js +96 -0
  8. package/dist/adapters/files-changelog.js.map +1 -0
  9. package/dist/adapters/files-ltx.d.ts +35 -0
  10. package/dist/adapters/files-ltx.js +9 -0
  11. package/dist/adapters/files-ltx.js.map +1 -0
  12. package/dist/adapters/ltx-vfs.d.ts +21 -0
  13. package/dist/adapters/ltx-vfs.js +286 -0
  14. package/dist/adapters/ltx-vfs.js.map +1 -0
  15. package/dist/adapters/node-sqlite.d.ts +45 -0
  16. package/dist/adapters/node-sqlite.js +254 -0
  17. package/dist/adapters/node-sqlite.js.map +1 -0
  18. package/dist/adapters/wasm-page-hook.d.ts +26 -0
  19. package/dist/adapters/wasm-page-hook.js +55 -0
  20. package/dist/adapters/wasm-page-hook.js.map +1 -0
  21. package/dist/adapters/wasm-session.d.ts +11 -0
  22. package/dist/adapters/wasm-session.js +76 -0
  23. package/dist/adapters/wasm-session.js.map +1 -0
  24. package/dist/adapters/wasm-sqlite.d.ts +89 -0
  25. package/dist/adapters/wasm-sqlite.js +258 -0
  26. package/dist/adapters/wasm-sqlite.js.map +1 -0
  27. package/dist/bindings/assets.d.ts +26 -0
  28. package/dist/bindings/assets.js +260 -0
  29. package/dist/bindings/assets.js.map +1 -0
  30. package/dist/bindings/cache.d.ts +16 -0
  31. package/dist/bindings/cache.js +34 -0
  32. package/dist/bindings/cache.js.map +1 -0
  33. package/dist/bindings/celld-kv.d.ts +26 -0
  34. package/dist/bindings/celld-kv.js +81 -0
  35. package/dist/bindings/celld-kv.js.map +1 -0
  36. package/dist/bindings/celld-queues.d.ts +56 -0
  37. package/dist/bindings/celld-queues.js +223 -0
  38. package/dist/bindings/celld-queues.js.map +1 -0
  39. package/dist/bindings/celld-workflows.d.ts +22 -0
  40. package/dist/bindings/celld-workflows.js +54 -0
  41. package/dist/bindings/celld-workflows.js.map +1 -0
  42. package/dist/bindings/cron.d.ts +27 -0
  43. package/dist/bindings/cron.js +232 -0
  44. package/dist/bindings/cron.js.map +1 -0
  45. package/dist/bindings/d1-migrations.d.ts +22 -0
  46. package/dist/bindings/d1-migrations.js +32 -0
  47. package/dist/bindings/d1-migrations.js.map +1 -0
  48. package/dist/bindings/html-rewriter.d.ts +8 -0
  49. package/dist/bindings/html-rewriter.js +75 -0
  50. package/dist/bindings/html-rewriter.js.map +1 -0
  51. package/dist/bindings/r2-celld.d.ts +3 -0
  52. package/dist/bindings/r2-celld.js +113 -0
  53. package/dist/bindings/r2-celld.js.map +1 -0
  54. package/dist/bindings/r2.d.ts +236 -0
  55. package/dist/bindings/r2.js +419 -0
  56. package/dist/bindings/r2.js.map +1 -0
  57. package/dist/bindings/worker-loader.d.ts +83 -0
  58. package/dist/bindings/worker-loader.js +183 -0
  59. package/dist/bindings/worker-loader.js.map +1 -0
  60. package/dist/bindings/workers-ai.d.ts +39 -0
  61. package/dist/bindings/workers-ai.js +175 -0
  62. package/dist/bindings/workers-ai.js.map +1 -0
  63. package/dist/browser.d.ts +7 -0
  64. package/dist/browser.js +8 -0
  65. package/dist/browser.js.map +1 -0
  66. package/dist/bucket/celld-cells.d.ts +86 -0
  67. package/dist/bucket/celld-cells.js +273 -0
  68. package/dist/bucket/celld-cells.js.map +1 -0
  69. package/dist/bucket/celld-format.d.ts +10 -0
  70. package/dist/bucket/celld-format.js +27 -0
  71. package/dist/bucket/celld-format.js.map +1 -0
  72. package/dist/bucket/idb-object-store.d.ts +9 -0
  73. package/dist/bucket/idb-object-store.js +73 -0
  74. package/dist/bucket/idb-object-store.js.map +1 -0
  75. package/dist/bucket/ltx-log.d.ts +34 -0
  76. package/dist/bucket/ltx-log.js +289 -0
  77. package/dist/bucket/ltx-log.js.map +1 -0
  78. package/dist/bucket/object-store.d.ts +51 -0
  79. package/dist/bucket/object-store.js +114 -0
  80. package/dist/bucket/object-store.js.map +1 -0
  81. package/dist/bucket/s3-object-store.d.ts +25 -0
  82. package/dist/bucket/s3-object-store.js +151 -0
  83. package/dist/bucket/s3-object-store.js.map +1 -0
  84. package/dist/bucket/sqlite-object-store.d.ts +10 -0
  85. package/dist/bucket/sqlite-object-store.js +107 -0
  86. package/dist/bucket/sqlite-object-store.js.map +1 -0
  87. package/dist/core/alarms.d.ts +27 -0
  88. package/dist/core/alarms.js +88 -0
  89. package/dist/core/alarms.js.map +1 -0
  90. package/dist/core/async-context.d.ts +34 -0
  91. package/dist/core/async-context.js +50 -0
  92. package/dist/core/async-context.js.map +1 -0
  93. package/dist/core/celld-schema.d.ts +14 -0
  94. package/dist/core/celld-schema.js +34 -0
  95. package/dist/core/celld-schema.js.map +1 -0
  96. package/dist/core/durable-object.d.ts +28 -0
  97. package/dist/core/durable-object.js +31 -0
  98. package/dist/core/durable-object.js.map +1 -0
  99. package/dist/core/gates.d.ts +33 -0
  100. package/dist/core/gates.js +89 -0
  101. package/dist/core/gates.js.map +1 -0
  102. package/dist/core/handles.d.ts +90 -0
  103. package/dist/core/handles.js +224 -0
  104. package/dist/core/handles.js.map +1 -0
  105. package/dist/core/id.d.ts +19 -0
  106. package/dist/core/id.js +64 -0
  107. package/dist/core/id.js.map +1 -0
  108. package/dist/core/namespace.d.ts +38 -0
  109. package/dist/core/namespace.js +141 -0
  110. package/dist/core/namespace.js.map +1 -0
  111. package/dist/core/object-host.d.ts +91 -0
  112. package/dist/core/object-host.js +616 -0
  113. package/dist/core/object-host.js.map +1 -0
  114. package/dist/core/request-body.d.ts +9 -0
  115. package/dist/core/request-body.js +55 -0
  116. package/dist/core/request-body.js.map +1 -0
  117. package/dist/core/runtime.d.ts +121 -0
  118. package/dist/core/runtime.js +366 -0
  119. package/dist/core/runtime.js.map +1 -0
  120. package/dist/core/shard.d.ts +7 -0
  121. package/dist/core/shard.js +10 -0
  122. package/dist/core/shard.js.map +1 -0
  123. package/dist/core/sql-split.d.ts +15 -0
  124. package/dist/core/sql-split.js +101 -0
  125. package/dist/core/sql-split.js.map +1 -0
  126. package/dist/core/sql-storage.d.ts +53 -0
  127. package/dist/core/sql-storage.js +407 -0
  128. package/dist/core/sql-storage.js.map +1 -0
  129. package/dist/core/state.d.ts +44 -0
  130. package/dist/core/state.js +93 -0
  131. package/dist/core/state.js.map +1 -0
  132. package/dist/core/storage.d.ts +103 -0
  133. package/dist/core/storage.js +351 -0
  134. package/dist/core/storage.js.map +1 -0
  135. package/dist/core/worker-rejections.d.ts +21 -0
  136. package/dist/core/worker-rejections.js +55 -0
  137. package/dist/core/worker-rejections.js.map +1 -0
  138. package/dist/index.d.ts +22 -0
  139. package/dist/index.js +23 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/isolate/browser.d.ts +16 -0
  142. package/dist/isolate/browser.js +37 -0
  143. package/dist/isolate/browser.js.map +1 -0
  144. package/dist/isolate/host.d.ts +24 -0
  145. package/dist/isolate/host.js +74 -0
  146. package/dist/isolate/host.js.map +1 -0
  147. package/dist/isolate/isolate-worker.d.ts +1 -0
  148. package/dist/isolate/isolate-worker.js +53 -0
  149. package/dist/isolate/isolate-worker.js.map +1 -0
  150. package/dist/isolate/isolate.d.ts +10 -0
  151. package/dist/isolate/isolate.js +169 -0
  152. package/dist/isolate/isolate.js.map +1 -0
  153. package/dist/isolate/node-entry.d.ts +1 -0
  154. package/dist/isolate/node-entry.js +12 -0
  155. package/dist/isolate/node-entry.js.map +1 -0
  156. package/dist/isolate/protocol.d.ts +66 -0
  157. package/dist/isolate/protocol.js +205 -0
  158. package/dist/isolate/protocol.js.map +1 -0
  159. package/dist/ltx/crc64.d.ts +6 -0
  160. package/dist/ltx/crc64.js +46 -0
  161. package/dist/ltx/crc64.js.map +1 -0
  162. package/dist/ltx/ltx-page-server.d.ts +65 -0
  163. package/dist/ltx/ltx-page-server.js +309 -0
  164. package/dist/ltx/ltx-page-server.js.map +1 -0
  165. package/dist/ltx/ltx-pages.d.ts +81 -0
  166. package/dist/ltx/ltx-pages.js +315 -0
  167. package/dist/ltx/ltx-pages.js.map +1 -0
  168. package/dist/ltx/ltx-store-worker.d.ts +1 -0
  169. package/dist/ltx/ltx-store-worker.js +38 -0
  170. package/dist/ltx/ltx-store-worker.js.map +1 -0
  171. package/dist/ltx/ltx.d.ts +45 -0
  172. package/dist/ltx/ltx.js +203 -0
  173. package/dist/ltx/ltx.js.map +1 -0
  174. package/dist/ltx/lz4.d.ts +9 -0
  175. package/dist/ltx/lz4.js +156 -0
  176. package/dist/ltx/lz4.js.map +1 -0
  177. package/dist/ltx/opfs-sync-files.d.ts +23 -0
  178. package/dist/ltx/opfs-sync-files.js +191 -0
  179. package/dist/ltx/opfs-sync-files.js.map +1 -0
  180. package/dist/ltx/xxh32.d.ts +1 -0
  181. package/dist/ltx/xxh32.js +43 -0
  182. package/dist/ltx/xxh32.js.map +1 -0
  183. package/dist/miniflare-compat/blob-service.d.ts +13 -0
  184. package/dist/miniflare-compat/blob-service.js +66 -0
  185. package/dist/miniflare-compat/blob-service.js.map +1 -0
  186. package/dist/miniflare-compat/kv-binding.d.ts +44 -0
  187. package/dist/miniflare-compat/kv-binding.js +99 -0
  188. package/dist/miniflare-compat/kv-binding.js.map +1 -0
  189. package/dist/miniflare-compat/shims/assert.d.ts +15 -0
  190. package/dist/miniflare-compat/shims/assert.js +24 -0
  191. package/dist/miniflare-compat/shims/assert.js.map +1 -0
  192. package/dist/miniflare-compat/shims/workerd-cloudflare.d.ts +7 -0
  193. package/dist/miniflare-compat/shims/workerd-cloudflare.js +6 -0
  194. package/dist/miniflare-compat/shims/workerd-cloudflare.js.map +1 -0
  195. package/dist/miniflare-compat/shims/workerd-globals.d.ts +1 -0
  196. package/dist/miniflare-compat/shims/workerd-globals.js +30 -0
  197. package/dist/miniflare-compat/shims/workerd-globals.js.map +1 -0
  198. package/dist/miniflare-compat/shims/workerd-internal.d.ts +20 -0
  199. package/dist/miniflare-compat/shims/workerd-internal.js +23 -0
  200. package/dist/miniflare-compat/shims/workerd-internal.js.map +1 -0
  201. package/dist/miniflare-compat/shims/workerd-performance.d.ts +4 -0
  202. package/dist/miniflare-compat/shims/workerd-performance.js +17 -0
  203. package/dist/miniflare-compat/shims/workerd-performance.js.map +1 -0
  204. package/dist/miniflare-compat/simulator-fetcher.d.ts +9 -0
  205. package/dist/miniflare-compat/simulator-fetcher.js +14 -0
  206. package/dist/miniflare-compat/simulator-fetcher.js.map +1 -0
  207. package/dist/miniflare-compat/vendored.d.ts +15 -0
  208. package/dist/miniflare-compat/vendored.js +27 -0
  209. package/dist/miniflare-compat/vendored.js.map +1 -0
  210. package/dist/node-compat/async_hooks.d.ts +22 -0
  211. package/dist/node-compat/async_hooks.js +176 -0
  212. package/dist/node-compat/async_hooks.js.map +1 -0
  213. package/dist/node-compat/browser-registry.d.ts +3 -0
  214. package/dist/node-compat/browser-registry.js +39 -0
  215. package/dist/node-compat/browser-registry.js.map +1 -0
  216. package/dist/node-compat/crypto.d.ts +60 -0
  217. package/dist/node-compat/crypto.js +143 -0
  218. package/dist/node-compat/crypto.js.map +1 -0
  219. package/dist/node-compat/diagnostics_channel.d.ts +27 -0
  220. package/dist/node-compat/diagnostics_channel.js +46 -0
  221. package/dist/node-compat/diagnostics_channel.js.map +1 -0
  222. package/dist/node-compat/fs.d.ts +35 -0
  223. package/dist/node-compat/fs.js +40 -0
  224. package/dist/node-compat/fs.js.map +1 -0
  225. package/dist/node-compat/globals.d.ts +3 -0
  226. package/dist/node-compat/globals.js +4 -0
  227. package/dist/node-compat/globals.js.map +1 -0
  228. package/dist/node-compat/install.d.ts +5 -0
  229. package/dist/node-compat/install.js +12 -0
  230. package/dist/node-compat/install.js.map +1 -0
  231. package/dist/node-compat/module.d.ts +12 -0
  232. package/dist/node-compat/module.js +36 -0
  233. package/dist/node-compat/module.js.map +1 -0
  234. package/dist/node-compat/modules.d.ts +8 -0
  235. package/dist/node-compat/modules.js +23 -0
  236. package/dist/node-compat/modules.js.map +1 -0
  237. package/dist/node-compat/os.d.ts +36 -0
  238. package/dist/node-compat/os.js +36 -0
  239. package/dist/node-compat/os.js.map +1 -0
  240. package/dist/node-compat/process.d.ts +14 -0
  241. package/dist/node-compat/process.js +16 -0
  242. package/dist/node-compat/process.js.map +1 -0
  243. package/dist/node-compat/shims.d.ts +4 -0
  244. package/dist/node.d.ts +5 -0
  245. package/dist/node.js +6 -0
  246. package/dist/node.js.map +1 -0
  247. package/dist/peer/celld-peer.d.ts +53 -0
  248. package/dist/peer/celld-peer.js +555 -0
  249. package/dist/peer/celld-peer.js.map +1 -0
  250. package/dist/ports.d.ts +183 -0
  251. package/dist/ports.js +10 -0
  252. package/dist/ports.js.map +1 -0
  253. package/dist/project/browser-bundle.d.ts +17 -0
  254. package/dist/project/browser-bundle.js +125 -0
  255. package/dist/project/browser-bundle.js.map +1 -0
  256. package/dist/project/browser-cookies.d.ts +12 -0
  257. package/dist/project/browser-cookies.js +90 -0
  258. package/dist/project/browser-cookies.js.map +1 -0
  259. package/dist/project/browser-host.d.ts +173 -0
  260. package/dist/project/browser-host.js +200 -0
  261. package/dist/project/browser-host.js.map +1 -0
  262. package/dist/project/browser-modules.d.ts +17 -0
  263. package/dist/project/browser-modules.js +89 -0
  264. package/dist/project/browser-modules.js.map +1 -0
  265. package/dist/project/browser-shards.d.ts +62 -0
  266. package/dist/project/browser-shards.js +210 -0
  267. package/dist/project/browser-shards.js.map +1 -0
  268. package/dist/project/browser-tabs.d.ts +103 -0
  269. package/dist/project/browser-tabs.js +418 -0
  270. package/dist/project/browser-tabs.js.map +1 -0
  271. package/dist/project/cloudflare-email.d.ts +8 -0
  272. package/dist/project/cloudflare-email.js +11 -0
  273. package/dist/project/cloudflare-email.js.map +1 -0
  274. package/dist/project/cloudflare-workers.d.ts +12 -0
  275. package/dist/project/cloudflare-workers.js +16 -0
  276. package/dist/project/cloudflare-workers.js.map +1 -0
  277. package/dist/project/host-modules.d.ts +4 -0
  278. package/dist/project/host-modules.js +40 -0
  279. package/dist/project/host-modules.js.map +1 -0
  280. package/dist/project/jsonc.d.ts +2 -0
  281. package/dist/project/jsonc.js +27 -0
  282. package/dist/project/jsonc.js.map +1 -0
  283. package/dist/project/lower-await.d.ts +2 -0
  284. package/dist/project/lower-await.js +151 -0
  285. package/dist/project/lower-await.js.map +1 -0
  286. package/dist/project/node-project.d.ts +38 -0
  287. package/dist/project/node-project.js +373 -0
  288. package/dist/project/node-project.js.map +1 -0
  289. package/dist/project/own-module.d.ts +6 -0
  290. package/dist/project/own-module.js +13 -0
  291. package/dist/project/own-module.js.map +1 -0
  292. package/dist/project/scheduler.d.ts +2 -0
  293. package/dist/project/scheduler.js +3 -0
  294. package/dist/project/scheduler.js.map +1 -0
  295. package/dist/project/site.d.ts +74 -0
  296. package/dist/project/site.js +206 -0
  297. package/dist/project/site.js.map +1 -0
  298. package/dist/project/virtual-modules.d.ts +3 -0
  299. package/dist/project/worker-scope.d.ts +27 -0
  300. package/dist/project/worker-scope.js +46 -0
  301. package/dist/project/worker-scope.js.map +1 -0
  302. package/dist/project/workerd-message-channel.d.ts +13 -0
  303. package/dist/project/workerd-message-channel.js +137 -0
  304. package/dist/project/workerd-message-channel.js.map +1 -0
  305. package/dist/project/workers-global-names.d.ts +6 -0
  306. package/dist/project/workers-global-names.js +15 -0
  307. package/dist/project/workers-global-names.js.map +1 -0
  308. package/dist/project/workers-globals-module.d.ts +8 -0
  309. package/dist/project/workers-globals-module.js +9 -0
  310. package/dist/project/workers-globals-module.js.map +1 -0
  311. package/dist/project/workers-globals.d.ts +9 -0
  312. package/dist/project/workers-globals.js +19 -0
  313. package/dist/project/workers-globals.js.map +1 -0
  314. package/dist/project/wrangler.d.ts +116 -0
  315. package/dist/project/wrangler.js +342 -0
  316. package/dist/project/wrangler.js.map +1 -0
  317. package/dist/router/cell-router.d.ts +72 -0
  318. package/dist/router/cell-router.js +247 -0
  319. package/dist/router/cell-router.js.map +1 -0
  320. package/dist/router/shard-worker.d.ts +44 -0
  321. package/dist/router/shard-worker.js +163 -0
  322. package/dist/router/shard-worker.js.map +1 -0
  323. package/dist/transport/cells-http.d.ts +25 -0
  324. package/dist/transport/cells-http.js +141 -0
  325. package/dist/transport/cells-http.js.map +1 -0
  326. package/dist/transport/cells-link.d.ts +27 -0
  327. package/dist/transport/cells-link.js +71 -0
  328. package/dist/transport/cells-link.js.map +1 -0
  329. package/dist/transport/port.d.ts +26 -0
  330. package/dist/transport/port.js +100 -0
  331. package/dist/transport/port.js.map +1 -0
  332. package/dist/v8/codec.d.ts +6 -0
  333. package/dist/v8/codec.js +9 -0
  334. package/dist/v8/codec.js.map +1 -0
  335. package/dist/v8/serialize.d.ts +10 -0
  336. package/dist/v8/serialize.js +601 -0
  337. package/dist/v8/serialize.js.map +1 -0
  338. package/dist/ws/client.d.ts +25 -0
  339. package/dist/ws/client.js +203 -0
  340. package/dist/ws/client.js.map +1 -0
  341. package/dist/ws/control.d.ts +48 -0
  342. package/dist/ws/control.js +44 -0
  343. package/dist/ws/control.js.map +1 -0
  344. package/dist/ws/frames.d.ts +38 -0
  345. package/dist/ws/frames.js +39 -0
  346. package/dist/ws/frames.js.map +1 -0
  347. package/dist/ws/server.d.ts +99 -0
  348. package/dist/ws/server.js +295 -0
  349. package/dist/ws/server.js.map +1 -0
  350. package/dist/ws/sw-connector.d.ts +10 -0
  351. package/dist/ws/sw-connector.js +25 -0
  352. package/dist/ws/sw-connector.js.map +1 -0
  353. package/dist/ws/upgrade.d.ts +28 -0
  354. package/dist/ws/upgrade.js +75 -0
  355. package/dist/ws/upgrade.js.map +1 -0
  356. package/package.json +111 -3
  357. package/vendor/celld/LICENSE +202 -0
  358. package/vendor/celld/kv.js +1131 -0
  359. package/vendor/celld/queues.js +1656 -0
  360. package/vendor/celld/workflows.js +1610 -0
  361. package/vendor/html-rewriter-wasm/html_rewriter.js +925 -0
  362. package/vendor/html-rewriter-wasm/html_rewriter_bg.wasm +0 -0
  363. package/vendor/miniflare/d1-api.js +738 -0
  364. package/vendor/miniflare/d1-database.js +6978 -0
  365. package/vendor/miniflare/kv-namespace.js +3061 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"celld-peer.js","sourceRoot":"","sources":["../../src/peer/celld-peer.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport type { ObjectStore } from \"../bucket/object-store.js\";\nimport { toAnotherNode } from \"../core/handles.js\";\nimport type { CellRuntime } from \"../core/runtime.js\";\nimport { deserialize, serialize } from \"../v8/serialize.js\";\nimport { createWebSocketClass } from \"../ws/client.js\";\nimport { CellsResponse, type CfWebSocket, takeClientPort, WebSocketPair } from \"../ws/server.js\";\nimport { withUpgrade } from \"../ws/upgrade.js\";\n\n/**\n * celld's peer protocol (peer_auth.rs, main/peer_tunnel.rs, protocol 5) for a cellb node\n * hosted in Node, so celld nodes can route a cell's requests to it when it owns the cell.\n *\n * Authentication: every peer request carries an HMAC-SHA-256 over\n * \"cells-peer-request-v1\\n5\\n<method>\\n<path?query>\\n<sha256(body)>\\n<source>\\n<target>\\n<ts>\\n<nonce>\"\n * keyed by the fleet secret in `fleet/peer-auth.json`, with headers x-cells-peer-{version,\n * source,target,timestamp,nonce,body-sha256,signature}; ±30 s clock window, nonce replay cache,\n * and the target must be this node.\n *\n * Tunnel: `GET /peer/tunnel` with `Upgrade: celld-tunnel` (kind `do` or `rpc`) is answered with\n * 101; then the connection carries plain HTTP/1.1 requests, one call each, with control headers\n * x-cells-scope (the cell, \"<Class>:<idhex>\"), x-cells-do-name, x-cells-request-id:\n * do — the application request as is; the reply streams back.\n * rpc — POST, method in x-cells-rpc-method, arguments V8-serialized (an array) or JSON; the\n * reply is the V8-serialized result, or a tagged error (0, then [error, props]).\n * A cell this node does not own answers 409 with `x-cells-route-error: stale-owner`, so celld\n * re-resolves the owner.\n */\nconst PROTOCOL = \"5\";\nconst DOMAIN = \"cells-peer-request-v1\";\nconst CLOCK_WINDOW_MS = 30_000;\nconst PEER_HEADERS = {\n version: \"x-cells-peer-version\",\n source: \"x-cells-peer-source\",\n target: \"x-cells-peer-target\",\n timestamp: \"x-cells-peer-timestamp\",\n nonce: \"x-cells-peer-nonce\",\n bodySha: \"x-cells-peer-body-sha256\",\n signature: \"x-cells-peer-signature\",\n} as const;\nconst CONTROL = [\n \"x-cells-scope\",\n \"x-cells-do-name\",\n \"x-cells-request-id\",\n \"x-cells-capacity-handoff\",\n];\n\n/** The fleet's peer secret (celld creates it in the bucket). */\nexport async function loadPeerKey(store: ObjectStore): Promise<Uint8Array> {\n const o = await store.get(\"fleet/peer-auth.json\");\n if (!o) throw new Error(\"the fleet has no peer authentication secret; start a celld node first\");\n const { version, key } = JSON.parse(new TextDecoder().decode(o.body)) as {\n version: number;\n key: string;\n };\n if (version !== 1 || !/^[0-9a-f]{64}$/.test(key))\n throw new Error(\"unexpected fleet/peer-auth.json\");\n return Uint8Array.from(Buffer.from(key, \"hex\"));\n}\n\nconst sha256hex = (b: Uint8Array) => createHash(\"sha256\").update(b).digest(\"hex\");\nconst mac = (\n key: Uint8Array,\n c: {\n method: string;\n path: string;\n bodySha: string;\n source: string;\n target: string;\n ts: string;\n nonce: string;\n },\n) =>\n createHmac(\"sha256\", key)\n .update(\n `${DOMAIN}\\n${PROTOCOL}\\n${c.method}\\n${c.path}\\n${c.bodySha}\\n${c.source}\\n${c.target}\\n${c.ts}\\n${c.nonce}`,\n )\n .digest();\n\n/** Headers that sign one peer request from `source` to `target`. */\nexport function signPeerRequest(\n key: Uint8Array,\n source: string,\n target: string,\n method: string,\n pathAndQuery: string,\n body: Uint8Array = new Uint8Array(),\n) {\n const ts = String(Date.now());\n const nonce = randomBytes(16).toString(\"hex\");\n const bodySha = sha256hex(body);\n const signature = mac(key, {\n method,\n path: pathAndQuery,\n bodySha,\n source,\n target,\n ts,\n nonce,\n }).toString(\"hex\");\n return {\n [PEER_HEADERS.version]: PROTOCOL,\n [PEER_HEADERS.source]: source,\n [PEER_HEADERS.target]: target,\n [PEER_HEADERS.timestamp]: ts,\n [PEER_HEADERS.nonce]: nonce,\n [PEER_HEADERS.bodySha]: bodySha,\n [PEER_HEADERS.signature]: signature,\n };\n}\n\n/** celld's verification; returns a status and message on failure. */\nexport function verifyPeerRequest(\n key: Uint8Array,\n self: string,\n method: string,\n pathAndQuery: string,\n headers: Record<string, string | string[] | undefined>,\n body: Uint8Array,\n seen: Map<string, number>,\n): { status: number; message: string; stale?: boolean } | undefined {\n const h = (n: string) => (typeof headers[n] === \"string\" ? (headers[n] as string) : undefined);\n const version = h(PEER_HEADERS.version);\n if (version === undefined) return { status: 401, message: \"peer authentication failed\" };\n if (version !== PROTOCOL)\n return { status: 426, message: \"peer protocol version is incompatible\" };\n const [source, target, ts, nonce, bodySha, signature] = [\n PEER_HEADERS.source,\n PEER_HEADERS.target,\n PEER_HEADERS.timestamp,\n PEER_HEADERS.nonce,\n PEER_HEADERS.bodySha,\n PEER_HEADERS.signature,\n ].map(h);\n if (!source || !target || !ts || !nonce || !bodySha || !signature)\n return { status: 401, message: \"peer authentication failed\" };\n const now = Date.now();\n if (!/^\\d+$/.test(ts) || Math.abs(now - Number(ts)) > CLOCK_WINDOW_MS)\n return { status: 401, message: \"peer authentication failed\" };\n if (\n sha256hex(body) !== bodySha ||\n !/^[0-9a-f]{32}$/.test(nonce) ||\n !/^[0-9a-f]{64}$/.test(signature)\n )\n return { status: 401, message: \"peer authentication failed\" };\n const expected = mac(key, { method, path: pathAndQuery, bodySha, source, target, ts, nonce });\n if (!timingSafeEqual(expected, Buffer.from(signature, \"hex\")))\n return { status: 401, message: \"peer authentication failed\" };\n if (target !== self)\n return { status: 409, message: \"peer request targets a different node session\", stale: true };\n for (const [n, t] of seen) if (now - t > 2 * CLOCK_WINDOW_MS) seen.delete(n);\n if (seen.has(nonce)) return { status: 409, message: \"peer request replay rejected\" };\n seen.set(nonce, now);\n return undefined;\n}\n\nconst readBody = async (req: IncomingMessage) => {\n const chunks: Buffer[] = [];\n for await (const c of req) chunks.push(c as Buffer);\n return new Uint8Array(Buffer.concat(chunks));\n};\n\n/** The cell a scope names, as a stub of this runtime (undefined: not a class we host). */\nfunction stubFor(runtime: CellRuntime, scope: string, name: string | undefined): any {\n const m = /^([^:]+):([0-9a-f]{64})$/.exec(scope);\n if (!m) return undefined;\n const binding = Object.entries(runtime.durableObjectBindings).find(\n ([, cls]) => cls === m[1],\n )?.[0];\n if (!binding) return undefined;\n const ns = runtime.env[binding] as any;\n return name !== undefined ? ns.getByName(name) : ns.get(ns.idFromString(m[2]));\n}\n\nconst notOwner = (e: unknown) =>\n /owned by another|OwnedElsewhere|lease/i.test(String((e as Error)?.message ?? e)) ||\n (e as Error)?.name === \"CellOwnedElsewhereError\";\n\nfunction reply(\n res: ServerResponse,\n status: number,\n headers: Record<string, string>,\n body?: Uint8Array | string,\n) {\n res.writeHead(status, { [PEER_HEADERS.version]: PROTOCOL, ...headers });\n res.end(body);\n}\nconst stale = (res: ServerResponse) =>\n reply(\n res,\n 409,\n { \"x-cells-route-error\": \"stale-owner\", \"content-type\": \"text/plain\" },\n \"stale route\",\n );\n\nexport interface CelldPeerServer {\n /** host:port celld dials (put it in the node record: celldBucket({ addr })). */\n addr: string;\n close(): Promise<void>;\n}\n\n/**\n * Serves celld's peer tunnel for `runtime` on `host:port` (0: any free port). `node` is this\n * node's name in the fleet (the same as celldBucket's `node`).\n */\nexport async function startCelldPeerServer(opts: {\n runtime: CellRuntime;\n store: ObjectStore;\n node: string;\n host?: string;\n port?: number;\n /** Answers celld's signed probe (celldBucket(...).probe): `celld diagnose --peer` reaches us. */\n probe?: (challenge: string) => Promise<unknown>;\n}): Promise<CelldPeerServer> {\n const key = await loadPeerKey(opts.store);\n const seen = new Map<string, number>();\n const host = opts.host ?? \"127.0.0.1\";\n\n const serveDo = async (req: IncomingMessage, res: ServerResponse) => {\n const scope = String(req.headers[\"x-cells-scope\"] ?? \"\");\n const name = req.headers[\"x-cells-do-name\"] as string | undefined;\n const stub = stubFor(opts.runtime, scope, name);\n if (!stub) return reply(res, 400, {}, \"malformed cell scope\");\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers))\n if (typeof v === \"string\" && !CONTROL.includes(k)) headers.set(k, v);\n const method = req.method ?? \"GET\";\n const body = method === \"GET\" || method === \"HEAD\" ? undefined : await readBody(req);\n const url = /^https?:\\/\\//.test(req.url ?? \"\")\n ? (req.url as string)\n : `http://${req.headers.host ?? \"cell\"}${req.url ?? \"/\"}`;\n try {\n const r: Response = await stub.fetch(new Request(url, { method, headers, body }));\n const out: Record<string, string> = {};\n r.headers.forEach((v, k) => {\n if (k !== \"content-length\" && k !== \"transfer-encoding\" && k !== \"connection\") out[k] = v;\n });\n reply(res, r.status, out, new Uint8Array(await r.arrayBuffer()));\n } catch (e) {\n if (notOwner(e)) return stale(res);\n reply(res, 500, { \"content-type\": \"text/plain\" }, String((e as Error)?.message ?? e));\n }\n };\n\n const serveRpc = async (req: IncomingMessage, res: ServerResponse) => {\n const scope = String(req.headers[\"x-cells-scope\"] ?? \"\");\n const stub = stubFor(opts.runtime, scope, req.headers[\"x-cells-do-name\"] as string | undefined);\n const method = req.headers[\"x-cells-rpc-method\"] as string | undefined;\n if (!stub) return reply(res, 400, {}, \"malformed cell scope\");\n if (!method) return reply(res, 400, {}, \"RPC method header is missing\");\n const raw = await readBody(req);\n const structured = req.headers[\"content-type\"] === \"application/octet-stream\";\n let args: unknown[];\n if (structured) {\n if (raw[0] !== 0xff) return reply(res, 501, {}, \"RPC stubs cannot cross to cellb\");\n args = deserialize(raw) as unknown[];\n } else args = JSON.parse(new TextDecoder().decode(raw)) as unknown[];\n try {\n const result = await stub[method](...(Array.isArray(args) ? args : [args]));\n if (structured)\n reply(\n res,\n 200,\n { \"content-type\": \"application/octet-stream\" },\n serialize(toAnotherNode(result)),\n );\n else reply(res, 200, { \"content-type\": \"application/json\" }, JSON.stringify(result ?? null));\n } catch (e) {\n if (notOwner(e)) return stale(res);\n if (!structured)\n return reply(\n res,\n 500,\n { \"content-type\": \"text/plain\" },\n `RPC failed: ${String((e as Error)?.message ?? e)}`,\n );\n // celld's callee exception: tag 0, then [error, own properties incl. name]\n const err = e instanceof Error ? e : new Error(String(e));\n const props = e instanceof Error ? { ...e, name: e.name } : { name: \"Error\" };\n const sc = serialize([err, props]);\n const tagged = new Uint8Array(sc.length + 1);\n tagged.set(sc, 1);\n reply(res, 200, { \"content-type\": \"application/octet-stream\" }, tagged);\n }\n };\n\n // One inner HTTP/1.1 server per tunnel kind: an upgraded socket becomes its connection.\n // celld's inner RPC requests carry no Host header: Node would answer 400 by default.\n const inner = {\n do: createServer({ requireHostHeader: false }, (q, s) => void serveDo(q, s)),\n rpc: createServer({ requireHostHeader: false }, (q, s) => void serveRpc(q, s)),\n };\n for (const s of Object.values(inner)) s.keepAliveTimeout = 0;\n // A tunneled WebSocket (celld: the client's own handshake crosses the tunnel and the owner\n // answers it): the cell's 101 + webSocket is bridged to the raw connection, framed by `ws`.\n const { WebSocketServer } = await import(\"ws\");\n const wss = new WebSocketServer({ noServer: true });\n inner.do.on(\"upgrade\", async (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n const fail = (status: number, body: string, extra: Record<string, string> = {}) => {\n const lines = [\n `HTTP/1.1 ${status} ${status === 409 ? \"Conflict\" : \"Error\"}`,\n `${PEER_HEADERS.version}: ${PROTOCOL}`,\n `content-length: ${Buffer.byteLength(body)}`,\n \"connection: close\",\n ];\n for (const [k, v] of Object.entries(extra)) lines.push(`${k}: ${v}`);\n socket.end(`${lines.join(\"\\r\\n\")}\\r\\n\\r\\n${body}`);\n };\n const stub = stubFor(\n opts.runtime,\n String(req.headers[\"x-cells-scope\"] ?? \"\"),\n req.headers[\"x-cells-do-name\"] as string | undefined,\n );\n if (!stub) return fail(400, \"malformed cell scope\");\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers))\n if (typeof v === \"string\" && !CONTROL.includes(k)) headers.set(k, v);\n const url = /^https?:\\/\\//.test(req.url ?? \"\")\n ? (req.url as string)\n : `http://${req.headers.host ?? \"cell\"}${req.url ?? \"/\"}`;\n const protocols = req.headers[\"sec-websocket-protocol\"] as string | undefined;\n let res: Response & { webSocket?: CfWebSocket | null };\n try {\n res = await stub.fetch(\n withUpgrade(\n new Request(url, { headers }),\n \"websocket\",\n protocols ? { \"Sec-WebSocket-Protocol\": protocols } : undefined,\n ),\n );\n } catch (e) {\n return notOwner(e)\n ? fail(409, \"stale route\", { \"x-cells-route-error\": \"stale-owner\" })\n : fail(500, String((e as Error)?.message ?? e));\n }\n if (res.status !== 101 || !res.webSocket) return fail(res.status, await res.text());\n const port = takeClientPort(res.webSocket);\n const WS = createWebSocketClass(async () => ({\n port,\n protocol: res.headers.get(\"Sec-WebSocket-Protocol\") ?? undefined,\n }));\n const cell = new WS(\"ws://cell/\") as WebSocket;\n cell.binaryType = \"arraybuffer\";\n const pending: (string | ArrayBuffer)[] = [];\n let open = false;\n wss.handleUpgrade(req, socket, head, (client) => {\n cell.onopen = () => {\n open = true;\n for (const m of pending.splice(0)) cell.send(m);\n };\n client.on(\"message\", (data: Buffer, isBinary: boolean) => {\n const m = isBinary ? (new Uint8Array(data).buffer as ArrayBuffer) : data.toString();\n if (open) cell.send(m);\n else pending.push(m);\n });\n cell.onmessage = (ev: MessageEvent) =>\n client.send(ev.data instanceof ArrayBuffer ? Buffer.from(ev.data) : ev.data);\n client.on(\"close\", (code: number, reason: Buffer) =>\n cell.close(\n code >= 1000 && code < 5000 && code !== 1005 && code !== 1006 ? code : 1000,\n reason.toString(),\n ),\n );\n cell.onclose = (ev: CloseEvent) =>\n client.close(\n ev.code >= 1000 && ev.code !== 1005 && ev.code !== 1006 ? ev.code : 1000,\n ev.reason,\n );\n });\n });\n\n const server: Server = createServer(async (req, res) => {\n if (req.url === \"/peer/probe\" && req.method === \"GET\" && opts.probe) {\n const denied = verifyPeerRequest(\n key,\n opts.node,\n \"GET\",\n \"/peer/probe\",\n req.headers,\n new Uint8Array(),\n seen,\n );\n if (denied)\n return reply(res, denied.status, { \"content-type\": \"text/plain\" }, denied.message);\n try {\n const answer = await opts.probe(String(req.headers[\"x-cells-probe-challenge\"] ?? \"\"));\n return reply(res, 200, { \"content-type\": \"application/json\" }, JSON.stringify(answer));\n } catch (e) {\n return reply(\n res,\n 400,\n { \"content-type\": \"text/plain\" },\n String((e as Error)?.message ?? e),\n );\n }\n }\n reply(res, 404, {}, \"not found\");\n });\n server.on(\"upgrade\", (req: IncomingMessage, socket: Duplex, head: Buffer) => {\n const path = req.url ?? \"/\";\n const refuse = (status: number, message: string, extra: Record<string, string> = {}) => {\n const lines = [\n `HTTP/1.1 ${status} ${message}`,\n `${PEER_HEADERS.version}: ${PROTOCOL}`,\n \"connection: close\",\n \"content-length: 0\",\n ];\n for (const [k, v] of Object.entries(extra)) lines.push(`${k}: ${v}`);\n socket.end(`${lines.join(\"\\r\\n\")}\\r\\n\\r\\n`);\n };\n if (path !== \"/peer/tunnel\" || req.headers.upgrade !== \"celld-tunnel\")\n return refuse(404, \"Not Found\");\n const denied = verifyPeerRequest(\n key,\n opts.node,\n req.method ?? \"GET\",\n path,\n req.headers,\n new Uint8Array(),\n seen,\n );\n if (denied)\n return refuse(\n denied.status,\n denied.message,\n denied.stale ? { \"x-cells-route-error\": \"stale-owner\" } : {},\n );\n if (req.headers[\"x-cells-tunnel-version\"] !== \"5\") return refuse(426, \"Upgrade Required\");\n const kind = req.headers[\"x-cells-tunnel-kind\"];\n if (kind !== \"do\" && kind !== \"rpc\") return refuse(400, \"Bad Request\");\n socket.write(\n [\n \"HTTP/1.1 101 Switching Protocols\",\n \"upgrade: celld-tunnel\",\n \"connection: upgrade\",\n \"x-cells-tunnel-version: 5\",\n `${PEER_HEADERS.version}: ${PROTOCOL}`,\n ].join(\"\\r\\n\") + \"\\r\\n\\r\\n\",\n );\n if (head?.length) socket.unshift(head);\n inner[kind].emit(\"connection\", socket);\n });\n await new Promise<void>((r) => server.listen(opts.port ?? 0, host, () => r()));\n const port = (server.address() as { port: number }).port;\n return {\n addr: `${host}:${port}`,\n close: () =>\n new Promise<void>((r) => {\n server.closeAllConnections?.();\n for (const s of Object.values(inner)) s.closeAllConnections?.();\n server.close(() => r());\n }),\n };\n}\n\n/**\n * The calling half (celld's node A): open a signed tunnel to the owner node and send one call\n * through it — `fetch` on a `do` tunnel, JS RPC on an `rpc` tunnel (V8-serialized arguments;\n * the reply decoded as celld encodes it, a callee exception rethrown with its properties).\n */\n/** A signed `celld-tunnel` upgrade to the owner node: the raw connection after its 101. */\nasync function openTunnel(\n key: Uint8Array,\n source: string,\n owner: { node: string; addr: string },\n kind: \"do\" | \"rpc\",\n): Promise<import(\"node:net\").Socket> {\n const { request } = await import(\"node:http\");\n const [host, port] = [\n owner.addr.slice(0, owner.addr.lastIndexOf(\":\")),\n Number(owner.addr.slice(owner.addr.lastIndexOf(\":\") + 1)),\n ];\n const socket = await new Promise<import(\"node:net\").Socket>((resolve, reject) => {\n const req = request({\n host,\n port,\n path: \"/peer/tunnel\",\n method: \"GET\",\n headers: {\n upgrade: \"celld-tunnel\",\n connection: \"upgrade\",\n \"x-cells-tunnel-version\": \"5\",\n \"x-cells-tunnel-kind\": kind,\n ...signPeerRequest(key, source, owner.node, \"GET\", \"/peer/tunnel\"),\n },\n });\n req.on(\"upgrade\", (_res, sock) => resolve(sock as import(\"node:net\").Socket));\n req.on(\"response\", (res) =>\n reject(\n Object.assign(new Error(`peer tunnel refused: ${res.statusCode}`), {\n stale: res.headers[\"x-cells-route-error\"] === \"stale-owner\",\n }),\n ),\n );\n req.on(\"error\", reject);\n req.end();\n });\n return socket;\n}\n\nasync function tunnelCall(\n key: Uint8Array,\n source: string,\n owner: { node: string; addr: string },\n kind: \"do\" | \"rpc\",\n inner: { method: string; path: string; headers: Record<string, string>; body?: Uint8Array },\n): Promise<{ status: number; headers: Record<string, string>; body: Uint8Array }> {\n const { request } = await import(\"node:http\");\n const socket = await openTunnel(key, source, owner, kind);\n try {\n return await new Promise((resolve, reject) => {\n const req = request(\n // no agent: the request runs on the upgraded socket itself\n {\n createConnection: () => socket,\n method: inner.method,\n path: inner.path,\n headers: inner.headers,\n },\n async (res) => {\n const chunks: Buffer[] = [];\n for await (const c of res) chunks.push(c as Buffer);\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(res.headers))\n if (typeof v === \"string\") headers[k] = v;\n resolve({\n status: res.statusCode ?? 500,\n headers,\n body: new Uint8Array(Buffer.concat(chunks)),\n });\n },\n );\n req.on(\"error\", reject);\n req.end(inner.body);\n });\n } finally {\n socket.destroy();\n }\n}\n\n/**\n * Routing to cells celld nodes own, for CellRuntimeOptions.peers: `ownerOf` reads the cell's\n * own.json, `endpoint` reaches the owner's address from its node record through the tunnel.\n */\nexport function celldPeers(opts: { store: ObjectStore; node: string }) {\n let key: Promise<Uint8Array> | undefined;\n const json = async <T>(k: string) => {\n const o = await opts.store.get(k);\n return o ? (JSON.parse(new TextDecoder().decode(o.body)) as T) : undefined;\n };\n const staleError = (cellKey: string) =>\n Object.assign(new Error(`${cellKey} is owned by another node`), {\n name: \"CellOwnedElsewhereError\",\n });\n return {\n async ownerOf(cellKey: string) {\n const own = await json<{ node: string }>(`cells/${cellKey.replace(\"/\", \":\")}/own.json`);\n return own?.node && own.node !== opts.node ? own.node : undefined;\n },\n link(): never {\n throw new Error(\"celld owners are reached through endpoint()\");\n },\n async endpoint(owner: string, cellKey: string, name: string | undefined) {\n const lease = await json<{ addr: string; expires_ms: number }>(`nodes/${owner}.json`);\n if (!lease?.addr || lease.expires_ms <= Date.now()) return undefined;\n key ??= loadPeerKey(opts.store);\n const k = await key;\n const target = { node: owner, addr: lease.addr };\n const scope = cellKey.replace(\"/\", \":\");\n const control = (h: Record<string, string>) => ({\n ...h,\n \"x-cells-scope\": scope,\n ...(name !== undefined ? { \"x-cells-do-name\": name } : {}),\n });\n // A WebSocket to a cell celld owns: the client handshake crosses a `do` tunnel and `ws`\n // speaks the frames on it; the caller gets a 101 with a WebSocketPair end bridged to it.\n const tunnelWebSocket = async (req: Request, url: URL) => {\n const socket = await openTunnel(k, opts.node, target, \"do\");\n const { WebSocket: WsClient } = await import(\"ws\");\n const protocols = req.headers\n .get(\"sec-websocket-protocol\")\n ?.split(\",\")\n .map((p) => p.trim())\n .filter(Boolean);\n const remote = new WsClient(`ws://${url.host}${url.pathname}${url.search}`, protocols, {\n createConnection: () => socket,\n headers: control({}),\n });\n await new Promise<void>((resolve, reject) => {\n remote.once(\"open\", () => resolve());\n remote.once(\n \"unexpected-response\",\n (_q: unknown, res: { statusCode?: number; headers: Record<string, unknown> }) =>\n reject(\n res.headers[\"x-cells-route-error\"] === \"stale-owner\"\n ? staleError(cellKey)\n : new Error(`WebSocket through the tunnel refused: ${res.statusCode}`),\n ),\n );\n remote.once(\"error\", reject);\n });\n const pair = new WebSocketPair();\n const [client, server] = [pair[0], pair[1]];\n server.accept();\n server.addEventListener(\"message\", (e) => remote.send((e as MessageEvent).data));\n remote.on(\"message\", (d: Buffer, isBinary: boolean) =>\n server.send(isBinary ? new Uint8Array(d) : d.toString()),\n );\n const code = (c: number) => (c >= 1000 && c !== 1005 && c !== 1006 ? c : 1000);\n server.addEventListener(\"close\", (e) =>\n remote.close(code((e as CloseEvent).code), (e as CloseEvent).reason),\n );\n remote.on(\"close\", (c: number, reason: Buffer) => server.close(code(c), reason.toString()));\n return new CellsResponse(null, {\n status: 101,\n webSocket: client,\n headers: remote.protocol ? { \"Sec-WebSocket-Protocol\": remote.protocol } : {},\n }) as Response;\n };\n return {\n async fetch(req: Request) {\n const url = new URL(req.url);\n if (req.headers.get(\"upgrade\")?.toLowerCase() === \"websocket\")\n return tunnelWebSocket(req, url);\n const headers: Record<string, string> = {};\n req.headers.forEach((v, h) => {\n if (!h.startsWith(\"x-cells-\")) headers[h] = v;\n });\n headers.host ??= url.host;\n const body =\n req.method === \"GET\" || req.method === \"HEAD\"\n ? undefined\n : new Uint8Array(await req.arrayBuffer());\n const r = await tunnelCall(k, opts.node, target, \"do\", {\n method: req.method,\n path: url.pathname + url.search,\n headers: control(headers),\n body,\n });\n if (r.status === 409 && r.headers[\"x-cells-route-error\"] === \"stale-owner\")\n throw staleError(cellKey);\n const out = new Headers();\n for (const [h, v] of Object.entries(r.headers))\n if (!h.startsWith(\"x-cells-\")) out.set(h, v);\n return new Response(r.status === 204 || r.status === 304 ? null : (r.body as BodyInit), {\n status: r.status,\n headers: out,\n });\n },\n async call(method: string, args: unknown[]) {\n const body = serialize(toAnotherNode(args));\n const r = await tunnelCall(k, opts.node, target, \"rpc\", {\n method: \"POST\",\n path: \"/\",\n headers: control({\n \"x-cells-rpc-method\": method,\n \"content-type\": \"application/octet-stream\",\n \"content-length\": String(body.length),\n }),\n body,\n });\n if (r.status === 409 && r.headers[\"x-cells-route-error\"] === \"stale-owner\")\n throw staleError(cellKey);\n if (r.status !== 200)\n throw new Error(\n `remote RPC failed with ${r.status}: ${new TextDecoder().decode(r.body)}`,\n );\n if (r.body[0] === 0xff) return deserialize(r.body);\n if (r.body[0] === 0) {\n const [error, props] = deserialize(r.body.subarray(1)) as [\n unknown,\n Record<string, unknown>,\n ];\n if (error instanceof Error) Object.assign(error, props, { remote: true });\n throw error;\n }\n throw new Error(\"RPC stubs cannot cross from celld to cellb\");\n },\n };\n },\n };\n}\n"]}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Ports: the only things that differ between browser and server hosts.
3
+ * Everything in `core/` depends on these interfaces and nothing else.
4
+ */
5
+ import type { ObjectStore } from "./bucket/object-store.js";
6
+ /** Result of one SQL statement, in array-of-arrays form (cheap to copy across ports). */
7
+ export interface SqlResult {
8
+ columnNames: string[];
9
+ rows: unknown[][];
10
+ rowsWritten: number;
11
+ }
12
+ /**
13
+ * SYNCHRONOUS SQLite driver, one per cell.
14
+ * Browser: SQLite WASM + opfs-sahpool VFS inside a dedicated Worker (P04).
15
+ * Server: node:sqlite DatabaseSync / better-sqlite3 / bun:sqlite.
16
+ */
17
+ export interface SyncSqlDriver {
18
+ /** Executes one statement (or a param-less script, returning the last statement's result). */
19
+ exec(sql: string, params: unknown[]): SqlResult;
20
+ /** Size of the database in bytes (ctx.storage.sql.databaseSize). */
21
+ databaseSize(): number;
22
+ /**
23
+ * Whether a transaction is open (SQLite's `sqlite3_get_autocommit() == 0`): after a failed
24
+ * statement, tells whether SQLite rolled the transaction back by itself (I/O errors, a full
25
+ * disk, out of memory). Optional; without it the storage asks SQLite with a statement.
26
+ */
27
+ inTransaction?(): boolean;
28
+ close(): void;
29
+ /** Loads a named SQLite extension (e.g. "sqlite_vec" for celld's `sqlite_vec` flag). */
30
+ loadExtension(name: string): void;
31
+ /**
32
+ * Change capture for transaction logs (SQLite session extension): `captureStart()` at
33
+ * BEGIN, `captureTake()` after COMMIT returns the transaction's changeset (empty if none),
34
+ * `applyChangeset()` replays one. `captureCoversRowidTables` is false when tables without
35
+ * a PRIMARY KEY are invisible to the session (node:sqlite has no ROWID session option).
36
+ */
37
+ captureStart?(): void;
38
+ captureTake?(): Uint8Array;
39
+ captureDiscard?(): void;
40
+ applyChangeset?(changeset: Uint8Array): void;
41
+ readonly captureCoversRowidTables?: boolean;
42
+ /** The database file page for page (page-level logs); defaults to image(). */
43
+ pageImage?(): Uint8Array;
44
+ /** Pages written since the previous call, when the driver can hook its file (SQLite WASM). */
45
+ takeDirtyPages(): {
46
+ pageSize: number;
47
+ pageCount: number;
48
+ pages: Map<number, Uint8Array>;
49
+ } | undefined;
50
+ discardDirtyPages?(): void;
51
+ /** Consistent image of the whole database (no transaction may be open). Needed for backups. */
52
+ image?(): Uint8Array;
53
+ /** Replaces the whole database with an image produced by `image()`. Needed for restores. */
54
+ restore?(image: Uint8Array): void;
55
+ }
56
+ /**
57
+ * Lease port: per-cell ownership, at most one live holder per cell key. `epoch` is a
58
+ * monotonically increasing fencing token: every durable write of the holder must carry
59
+ * it, so a paused ex-holder cannot overwrite its successor. (Browser shards are not
60
+ * leased through this port: a shard worker holds the shard's Web Lock.)
61
+ */
62
+ export interface LeaseHandle {
63
+ readonly name: string;
64
+ readonly epoch: number;
65
+ /** Aborted when the holder must stop serving (renewal failed, deadline passed, fenced). */
66
+ readonly lost: AbortSignal;
67
+ release(): Promise<void>;
68
+ }
69
+ export interface Lease {
70
+ tryAcquire(name: string): Promise<LeaseHandle | undefined>;
71
+ }
72
+ export interface Clock {
73
+ now(): number;
74
+ setTimeout(fn: () => void, ms: number): unknown;
75
+ clearTimeout(handle: unknown): void;
76
+ }
77
+ export declare const systemClock: Clock;
78
+ /** Opens (or creates) the SQLite database of a cell. */
79
+ export type OpenCellSql = ((cellKey: string) => SyncSqlDriver) & {
80
+ /**
81
+ * Opening is synchronous, but a store may need time to make room (an OPFS pool grows
82
+ * asynchronously). Called before a cell's first event: a promise to await before opening
83
+ * `cellKey`, or undefined when it can open now. The runtime then opens it.
84
+ */
85
+ room?(cellKey: string): Promise<void> | undefined;
86
+ };
87
+ /**
88
+ * Durability port: called after every local commit. The output gate holds
89
+ * outgoing responses until the returned promise resolves. P06 plugs
90
+ * replication to a FilesApi (OPFS / S3) here; the default resolves at once.
91
+ */
92
+ export interface CellDurability {
93
+ committed(cellKey: string, info: {
94
+ seq: number;
95
+ changes?: CommitChanges;
96
+ /** The committed database image (or a thunk producing it on demand). */
97
+ image?: Uint8Array | (() => Uint8Array | undefined | Promise<Uint8Array | undefined>);
98
+ /** The transaction's changed pages, when the driver hooks its file. */
99
+ pages?: {
100
+ pageSize: number;
101
+ pageCount: number;
102
+ pages: Map<number, Uint8Array>;
103
+ };
104
+ epoch?: number;
105
+ }): Promise<void>;
106
+ /**
107
+ * celld's alarm wake index: after a commit that changed the alarm, its publication
108
+ * (writer epoch, sequence, due time) — written once the commit is durable.
109
+ */
110
+ publishWake?(cellKey: string, wake: {
111
+ epoch: number;
112
+ sequence: number;
113
+ at: number | null;
114
+ }): Promise<void>;
115
+ /** Alarms published in the shared wake index (by any node), so this node can fire them. */
116
+ wakes?(): Promise<{
117
+ cellKey: string;
118
+ className: string;
119
+ at: number;
120
+ }[]>;
121
+ /** Asks the runtime for the whole database image after each commit (page-level logs: LTX). */
122
+ readonly capturePages?: boolean;
123
+ /** Asks the runtime to capture each transaction's changes (transaction-log durability). */
124
+ readonly captureChanges?: boolean;
125
+ }
126
+ /**
127
+ * One committed transaction, as a log segment: schema statements, the row changes (a
128
+ * SQLite changeset), and — only for drivers whose capture misses tables without a PRIMARY
129
+ * KEY — the write statements on such tables. `logSeq` is stored in the database itself
130
+ * (`_cf_METADATA`), so a snapshot knows which segments it already contains.
131
+ */
132
+ export interface CommitChanges {
133
+ logSeq: number;
134
+ /** Fencing epoch of the owner that committed it (from the cell's lease), if owned. */
135
+ epoch?: number;
136
+ ddl: string[];
137
+ changeset: Uint8Array;
138
+ statements: [string, unknown[]][];
139
+ }
140
+ /** Serialization of KV values (CF uses V8 serialization; swap for webrun-msgpack later). */
141
+ export interface ValueCodec {
142
+ encode(value: unknown): Uint8Array;
143
+ decode(bytes: Uint8Array): unknown;
144
+ }
145
+ export interface BackupInfo {
146
+ /** Local commit counter of the cell at snapshot time (monotonic per live instance). */
147
+ seq: number;
148
+ takenAt: number;
149
+ reason: "interval" | "manual" | "close";
150
+ /** Last transaction-log segment contained in the image (0 when no log is kept). */
151
+ logSeq?: number;
152
+ }
153
+ /**
154
+ * Durability by periodic backup: `save` receives a consistent SQLite image of a
155
+ * cell whenever it changed since the last successful save (every `intervalMs`,
156
+ * on `runtime.backupNow()` and on `runtime.close()`). `load` restores a cell
157
+ * whose local database is empty, and under a cell lease replaces the local
158
+ * database on every acquisition. RPO = interval: writes after the last
159
+ * successful save can be lost with the local store (e.g. an evicted OPFS).
160
+ */
161
+ export interface CellBackup {
162
+ save(cellKey: string, image: Uint8Array, info: BackupInfo): Promise<void>;
163
+ load?(cellKey: string): Promise<Uint8Array | undefined>;
164
+ /** Transaction-log segments after `afterLogSeq`, in order (replayed after `load`). */
165
+ replay?(cellKey: string, afterLogSeq: number): AsyncIterable<CommitChanges>;
166
+ intervalMs?: number;
167
+ onError?(cellKey: string, error: unknown): void;
168
+ }
169
+ /**
170
+ * Where a runtime keeps its cells beyond the local SQLite files, as one bundle: a celld fleet
171
+ * bucket (`celldBucket`) or a log on a FilesApi (`filesApiChangeLog`, `filesApiLtxLog`) fills
172
+ * the members it has. The runtime owns it: `runtime.close()` takes the final backups first,
173
+ * then calls `close()`.
174
+ */
175
+ export interface CellStorage {
176
+ durability?: CellDurability;
177
+ backup?: CellBackup;
178
+ /** Per-cell ownership: each object takes this lease before it opens (fencing epoch → log). */
179
+ ownership?: Lease;
180
+ /** Where R2 bindings keep their objects (a celld fleet bucket, in celld's layout). */
181
+ objects?: ObjectStore;
182
+ close?(): Promise<void>;
183
+ }
package/dist/ports.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ports: the only things that differ between browser and server hosts.
3
+ * Everything in `core/` depends on these interfaces and nothing else.
4
+ */
5
+ export const systemClock = {
6
+ now: () => Date.now(),
7
+ setTimeout: (fn, ms) => setTimeout(fn, ms),
8
+ clearTimeout: (h) => clearTimeout(h),
9
+ };
10
+ //# sourceMappingURL=ports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA8EH,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC;IAC1C,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAkC,CAAC;CACtE,CAAC","sourcesContent":["/**\n * Ports: the only things that differ between browser and server hosts.\n * Everything in `core/` depends on these interfaces and nothing else.\n */\n\nimport type { ObjectStore } from \"./bucket/object-store.js\";\n\n/** Result of one SQL statement, in array-of-arrays form (cheap to copy across ports). */\nexport interface SqlResult {\n columnNames: string[];\n rows: unknown[][];\n rowsWritten: number;\n}\n\n/**\n * SYNCHRONOUS SQLite driver, one per cell.\n * Browser: SQLite WASM + opfs-sahpool VFS inside a dedicated Worker (P04).\n * Server: node:sqlite DatabaseSync / better-sqlite3 / bun:sqlite.\n */\nexport interface SyncSqlDriver {\n /** Executes one statement (or a param-less script, returning the last statement's result). */\n exec(sql: string, params: unknown[]): SqlResult;\n /** Size of the database in bytes (ctx.storage.sql.databaseSize). */\n databaseSize(): number;\n /**\n * Whether a transaction is open (SQLite's `sqlite3_get_autocommit() == 0`): after a failed\n * statement, tells whether SQLite rolled the transaction back by itself (I/O errors, a full\n * disk, out of memory). Optional; without it the storage asks SQLite with a statement.\n */\n inTransaction?(): boolean;\n close(): void;\n /** Loads a named SQLite extension (e.g. \"sqlite_vec\" for celld's `sqlite_vec` flag). */\n loadExtension(name: string): void;\n /**\n * Change capture for transaction logs (SQLite session extension): `captureStart()` at\n * BEGIN, `captureTake()` after COMMIT returns the transaction's changeset (empty if none),\n * `applyChangeset()` replays one. `captureCoversRowidTables` is false when tables without\n * a PRIMARY KEY are invisible to the session (node:sqlite has no ROWID session option).\n */\n captureStart?(): void;\n captureTake?(): Uint8Array;\n captureDiscard?(): void;\n applyChangeset?(changeset: Uint8Array): void;\n readonly captureCoversRowidTables?: boolean;\n /** The database file page for page (page-level logs); defaults to image(). */\n pageImage?(): Uint8Array;\n /** Pages written since the previous call, when the driver can hook its file (SQLite WASM). */\n takeDirtyPages():\n | { pageSize: number; pageCount: number; pages: Map<number, Uint8Array> }\n | undefined;\n discardDirtyPages?(): void;\n /** Consistent image of the whole database (no transaction may be open). Needed for backups. */\n image?(): Uint8Array;\n /** Replaces the whole database with an image produced by `image()`. Needed for restores. */\n restore?(image: Uint8Array): void;\n}\n\n/**\n * Lease port: per-cell ownership, at most one live holder per cell key. `epoch` is a\n * monotonically increasing fencing token: every durable write of the holder must carry\n * it, so a paused ex-holder cannot overwrite its successor. (Browser shards are not\n * leased through this port: a shard worker holds the shard's Web Lock.)\n */\nexport interface LeaseHandle {\n readonly name: string;\n readonly epoch: number;\n /** Aborted when the holder must stop serving (renewal failed, deadline passed, fenced). */\n readonly lost: AbortSignal;\n release(): Promise<void>;\n}\n\nexport interface Lease {\n tryAcquire(name: string): Promise<LeaseHandle | undefined>;\n}\n\nexport interface Clock {\n now(): number;\n setTimeout(fn: () => void, ms: number): unknown;\n clearTimeout(handle: unknown): void;\n}\n\nexport const systemClock: Clock = {\n now: () => Date.now(),\n setTimeout: (fn, ms) => setTimeout(fn, ms),\n clearTimeout: (h) => clearTimeout(h as ReturnType<typeof setTimeout>),\n};\n\n/** Opens (or creates) the SQLite database of a cell. */\nexport type OpenCellSql = ((cellKey: string) => SyncSqlDriver) & {\n /**\n * Opening is synchronous, but a store may need time to make room (an OPFS pool grows\n * asynchronously). Called before a cell's first event: a promise to await before opening\n * `cellKey`, or undefined when it can open now. The runtime then opens it.\n */\n room?(cellKey: string): Promise<void> | undefined;\n};\n\n/**\n * Durability port: called after every local commit. The output gate holds\n * outgoing responses until the returned promise resolves. P06 plugs\n * replication to a FilesApi (OPFS / S3) here; the default resolves at once.\n */\nexport interface CellDurability {\n committed(\n cellKey: string,\n info: {\n seq: number;\n changes?: CommitChanges;\n /** The committed database image (or a thunk producing it on demand). */\n image?: Uint8Array | (() => Uint8Array | undefined | Promise<Uint8Array | undefined>);\n /** The transaction's changed pages, when the driver hooks its file. */\n pages?: { pageSize: number; pageCount: number; pages: Map<number, Uint8Array> };\n epoch?: number;\n },\n ): Promise<void>;\n /**\n * celld's alarm wake index: after a commit that changed the alarm, its publication\n * (writer epoch, sequence, due time) — written once the commit is durable.\n */\n publishWake?(\n cellKey: string,\n wake: { epoch: number; sequence: number; at: number | null },\n ): Promise<void>;\n /** Alarms published in the shared wake index (by any node), so this node can fire them. */\n wakes?(): Promise<{ cellKey: string; className: string; at: number }[]>;\n /** Asks the runtime for the whole database image after each commit (page-level logs: LTX). */\n readonly capturePages?: boolean;\n /** Asks the runtime to capture each transaction's changes (transaction-log durability). */\n readonly captureChanges?: boolean;\n}\n\n/**\n * One committed transaction, as a log segment: schema statements, the row changes (a\n * SQLite changeset), and — only for drivers whose capture misses tables without a PRIMARY\n * KEY — the write statements on such tables. `logSeq` is stored in the database itself\n * (`_cf_METADATA`), so a snapshot knows which segments it already contains.\n */\nexport interface CommitChanges {\n logSeq: number;\n /** Fencing epoch of the owner that committed it (from the cell's lease), if owned. */\n epoch?: number;\n ddl: string[];\n changeset: Uint8Array;\n statements: [string, unknown[]][];\n}\n\n/** Serialization of KV values (CF uses V8 serialization; swap for webrun-msgpack later). */\nexport interface ValueCodec {\n encode(value: unknown): Uint8Array;\n decode(bytes: Uint8Array): unknown;\n}\n\nexport interface BackupInfo {\n /** Local commit counter of the cell at snapshot time (monotonic per live instance). */\n seq: number;\n takenAt: number;\n reason: \"interval\" | \"manual\" | \"close\";\n /** Last transaction-log segment contained in the image (0 when no log is kept). */\n logSeq?: number;\n}\n\n/**\n * Durability by periodic backup: `save` receives a consistent SQLite image of a\n * cell whenever it changed since the last successful save (every `intervalMs`,\n * on `runtime.backupNow()` and on `runtime.close()`). `load` restores a cell\n * whose local database is empty, and under a cell lease replaces the local\n * database on every acquisition. RPO = interval: writes after the last\n * successful save can be lost with the local store (e.g. an evicted OPFS).\n */\nexport interface CellBackup {\n save(cellKey: string, image: Uint8Array, info: BackupInfo): Promise<void>;\n load?(cellKey: string): Promise<Uint8Array | undefined>;\n /** Transaction-log segments after `afterLogSeq`, in order (replayed after `load`). */\n replay?(cellKey: string, afterLogSeq: number): AsyncIterable<CommitChanges>;\n intervalMs?: number;\n onError?(cellKey: string, error: unknown): void;\n}\n\n/**\n * Where a runtime keeps its cells beyond the local SQLite files, as one bundle: a celld fleet\n * bucket (`celldBucket`) or a log on a FilesApi (`filesApiChangeLog`, `filesApiLtxLog`) fills\n * the members it has. The runtime owns it: `runtime.close()` takes the final backups first,\n * then calls `close()`.\n */\nexport interface CellStorage {\n durability?: CellDurability;\n backup?: CellBackup;\n /** Per-cell ownership: each object takes this lease before it opens (fencing epoch → log). */\n ownership?: Lease;\n /** Where R2 bindings keep their objects (a celld fleet bucket, in celld's layout). */\n objects?: ObjectStore;\n close?(): Promise<void>;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Node side of a browser-hosted project: bundles Worker code for a browser realm, for
3
+ * `browserProjectRuntime({ code: { bundle } })`. The bundle reads `cloudflare:workers` and the
4
+ * Workers globals (`Response` with status 101, `WebSocketPair`) from what that runtime installs;
5
+ * with nodejs_compat, `node:*` modules (and their bare names) become browser polyfills.
6
+ */
7
+ /** Bundles the Worker module at `entry` into one ES module for `browserProjectRuntime`. */
8
+ export declare function bundleWorkerForBrowser(entry: string, opts?: {
9
+ nodeCompat?: boolean;
10
+ /**
11
+ * Lower `await` to generators (default: with `nodeCompat`), so that the node:async_hooks
12
+ * polyfill carries AsyncLocalStorage stores through it. `false` only for browsers with TC39
13
+ * AsyncContext, whose engine carries them through native awaits; a lowered bundle runs there
14
+ * too.
15
+ */
16
+ lowerAwait?: boolean;
17
+ }): Promise<string>;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Node side of a browser-hosted project: bundles Worker code for a browser realm, for
3
+ * `browserProjectRuntime({ code: { bundle } })`. The bundle reads `cloudflare:workers` and the
4
+ * Workers globals (`Response` with status 101, `WebSocketPair`) from what that runtime installs;
5
+ * with nodejs_compat, `node:*` modules (and their bare names) become browser polyfills.
6
+ */
7
+ import { builtinModules, createRequire } from "node:module";
8
+ import { resolve } from "node:path";
9
+ import { build } from "esbuild";
10
+ import { NODE_POLYFILL_FILES, NODE_POLYFILL_PACKAGES } from "../node-compat/modules.js";
11
+ import { PROJECT_WORKERS_MODULE_SHIM } from "./browser-modules.js";
12
+ import { lowerAwait } from "./lower-await.js";
13
+ import { ownModule } from "./own-module.js";
14
+ import { SCHEDULER_EXPRESSION } from "./scheduler.js";
15
+ import { WORKERS_GLOBAL_NAMES } from "./workers-global-names.js";
16
+ const pkg = resolve(import.meta.dirname, "../..");
17
+ const requireFromPkg = createRequire(resolve(pkg, "package.json"));
18
+ /**
19
+ * A Node.js module with no browser polyfill, as an ES module: every export the module has on
20
+ * this Node.js (the bundler runs on it) is a function that throws when called (a class to extend
21
+ * too), and the default export answers any member the same way.
22
+ */
23
+ function nodeStub(name) {
24
+ let names = [];
25
+ try {
26
+ names = Object.keys(requireFromPkg(name)).filter((n) => n !== "default");
27
+ }
28
+ catch {
29
+ // not a module of this Node.js: the default export only
30
+ }
31
+ const what = JSON.stringify(name);
32
+ return [
33
+ `const fail = (key) => { throw new Error(${what} + "." + key + " is not available in browsers (nodejs_compat)"); };`,
34
+ "const stub = (key) => function () { fail(key); };",
35
+ ...names.map((n, i) => `const s${i} = stub(${JSON.stringify(n)}); export { s${i} as ${JSON.stringify(n)} };`),
36
+ "export default new Proxy(Object.create(null), {",
37
+ " get(target, key) {",
38
+ ' if (typeof key === "symbol" || key === "then" || key === "__esModule") return undefined;',
39
+ " if (!Object.hasOwn(target, key)) target[key] = stub(String(key));",
40
+ " return target[key];",
41
+ " },",
42
+ "});",
43
+ ].join("\n");
44
+ }
45
+ const GLOBALS_SHIM = `${WORKERS_GLOBAL_NAMES.map((n) => `export const ${n} = globalThis.__cellsGlobals.${n};`).join(" ")} export const scheduler = ${SCHEDULER_EXPRESSION};`;
46
+ /** A bare Node.js built-in name ("path", "fs/promises"): nodejs_compat takes it as `node:…`. */
47
+ const bareBuiltin = new Set(builtinModules.filter((m) => !m.startsWith("_") && !m.includes(":")));
48
+ /** Bundles the Worker module at `entry` into one ES module for `browserProjectRuntime`. */
49
+ export async function bundleWorkerForBrowser(entry, opts = {}) {
50
+ const lower = opts.lowerAwait ?? opts.nodeCompat;
51
+ const options = (esbuildLowers) => ({
52
+ entryPoints: [entry],
53
+ write: false,
54
+ bundle: true,
55
+ format: "esm",
56
+ platform: "browser",
57
+ target: "es2022",
58
+ // Function names are observable (the npm assert polyfill reports its caller's name as the
59
+ // operator); bundling must not rename them.
60
+ keepNames: true,
61
+ // nodejs_compat: `await` lowered to generators, so that each one resumes through
62
+ // Promise.prototype.then and carries its AsyncLocalStorage stores (node-compat/async_hooks.ts).
63
+ ...(esbuildLowers
64
+ ? { supported: { "async-await": false, "async-generator": false, "for-await": false } }
65
+ : {}),
66
+ logLevel: "silent",
67
+ inject: [
68
+ "cells:globals",
69
+ ...(opts.nodeCompat ? [ownModule(import.meta.dirname, "../node-compat/globals")] : []),
70
+ ],
71
+ plugins: [
72
+ {
73
+ name: "cells-browser",
74
+ setup(b) {
75
+ // nodejs_compat: node:* → browser polyfills, bundled in.
76
+ if (opts.nodeCompat)
77
+ b.onResolve({ filter: /^(node:)?[a-z_/]+$/ }, (a) => {
78
+ const name = a.path.startsWith("node:") ? a.path : `node:${a.path}`;
79
+ if (!a.path.startsWith("node:") && !bareBuiltin.has(a.path))
80
+ return undefined;
81
+ const file = NODE_POLYFILL_FILES[name];
82
+ if (file)
83
+ return { path: ownModule(import.meta.dirname, `../node-compat/${file}`) };
84
+ const polyfill = NODE_POLYFILL_PACKAGES[name];
85
+ // "buffer/" (trailing slash): the npm package, not the Node.js built-in of that name
86
+ if (polyfill)
87
+ return { path: requireFromPkg.resolve(`${polyfill}/`) };
88
+ // No browser polyfill: a stub that loads and throws when used, as wrangler's
89
+ // nodejs_compat stubs do on Cloudflare (libraries import such modules in code
90
+ // paths a Worker never takes, e.g. a CLI's login).
91
+ return { path: name, namespace: "cells-node-stub" };
92
+ });
93
+ b.onLoad({ filter: /.*/, namespace: "cells-node-stub" }, (a) => ({
94
+ contents: nodeStub(a.path),
95
+ loader: "js",
96
+ }));
97
+ b.onResolve({ filter: /^cloudflare:email$/ }, () => ({
98
+ path: ownModule(import.meta.dirname, "cloudflare-email"),
99
+ }));
100
+ b.onResolve({ filter: /^cloudflare:workers$|^cells:globals$/ }, (a) => ({
101
+ path: a.path,
102
+ namespace: "cells",
103
+ }));
104
+ b.onLoad({ filter: /.*/, namespace: "cells" }, (a) => ({
105
+ contents: a.path === "cloudflare:workers" ? PROJECT_WORKERS_MODULE_SHIM : GLOBALS_SHIM,
106
+ loader: "js",
107
+ }));
108
+ },
109
+ },
110
+ ],
111
+ });
112
+ try {
113
+ return (await build(options(!!lower))).outputFiles[0].text;
114
+ }
115
+ catch (err) {
116
+ // esbuild cannot lower a top-level await, and refuses to keep one while it lowers the rest
117
+ // (Astro's builds have one: `await import(…)` of the live content config). Such code is
118
+ // bundled as it is, then lowered by lowerAwait, which leaves top-level awaits native: module
119
+ // evaluation runs in no request's context, so they carry no store anyway.
120
+ if (!lower || !/Top-level await is not available/.test(String(err)))
121
+ throw err;
122
+ return lowerAwait((await build(options(false))).outputFiles[0].text);
123
+ }
124
+ }
125
+ //# sourceMappingURL=browser-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-bundle.js","sourceRoot":"","sources":["../../src/project/browser-bundle.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Node side of a browser-hosted project: bundles Worker code for a browser realm, for\n * `browserProjectRuntime({ code: { bundle } })`. The bundle reads `cloudflare:workers` and the\n * Workers globals (`Response` with status 101, `WebSocketPair`) from what that runtime installs;\n * with nodejs_compat, `node:*` modules (and their bare names) become browser polyfills.\n */\n\nimport { builtinModules, createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { type BuildOptions, build } from \"esbuild\";\nimport { NODE_POLYFILL_FILES, NODE_POLYFILL_PACKAGES } from \"../node-compat/modules.js\";\nimport { PROJECT_WORKERS_MODULE_SHIM } from \"./browser-modules.js\";\nimport { lowerAwait } from \"./lower-await.js\";\nimport { ownModule } from \"./own-module.js\";\nimport { SCHEDULER_EXPRESSION } from \"./scheduler.js\";\nimport { WORKERS_GLOBAL_NAMES } from \"./workers-global-names.js\";\n\nconst pkg = resolve(import.meta.dirname, \"../..\");\nconst requireFromPkg = createRequire(resolve(pkg, \"package.json\"));\n\n/**\n * A Node.js module with no browser polyfill, as an ES module: every export the module has on\n * this Node.js (the bundler runs on it) is a function that throws when called (a class to extend\n * too), and the default export answers any member the same way.\n */\nfunction nodeStub(name: string): string {\n let names: string[] = [];\n try {\n names = Object.keys(requireFromPkg(name)).filter((n) => n !== \"default\");\n } catch {\n // not a module of this Node.js: the default export only\n }\n const what = JSON.stringify(name);\n return [\n `const fail = (key) => { throw new Error(${what} + \".\" + key + \" is not available in browsers (nodejs_compat)\"); };`,\n \"const stub = (key) => function () { fail(key); };\",\n ...names.map(\n (n, i) =>\n `const s${i} = stub(${JSON.stringify(n)}); export { s${i} as ${JSON.stringify(n)} };`,\n ),\n \"export default new Proxy(Object.create(null), {\",\n \" get(target, key) {\",\n ' if (typeof key === \"symbol\" || key === \"then\" || key === \"__esModule\") return undefined;',\n \" if (!Object.hasOwn(target, key)) target[key] = stub(String(key));\",\n \" return target[key];\",\n \" },\",\n \"});\",\n ].join(\"\\n\");\n}\n\nconst GLOBALS_SHIM = `${WORKERS_GLOBAL_NAMES.map((n) => `export const ${n} = globalThis.__cellsGlobals.${n};`).join(\" \")} export const scheduler = ${SCHEDULER_EXPRESSION};`;\n\n/** A bare Node.js built-in name (\"path\", \"fs/promises\"): nodejs_compat takes it as `node:…`. */\nconst bareBuiltin = new Set(builtinModules.filter((m) => !m.startsWith(\"_\") && !m.includes(\":\")));\n\n/** Bundles the Worker module at `entry` into one ES module for `browserProjectRuntime`. */\nexport async function bundleWorkerForBrowser(\n entry: string,\n opts: {\n nodeCompat?: boolean;\n /**\n * Lower `await` to generators (default: with `nodeCompat`), so that the node:async_hooks\n * polyfill carries AsyncLocalStorage stores through it. `false` only for browsers with TC39\n * AsyncContext, whose engine carries them through native awaits; a lowered bundle runs there\n * too.\n */\n lowerAwait?: boolean;\n } = {},\n): Promise<string> {\n const lower = opts.lowerAwait ?? opts.nodeCompat;\n const options = (esbuildLowers: boolean): BuildOptions & { write: false } => ({\n entryPoints: [entry],\n write: false,\n bundle: true,\n format: \"esm\",\n platform: \"browser\",\n target: \"es2022\",\n // Function names are observable (the npm assert polyfill reports its caller's name as the\n // operator); bundling must not rename them.\n keepNames: true,\n // nodejs_compat: `await` lowered to generators, so that each one resumes through\n // Promise.prototype.then and carries its AsyncLocalStorage stores (node-compat/async_hooks.ts).\n ...(esbuildLowers\n ? { supported: { \"async-await\": false, \"async-generator\": false, \"for-await\": false } }\n : {}),\n logLevel: \"silent\",\n inject: [\n \"cells:globals\",\n ...(opts.nodeCompat ? [ownModule(import.meta.dirname, \"../node-compat/globals\")] : []),\n ],\n plugins: [\n {\n name: \"cells-browser\",\n setup(b) {\n // nodejs_compat: node:* → browser polyfills, bundled in.\n if (opts.nodeCompat)\n b.onResolve({ filter: /^(node:)?[a-z_/]+$/ }, (a) => {\n const name = a.path.startsWith(\"node:\") ? a.path : `node:${a.path}`;\n if (!a.path.startsWith(\"node:\") && !bareBuiltin.has(a.path)) return undefined;\n const file = NODE_POLYFILL_FILES[name];\n if (file) return { path: ownModule(import.meta.dirname, `../node-compat/${file}`) };\n const polyfill = NODE_POLYFILL_PACKAGES[name];\n // \"buffer/\" (trailing slash): the npm package, not the Node.js built-in of that name\n if (polyfill) return { path: requireFromPkg.resolve(`${polyfill}/`) };\n // No browser polyfill: a stub that loads and throws when used, as wrangler's\n // nodejs_compat stubs do on Cloudflare (libraries import such modules in code\n // paths a Worker never takes, e.g. a CLI's login).\n return { path: name, namespace: \"cells-node-stub\" };\n });\n b.onLoad({ filter: /.*/, namespace: \"cells-node-stub\" }, (a) => ({\n contents: nodeStub(a.path),\n loader: \"js\",\n }));\n b.onResolve({ filter: /^cloudflare:email$/ }, () => ({\n path: ownModule(import.meta.dirname, \"cloudflare-email\"),\n }));\n b.onResolve({ filter: /^cloudflare:workers$|^cells:globals$/ }, (a) => ({\n path: a.path,\n namespace: \"cells\",\n }));\n b.onLoad({ filter: /.*/, namespace: \"cells\" }, (a) => ({\n contents: a.path === \"cloudflare:workers\" ? PROJECT_WORKERS_MODULE_SHIM : GLOBALS_SHIM,\n loader: \"js\",\n }));\n },\n },\n ],\n });\n try {\n return (await build(options(!!lower))).outputFiles[0].text;\n } catch (err) {\n // esbuild cannot lower a top-level await, and refuses to keep one while it lowers the rest\n // (Astro's builds have one: `await import(…)` of the live content config). Such code is\n // bundled as it is, then lowered by lowerAwait, which leaves top-level awaits native: module\n // evaluation runs in no request's context, so they carry no store anyway.\n if (!lower || !/Top-level await is not available/.test(String(err))) throw err;\n return lowerAwait((await build(options(false))).outputFiles[0].text);\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ /** Headers for an ingress request: the request's own, plus the cookies its URL would carry. */
2
+ export declare function withPageCookies(scope: unknown, req: Request): Promise<Headers>;
3
+ /** One `Set-Cookie` value as Cookie Store options; `expires: 0` deletes. */
4
+ export declare function parseSetCookie(value: string, now?: number): {
5
+ name: string;
6
+ value: string;
7
+ path?: string;
8
+ expires?: number;
9
+ sameSite?: "strict" | "lax" | "none";
10
+ };
11
+ /** Stores the Worker's tunneled Set-Cookie values and returns the response without them. */
12
+ export declare function applyWorkerCookies(scope: unknown, res: Response): Promise<Response>;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Cookies for Workers served through a ServiceWorker. A browser hands a ServiceWorker no
3
+ * `Cookie` header and ignores `Set-Cookie` on the responses it builds, so the router does what
4
+ * the browser's network stack would: it sends the page's cookies to the Worker under
5
+ * `x-cellb-cookie` (an ingress that carries it gets the Worker's `Set-Cookie` values back under
6
+ * `x-cellb-set-cookie`, cells-http.ts), and stores those through the Cookie Store API.
7
+ *
8
+ * What differs from a server's cookies: they are written by script, so `HttpOnly` cannot be set
9
+ * and they are readable by the page's own scripts; `Domain` is ignored (the origin's host); and
10
+ * every cookie is stored with `Path=/` and sent with every request. Chromium lets a
11
+ * ServiceWorker read cookies only for its default URL (`getAll({ url })` throws "URL must be
12
+ * within Service Worker scope" for any URL), so a cookie scoped to `/_emdash/` could not be read
13
+ * back at all.
14
+ */
15
+ import { H } from "../transport/cells-link.js";
16
+ const storeOf = (scope) => scope.cookieStore;
17
+ /** Headers for an ingress request: the request's own, plus the cookies its URL would carry. */
18
+ export async function withPageCookies(scope, req) {
19
+ const headers = new Headers(req.headers);
20
+ const store = storeOf(scope);
21
+ if (!store)
22
+ return headers; // no Cookie Store API: no cookies either way
23
+ const cookies = await store.getAll().catch(() => []);
24
+ headers.set(H.cookie, cookies.map((c) => `${c.name}=${c.value}`).join("; "));
25
+ return headers;
26
+ }
27
+ /** One `Set-Cookie` value as Cookie Store options; `expires: 0` deletes. */
28
+ export function parseSetCookie(value, now = Date.now()) {
29
+ const [pair, ...attrs] = value.split(";");
30
+ const eq = pair.indexOf("=");
31
+ const cookie = {
32
+ name: (eq < 0 ? "" : pair.slice(0, eq)).trim(),
33
+ value: (eq < 0 ? pair : pair.slice(eq + 1)).trim(),
34
+ };
35
+ let maxAge;
36
+ for (const attr of attrs) {
37
+ const i = attr.indexOf("=");
38
+ const key = (i < 0 ? attr : attr.slice(0, i)).trim().toLowerCase();
39
+ const val = i < 0 ? "" : attr.slice(i + 1).trim();
40
+ if (key === "path")
41
+ cookie.path = val || "/";
42
+ else if (key === "expires") {
43
+ const t = Date.parse(val);
44
+ if (!Number.isNaN(t))
45
+ cookie.expires = t;
46
+ }
47
+ else if (key === "max-age" && /^-?\d+$/.test(val))
48
+ maxAge = Number(val);
49
+ else if (key === "samesite") {
50
+ const s = val.toLowerCase();
51
+ if (s === "strict" || s === "lax" || s === "none")
52
+ cookie.sameSite = s;
53
+ }
54
+ }
55
+ // Max-Age wins over Expires (RFC 6265); zero or less deletes.
56
+ if (maxAge !== undefined)
57
+ cookie.expires = maxAge <= 0 ? 0 : now + maxAge * 1000;
58
+ return cookie;
59
+ }
60
+ /** Stores the Worker's tunneled Set-Cookie values and returns the response without them. */
61
+ export async function applyWorkerCookies(scope, res) {
62
+ const tunneled = res.headers.get(H.setCookie);
63
+ if (tunneled === null)
64
+ return res;
65
+ const store = storeOf(scope);
66
+ for (const raw of tunneled.split(",").filter(Boolean)) {
67
+ const c = parseSetCookie(decodeURIComponent(raw));
68
+ if (!c.name || !store)
69
+ continue;
70
+ try {
71
+ if (c.expires !== undefined && c.expires <= Date.now())
72
+ await store.delete({ name: c.name, path: "/" });
73
+ else
74
+ await store.set({
75
+ name: c.name,
76
+ value: c.value,
77
+ path: "/",
78
+ expires: c.expires ?? null,
79
+ sameSite: c.sameSite ?? "lax",
80
+ });
81
+ }
82
+ catch (err) {
83
+ console.warn(`cellb: cookie ${c.name} not stored: ${err?.message ?? err}`);
84
+ }
85
+ }
86
+ const headers = new Headers(res.headers);
87
+ headers.delete(H.setCookie);
88
+ return new Response(res.body, { status: res.status, statusText: res.statusText, headers });
89
+ }
90
+ //# sourceMappingURL=browser-cookies.js.map