@swirls/looms 0.0.2 → 0.2.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 (375) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/dist/actor/cell.d.ts +9 -4
  3. package/dist/actor/cell.js +7 -11
  4. package/dist/actor/host.d.ts +7 -3
  5. package/dist/actor/host.js +57 -33
  6. package/dist/actor/index.d.ts +1 -1
  7. package/dist/actor/index.js +1 -1
  8. package/dist/actor/routing.d.ts +12 -1
  9. package/dist/actor/routing.js +57 -51
  10. package/dist/agent/agent-session.d.ts +5 -0
  11. package/dist/agent/agent-session.js +270 -0
  12. package/dist/agent/debugger/agent-chat.d.ts +2 -0
  13. package/dist/agent/debugger/agent-chat.js +176 -0
  14. package/dist/agent/debugger/index.d.ts +5 -0
  15. package/dist/agent/debugger/index.js +19 -0
  16. package/dist/agent/debugger/summarize.d.ts +2 -0
  17. package/dist/agent/debugger/summarize.js +51 -0
  18. package/dist/agent/debugger/token-usage.d.ts +3 -0
  19. package/dist/agent/debugger/token-usage.js +11 -0
  20. package/dist/agent/definitions-store.d.ts +2 -3
  21. package/dist/agent/definitions-store.js +2 -4
  22. package/dist/agent/definitions.d.ts +47 -29
  23. package/dist/agent/definitions.js +39 -12
  24. package/dist/agent/effects.d.ts +359 -2
  25. package/dist/agent/effects.js +60 -34
  26. package/dist/agent/events.d.ts +175 -19
  27. package/dist/agent/events.js +45 -10
  28. package/dist/agent/index.d.ts +1 -0
  29. package/dist/agent/index.js +1 -0
  30. package/dist/agent/llm.d.ts +11 -2
  31. package/dist/agent/llm.js +13 -3
  32. package/dist/agent/module.d.ts +812 -78
  33. package/dist/agent/module.js +16 -4
  34. package/dist/agent/scope.d.ts +174 -18
  35. package/dist/agent/signals.d.ts +26 -1
  36. package/dist/agent/signals.js +79 -0
  37. package/dist/agent/threads.d.ts +3 -33
  38. package/dist/agent/threads.js +20 -25
  39. package/dist/agent/tool-schema.d.ts +1 -17
  40. package/dist/agent/tool-schema.js +3 -43
  41. package/dist/agent/types.d.ts +49 -4
  42. package/dist/agent/types.js +5 -5
  43. package/dist/ai-vercel/index.d.ts +1 -0
  44. package/dist/ai-vercel/index.js +1 -0
  45. package/dist/ai-vercel/messages.js +22 -7
  46. package/dist/ai-vercel/vercel-evaluator.d.ts +36 -0
  47. package/dist/ai-vercel/vercel-evaluator.js +73 -0
  48. package/dist/ai-vercel/vercel-llm.js +64 -44
  49. package/dist/approval/debugger/approvals-view.d.ts +3 -0
  50. package/dist/approval/debugger/approvals-view.js +16 -0
  51. package/dist/approval/debugger/index.d.ts +4 -0
  52. package/dist/approval/debugger/index.js +11 -0
  53. package/dist/approval/debugger/summarize.d.ts +2 -0
  54. package/dist/approval/debugger/summarize.js +17 -0
  55. package/dist/approval/effects.d.ts +89 -0
  56. package/dist/approval/module.d.ts +179 -29
  57. package/dist/approval/projections.d.ts +0 -14
  58. package/dist/approval/projections.js +20 -3
  59. package/dist/approval/signals.d.ts +2 -0
  60. package/dist/approval/signals.js +18 -2
  61. package/dist/cli/cli.js +2 -0
  62. package/dist/cli/commands.js +12 -16
  63. package/dist/client/client.d.ts +1213 -18
  64. package/dist/client/client.js +120 -120
  65. package/dist/client/index.d.ts +1 -1
  66. package/dist/client/index.js +1 -1
  67. package/dist/client/sse.d.ts +13 -0
  68. package/dist/client/sse.js +38 -44
  69. package/dist/cloudflare/alarm-scheduler.d.ts +12 -2
  70. package/dist/cloudflare/alarm-scheduler.js +34 -7
  71. package/dist/cloudflare/durable-object.d.ts +10 -2
  72. package/dist/cloudflare/durable-object.js +59 -28
  73. package/dist/cloudflare/event-store.d.ts +7 -2
  74. package/dist/cloudflare/event-store.js +8 -7
  75. package/dist/cloudflare/index.d.ts +2 -2
  76. package/dist/cloudflare/index.js +2 -2
  77. package/dist/cloudflare/router.d.ts +1 -1
  78. package/dist/cloudflare/router.js +15 -16
  79. package/dist/core/catalog.d.ts +3 -3
  80. package/dist/core/catalog.js +2 -5
  81. package/dist/core/coalesce.js +5 -3
  82. package/dist/core/compose.d.ts +2 -1
  83. package/dist/core/compose.js +19 -2
  84. package/dist/core/debugger-host.d.ts +16 -0
  85. package/dist/core/debugger-host.js +1 -0
  86. package/dist/core/definition-store.d.ts +11 -0
  87. package/dist/core/definition-store.js +6 -0
  88. package/dist/core/effects.d.ts +127 -15
  89. package/dist/core/effects.js +89 -17
  90. package/dist/core/envelope.d.ts +27 -7
  91. package/dist/core/envelope.js +20 -6
  92. package/dist/core/event-codec.d.ts +4 -2
  93. package/dist/core/event-codec.js +10 -5
  94. package/dist/core/event-index.js +1 -3
  95. package/dist/core/fold.d.ts +3 -0
  96. package/dist/core/fold.js +171 -24
  97. package/dist/core/ids.d.ts +5 -0
  98. package/dist/core/ids.js +35 -2
  99. package/dist/core/index.d.ts +7 -1
  100. package/dist/core/index.js +6 -1
  101. package/dist/core/kind.d.ts +22 -0
  102. package/dist/core/kind.js +17 -0
  103. package/dist/core/limits.d.ts +34 -0
  104. package/dist/core/limits.js +46 -0
  105. package/dist/core/match.d.ts +1 -0
  106. package/dist/core/match.js +10 -1
  107. package/dist/core/module-scope.d.ts +22 -20
  108. package/dist/core/module-scope.js +38 -28
  109. package/dist/core/module.d.ts +18 -5
  110. package/dist/core/module.js +4 -0
  111. package/dist/core/projection.d.ts +13 -13
  112. package/dist/core/projection.js +9 -5
  113. package/dist/core/protocol.d.ts +68 -11
  114. package/dist/core/protocol.js +82 -11
  115. package/dist/core/published.d.ts +43 -0
  116. package/dist/core/published.js +44 -0
  117. package/dist/core/replay.d.ts +312 -3
  118. package/dist/core/replay.js +11 -1
  119. package/dist/core/schema.d.ts +11 -20
  120. package/dist/core/schema.js +63 -80
  121. package/dist/core/serialize.js +2 -4
  122. package/dist/core/snapshot-store.d.ts +6 -1
  123. package/dist/core/snapshot-store.js +15 -2
  124. package/dist/core/snapshots.d.ts +5 -1
  125. package/dist/core/snapshots.js +10 -15
  126. package/dist/core/sqlite-store.js +95 -11
  127. package/dist/core/state.d.ts +142 -4
  128. package/dist/core/state.js +78 -0
  129. package/dist/core/store.d.ts +38 -3
  130. package/dist/core/store.js +77 -22
  131. package/dist/core/thread.d.ts +10 -9
  132. package/dist/core/types.d.ts +5 -8
  133. package/dist/core/types.js +28 -24
  134. package/dist/core/validate-event.js +14 -4
  135. package/dist/core/worker-callback.d.ts +17 -0
  136. package/dist/core/worker-callback.js +1 -0
  137. package/dist/debugger/app/assets/index-B3Ah8WAE.css +2 -0
  138. package/dist/debugger/app/assets/index-Qb371t_O.js +22 -0
  139. package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
  140. package/dist/debugger/app/assets/routes-CjtEHgPQ.js +47 -0
  141. package/dist/debugger/app/index.html +14 -0
  142. package/dist/debugger/components/composer.d.ts +17 -0
  143. package/dist/debugger/components/composer.js +25 -0
  144. package/dist/debugger/components/debugger-split.d.ts +2 -1
  145. package/dist/debugger/components/debugger-split.js +2 -2
  146. package/dist/debugger/components/event-inspector.d.ts +2 -1
  147. package/dist/debugger/components/event-inspector.js +25 -16
  148. package/dist/debugger/components/event-stream.d.ts +2 -1
  149. package/dist/debugger/components/event-stream.js +14 -74
  150. package/dist/debugger/components/follow-list.d.ts +19 -0
  151. package/dist/debugger/components/follow-list.js +96 -0
  152. package/dist/debugger/components/json-tree.d.ts +11 -0
  153. package/dist/debugger/components/json-tree.js +120 -0
  154. package/dist/debugger/components/json-view.js +2 -2
  155. package/dist/debugger/components/run-tree.js +53 -20
  156. package/dist/debugger/components/status-dot.d.ts +4 -0
  157. package/dist/debugger/components/status-dot.js +6 -2
  158. package/dist/debugger/context.d.ts +14 -0
  159. package/dist/debugger/context.js +17 -0
  160. package/dist/debugger/contracts.d.ts +7 -4
  161. package/dist/debugger/events/builtin-families.d.ts +3 -0
  162. package/dist/debugger/events/builtin-families.js +9 -0
  163. package/dist/debugger/events/catalog.d.ts +3 -4
  164. package/dist/debugger/events/catalog.js +27 -17
  165. package/dist/debugger/events/protocol-summarize.d.ts +1 -2
  166. package/dist/debugger/events/protocol-summarize.js +42 -24
  167. package/dist/debugger/index.d.ts +20 -6
  168. package/dist/debugger/index.js +19 -5
  169. package/dist/debugger/lib/cn.d.ts +1 -0
  170. package/dist/debugger/lib/cn.js +3 -0
  171. package/dist/debugger/lib/event-meta.d.ts +2 -3
  172. package/dist/debugger/lib/event-meta.js +6 -12
  173. package/dist/debugger/lib/json.d.ts +25 -0
  174. package/dist/debugger/lib/json.js +87 -0
  175. package/dist/debugger/lib/payload.d.ts +7 -0
  176. package/dist/debugger/lib/payload.js +11 -0
  177. package/dist/debugger/lib/time.d.ts +3 -0
  178. package/dist/debugger/lib/time.js +24 -0
  179. package/dist/debugger/plugin.d.ts +36 -0
  180. package/dist/debugger/plugin.js +14 -0
  181. package/dist/debugger/server/index.d.ts +14 -0
  182. package/dist/debugger/server/index.js +114 -0
  183. package/dist/debugger/shell/debugger-shell.d.ts +15 -0
  184. package/dist/debugger/shell/debugger-shell.js +43 -0
  185. package/dist/debugger/shell/definition-key.d.ts +3 -0
  186. package/dist/debugger/shell/definition-key.js +4 -0
  187. package/dist/debugger/shell/events-pane.d.ts +12 -0
  188. package/dist/debugger/shell/events-pane.js +25 -0
  189. package/dist/debugger/shell/projections-panel.d.ts +4 -0
  190. package/dist/debugger/shell/projections-panel.js +59 -0
  191. package/dist/debugger/shell/run-controls.d.ts +4 -0
  192. package/dist/debugger/shell/run-controls.js +72 -0
  193. package/dist/debugger/shell/run-search.d.ts +6 -0
  194. package/dist/debugger/shell/run-search.js +102 -0
  195. package/dist/debugger/shell/run-type-menu.d.ts +6 -0
  196. package/dist/debugger/shell/run-type-menu.js +11 -0
  197. package/dist/debugger/shell/schema-form.d.ts +31 -0
  198. package/dist/debugger/shell/schema-form.js +117 -0
  199. package/dist/debugger/shell/start-form.d.ts +3 -0
  200. package/dist/debugger/shell/start-form.js +75 -0
  201. package/dist/debugger/shell/use-start-run.d.ts +14 -0
  202. package/dist/debugger/shell/use-start-run.js +32 -0
  203. package/dist/debugger/shell/workspace.d.ts +6 -0
  204. package/dist/debugger/shell/workspace.js +15 -0
  205. package/dist/debugger/styles.css +111 -27
  206. package/dist/debugger/ui/button.d.ts +24 -0
  207. package/dist/debugger/ui/button.js +24 -0
  208. package/dist/debugger/ui/command.d.ts +9 -0
  209. package/dist/debugger/ui/command.js +24 -0
  210. package/dist/debugger/ui/dropdown-menu.d.ts +13 -0
  211. package/dist/debugger/ui/dropdown-menu.js +37 -0
  212. package/dist/debugger/ui/panel.d.ts +14 -0
  213. package/dist/debugger/ui/panel.js +16 -0
  214. package/dist/debugger/ui/popover.d.ts +7 -0
  215. package/dist/debugger/ui/popover.js +17 -0
  216. package/dist/debugger/ui/resizable.d.ts +7 -0
  217. package/dist/debugger/ui/resizable.js +14 -0
  218. package/dist/debugger/ui/scroll-area.d.ts +2 -1
  219. package/dist/debugger/ui/scroll-area.js +5 -3
  220. package/dist/debugger/ui/select.d.ts +10 -0
  221. package/dist/debugger/ui/select.js +21 -0
  222. package/dist/debugger/ui/tabs.js +2 -2
  223. package/dist/debugger/ui/textarea.d.ts +3 -0
  224. package/dist/debugger/ui/textarea.js +7 -0
  225. package/dist/evaluator/definitions-store.d.ts +11 -0
  226. package/dist/evaluator/definitions-store.js +8 -0
  227. package/dist/evaluator/definitions.d.ts +18 -0
  228. package/dist/evaluator/definitions.js +4 -0
  229. package/dist/evaluator/effects.d.ts +226 -0
  230. package/dist/evaluator/effects.js +132 -0
  231. package/dist/evaluator/evaluator.d.ts +24 -0
  232. package/dist/evaluator/evaluator.js +67 -0
  233. package/dist/evaluator/events.d.ts +59 -0
  234. package/dist/evaluator/events.js +21 -0
  235. package/dist/evaluator/index.d.ts +11 -0
  236. package/dist/evaluator/index.js +11 -0
  237. package/dist/evaluator/module.d.ts +606 -0
  238. package/dist/evaluator/module.js +25 -0
  239. package/dist/evaluator/projections.d.ts +50 -0
  240. package/dist/evaluator/projections.js +20 -0
  241. package/dist/evaluator/scope.d.ts +59 -0
  242. package/dist/evaluator/scope.js +7 -0
  243. package/dist/evaluator/signals.d.ts +3 -0
  244. package/dist/evaluator/signals.js +17 -0
  245. package/dist/evaluator/threads.d.ts +62 -0
  246. package/dist/evaluator/threads.js +117 -0
  247. package/dist/evaluator/types.d.ts +125 -0
  248. package/dist/evaluator/types.js +51 -0
  249. package/dist/projectors/delivery.d.ts +83 -0
  250. package/dist/projectors/delivery.js +182 -0
  251. package/dist/projectors/index-model.d.ts +1 -1
  252. package/dist/projectors/index-model.js +4 -6
  253. package/dist/projectors/index.d.ts +2 -0
  254. package/dist/projectors/index.js +2 -0
  255. package/dist/projectors/memory.d.ts +1 -1
  256. package/dist/projectors/memory.js +10 -8
  257. package/dist/projectors/postgres.js +44 -58
  258. package/dist/projectors/projector.d.ts +17 -0
  259. package/dist/projectors/projector.js +26 -1
  260. package/dist/projectors/sqlite-delivery.d.ts +4 -0
  261. package/dist/projectors/sqlite-delivery.js +147 -0
  262. package/dist/projectors/sqlite.js +23 -23
  263. package/dist/projectors/with-projectors.d.ts +7 -2
  264. package/dist/projectors/with-projectors.js +27 -28
  265. package/dist/react/notify.js +11 -8
  266. package/dist/react/react.d.ts +2 -3
  267. package/dist/react/react.js +14 -30
  268. package/dist/react/sse.d.ts +1 -1
  269. package/dist/react/sse.js +1 -1
  270. package/dist/react/store.d.ts +3 -3
  271. package/dist/react/store.js +109 -119
  272. package/dist/runtime/cancellation.d.ts +16 -0
  273. package/dist/runtime/cancellation.js +129 -0
  274. package/dist/runtime/deadline-transition-planner.d.ts +31 -0
  275. package/dist/runtime/deadline-transition-planner.js +139 -0
  276. package/dist/runtime/dispatch-effect.d.ts +3 -2
  277. package/dist/runtime/dispatch-effect.js +7 -13
  278. package/dist/runtime/errors.d.ts +51 -0
  279. package/dist/runtime/errors.js +39 -0
  280. package/dist/runtime/{runtime-helpers.d.ts → helpers.d.ts} +24 -4
  281. package/dist/runtime/{runtime-helpers.js → helpers.js} +56 -19
  282. package/dist/runtime/index.d.ts +3 -3
  283. package/dist/runtime/index.js +3 -3
  284. package/dist/runtime/ingress.d.ts +15 -0
  285. package/dist/runtime/ingress.js +42 -0
  286. package/dist/runtime/local-effect-executor.d.ts +21 -0
  287. package/dist/runtime/local-effect-executor.js +137 -0
  288. package/dist/runtime/looms.d.ts +30 -4
  289. package/dist/runtime/looms.js +57 -37
  290. package/dist/runtime/observer.d.ts +45 -0
  291. package/dist/runtime/observer.js +11 -0
  292. package/dist/runtime/repository.d.ts +55 -0
  293. package/dist/runtime/repository.js +293 -0
  294. package/dist/runtime/retry-policy.d.ts +16 -0
  295. package/dist/runtime/retry-policy.js +29 -0
  296. package/dist/runtime/run-execution-context.d.ts +30 -0
  297. package/dist/runtime/run-execution-context.js +56 -0
  298. package/dist/runtime/run-start.d.ts +4 -0
  299. package/dist/runtime/run-start.js +44 -0
  300. package/dist/runtime/runtime.d.ts +6 -87
  301. package/dist/runtime/runtime.js +248 -470
  302. package/dist/runtime/server/auth.d.ts +41 -0
  303. package/dist/runtime/server/auth.js +45 -0
  304. package/dist/runtime/server/debugger-host.d.ts +11 -0
  305. package/dist/runtime/server/debugger-host.js +32 -0
  306. package/dist/runtime/server/fetch-handler.d.ts +18 -0
  307. package/dist/runtime/server/fetch-handler.js +62 -0
  308. package/dist/runtime/server/http.d.ts +38 -0
  309. package/dist/runtime/server/http.js +66 -0
  310. package/dist/runtime/server/route-table.d.ts +55 -0
  311. package/dist/runtime/server/route-table.js +74 -0
  312. package/dist/runtime/server/routes/definitions.d.ts +3 -0
  313. package/dist/runtime/server/routes/definitions.js +20 -0
  314. package/dist/runtime/server/routes/effects.d.ts +3 -0
  315. package/dist/runtime/server/routes/effects.js +59 -0
  316. package/dist/runtime/server/routes/operations.d.ts +3 -0
  317. package/dist/runtime/server/routes/operations.js +14 -0
  318. package/dist/runtime/server/routes/runs.d.ts +3 -0
  319. package/dist/runtime/server/routes/runs.js +199 -0
  320. package/dist/runtime/server.d.ts +4 -8
  321. package/dist/runtime/server.js +6 -211
  322. package/dist/runtime/sse.d.ts +2 -1
  323. package/dist/runtime/sse.js +24 -17
  324. package/dist/runtime/types.d.ts +117 -0
  325. package/dist/runtime/types.js +1 -0
  326. package/dist/runtime/wake-engine.d.ts +20 -0
  327. package/dist/runtime/wake-engine.js +311 -0
  328. package/dist/runtime/wake-scheduler.d.ts +3 -4
  329. package/dist/runtime/wake-scheduler.js +25 -31
  330. package/dist/runtime/worker-callbacks.d.ts +16 -0
  331. package/dist/runtime/worker-callbacks.js +167 -0
  332. package/dist/runtime/worker-effect-dispatch.d.ts +36 -0
  333. package/dist/runtime/worker-effect-dispatch.js +126 -0
  334. package/dist/s2/config.d.ts +1 -1
  335. package/dist/s2/config.js +1 -1
  336. package/dist/s2/lite.js +70 -82
  337. package/dist/s2/pagination.d.ts +15 -0
  338. package/dist/s2/pagination.js +36 -0
  339. package/dist/s2/projector.js +6 -5
  340. package/dist/s2/snapshot-store.js +188 -161
  341. package/dist/s2/store.d.ts +3 -21
  342. package/dist/s2/store.js +71 -165
  343. package/dist/testing/index.d.ts +15 -0
  344. package/dist/testing/index.js +53 -16
  345. package/dist/workflow/debugger/index.d.ts +4 -0
  346. package/dist/workflow/debugger/index.js +11 -0
  347. package/dist/workflow/debugger/nodes-view.d.ts +3 -0
  348. package/dist/workflow/debugger/nodes-view.js +13 -0
  349. package/dist/workflow/debugger/summarize.d.ts +2 -0
  350. package/dist/workflow/debugger/summarize.js +30 -0
  351. package/dist/workflow/definitions-store.d.ts +2 -3
  352. package/dist/workflow/definitions-store.js +2 -2
  353. package/dist/workflow/definitions.d.ts +78 -22
  354. package/dist/workflow/definitions.js +80 -14
  355. package/dist/workflow/effects.d.ts +453 -107
  356. package/dist/workflow/effects.js +214 -115
  357. package/dist/workflow/events.d.ts +149 -5
  358. package/dist/workflow/events.js +27 -5
  359. package/dist/workflow/graph.d.ts +56 -0
  360. package/dist/workflow/graph.js +207 -0
  361. package/dist/workflow/index.d.ts +1 -0
  362. package/dist/workflow/index.js +1 -0
  363. package/dist/workflow/module.d.ts +1047 -266
  364. package/dist/workflow/projections.d.ts +14 -12
  365. package/dist/workflow/projections.js +30 -8
  366. package/dist/workflow/scope.d.ts +146 -4
  367. package/dist/workflow/threads.d.ts +383 -155
  368. package/dist/workflow/threads.js +308 -110
  369. package/package.json +26 -2
  370. package/dist/debugger/events/domain-summarize.d.ts +0 -3
  371. package/dist/debugger/events/domain-summarize.js +0 -107
  372. package/dist/debugger/events/family.d.ts +0 -8
  373. package/dist/debugger/events/family.js +0 -44
  374. package/dist/runtime/events-api.d.ts +0 -4
  375. package/dist/runtime/events-api.js +0 -84
@@ -0,0 +1,41 @@
1
+ import { Effect } from 'effect';
2
+ /**
3
+ * What a route can do. `public` routes (health) are never passed to `authorize`; `read` and
4
+ * `write` cover run state, `worker` covers external worker callbacks, and `operations` covers
5
+ * operator repair endpoints.
6
+ */
7
+ export type RouteAccess = 'public' | 'read' | 'write' | 'worker' | 'operations';
8
+ export type AuthorizedAccess = Exclude<RouteAccess, 'public'>;
9
+ export interface RouteInfo {
10
+ readonly access: AuthorizedAccess;
11
+ /** Stable route name, such as `runs.signal` or `effects.retry`. */
12
+ readonly name: string;
13
+ readonly runId?: string;
14
+ }
15
+ export type AuthDecision = {
16
+ readonly allowed: true;
17
+ } | {
18
+ readonly allowed: false;
19
+ readonly status: number;
20
+ readonly error: string;
21
+ };
22
+ export type Authorize = (request: Request, route: RouteInfo) => Effect.Effect<AuthDecision>;
23
+ export declare const authAllowed: AuthDecision;
24
+ export declare function authDenied(status: number, error: string): AuthDecision;
25
+ export declare function authResponse(decision: AuthDecision): Response | null;
26
+ /**
27
+ * Used when a host supplies no `authorize`: run reads and writes stay open, while worker callbacks
28
+ * and operational endpoints are unavailable until a host opts in.
29
+ */
30
+ export declare const defaultAuthorize: Authorize;
31
+ export interface BearerTokens {
32
+ readonly read?: string;
33
+ readonly write?: string;
34
+ readonly worker?: string;
35
+ readonly operations?: string;
36
+ }
37
+ /**
38
+ * Requires `Authorization: Bearer <token>` for every access level that has a token. Levels without
39
+ * a token keep the default behavior: reads and writes are open, worker and operations routes 503.
40
+ */
41
+ export declare function bearerAuth(tokens: BearerTokens): Authorize;
@@ -0,0 +1,45 @@
1
+ import { Effect } from 'effect';
2
+ export const authAllowed = { allowed: true };
3
+ export function authDenied(status, error) {
4
+ return { allowed: false, status, error };
5
+ }
6
+ export function authResponse(decision) {
7
+ return decision.allowed
8
+ ? null
9
+ : Response.json({ error: decision.error }, { status: decision.status });
10
+ }
11
+ const unauthorized = authDenied(401, 'Unauthorized');
12
+ function notConfigured(access) {
13
+ return authDenied(503, access === 'worker'
14
+ ? 'Worker callbacks are not configured'
15
+ : 'Operational endpoints are not configured');
16
+ }
17
+ /**
18
+ * Used when a host supplies no `authorize`: run reads and writes stay open, while worker callbacks
19
+ * and operational endpoints are unavailable until a host opts in.
20
+ */
21
+ export const defaultAuthorize = (_request, route) => Effect.succeed(route.access === 'worker' || route.access === 'operations'
22
+ ? notConfigured(route.access)
23
+ : authAllowed);
24
+ function constantTimeEquals(actual, expected) {
25
+ const length = Math.max(actual.length, expected.length);
26
+ let difference = actual.length ^ expected.length;
27
+ for (let index = 0; index < length; index += 1) {
28
+ difference |= (actual.charCodeAt(index) || 0) ^ (expected.charCodeAt(index) || 0);
29
+ }
30
+ return difference === 0;
31
+ }
32
+ /**
33
+ * Requires `Authorization: Bearer <token>` for every access level that has a token. Levels without
34
+ * a token keep the default behavior: reads and writes are open, worker and operations routes 503.
35
+ */
36
+ export function bearerAuth(tokens) {
37
+ return (request, route) => {
38
+ const token = tokens[route.access];
39
+ if (token === undefined) {
40
+ return defaultAuthorize(request, route);
41
+ }
42
+ const header = request.headers.get('authorization') ?? '';
43
+ return Effect.succeed(constantTimeEquals(header, `Bearer ${token}`) ? authAllowed : unauthorized);
44
+ };
45
+ }
@@ -0,0 +1,11 @@
1
+ import { Effect } from 'effect';
2
+ import type { DebuggerHost } from '@swirls/looms/core';
3
+ import { type Authorize } from './auth';
4
+ export interface DebuggerMount {
5
+ readonly basePath: string;
6
+ readonly host: DebuggerHost;
7
+ }
8
+ export declare function mountDebugger(host: DebuggerHost): DebuggerMount;
9
+ /** Path below the mount, or null when `pathname` is outside it. */
10
+ export declare function debuggerPath(mount: DebuggerMount, pathname: string): string | null;
11
+ export declare function serveDebugger(req: Request, mount: DebuggerMount, path: string, authorize: Authorize): Effect.Effect<Response | null>;
@@ -0,0 +1,32 @@
1
+ import { Effect } from 'effect';
2
+ import { authResponse } from './auth.js';
3
+ import { isLoomsApiPath } from './http.js';
4
+ export function mountDebugger(host) {
5
+ const path = host.basePath;
6
+ if (!path.startsWith('/') || path.includes('//') || path.split('/').includes('..')) {
7
+ throw new Error(`debugger basePath must be an absolute URL path: ${path}`);
8
+ }
9
+ const basePath = path.endsWith('/') ? path.slice(0, -1) : path;
10
+ if (basePath === '') {
11
+ throw new Error('debugger basePath must not be /');
12
+ }
13
+ if (isLoomsApiPath(basePath)) {
14
+ throw new Error(`debugger basePath overlaps the HTTP API: ${basePath}`);
15
+ }
16
+ return { basePath, host };
17
+ }
18
+ /** Path below the mount, or null when `pathname` is outside it. */
19
+ export function debuggerPath(mount, pathname) {
20
+ if (pathname === mount.basePath) {
21
+ return '';
22
+ }
23
+ return pathname.startsWith(`${mount.basePath}/`) ? pathname.slice(mount.basePath.length) : null;
24
+ }
25
+ export function serveDebugger(req, mount, path, authorize) {
26
+ return authorize(req, { access: 'read', name: 'debugger' }).pipe(Effect.flatMap((decision) => {
27
+ const denied = authResponse(decision);
28
+ return denied
29
+ ? Effect.succeed(denied)
30
+ : Effect.promise(() => mount.host.fetch(req, { basePath: mount.basePath, path }));
31
+ }));
32
+ }
@@ -0,0 +1,18 @@
1
+ import type { EventStore } from '@swirls/looms/core';
2
+ import type { LoomsRuntime } from '../runtime';
3
+ import { type Authorize } from './auth';
4
+ import { type DebuggerMount } from './debugger-host';
5
+ export interface FetchHandlerOptions {
6
+ readonly runtime: LoomsRuntime;
7
+ readonly store: EventStore;
8
+ /**
9
+ * Decides whether a request may use a route. Defaults to open reads and writes with worker and
10
+ * operations routes unavailable; use `bearerAuth` or your own policy to change that.
11
+ */
12
+ readonly authorize?: Authorize;
13
+ /** Debugger UI served beside the API and authorized as `{ access: 'read', name: 'debugger' }`. */
14
+ readonly debugger?: DebuggerMount;
15
+ }
16
+ /** Whether the fetch handler answers `pathname`: the HTTP API or the debugger mount. */
17
+ export declare function handlesPath(pathname: string, mount: DebuggerMount | undefined): boolean;
18
+ export declare function createFetchHandler(options: FetchHandlerOptions): (req: Request) => Promise<Response | null>;
@@ -0,0 +1,62 @@
1
+ import { Effect, Predicate } from 'effect';
2
+ import { authResponse, defaultAuthorize } from './auth.js';
3
+ import { debuggerPath, serveDebugger } from './debugger-host.js';
4
+ import { acceptsEventStream, isLoomsApiPath, toErrorResponse } from './http.js';
5
+ import { matchRoute } from './route-table.js';
6
+ import { definitionRoutes } from './routes/definitions.js';
7
+ import { effectRoutes } from './routes/effects.js';
8
+ import { operationRoutes } from './routes/operations.js';
9
+ import { runRoutes } from './routes/runs.js';
10
+ function createRoutes(options) {
11
+ return [
12
+ ...definitionRoutes(options),
13
+ ...runRoutes(options),
14
+ ...effectRoutes(options),
15
+ ...operationRoutes(options),
16
+ ];
17
+ }
18
+ function authorizeRoute(req, matched, authorize) {
19
+ const { access, name } = matched.route;
20
+ if (access === 'public') {
21
+ return Effect.succeed(null);
22
+ }
23
+ const runId = matched.params.runId;
24
+ return authorize(req, Predicate.isString(runId) ? { access, name, runId } : { access, name }).pipe(Effect.map(authResponse));
25
+ }
26
+ /** Whether the fetch handler answers `pathname`: the HTTP API or the debugger mount. */
27
+ export function handlesPath(pathname, mount) {
28
+ return isLoomsApiPath(pathname) || (mount !== undefined && debuggerPath(mount, pathname) !== null);
29
+ }
30
+ export function createFetchHandler(options) {
31
+ const routes = createRoutes(options);
32
+ const authorize = options.authorize ?? defaultAuthorize;
33
+ const mount = options.debugger;
34
+ return (req) => {
35
+ const url = new URL(req.url);
36
+ const mountedPath = mount ? debuggerPath(mount, url.pathname) : null;
37
+ if (mount && mountedPath !== null) {
38
+ return respond(serveDebugger(req, mount, mountedPath, authorize));
39
+ }
40
+ if (!isLoomsApiPath(url.pathname)) {
41
+ return Promise.resolve(null);
42
+ }
43
+ const accept = req.headers.get('accept') ?? '';
44
+ if (req.method === 'GET' && accept.includes('text/html') && !acceptsEventStream(req)) {
45
+ return Promise.resolve(null);
46
+ }
47
+ return respond(Effect.gen(function* () {
48
+ const matched = matchRoute(routes, req.method, url.pathname);
49
+ if (!matched) {
50
+ return new Response('Not Found', { status: 404 });
51
+ }
52
+ const denied = yield* authorizeRoute(req, matched, authorize);
53
+ if (denied) {
54
+ return denied;
55
+ }
56
+ return yield* matched.route.handle({ req, url, params: matched.params });
57
+ }));
58
+ };
59
+ }
60
+ function respond(effect) {
61
+ return Effect.runPromise(effect.pipe(Effect.catch((error) => Effect.succeed(toErrorResponse(error))), Effect.catchCause((cause) => Effect.logError('[@swirls/looms/runtime] request failed', cause).pipe(Effect.as(Response.json({ error: 'Internal server error' }, { status: 500 }))))));
62
+ }
@@ -0,0 +1,38 @@
1
+ import { Effect, Schema } from 'effect';
2
+ import { EventStoreTag, type EventStore, type JsonValue } from '@swirls/looms/core';
3
+ import { type LoomsRuntime } from '../runtime';
4
+ export interface RouteOptions {
5
+ readonly runtime: LoomsRuntime;
6
+ readonly store: EventStore;
7
+ }
8
+ declare const RequestBodyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
9
+ readonly _tag: "RequestBodyError";
10
+ } & Readonly<A>;
11
+ export declare class RequestBodyError extends RequestBodyError_base<{
12
+ readonly cause: unknown;
13
+ readonly message: string;
14
+ }> {
15
+ constructor(cause: unknown);
16
+ }
17
+ declare const RequestQueryError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
18
+ readonly _tag: "RequestQueryError";
19
+ } & Readonly<A>;
20
+ export declare class RequestQueryError extends RequestQueryError_base<{
21
+ readonly message: string;
22
+ }> {
23
+ }
24
+ export declare const EventInputBodySchema: Schema.Struct<{
25
+ readonly type: Schema.String;
26
+ readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
27
+ readonly threadId: Schema.optional<Schema.NullOr<Schema.String>>;
28
+ }>;
29
+ export declare function isLoomsApiPath(path: string): boolean;
30
+ export declare function provideStore<A, E>(effect: Effect.Effect<A, E, EventStoreTag>, store: EventStore): Effect.Effect<A, E>;
31
+ export declare const readJson: (req: Request) => Effect.Effect<JsonValue, RequestBodyError>;
32
+ export declare function extractIdempotencyKey(req: Request, bodyKey?: string): string | undefined;
33
+ export declare function acceptsEventStream(req: Request): boolean;
34
+ export declare function readIntegerQuery(url: URL, name: string, options: {
35
+ minimum: number;
36
+ }): Effect.Effect<number | null, RequestQueryError>;
37
+ export declare function toErrorResponse(err: Error): Response;
38
+ export {};
@@ -0,0 +1,66 @@
1
+ import { Data, Effect, Schema } from 'effect';
2
+ import { EventStoreTag, InvalidEventError, InvalidInputError, JsonValueSchema, } from '@swirls/looms/core';
3
+ import { RunOverloadedError, StartRunConflictError } from '../runtime.js';
4
+ export class RequestBodyError extends Data.TaggedError('RequestBodyError') {
5
+ constructor(cause) {
6
+ super({ cause, message: 'Invalid JSON request body' });
7
+ this.name = 'RequestBodyError';
8
+ }
9
+ }
10
+ export class RequestQueryError extends Data.TaggedError('RequestQueryError') {
11
+ }
12
+ export const EventInputBodySchema = Schema.Struct({
13
+ type: Schema.String,
14
+ payload: JsonValueSchema,
15
+ threadId: Schema.optional(Schema.NullOr(Schema.String)),
16
+ });
17
+ const LOOMS_API_ROOTS = ['/health', '/runs', '/definitions', '/operations'];
18
+ export function isLoomsApiPath(path) {
19
+ return LOOMS_API_ROOTS.some((root) => path === root || path.startsWith(`${root}/`));
20
+ }
21
+ export function provideStore(effect, store) {
22
+ return Effect.provideService(effect, EventStoreTag, store);
23
+ }
24
+ export const readJson = (req) => Effect.tryPromise({
25
+ try: () => req.json(),
26
+ catch: (cause) => new RequestBodyError(cause),
27
+ }).pipe(Effect.flatMap(Schema.decodeUnknownEffect(JsonValueSchema)), Effect.mapError((cause) => cause instanceof RequestBodyError ? cause : new RequestBodyError(cause)));
28
+ export function extractIdempotencyKey(req, bodyKey) {
29
+ return (bodyKey ??
30
+ req.headers.get('idempotency-key') ??
31
+ req.headers.get('x-idempotency-key') ??
32
+ undefined);
33
+ }
34
+ export function acceptsEventStream(req) {
35
+ return (req.headers.get('accept') ?? '')
36
+ .split(',')
37
+ .some((value) => value.split(';', 1)[0]?.trim().toLowerCase() === 'text/event-stream');
38
+ }
39
+ export function readIntegerQuery(url, name, options) {
40
+ const raw = url.searchParams.get(name);
41
+ if (raw === null) {
42
+ return Effect.succeed(null);
43
+ }
44
+ const value = Number(raw);
45
+ if (!Number.isSafeInteger(value) || value < options.minimum || raw.trim() === '') {
46
+ return Effect.fail(new RequestQueryError({
47
+ message: `${name} must be an integer greater than or equal to ${options.minimum}`,
48
+ }));
49
+ }
50
+ return Effect.succeed(value);
51
+ }
52
+ export function toErrorResponse(err) {
53
+ if (err instanceof RequestBodyError || err instanceof RequestQueryError) {
54
+ return Response.json({ error: err.message }, { status: 400 });
55
+ }
56
+ if (err instanceof InvalidInputError || err instanceof InvalidEventError) {
57
+ return Response.json({ error: err.message, issues: err.issues }, { status: 400 });
58
+ }
59
+ if (err instanceof RunOverloadedError) {
60
+ return Response.json({ error: err.message }, { status: 429 });
61
+ }
62
+ if (err instanceof StartRunConflictError) {
63
+ return Response.json({ error: err.message, mismatches: err.mismatches }, { status: 409 });
64
+ }
65
+ return Response.json({ error: err.message }, { status: 500 });
66
+ }
@@ -0,0 +1,55 @@
1
+ import type { Effect } from 'effect';
2
+ import type { RouteAccess } from './auth';
3
+ export type ParamValue = string | number;
4
+ /** Decodes one path segment, or returns null when the segment does not match. */
5
+ export interface ParamDecoder<T extends ParamValue> {
6
+ decode(raw: string): T | null;
7
+ }
8
+ export declare const text: ParamDecoder<string>;
9
+ export declare const integer: ParamDecoder<number>;
10
+ export declare function oneOf<const T extends string>(values: readonly T[]): ParamDecoder<T>;
11
+ type PathParamNames<TPath extends string> = TPath extends `${string}:${infer Param}/${infer Rest}` ? Param | PathParamNames<`/${Rest}`> : TPath extends `${string}:${infer Param}` ? Param : never;
12
+ type ParamDecoders<TPath extends string> = {
13
+ readonly [K in PathParamNames<TPath>]?: ParamDecoder<ParamValue>;
14
+ };
15
+ type DecodedParams<TPath extends string, TDecoders> = {
16
+ readonly [K in PathParamNames<TPath>]: K extends keyof TDecoders ? TDecoders[K] extends ParamDecoder<infer T> ? T : string : string;
17
+ };
18
+ export interface RouteContext<TParams> {
19
+ readonly req: Request;
20
+ readonly url: URL;
21
+ readonly params: TParams;
22
+ }
23
+ export interface RouteDefinition<TPath extends string, TDecoders extends ParamDecoders<TPath>> {
24
+ readonly method: 'GET' | 'POST';
25
+ /** Path pattern such as `/runs/:runId/effects/:effectId`; parameters decode as text by default. */
26
+ readonly path: TPath;
27
+ readonly name: string;
28
+ readonly access: RouteAccess;
29
+ readonly params?: TDecoders;
30
+ handle(context: RouteContext<DecodedParams<TPath, TDecoders>>): Effect.Effect<Response, Error>;
31
+ }
32
+ type Segment = {
33
+ readonly kind: 'literal';
34
+ readonly value: string;
35
+ } | {
36
+ readonly kind: 'param';
37
+ readonly name: string;
38
+ readonly decoder: ParamDecoder<ParamValue>;
39
+ };
40
+ export type RouteParams = Readonly<Record<string, ParamValue>>;
41
+ export interface Route {
42
+ readonly method: 'GET' | 'POST';
43
+ readonly name: string;
44
+ readonly access: RouteAccess;
45
+ readonly segments: readonly Segment[];
46
+ handle(context: RouteContext<RouteParams>): Effect.Effect<Response, Error>;
47
+ }
48
+ export declare function route<const TPath extends string, const TDecoders extends ParamDecoders<TPath> = Record<never, never>>(definition: RouteDefinition<TPath, TDecoders>): Route;
49
+ export interface MatchedRoute {
50
+ readonly route: Route;
51
+ readonly params: RouteParams;
52
+ }
53
+ /** First route, in table order, whose method and path match. */
54
+ export declare function matchRoute(routes: readonly Route[], method: string, pathname: string): MatchedRoute | null;
55
+ export {};
@@ -0,0 +1,74 @@
1
+ export const text = {
2
+ decode: (raw) => {
3
+ try {
4
+ return decodeURIComponent(raw);
5
+ }
6
+ catch {
7
+ return null;
8
+ }
9
+ },
10
+ };
11
+ export const integer = {
12
+ decode: (raw) => (/^\d+$/.test(raw) ? Number(raw) : null),
13
+ };
14
+ export function oneOf(values) {
15
+ return { decode: (raw) => values.find((value) => value === raw) ?? null };
16
+ }
17
+ export function route(definition) {
18
+ const decoders = definition.params ?? {};
19
+ const segments = definition.path
20
+ .split('/')
21
+ .slice(1)
22
+ .map((part) => {
23
+ if (!part.startsWith(':')) {
24
+ return { kind: 'literal', value: part };
25
+ }
26
+ const name = part.slice(1);
27
+ return { kind: 'param', name, decoder: decoders[name] ?? text };
28
+ });
29
+ // SAFETY: matchRoute only calls a route with every path parameter decoded by its decoders.
30
+ return {
31
+ method: definition.method,
32
+ name: definition.name,
33
+ access: definition.access,
34
+ segments,
35
+ handle: (context) =>
36
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
37
+ definition.handle(context),
38
+ };
39
+ }
40
+ function matchSegments(segments, parts) {
41
+ if (segments.length !== parts.length) {
42
+ return null;
43
+ }
44
+ const params = {};
45
+ for (const [index, segment] of segments.entries()) {
46
+ const part = parts[index];
47
+ if (segment.kind === 'literal') {
48
+ if (segment.value !== part) {
49
+ return null;
50
+ }
51
+ continue;
52
+ }
53
+ const value = segment.decoder.decode(part);
54
+ if (value === null) {
55
+ return null;
56
+ }
57
+ params[segment.name] = value;
58
+ }
59
+ return params;
60
+ }
61
+ /** First route, in table order, whose method and path match. */
62
+ export function matchRoute(routes, method, pathname) {
63
+ const parts = pathname.split('/').slice(1);
64
+ for (const candidate of routes) {
65
+ if (candidate.method !== method) {
66
+ continue;
67
+ }
68
+ const params = matchSegments(candidate.segments, parts);
69
+ if (params) {
70
+ return { route: candidate, params };
71
+ }
72
+ }
73
+ return null;
74
+ }
@@ -0,0 +1,3 @@
1
+ import type { RouteOptions } from '../http';
2
+ import { type Route } from '../route-table';
3
+ export declare function definitionRoutes({ runtime }: RouteOptions): readonly Route[];
@@ -0,0 +1,20 @@
1
+ import { Effect } from 'effect';
2
+ import { publishDefinition } from '@swirls/looms/core';
3
+ import { route } from '../route-table.js';
4
+ export function definitionRoutes({ runtime }) {
5
+ return [
6
+ route({
7
+ method: 'GET',
8
+ path: '/definitions',
9
+ name: 'definitions.list',
10
+ access: 'read',
11
+ handle: () => {
12
+ const catalog = {
13
+ definitions: runtime.registry.definitions.map(publishDefinition),
14
+ projections: [...runtime.registry.projections.keys()],
15
+ };
16
+ return Effect.succeed(Response.json(catalog));
17
+ },
18
+ }),
19
+ ];
20
+ }
@@ -0,0 +1,3 @@
1
+ import { type RouteOptions } from '../http';
2
+ import { type Route } from '../route-table';
3
+ export declare function effectRoutes({ runtime, store }: RouteOptions): readonly Route[];
@@ -0,0 +1,59 @@
1
+ import { Effect, Schema } from 'effect';
2
+ import { EventInputBodySchema, provideStore, readJson } from '../http.js';
3
+ import { integer, oneOf, route } from '../route-table.js';
4
+ const WORKER_CALLBACK_KINDS = [
5
+ 'started',
6
+ 'heartbeat',
7
+ 'complete',
8
+ 'fail',
9
+ 'cancelled',
10
+ ];
11
+ const WorkerCallbackBodySchema = Schema.Struct({
12
+ events: Schema.optional(Schema.Array(EventInputBodySchema)),
13
+ error: Schema.optional(Schema.String),
14
+ });
15
+ function workerCallbackInput(params, body) {
16
+ const callback = { effectId: params.effectId, attempt: params.attempt };
17
+ switch (params.action) {
18
+ case 'complete':
19
+ return { ...callback, kind: 'complete', events: body.events ?? [] };
20
+ case 'fail':
21
+ return body.error ? { ...callback, kind: 'fail', error: body.error } : null;
22
+ default:
23
+ return { ...callback, kind: params.action };
24
+ }
25
+ }
26
+ export function effectRoutes({ runtime, store }) {
27
+ return [
28
+ route({
29
+ method: 'GET',
30
+ path: '/runs/:runId/effects',
31
+ name: 'effects.list',
32
+ access: 'read',
33
+ handle: ({ params }) => provideStore(runtime.inspectRun(params.runId), store).pipe(Effect.map((status) => Response.json({ runId: params.runId, effects: status.effects }))),
34
+ }),
35
+ route({
36
+ method: 'POST',
37
+ path: '/runs/:runId/effects/:effectId/retry',
38
+ name: 'effects.retry',
39
+ access: 'operations',
40
+ handle: ({ params }) => provideStore(runtime.retryEffect(params.runId, params.effectId), store).pipe(Effect.map((state) => Response.json({ runId: params.runId, effectId: params.effectId, state }))),
41
+ }),
42
+ route({
43
+ method: 'POST',
44
+ path: '/runs/:runId/effects/:effectId/:attempt/:action',
45
+ name: 'effects.workerCallback',
46
+ access: 'worker',
47
+ params: { attempt: integer, action: oneOf(WORKER_CALLBACK_KINDS) },
48
+ handle: ({ req, params }) => Effect.gen(function* () {
49
+ const body = yield* readJson(req).pipe(Effect.flatMap(Schema.decodeUnknownEffect(WorkerCallbackBodySchema)));
50
+ const input = workerCallbackInput(params, body);
51
+ if (!input) {
52
+ return Response.json({ error: 'error required' }, { status: 400 });
53
+ }
54
+ const state = yield* provideStore(runtime.workerCallback(params.runId, input), store);
55
+ return Response.json({ runId: params.runId, state });
56
+ }),
57
+ }),
58
+ ];
59
+ }
@@ -0,0 +1,3 @@
1
+ import { type RouteOptions } from '../http';
2
+ import { type Route } from '../route-table';
3
+ export declare function operationRoutes({ runtime, store }: RouteOptions): readonly Route[];
@@ -0,0 +1,14 @@
1
+ import { Effect } from 'effect';
2
+ import { provideStore } from '../http.js';
3
+ import { route } from '../route-table.js';
4
+ export function operationRoutes({ runtime, store }) {
5
+ return [
6
+ route({
7
+ method: 'POST',
8
+ path: '/operations/deadlines/rescan',
9
+ name: 'operations.rescanDeadlines',
10
+ access: 'operations',
11
+ handle: () => provideStore(runtime.recoverDeadlines, store).pipe(Effect.map((scheduled) => Response.json({ scheduled }))),
12
+ }),
13
+ ];
14
+ }
@@ -0,0 +1,3 @@
1
+ import { type RouteOptions } from '../http';
2
+ import { type Route } from '../route-table';
3
+ export declare function runRoutes({ runtime, store }: RouteOptions): readonly Route[];