@statewalker/cellb 0.0.0-stage → 0.1.0

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 +362 -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,366 @@
1
+ import { systemClock, } from "../ports.js";
2
+ import { httpEndpoint, postVia } from "../transport/cells-link.js";
3
+ import { v8Codec, v8CodecWith } from "../v8/codec.js";
4
+ import { takeClientPort } from "../ws/server.js";
5
+ import { withUpgrade } from "../ws/upgrade.js";
6
+ import { AlarmScheduler } from "./alarms.js";
7
+ import { asyncRoot } from "./async-context.js";
8
+ import { ctxExports, storedExports } from "./handles.js";
9
+ import { DurableObjectId, namespaceKey } from "./id.js";
10
+ import { DurableObjectNamespace, localEndpoint } from "./namespace.js";
11
+ import { CellOwnedElsewhereError, ObjectHost } from "./object-host.js";
12
+ import { installRequestBody } from "./request-body.js";
13
+ import { rejectionScope, reportToStderr } from "./worker-rejections.js";
14
+ export function createCellRuntime(opts) {
15
+ installRequestBody(); // Firefox: `request.body` for the Worker code (and for the retry below)
16
+ const storage = opts.storage ?? {};
17
+ const { backup, ownership } = storage;
18
+ const durability = storage.durability ?? { committed: () => Promise.resolve() };
19
+ // V8 serialization: storage values in celld's (and workerd's) format.
20
+ const codec = opts.codec ?? v8Codec;
21
+ const hosts = new Map();
22
+ const background = new Set();
23
+ // Events start in the context the runtime was made in, not their caller's (Cloudflare).
24
+ // …and in a scope that keeps the Worker's unhandled rejections its own (Node).
25
+ const rejections = rejectionScope(opts.onUnhandledRejection ?? reportToStderr(opts.scriptName ?? "worker"));
26
+ const root = asyncRoot();
27
+ const eventsRoot = (fn) => root(() => rejections(fn));
28
+ const waitUntil = (p) => {
29
+ const t = p.catch(() => { }).finally(() => background.delete(t));
30
+ background.add(t);
31
+ };
32
+ const env = { ...opts.vars };
33
+ const bindingClasses = {};
34
+ const exportsObj = ctxExports(opts.worker, env);
35
+ // Storage values: V8 serialization; ctx.exports stubs are stored too (workerd).
36
+ const storageCodec = opts.codec ?? v8CodecWith(storedExports(exportsObj));
37
+ const clock = opts.clock ?? systemClock;
38
+ // Hosts by class name: the alarm scheduler wakes objects that nobody is calling.
39
+ const hostsByClass = new Map();
40
+ const alarms = new AlarmScheduler({
41
+ clock,
42
+ openIndex: () => opts.openSql("__cellb/alarms"),
43
+ fire: (e) => fireAlarm(e),
44
+ });
45
+ // One alarm() at a time per object (as on Cloudflare): a re-armed alarm that comes due
46
+ // while the previous handler still runs waits for it.
47
+ const alarmRuns = new Map();
48
+ const ownedRetries = new Map();
49
+ function fireAlarm(e) {
50
+ const prev = alarmRuns.get(e.cellKey) ?? Promise.resolve();
51
+ const next = prev.then(() => fireAlarmNow(e));
52
+ alarmRuns.set(e.cellKey, next);
53
+ void next.finally(() => {
54
+ if (alarmRuns.get(e.cellKey) === next)
55
+ alarmRuns.delete(e.cellKey);
56
+ });
57
+ return next;
58
+ }
59
+ /**
60
+ * celld's alarm lifecycle, in the cell's own storage (so it survives restarts and moves
61
+ * between nodes, celld included): the row stays while its handler runs (getAlarm() reads
62
+ * null meanwhile); success deletes it, failure reschedules it with backoff and counts the
63
+ * failure in the row (`retry`, `counted_retry`) — alarmInfo.retryCount is that count.
64
+ */
65
+ async function fireAlarmNow(e) {
66
+ const hostFor = hostsByClass.get(e.className);
67
+ if (!hostFor)
68
+ return;
69
+ const host = hostFor(new DurableObjectId(e.idHex));
70
+ try {
71
+ await host.deliver(async (obj, state) => {
72
+ // A wake (local timer, or an entry of the shared wake index) is a hint: the stored
73
+ // alarm decides. Gone → nothing to do; moved later → wait for that time.
74
+ const row = state.storage.alarmRowSync();
75
+ if (!row)
76
+ return;
77
+ if (row.at > clock.now()) {
78
+ alarms.set(e, row.at);
79
+ return;
80
+ }
81
+ state.storage.beginAlarm(row);
82
+ let ok = true;
83
+ try {
84
+ if (typeof obj.alarm === "function")
85
+ await obj.alarm({
86
+ retryCount: row.retry,
87
+ isRetry: row.retry > 0,
88
+ scheduledTime: row.at, // alarmInfo.scheduledTime, as in workerd
89
+ });
90
+ }
91
+ catch {
92
+ ok = false;
93
+ }
94
+ state.storage.finishAlarm(row, ok, clock.now());
95
+ });
96
+ ownedRetries.delete(e.cellKey);
97
+ }
98
+ catch (err) {
99
+ // Owned by another node (celld or cellb): its owner fires the alarm.
100
+ if (isOwnedElsewhere(err)) {
101
+ hosts.get(e.cellKey)?.close();
102
+ hosts.delete(e.cellKey);
103
+ // A live owner fires it. A stopped one's lease expires within its TTL: look again a
104
+ // few times before leaving it to the next poll of the wake index.
105
+ const n = (ownedRetries.get(e.cellKey) ?? 0) + 1;
106
+ if (n <= 15) {
107
+ ownedRetries.set(e.cellKey, n);
108
+ alarms.set(e, clock.now() + 2_000);
109
+ }
110
+ else
111
+ ownedRetries.delete(e.cellKey);
112
+ }
113
+ // Any other failure (broken object, storage error): the row is unchanged; it fires again
114
+ // when the object is next opened or the index is polled.
115
+ }
116
+ }
117
+ for (const [binding, { className }] of Object.entries(opts.durableObjects ?? {})) {
118
+ const cls = opts.worker[className];
119
+ if (typeof cls !== "function")
120
+ throw new Error(`Durable Object class "${className}" is not exported by the worker`);
121
+ const hostFor = (id) => {
122
+ const cellKey = `${className}/${id.toString()}`;
123
+ let h = hosts.get(cellKey);
124
+ if (!h || h.broken) {
125
+ h?.close();
126
+ h = new ObjectHost({
127
+ cellKey,
128
+ id,
129
+ cls,
130
+ env,
131
+ openSql: opts.openSql,
132
+ durability,
133
+ codec: storageCodec,
134
+ waitUntil,
135
+ backup,
136
+ onAlarmChange: (at) => alarms.set({ cellKey, className, idHex: id.toString() }, at),
137
+ exports: exportsObj,
138
+ facet: opts.facets,
139
+ asyncRoot: eventsRoot,
140
+ acquire: ownership ? (key) => ownership.tryAcquire(key) : undefined,
141
+ sqlExtensions: opts.sqlExtensions,
142
+ deleteAllPreservesAlarm: opts.deleteAllPreservesAlarm,
143
+ });
144
+ hosts.set(cellKey, h);
145
+ }
146
+ return h;
147
+ };
148
+ hostsByClass.set(className, hostFor);
149
+ const nsKey = opts.namespaceKeys?.[className] ?? namespaceKey(opts.scriptName ?? "worker", className);
150
+ env[binding] = new DurableObjectNamespace(nsKey, (id) => {
151
+ const remote = opts.route?.(`${className}/${id.toString()}`, id);
152
+ if (remote)
153
+ return () => httpEndpoint(postVia(remote), codec, binding, className, id);
154
+ const cellKey = `${className}/${id.toString()}`;
155
+ // A cell not open yet waits for room in its store before its first event (OPFS pool).
156
+ const ready = () => (hosts.has(cellKey) ? undefined : opts.openSql.room?.(cellKey));
157
+ const local = localEndpoint(() => hostFor(id), ready);
158
+ const peers = opts.peers;
159
+ if (!peers)
160
+ return local;
161
+ // Local first; a cell owned by another node is reached through that node.
162
+ const viaOwner = async () => {
163
+ const owner = await peers.ownerOf(cellKey);
164
+ if (!owner)
165
+ throw new CellOwnedElsewhereError(cellKey);
166
+ const direct = await peers.endpoint?.(owner, cellKey, id.name);
167
+ if (direct)
168
+ return direct;
169
+ return httpEndpoint(postVia(peers.link(owner)), codec, binding, className, id);
170
+ };
171
+ // The host reports a failed open as a broken object; the cause tells why.
172
+ const elsewhere = (e) => {
173
+ for (let x = e, i = 0; x && i < 5; x = x.cause, i++)
174
+ if (x.name === "CellOwnedElsewhereError")
175
+ return true;
176
+ return false;
177
+ };
178
+ return () => {
179
+ const l = local();
180
+ return {
181
+ get local() {
182
+ return l.local; // not copied: reading it opens the cell
183
+ },
184
+ fetch: async (req) => {
185
+ const spare = req.body ? req.clone() : req;
186
+ try {
187
+ return await l.fetch(req);
188
+ }
189
+ catch (e) {
190
+ if (!elsewhere(e))
191
+ throw e;
192
+ hosts.get(cellKey)?.close();
193
+ hosts.delete(cellKey);
194
+ return (await viaOwner()).fetch(spare);
195
+ }
196
+ },
197
+ call: async (method, args) => {
198
+ try {
199
+ return await l.call(method, args);
200
+ }
201
+ catch (e) {
202
+ if (!elsewhere(e))
203
+ throw e;
204
+ hosts.get(cellKey)?.close();
205
+ hosts.delete(cellKey);
206
+ return (await viaOwner()).call(method, args);
207
+ }
208
+ },
209
+ };
210
+ };
211
+ });
212
+ bindingClasses[binding] = className;
213
+ // ctx.exports.<Class> of a class with a namespace is also that namespace, as in workerd
214
+ // (`ctx.exports.MyActor.getByName("a")`); it stays usable as a facet class handle.
215
+ const ns = env[binding];
216
+ const exported = exportsObj[className];
217
+ if (exported && !("getByName" in exported))
218
+ for (const [m, d] of Object.entries(Object.getOwnPropertyDescriptors(DurableObjectNamespace.prototype)))
219
+ if (m !== "constructor" && typeof d.value === "function")
220
+ exported[m] = d.value.bind(ns);
221
+ }
222
+ alarms.restore();
223
+ // Alarms published by any node in a shared wake index (celld's): this node fires them too.
224
+ // An entry is only a hint: firing opens the cell and runs alarm() only if its stored alarm
225
+ // is still due at that time.
226
+ // The index is read at start and then every `wakePollMs` (default 30 s), so alarms of cells
227
+ // whose owner went away are picked up — celld's waker does the same.
228
+ const wakes = storage.durability?.wakes;
229
+ let wakeTimer;
230
+ let wakesStopped = false;
231
+ if (wakes) {
232
+ const known = new Set(Object.values(bindingClasses));
233
+ const poll = async () => {
234
+ try {
235
+ for (const w of await wakes.call(storage.durability))
236
+ if (known.has(w.className) && !alarmRuns.has(w.cellKey))
237
+ alarms.set({ cellKey: w.cellKey, className: w.className, idHex: w.cellKey.split("/")[1] }, w.at);
238
+ }
239
+ catch {
240
+ // the index is unavailable for now: next poll
241
+ }
242
+ if (!wakesStopped)
243
+ wakeTimer = clock.setTimeout(() => void poll(), opts.wakePollMs ?? 30_000);
244
+ };
245
+ void poll();
246
+ }
247
+ // Idle sweep for hibernation (opt-in).
248
+ let hibernationTimer;
249
+ if (opts.hibernateAfterMs !== undefined) {
250
+ const every = Math.max(1_000, opts.hibernateAfterMs / 2);
251
+ const sweep = () => {
252
+ runtime.hibernateIdle();
253
+ hibernationTimer = clock.setTimeout(sweep, every);
254
+ };
255
+ hibernationTimer = clock.setTimeout(sweep, every);
256
+ }
257
+ const backupAll = (reason) => Promise.all([...hosts.values()].map((h) => h.backupIfDirty(reason, clock.now()))).then(() => { });
258
+ let timer;
259
+ let closed = false;
260
+ const schedule = () => {
261
+ if (!backup || closed)
262
+ return;
263
+ timer = clock.setTimeout(() => {
264
+ void backupAll("interval").finally(schedule);
265
+ }, backup.intervalMs ?? 30_000);
266
+ };
267
+ schedule();
268
+ const runtime = {
269
+ env,
270
+ exports: exportsObj,
271
+ durableObjectBindings: bindingClasses,
272
+ backupNow: () => backupAll("manual"),
273
+ async connectWebSocket(url, protocols = [], headers) {
274
+ const h = new Headers(headers);
275
+ h.set("Upgrade", "websocket");
276
+ if (protocols.length)
277
+ h.set("Sec-WebSocket-Protocol", protocols.join(", "));
278
+ const httpUrl = url.replace(/^ws(s?):/, "http$1:");
279
+ const res = (await this.fetch(withUpgrade(new Request(httpUrl, { headers: h }), "websocket", protocols.length ? { "Sec-WebSocket-Protocol": protocols.join(", ") } : undefined)));
280
+ if (res.status !== 101 || !res.webSocket)
281
+ throw new Error(`WebSocket upgrade refused: HTTP ${res.status}`);
282
+ return {
283
+ port: takeClientPort(res.webSocket),
284
+ protocol: res.headers.get("Sec-WebSocket-Protocol") ?? undefined,
285
+ };
286
+ },
287
+ restartObject(cellKey) {
288
+ hosts.get(cellKey)?.restart();
289
+ },
290
+ hibernateIdle(idleMs = opts.hibernateAfterMs ?? 0) {
291
+ const now = Date.now();
292
+ let n = 0;
293
+ const closeMs = opts.closeDatabaseAfterMs;
294
+ for (const h of hosts.values()) {
295
+ const idle = now - h.lastActive;
296
+ if (idle >= idleMs && h.hibernate())
297
+ n++;
298
+ if (closeMs !== undefined && idle >= closeMs)
299
+ h.closeDatabase();
300
+ }
301
+ return n;
302
+ },
303
+ async close() {
304
+ if (hibernationTimer !== undefined)
305
+ clock.clearTimeout(hibernationTimer);
306
+ closed = true;
307
+ wakesStopped = true;
308
+ if (wakeTimer !== undefined)
309
+ clock.clearTimeout(wakeTimer);
310
+ alarms.stop();
311
+ clock.clearTimeout(timer);
312
+ timer = undefined;
313
+ await backupAll("close");
314
+ // The releases reach the store before it closes.
315
+ await Promise.all([...hosts.values()].map((h) => h.close()));
316
+ hosts.clear();
317
+ alarms.close(); // every database of the runtime is closed now
318
+ await storage.close?.();
319
+ },
320
+ async fetch(req) {
321
+ const handler = opts.worker.default?.fetch;
322
+ if (!handler)
323
+ return new Response("Worker has no fetch handler", { status: 500 });
324
+ const ctx = {
325
+ waitUntil,
326
+ passThroughOnException() { },
327
+ exports: exportsObj,
328
+ };
329
+ // celld's ingress: an inbound request has a `cf` object (no edge fields).
330
+ if (req.cf === undefined)
331
+ Object.defineProperty(req, "cf", { value: {}, enumerable: true });
332
+ try {
333
+ const r = await rejections(() => handler.call(opts.worker.default, req, env, ctx));
334
+ // A non-Response is sent as text (celld), not a failure.
335
+ return r instanceof Response ? r : new Response(String(r));
336
+ }
337
+ catch (e) {
338
+ const err = e;
339
+ return new Response(`Worker failed: rejected: ${err?.name ?? "Error"}: ${err?.message ?? String(e)}`, {
340
+ status: 500,
341
+ headers: { "content-type": "application/json" },
342
+ });
343
+ }
344
+ },
345
+ runEvent: (fn) => rejections(fn),
346
+ evictAll() {
347
+ for (const h of hosts.values())
348
+ h.close();
349
+ hosts.clear();
350
+ },
351
+ async drain() {
352
+ while (background.size)
353
+ await Promise.all([...background]);
354
+ },
355
+ waitUntil,
356
+ };
357
+ return runtime;
358
+ }
359
+ /** The error (or its cause chain) says another node owns the cell. */
360
+ export function isOwnedElsewhere(e) {
361
+ for (let x = e, i = 0; x && i < 5; x = x.cause, i++)
362
+ if (x.name === "CellOwnedElsewhereError")
363
+ return true;
364
+ return false;
365
+ }
366
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/core/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type CellDurability,\n type CellStorage,\n type Clock,\n type OpenCellSql,\n systemClock,\n type ValueCodec,\n} from \"../ports.js\";\nimport { httpEndpoint, postVia, type Send } from \"../transport/cells-link.js\";\nimport { v8Codec, v8CodecWith } from \"../v8/codec.js\";\nimport { type CfWebSocket, takeClientPort } from \"../ws/server.js\";\nimport { withUpgrade } from \"../ws/upgrade.js\";\nimport { type AlarmEntry, AlarmScheduler } from \"./alarms.js\";\nimport { type AsyncRoot, asyncRoot } from \"./async-context.js\";\nimport type { ExecutionContext } from \"./durable-object.js\";\nimport { ctxExports, type DurableObjectClass, storedExports } from \"./handles.js\";\nimport { DurableObjectId, namespaceKey } from \"./id.js\";\nimport { DurableObjectNamespace, localEndpoint, type ObjectEndpoint } from \"./namespace.js\";\nimport { CellOwnedElsewhereError, ObjectHost } from \"./object-host.js\";\nimport { installRequestBody } from \"./request-body.js\";\nimport { type RejectionHandler, rejectionScope, reportToStderr } from \"./worker-rejections.js\";\n\nexport interface WorkerModule {\n default: { fetch?(req: Request, env: any, ctx: ExecutionContext): Response | Promise<Response> };\n [exportName: string]: unknown;\n}\n\nexport interface CellRuntimeOptions {\n /**\n * A promise the Worker's code leaves rejected (Node: the Worker shares the host's process).\n * It is the Worker's, as on workerd and celld: it reaches this handler, not the process's\n * `unhandledRejection` listeners. Default: one line on stderr, outside the Worker's console.\n */\n onUnhandledRejection?: RejectionHandler;\n /** The Worker's module namespace (what wrangler/celld bundle as main module). */\n worker: WorkerModule;\n /** Durable Object bindings: env name → exported class name (wrangler `durable_objects.bindings`). */\n durableObjects?: Record<string, { className: string }>;\n /** Plain vars / other bindings merged into env. */\n vars?: Record<string, unknown>;\n openSql: OpenCellSql;\n /** Durability, backup and ownership of the cells; closed by `close()`, after the runtime. */\n storage?: CellStorage;\n codec?: ValueCodec;\n /**\n * Placement: return a `send` when the cell lives elsewhere (another shard\n * worker, tab or peer); `undefined` means \"host it here\". Default: all local.\n */\n route?: (cellKey: string, id: DurableObjectId) => Send | undefined;\n /** How often to re-read a shared alarm wake index (durability.wakes), in ms. Default 30 s. */\n wakePollMs?: number;\n /** Every object of this runtime is a facet of an outer cell (an isolate's runtime). */\n facets?: boolean;\n /** The Worker script's name (wrangler `name`): object ids derive from it, as on celld. */\n scriptName?: string;\n /** Namespace keys overriding the script-scoped default, per class (celld's fleet-wide ones). */\n namespaceKeys?: Record<string, string>;\n /**\n * Routing between nodes (celld's peer routing): when this node cannot own a cell\n * (`CellOwnedElsewhereError`), the call goes to the owner's node over an internal link\n * (`cellsHttpHandler` on the far side). `ownerOf` reads the cell's lease holder.\n */\n peers?: {\n ownerOf(cellKey: string): Promise<string | undefined>;\n link(owner: string): Send;\n /**\n * Talks to an owner directly, for owners that do not speak cellsHttpHandler (a celld node,\n * reached through celld's peer tunnel). Takes precedence over `link` when it returns one.\n */\n endpoint?(\n owner: string,\n cellKey: string,\n name: string | undefined,\n ): Promise<ObjectEndpoint | undefined>;\n };\n /** Hibernate objects idle this long (ms); swept every max(1 s, half of it). Off by default. */\n hibernateAfterMs?: number;\n /**\n * Close the SQLite database of a hibernated object idle this long (ms); the next event reopens\n * it. Swept with `hibernateAfterMs`, so it needs that too. Off by default: the database must\n * come back, so use local SQLite that persists (a directory, an OPFS pool) or storage that\n * restores the cell (a log or a backup).\n */\n closeDatabaseAfterMs?: number;\n /** SQLite extensions loaded into every cell database (celld's `sqlite_vec` flag). */\n sqlExtensions?: string[];\n /** `delete_all_preserves_alarm`: storage.deleteAll() keeps the alarm (default: deletes it). */\n deleteAllPreservesAlarm?: boolean;\n /** Timers of the runtime (backups); injectable for tests. */\n clock?: Clock;\n}\n\nexport interface CellRuntime {\n /** Ingress: a (Request) ⇒ Response handler — exactly what webrun-http-browser / node:http mount. */\n fetch(req: Request): Promise<Response>;\n readonly env: Record<string, unknown>;\n /** The Worker's `ctx.exports` (also `exports` of `cloudflare:workers`). */\n readonly exports: Record<string, unknown>;\n /**\n * Runs Worker code the host dispatches itself (a cron trigger's `scheduled()`) as the Worker's\n * event: a promise it leaves rejected goes to `onUnhandledRejection`, not to the process.\n */\n runEvent<R>(fn: () => R): R;\n /** Drops live instances (simulates eviction / hibernation); storage survives if openSql persists it. */\n evictAll(): void;\n /** Settles all waitUntil() promises. */\n drain(): Promise<void>;\n /**\n * Keeps `p` running in the background until `drain()` (what `waitUntil` of\n * `cloudflare:workers` does: on Cloudflare it extends the current event).\n */\n waitUntil(p: Promise<unknown>): void;\n /** Durable Object binding → class name (the namespace key used by idFromName). */\n readonly durableObjectBindings: Readonly<Record<string, string>>;\n /**\n * WebSocket ingress: runs the Worker's fetch with an Upgrade request; on a 101\n * with `webSocket`, returns the client end's MessagePort (to be transferred to\n * the real client, e.g. a page's CellsWebSocket).\n */\n connectWebSocket(\n url: string,\n protocols?: string[],\n headers?: HeadersInit,\n ): Promise<{ port: MessagePort; protocol?: string }>;\n /** Backs up every live cell that changed since its last successful save. */\n backupNow(): Promise<void>;\n /**\n * Hibernates every object idle for at least `idleMs` (default: `hibernateAfterMs`):\n * instances are dropped, storage and hibernatable WebSockets stay. Returns how many slept.\n * Hibernated objects idle for `closeDatabaseAfterMs` also close their database.\n */\n hibernateIdle(idleMs?: number): number;\n /** Replaces one object's instance with a fresh one on the same storage (facet abort). */\n restartObject(cellKey: string): void;\n /** Final backup of changed cells, then stops timers, closes every database and the storage. */\n close(): Promise<void>;\n}\n\nexport function createCellRuntime(opts: CellRuntimeOptions): CellRuntime {\n installRequestBody(); // Firefox: `request.body` for the Worker code (and for the retry below)\n const storage = opts.storage ?? {};\n const { backup, ownership } = storage;\n const durability: CellDurability = storage.durability ?? { committed: () => Promise.resolve() };\n // V8 serialization: storage values in celld's (and workerd's) format.\n const codec = opts.codec ?? v8Codec;\n const hosts = new Map<string, ObjectHost>();\n const background = new Set<Promise<unknown>>();\n // Events start in the context the runtime was made in, not their caller's (Cloudflare).\n // …and in a scope that keeps the Worker's unhandled rejections its own (Node).\n const rejections = rejectionScope(\n opts.onUnhandledRejection ?? reportToStderr(opts.scriptName ?? \"worker\"),\n );\n const root = asyncRoot();\n const eventsRoot: AsyncRoot = (fn) => root(() => rejections(fn));\n const waitUntil = (p: Promise<unknown>) => {\n const t = p.catch(() => {}).finally(() => background.delete(t));\n background.add(t);\n };\n const env: Record<string, unknown> = { ...opts.vars };\n const bindingClasses: Record<string, string> = {};\n const exportsObj = ctxExports(opts.worker, env);\n // Storage values: V8 serialization; ctx.exports stubs are stored too (workerd).\n const storageCodec = opts.codec ?? v8CodecWith(storedExports(exportsObj));\n const clock = opts.clock ?? systemClock;\n // Hosts by class name: the alarm scheduler wakes objects that nobody is calling.\n const hostsByClass = new Map<string, (id: DurableObjectId) => ObjectHost>();\n const alarms = new AlarmScheduler({\n clock,\n openIndex: () => opts.openSql(\"__cellb/alarms\"),\n fire: (e) => fireAlarm(e),\n });\n // One alarm() at a time per object (as on Cloudflare): a re-armed alarm that comes due\n // while the previous handler still runs waits for it.\n const alarmRuns = new Map<string, Promise<void>>();\n const ownedRetries = new Map<string, number>();\n function fireAlarm(e: AlarmEntry): Promise<void> {\n const prev = alarmRuns.get(e.cellKey) ?? Promise.resolve();\n const next = prev.then(() => fireAlarmNow(e));\n alarmRuns.set(e.cellKey, next);\n void next.finally(() => {\n if (alarmRuns.get(e.cellKey) === next) alarmRuns.delete(e.cellKey);\n });\n return next;\n }\n /**\n * celld's alarm lifecycle, in the cell's own storage (so it survives restarts and moves\n * between nodes, celld included): the row stays while its handler runs (getAlarm() reads\n * null meanwhile); success deletes it, failure reschedules it with backoff and counts the\n * failure in the row (`retry`, `counted_retry`) — alarmInfo.retryCount is that count.\n */\n async function fireAlarmNow(e: AlarmEntry): Promise<void> {\n const hostFor = hostsByClass.get(e.className);\n if (!hostFor) return;\n const host = hostFor(new DurableObjectId(e.idHex));\n try {\n await host.deliver(async (obj, state) => {\n // A wake (local timer, or an entry of the shared wake index) is a hint: the stored\n // alarm decides. Gone → nothing to do; moved later → wait for that time.\n const row = state.storage.alarmRowSync();\n if (!row) return;\n if (row.at > clock.now()) {\n alarms.set(e, row.at);\n return;\n }\n state.storage.beginAlarm(row);\n let ok = true;\n try {\n if (typeof obj.alarm === \"function\")\n await obj.alarm({\n retryCount: row.retry,\n isRetry: row.retry > 0,\n scheduledTime: row.at, // alarmInfo.scheduledTime, as in workerd\n });\n } catch {\n ok = false;\n }\n state.storage.finishAlarm(row, ok, clock.now());\n });\n ownedRetries.delete(e.cellKey);\n } catch (err) {\n // Owned by another node (celld or cellb): its owner fires the alarm.\n if (isOwnedElsewhere(err)) {\n hosts.get(e.cellKey)?.close();\n hosts.delete(e.cellKey);\n // A live owner fires it. A stopped one's lease expires within its TTL: look again a\n // few times before leaving it to the next poll of the wake index.\n const n = (ownedRetries.get(e.cellKey) ?? 0) + 1;\n if (n <= 15) {\n ownedRetries.set(e.cellKey, n);\n alarms.set(e, clock.now() + 2_000);\n } else ownedRetries.delete(e.cellKey);\n }\n // Any other failure (broken object, storage error): the row is unchanged; it fires again\n // when the object is next opened or the index is polled.\n }\n }\n\n for (const [binding, { className }] of Object.entries(opts.durableObjects ?? {})) {\n const cls = opts.worker[className] as DurableObjectClass | undefined;\n if (typeof cls !== \"function\")\n throw new Error(`Durable Object class \"${className}\" is not exported by the worker`);\n const hostFor = (id: DurableObjectId): ObjectHost => {\n const cellKey = `${className}/${id.toString()}`;\n let h = hosts.get(cellKey);\n if (!h || h.broken) {\n h?.close();\n h = new ObjectHost({\n cellKey,\n id,\n cls,\n env,\n openSql: opts.openSql,\n durability,\n codec: storageCodec,\n waitUntil,\n backup,\n onAlarmChange: (at) => alarms.set({ cellKey, className, idHex: id.toString() }, at),\n exports: exportsObj,\n facet: opts.facets,\n asyncRoot: eventsRoot,\n acquire: ownership ? (key) => ownership.tryAcquire(key) : undefined,\n sqlExtensions: opts.sqlExtensions,\n deleteAllPreservesAlarm: opts.deleteAllPreservesAlarm,\n });\n hosts.set(cellKey, h);\n }\n return h;\n };\n hostsByClass.set(className, hostFor);\n const nsKey =\n opts.namespaceKeys?.[className] ?? namespaceKey(opts.scriptName ?? \"worker\", className);\n env[binding] = new DurableObjectNamespace(nsKey, (id) => {\n const remote = opts.route?.(`${className}/${id.toString()}`, id);\n if (remote) return () => httpEndpoint(postVia(remote), codec, binding, className, id);\n const cellKey = `${className}/${id.toString()}`;\n // A cell not open yet waits for room in its store before its first event (OPFS pool).\n const ready = () => (hosts.has(cellKey) ? undefined : opts.openSql.room?.(cellKey));\n const local = localEndpoint(() => hostFor(id), ready);\n const peers = opts.peers;\n if (!peers) return local;\n // Local first; a cell owned by another node is reached through that node.\n const viaOwner = async () => {\n const owner = await peers.ownerOf(cellKey);\n if (!owner) throw new CellOwnedElsewhereError(cellKey);\n const direct = await peers.endpoint?.(owner, cellKey, id.name);\n if (direct) return direct;\n return httpEndpoint(postVia(peers.link(owner)), codec, binding, className, id);\n };\n // The host reports a failed open as a broken object; the cause tells why.\n const elsewhere = (e: unknown): boolean => {\n for (\n let x = e as { name?: string; cause?: unknown } | undefined, i = 0;\n x && i < 5;\n x = x.cause as never, i++\n )\n if (x.name === \"CellOwnedElsewhereError\") return true;\n return false;\n };\n return () => {\n const l = local();\n return {\n get local() {\n return l.local; // not copied: reading it opens the cell\n },\n fetch: async (req: Request) => {\n const spare = req.body ? req.clone() : req;\n try {\n return await l.fetch(req);\n } catch (e) {\n if (!elsewhere(e)) throw e;\n hosts.get(cellKey)?.close();\n hosts.delete(cellKey);\n return (await viaOwner()).fetch(spare);\n }\n },\n call: async (method: string, args: unknown[]) => {\n try {\n return await l.call(method, args);\n } catch (e) {\n if (!elsewhere(e)) throw e;\n hosts.get(cellKey)?.close();\n hosts.delete(cellKey);\n return (await viaOwner()).call(method, args);\n }\n },\n };\n };\n });\n bindingClasses[binding] = className;\n // ctx.exports.<Class> of a class with a namespace is also that namespace, as in workerd\n // (`ctx.exports.MyActor.getByName(\"a\")`); it stays usable as a facet class handle.\n const ns = env[binding] as DurableObjectNamespace;\n const exported = exportsObj[className] as Record<string, unknown> | undefined;\n if (exported && !(\"getByName\" in exported))\n for (const [m, d] of Object.entries(\n Object.getOwnPropertyDescriptors(DurableObjectNamespace.prototype),\n ))\n if (m !== \"constructor\" && typeof d.value === \"function\") exported[m] = d.value.bind(ns);\n }\n\n alarms.restore();\n // Alarms published by any node in a shared wake index (celld's): this node fires them too.\n // An entry is only a hint: firing opens the cell and runs alarm() only if its stored alarm\n // is still due at that time.\n // The index is read at start and then every `wakePollMs` (default 30 s), so alarms of cells\n // whose owner went away are picked up — celld's waker does the same.\n const wakes = storage.durability?.wakes;\n let wakeTimer: unknown;\n let wakesStopped = false;\n if (wakes) {\n const known = new Set(Object.values(bindingClasses));\n const poll = async () => {\n try {\n for (const w of await wakes.call(storage.durability))\n if (known.has(w.className) && !alarmRuns.has(w.cellKey))\n alarms.set(\n { cellKey: w.cellKey, className: w.className, idHex: w.cellKey.split(\"/\")[1] },\n w.at,\n );\n } catch {\n // the index is unavailable for now: next poll\n }\n if (!wakesStopped) wakeTimer = clock.setTimeout(() => void poll(), opts.wakePollMs ?? 30_000);\n };\n void poll();\n }\n // Idle sweep for hibernation (opt-in).\n let hibernationTimer: unknown;\n if (opts.hibernateAfterMs !== undefined) {\n const every = Math.max(1_000, opts.hibernateAfterMs / 2);\n const sweep = () => {\n runtime.hibernateIdle();\n hibernationTimer = clock.setTimeout(sweep, every);\n };\n hibernationTimer = clock.setTimeout(sweep, every);\n }\n const backupAll = (reason: \"interval\" | \"manual\" | \"close\") =>\n Promise.all([...hosts.values()].map((h) => h.backupIfDirty(reason, clock.now()))).then(\n () => {},\n );\n let timer: unknown;\n let closed = false;\n const schedule = () => {\n if (!backup || closed) return;\n timer = clock.setTimeout(() => {\n void backupAll(\"interval\").finally(schedule);\n }, backup.intervalMs ?? 30_000);\n };\n schedule();\n\n const runtime: CellRuntime = {\n env,\n exports: exportsObj,\n durableObjectBindings: bindingClasses,\n backupNow: () => backupAll(\"manual\"),\n async connectWebSocket(url, protocols = [], headers) {\n const h = new Headers(headers);\n h.set(\"Upgrade\", \"websocket\");\n if (protocols.length) h.set(\"Sec-WebSocket-Protocol\", protocols.join(\", \"));\n const httpUrl = url.replace(/^ws(s?):/, \"http$1:\");\n const res = (await this.fetch(\n withUpgrade(\n new Request(httpUrl, { headers: h }),\n \"websocket\",\n protocols.length ? { \"Sec-WebSocket-Protocol\": protocols.join(\", \") } : undefined,\n ),\n )) as Response & {\n webSocket?: CfWebSocket | null;\n };\n if (res.status !== 101 || !res.webSocket)\n throw new Error(`WebSocket upgrade refused: HTTP ${res.status}`);\n return {\n port: takeClientPort(res.webSocket),\n protocol: res.headers.get(\"Sec-WebSocket-Protocol\") ?? undefined,\n };\n },\n restartObject(cellKey: string) {\n hosts.get(cellKey)?.restart();\n },\n hibernateIdle(idleMs = opts.hibernateAfterMs ?? 0) {\n const now = Date.now();\n let n = 0;\n const closeMs = opts.closeDatabaseAfterMs;\n for (const h of hosts.values()) {\n const idle = now - h.lastActive;\n if (idle >= idleMs && h.hibernate()) n++;\n if (closeMs !== undefined && idle >= closeMs) h.closeDatabase();\n }\n return n;\n },\n async close() {\n if (hibernationTimer !== undefined) clock.clearTimeout(hibernationTimer);\n closed = true;\n wakesStopped = true;\n if (wakeTimer !== undefined) clock.clearTimeout(wakeTimer);\n alarms.stop();\n clock.clearTimeout(timer);\n timer = undefined;\n await backupAll(\"close\");\n // The releases reach the store before it closes.\n await Promise.all([...hosts.values()].map((h) => h.close()));\n hosts.clear();\n alarms.close(); // every database of the runtime is closed now\n await storage.close?.();\n },\n async fetch(req) {\n const handler = opts.worker.default?.fetch;\n if (!handler) return new Response(\"Worker has no fetch handler\", { status: 500 });\n const ctx = {\n waitUntil,\n passThroughOnException() {},\n exports: exportsObj,\n } as ExecutionContext;\n // celld's ingress: an inbound request has a `cf` object (no edge fields).\n if ((req as { cf?: unknown }).cf === undefined)\n Object.defineProperty(req, \"cf\", { value: {}, enumerable: true });\n try {\n const r = await rejections(() => handler.call(opts.worker.default, req, env, ctx));\n // A non-Response is sent as text (celld), not a failure.\n return r instanceof Response ? r : new Response(String(r));\n } catch (e) {\n const err = e as Error;\n return new Response(\n `Worker failed: rejected: ${err?.name ?? \"Error\"}: ${err?.message ?? String(e)}`,\n {\n status: 500,\n headers: { \"content-type\": \"application/json\" },\n },\n );\n }\n },\n runEvent: (fn) => rejections(fn),\n evictAll() {\n for (const h of hosts.values()) h.close();\n hosts.clear();\n },\n async drain() {\n while (background.size) await Promise.all([...background]);\n },\n waitUntil,\n };\n return runtime;\n}\n\n/** The error (or its cause chain) says another node owns the cell. */\nexport function isOwnedElsewhere(e: unknown): boolean {\n for (\n let x = e as { name?: string; cause?: unknown } | undefined, i = 0;\n x && i < 5;\n x = x.cause as never, i++\n )\n if (x.name === \"CellOwnedElsewhereError\") return true;\n return false;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Fixed sharding of cells: a cell lives in shard `shardOf(id, n)` for the
3
+ * lifetime of the deployment. A shard is the unit of ownership (one Web Lock /
4
+ * lease), of storage (one opfs-sahpool — pools are exclusive per worker) and of
5
+ * placement (one worker). Changing `n` requires migration.
6
+ */
7
+ export declare function shardOf(idHex: string, shards: number): number;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Fixed sharding of cells: a cell lives in shard `shardOf(id, n)` for the
3
+ * lifetime of the deployment. A shard is the unit of ownership (one Web Lock /
4
+ * lease), of storage (one opfs-sahpool — pools are exclusive per worker) and of
5
+ * placement (one worker). Changing `n` requires migration.
6
+ */
7
+ export function shardOf(idHex, shards) {
8
+ return parseInt(idHex.slice(0, 8), 16) % shards;
9
+ }
10
+ //# sourceMappingURL=shard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shard.js","sourceRoot":"","sources":["../../src/core/shard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa,EAAE,MAAc;IACnD,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC;AAClD,CAAC","sourcesContent":["/**\n * Fixed sharding of cells: a cell lives in shard `shardOf(id, n)` for the\n * lifetime of the deployment. A shard is the unit of ownership (one Web Lock /\n * lease), of storage (one opfs-sahpool — pools are exclusive per worker) and of\n * placement (one worker). Changing `n` requires migration.\n */\nexport function shardOf(idHex: string, shards: number): number {\n return parseInt(idHex.slice(0, 8), 16) % shards;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /** Splits a param-less SQL script on top-level `;` (respects quotes, comments, triggers). */
2
+ export declare function splitSqlStatements(sql: string): string[];
3
+ /**
4
+ * The complete statements at the start of a chunk of SQL text (each ended by a top-level `;`,
5
+ * as `sqlite3_complete` sees it) and the text after the last of them, untouched.
6
+ */
7
+ export declare function completeSqlStatements(sql: string): {
8
+ statements: string[];
9
+ remainder: string;
10
+ };
11
+ /**
12
+ * Whether `sql` holds no statement to run (workerd and celld: "SQL code did not contain a
13
+ * statement"): nothing but whitespace, comments and `;`, or a last statement of comments alone.
14
+ */
15
+ export declare function lacksStatement(sql: string): boolean;
@@ -0,0 +1,101 @@
1
+ /** A trigger's creation, also under EXPLAIN (`sql.ingest()` prepares each statement so). */
2
+ const TRIGGER = /^\s*(?:EXPLAIN\s+)?CREATE\s+(?:TEMP\s+|TEMPORARY\s+)?TRIGGER\b/i;
3
+ /**
4
+ * Whether a trigger's text so far ends its body: its `BEGIN` closed by an `END` that does not
5
+ * close a `CASE` (a body's statements may hold `CASE … END`, as in `SELECT CASE WHEN … THEN
6
+ * RAISE(ABORT, …) END;`). Quoted text and identifiers are left out of the count.
7
+ */
8
+ function triggerEnded(text) {
9
+ const words = text
10
+ .replace(/'[^']*'|"[^"]*"|`[^`]*`|\[[^\]]*\]/g, " ")
11
+ .match(/\b(BEGIN|CASE|END)\b/gi);
12
+ if (!words)
13
+ return false;
14
+ let depth = 0;
15
+ let begun = false;
16
+ for (const w of words) {
17
+ const u = w.toUpperCase();
18
+ if (u === "BEGIN") {
19
+ begun = true;
20
+ depth++;
21
+ }
22
+ else if (u === "CASE")
23
+ depth++;
24
+ else
25
+ depth--;
26
+ }
27
+ return begun && depth <= 0 && /\bEND\s*$/i.test(text);
28
+ }
29
+ /**
30
+ * The statements of a SQL script ended by a top-level `;` (quotes, comments and trigger bodies
31
+ * respected), each without its comments, with the offset just past its `;`; then the text after
32
+ * the last one, with `end` undefined.
33
+ */
34
+ function* scanSql(sql) {
35
+ let cur = "";
36
+ for (let i = 0; i < sql.length; i++) {
37
+ const c = sql[i];
38
+ if (c === "'" || c === '"' || c === "`") {
39
+ const end = sql.indexOf(c, i + 1);
40
+ const j = end < 0 ? sql.length : end;
41
+ cur += sql.slice(i, j + 1);
42
+ i = j;
43
+ }
44
+ else if (c === "-" && sql[i + 1] === "-") {
45
+ const end = sql.indexOf("\n", i);
46
+ i = end < 0 ? sql.length : end;
47
+ }
48
+ else if (c === "/" && sql[i + 1] === "*") {
49
+ const end = sql.indexOf("*/", i + 2);
50
+ i = end < 0 ? sql.length : end + 1;
51
+ }
52
+ else if (c === ";") {
53
+ // A trigger body (CREATE TRIGGER … BEGIN …; …; END) is one statement.
54
+ if (TRIGGER.test(cur) && !triggerEnded(cur)) {
55
+ cur += c;
56
+ continue;
57
+ }
58
+ yield { text: cur, end: i + 1 };
59
+ cur = "";
60
+ }
61
+ else
62
+ cur += c;
63
+ }
64
+ yield { text: cur };
65
+ }
66
+ /** Splits a param-less SQL script on top-level `;` (respects quotes, comments, triggers). */
67
+ export function splitSqlStatements(sql) {
68
+ const out = [];
69
+ for (const { text } of scanSql(sql))
70
+ if (text.trim())
71
+ out.push(text.trim());
72
+ return out.length ? out : [sql];
73
+ }
74
+ /**
75
+ * The complete statements at the start of a chunk of SQL text (each ended by a top-level `;`,
76
+ * as `sqlite3_complete` sees it) and the text after the last of them, untouched.
77
+ */
78
+ export function completeSqlStatements(sql) {
79
+ const statements = [];
80
+ let rest = 0;
81
+ for (const { text, end } of scanSql(sql)) {
82
+ if (end === undefined)
83
+ break;
84
+ if (text.trim())
85
+ statements.push(text.trim());
86
+ rest = end;
87
+ }
88
+ return { statements, remainder: sql.slice(rest) };
89
+ }
90
+ const COMMENTS = /--[^\n]*(\n|$)|\/\*[\s\S]*?(\*\/|$)/g;
91
+ /**
92
+ * Whether `sql` holds no statement to run (workerd and celld: "SQL code did not contain a
93
+ * statement"): nothing but whitespace, comments and `;`, or a last statement of comments alone.
94
+ */
95
+ export function lacksStatement(sql) {
96
+ if (sql.replace(COMMENTS, " ").replace(/;/g, " ").trim() === "")
97
+ return true;
98
+ const { remainder } = completeSqlStatements(sql);
99
+ return remainder.trim() !== "" && remainder.replace(COMMENTS, " ").trim() === "";
100
+ }
101
+ //# sourceMappingURL=sql-split.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-split.js","sourceRoot":"","sources":["../../src/core/sql-split.ts"],"names":[],"mappings":"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","sourcesContent":["/** A trigger's creation, also under EXPLAIN (`sql.ingest()` prepares each statement so). */\nconst TRIGGER = /^\\s*(?:EXPLAIN\\s+)?CREATE\\s+(?:TEMP\\s+|TEMPORARY\\s+)?TRIGGER\\b/i;\n\n/**\n * Whether a trigger's text so far ends its body: its `BEGIN` closed by an `END` that does not\n * close a `CASE` (a body's statements may hold `CASE … END`, as in `SELECT CASE WHEN … THEN\n * RAISE(ABORT, …) END;`). Quoted text and identifiers are left out of the count.\n */\nfunction triggerEnded(text: string): boolean {\n const words = text\n .replace(/'[^']*'|\"[^\"]*\"|`[^`]*`|\\[[^\\]]*\\]/g, \" \")\n .match(/\\b(BEGIN|CASE|END)\\b/gi);\n if (!words) return false;\n let depth = 0;\n let begun = false;\n for (const w of words) {\n const u = w.toUpperCase();\n if (u === \"BEGIN\") {\n begun = true;\n depth++;\n } else if (u === \"CASE\") depth++;\n else depth--;\n }\n return begun && depth <= 0 && /\\bEND\\s*$/i.test(text);\n}\n\n/**\n * The statements of a SQL script ended by a top-level `;` (quotes, comments and trigger bodies\n * respected), each without its comments, with the offset just past its `;`; then the text after\n * the last one, with `end` undefined.\n */\nfunction* scanSql(sql: string): Generator<{ text: string; end?: number }> {\n let cur = \"\";\n for (let i = 0; i < sql.length; i++) {\n const c = sql[i];\n if (c === \"'\" || c === '\"' || c === \"`\") {\n const end = sql.indexOf(c, i + 1);\n const j = end < 0 ? sql.length : end;\n cur += sql.slice(i, j + 1);\n i = j;\n } else if (c === \"-\" && sql[i + 1] === \"-\") {\n const end = sql.indexOf(\"\\n\", i);\n i = end < 0 ? sql.length : end;\n } else if (c === \"/\" && sql[i + 1] === \"*\") {\n const end = sql.indexOf(\"*/\", i + 2);\n i = end < 0 ? sql.length : end + 1;\n } else if (c === \";\") {\n // A trigger body (CREATE TRIGGER … BEGIN …; …; END) is one statement.\n if (TRIGGER.test(cur) && !triggerEnded(cur)) {\n cur += c;\n continue;\n }\n yield { text: cur, end: i + 1 };\n cur = \"\";\n } else cur += c;\n }\n yield { text: cur };\n}\n\n/** Splits a param-less SQL script on top-level `;` (respects quotes, comments, triggers). */\nexport function splitSqlStatements(sql: string): string[] {\n const out: string[] = [];\n for (const { text } of scanSql(sql)) if (text.trim()) out.push(text.trim());\n return out.length ? out : [sql];\n}\n\n/**\n * The complete statements at the start of a chunk of SQL text (each ended by a top-level `;`,\n * as `sqlite3_complete` sees it) and the text after the last of them, untouched.\n */\nexport function completeSqlStatements(sql: string): { statements: string[]; remainder: string } {\n const statements: string[] = [];\n let rest = 0;\n for (const { text, end } of scanSql(sql)) {\n if (end === undefined) break;\n if (text.trim()) statements.push(text.trim());\n rest = end;\n }\n return { statements, remainder: sql.slice(rest) };\n}\n\nconst COMMENTS = /--[^\\n]*(\\n|$)|\\/\\*[\\s\\S]*?(\\*\\/|$)/g;\n\n/**\n * Whether `sql` holds no statement to run (workerd and celld: \"SQL code did not contain a\n * statement\"): nothing but whitespace, comments and `;`, or a last statement of comments alone.\n */\nexport function lacksStatement(sql: string): boolean {\n if (sql.replace(COMMENTS, \" \").replace(/;/g, \" \").trim() === \"\") return true;\n const { remainder } = completeSqlStatements(sql);\n return remainder.trim() !== \"\" && remainder.replace(COMMENTS, \" \").trim() === \"\";\n}\n"]}