dotdo 0.0.1 → 0.0.2

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 (727) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +446 -315
  3. package/dist/ai/index.js +19 -0
  4. package/dist/ai/index.js.map +1 -0
  5. package/dist/ai/template-literals.js +852 -0
  6. package/dist/ai/template-literals.js.map +1 -0
  7. package/dist/api/analytics/router.js +601 -0
  8. package/dist/api/analytics/router.js.map +1 -0
  9. package/dist/api/index.js +158 -0
  10. package/dist/api/index.js.map +1 -0
  11. package/dist/api/middleware/auth-federation.js +573 -0
  12. package/dist/api/middleware/auth-federation.js.map +1 -0
  13. package/dist/api/middleware/auth.js +544 -0
  14. package/dist/api/middleware/auth.js.map +1 -0
  15. package/dist/api/middleware/error-handling.js +176 -0
  16. package/dist/api/middleware/error-handling.js.map +1 -0
  17. package/dist/api/middleware/request-id.js +21 -0
  18. package/dist/api/middleware/request-id.js.map +1 -0
  19. package/dist/api/pages.js +1180 -0
  20. package/dist/api/pages.js.map +1 -0
  21. package/dist/api/routes/api.js +612 -0
  22. package/dist/api/routes/api.js.map +1 -0
  23. package/dist/api/routes/browsers.js +471 -0
  24. package/dist/api/routes/browsers.js.map +1 -0
  25. package/dist/api/routes/do.js +188 -0
  26. package/dist/api/routes/do.js.map +1 -0
  27. package/dist/api/routes/mcp.js +459 -0
  28. package/dist/api/routes/mcp.js.map +1 -0
  29. package/dist/api/routes/obs.js +445 -0
  30. package/dist/api/routes/obs.js.map +1 -0
  31. package/dist/api/routes/openapi.js +794 -0
  32. package/dist/api/routes/openapi.js.map +1 -0
  33. package/dist/api/routes/rpc.js +1103 -0
  34. package/dist/api/routes/rpc.js.map +1 -0
  35. package/dist/api/routes/sandboxes.js +389 -0
  36. package/dist/api/routes/sandboxes.js.map +1 -0
  37. package/dist/api/test-do.js +38 -0
  38. package/dist/api/test-do.js.map +1 -0
  39. package/dist/api/types.js +11 -0
  40. package/dist/api/types.js.map +1 -0
  41. package/dist/cli/bin.js +2 -0
  42. package/dist/cli/main.js +52342 -0
  43. package/dist/db/actions.js +212 -0
  44. package/dist/db/actions.js.map +1 -0
  45. package/dist/db/auth.js +506 -0
  46. package/dist/db/auth.js.map +1 -0
  47. package/dist/db/branches.js +65 -0
  48. package/dist/db/branches.js.map +1 -0
  49. package/dist/db/clickhouse.js +1074 -0
  50. package/dist/db/clickhouse.js.map +1 -0
  51. package/dist/db/dlq.js +39 -0
  52. package/dist/db/dlq.js.map +1 -0
  53. package/dist/db/events.js +28 -0
  54. package/dist/db/events.js.map +1 -0
  55. package/dist/db/exec.js +64 -0
  56. package/dist/db/exec.js.map +1 -0
  57. package/dist/db/files.js +85 -0
  58. package/dist/db/files.js.map +1 -0
  59. package/dist/db/flags.js +24 -0
  60. package/dist/db/flags.js.map +1 -0
  61. package/dist/db/git.js +116 -0
  62. package/dist/db/git.js.map +1 -0
  63. package/dist/db/iceberg/inverted-index.js +862 -0
  64. package/dist/db/iceberg/inverted-index.js.map +1 -0
  65. package/dist/db/iceberg/puffin.js +878 -0
  66. package/dist/db/iceberg/puffin.js.map +1 -0
  67. package/dist/db/iceberg/search-manifest.js +422 -0
  68. package/dist/db/iceberg/search-manifest.js.map +1 -0
  69. package/dist/db/iceberg/types.js +8 -0
  70. package/dist/db/iceberg/types.js.map +1 -0
  71. package/dist/db/index.js +121 -0
  72. package/dist/db/index.js.map +1 -0
  73. package/dist/db/integrations.js +368 -0
  74. package/dist/db/integrations.js.map +1 -0
  75. package/dist/db/json-indexes.js +332 -0
  76. package/dist/db/json-indexes.js.map +1 -0
  77. package/dist/db/linked-accounts.js +287 -0
  78. package/dist/db/linked-accounts.js.map +1 -0
  79. package/dist/db/nouns.js +183 -0
  80. package/dist/db/nouns.js.map +1 -0
  81. package/dist/db/objects.js +170 -0
  82. package/dist/db/objects.js.map +1 -0
  83. package/dist/db/primitives/dag-scheduler/index.js +869 -0
  84. package/dist/db/primitives/dag-scheduler/index.js.map +1 -0
  85. package/dist/db/primitives/exactly-once-context.js +237 -0
  86. package/dist/db/primitives/exactly-once-context.js.map +1 -0
  87. package/dist/db/primitives/index.js +62 -0
  88. package/dist/db/primitives/index.js.map +1 -0
  89. package/dist/db/primitives/keyed-router.js +145 -0
  90. package/dist/db/primitives/keyed-router.js.map +1 -0
  91. package/dist/db/primitives/observability.js +162 -0
  92. package/dist/db/primitives/observability.js.map +1 -0
  93. package/dist/db/primitives/schema-evolution.js +643 -0
  94. package/dist/db/primitives/schema-evolution.js.map +1 -0
  95. package/dist/db/primitives/stateful-operator/index.js +770 -0
  96. package/dist/db/primitives/stateful-operator/index.js.map +1 -0
  97. package/dist/db/primitives/temporal-store.js +306 -0
  98. package/dist/db/primitives/temporal-store.js.map +1 -0
  99. package/dist/db/primitives/typed-column-store.js +1229 -0
  100. package/dist/db/primitives/typed-column-store.js.map +1 -0
  101. package/dist/db/primitives/utils/duration.js +162 -0
  102. package/dist/db/primitives/utils/duration.js.map +1 -0
  103. package/dist/db/primitives/utils/murmur3.js +118 -0
  104. package/dist/db/primitives/utils/murmur3.js.map +1 -0
  105. package/dist/db/primitives/watermark-service.js +136 -0
  106. package/dist/db/primitives/watermark-service.js.map +1 -0
  107. package/dist/db/primitives/window-manager.js +764 -0
  108. package/dist/db/primitives/window-manager.js.map +1 -0
  109. package/dist/db/relationships.js +66 -0
  110. package/dist/db/relationships.js.map +1 -0
  111. package/dist/db/schema-minimal.js +61 -0
  112. package/dist/db/schema-minimal.js.map +1 -0
  113. package/dist/db/search.js +28 -0
  114. package/dist/db/search.js.map +1 -0
  115. package/dist/db/stores.js +1665 -0
  116. package/dist/db/stores.js.map +1 -0
  117. package/dist/db/things.js +297 -0
  118. package/dist/db/things.js.map +1 -0
  119. package/dist/db/vault.js +171 -0
  120. package/dist/db/vault.js.map +1 -0
  121. package/dist/db/verbs.js +102 -0
  122. package/dist/db/verbs.js.map +1 -0
  123. package/dist/do/base.js +48 -0
  124. package/dist/do/base.js.map +1 -0
  125. package/dist/do/bash.js +35 -0
  126. package/dist/do/bash.js.map +1 -0
  127. package/dist/do/fs.js +25 -0
  128. package/dist/do/fs.js.map +1 -0
  129. package/dist/do/full.js +61 -0
  130. package/dist/do/full.js.map +1 -0
  131. package/dist/do/git.js +28 -0
  132. package/dist/do/git.js.map +1 -0
  133. package/dist/do/index.js +52 -0
  134. package/dist/do/index.js.map +1 -0
  135. package/dist/do/tiny.js +31 -0
  136. package/dist/do/tiny.js.map +1 -0
  137. package/dist/lib/DOAuth.js +261 -0
  138. package/dist/lib/DOAuth.js.map +1 -0
  139. package/dist/lib/DODispatcher.js +72 -0
  140. package/dist/lib/DODispatcher.js.map +1 -0
  141. package/dist/lib/Modifier.js +189 -0
  142. package/dist/lib/Modifier.js.map +1 -0
  143. package/dist/lib/StateStorage.js +403 -0
  144. package/dist/lib/StateStorage.js.map +1 -0
  145. package/dist/lib/TypeRegistry.js +122 -0
  146. package/dist/lib/TypeRegistry.js.map +1 -0
  147. package/dist/lib/agent/tools/bash.js +336 -0
  148. package/dist/lib/agent/tools/bash.js.map +1 -0
  149. package/dist/lib/agent/tools/edit.js +157 -0
  150. package/dist/lib/agent/tools/edit.js.map +1 -0
  151. package/dist/lib/agent/tools/glob.js +137 -0
  152. package/dist/lib/agent/tools/glob.js.map +1 -0
  153. package/dist/lib/agent/tools/grep.js +315 -0
  154. package/dist/lib/agent/tools/grep.js.map +1 -0
  155. package/dist/lib/agent/tools/index.js +71 -0
  156. package/dist/lib/agent/tools/index.js.map +1 -0
  157. package/dist/lib/agent/tools/read.js +212 -0
  158. package/dist/lib/agent/tools/read.js.map +1 -0
  159. package/dist/lib/agent/tools/types.js +197 -0
  160. package/dist/lib/agent/tools/types.js.map +1 -0
  161. package/dist/lib/agent/tools/write.js +159 -0
  162. package/dist/lib/agent/tools/write.js.map +1 -0
  163. package/dist/lib/ai/gateway.js +247 -0
  164. package/dist/lib/ai/gateway.js.map +1 -0
  165. package/dist/lib/ai/tool-loop-agent.js +591 -0
  166. package/dist/lib/ai/tool-loop-agent.js.map +1 -0
  167. package/dist/lib/auto-wiring.js +439 -0
  168. package/dist/lib/auto-wiring.js.map +1 -0
  169. package/dist/lib/browse/browserbase.js +163 -0
  170. package/dist/lib/browse/browserbase.js.map +1 -0
  171. package/dist/lib/browse/cloudflare.js +144 -0
  172. package/dist/lib/browse/cloudflare.js.map +1 -0
  173. package/dist/lib/browse/index.js +62 -0
  174. package/dist/lib/browse/index.js.map +1 -0
  175. package/dist/lib/browse/types.js +13 -0
  176. package/dist/lib/browse/types.js.map +1 -0
  177. package/dist/lib/cache/index.js +37 -0
  178. package/dist/lib/cache/index.js.map +1 -0
  179. package/dist/lib/cache/visibility.js +638 -0
  180. package/dist/lib/cache/visibility.js.map +1 -0
  181. package/dist/lib/capabilities.js +268 -0
  182. package/dist/lib/capabilities.js.map +1 -0
  183. package/dist/lib/channels/base.js +106 -0
  184. package/dist/lib/channels/base.js.map +1 -0
  185. package/dist/lib/channels/discord.js +94 -0
  186. package/dist/lib/channels/discord.js.map +1 -0
  187. package/dist/lib/channels/email.js +204 -0
  188. package/dist/lib/channels/email.js.map +1 -0
  189. package/dist/lib/channels/index.js +90 -0
  190. package/dist/lib/channels/index.js.map +1 -0
  191. package/dist/lib/channels/mdxui-chat.js +95 -0
  192. package/dist/lib/channels/mdxui-chat.js.map +1 -0
  193. package/dist/lib/channels/slack-blockkit.js +121 -0
  194. package/dist/lib/channels/slack-blockkit.js.map +1 -0
  195. package/dist/lib/channels/types.js +7 -0
  196. package/dist/lib/channels/types.js.map +1 -0
  197. package/dist/lib/cloudflare/ai.js +654 -0
  198. package/dist/lib/cloudflare/ai.js.map +1 -0
  199. package/dist/lib/cloudflare/index.js +88 -0
  200. package/dist/lib/cloudflare/index.js.map +1 -0
  201. package/dist/lib/cloudflare/kv.js +342 -0
  202. package/dist/lib/cloudflare/kv.js.map +1 -0
  203. package/dist/lib/cloudflare/queues.js +434 -0
  204. package/dist/lib/cloudflare/queues.js.map +1 -0
  205. package/dist/lib/cloudflare/r2.js +604 -0
  206. package/dist/lib/cloudflare/r2.js.map +1 -0
  207. package/dist/lib/cloudflare/vectorize.js +494 -0
  208. package/dist/lib/cloudflare/vectorize.js.map +1 -0
  209. package/dist/lib/cloudflare/workflows.js +569 -0
  210. package/dist/lib/cloudflare/workflows.js.map +1 -0
  211. package/dist/lib/colo/caching.js +196 -0
  212. package/dist/lib/colo/caching.js.map +1 -0
  213. package/dist/lib/colo/detection.js +194 -0
  214. package/dist/lib/colo/detection.js.map +1 -0
  215. package/dist/lib/colo/external-data.js +219 -0
  216. package/dist/lib/colo/external-data.js.map +1 -0
  217. package/dist/lib/colo/globe-data.js +179 -0
  218. package/dist/lib/colo/globe-data.js.map +1 -0
  219. package/dist/lib/colo/index.js +16 -0
  220. package/dist/lib/colo/index.js.map +1 -0
  221. package/dist/lib/decorators.js +37 -0
  222. package/dist/lib/decorators.js.map +1 -0
  223. package/dist/lib/discovery.js +81 -0
  224. package/dist/lib/discovery.js.map +1 -0
  225. package/dist/lib/executors/AgenticFunctionExecutor.js +619 -0
  226. package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -0
  227. package/dist/lib/executors/BaseFunctionExecutor.js +328 -0
  228. package/dist/lib/executors/BaseFunctionExecutor.js.map +1 -0
  229. package/dist/lib/executors/CascadeExecutor.js +418 -0
  230. package/dist/lib/executors/CascadeExecutor.js.map +1 -0
  231. package/dist/lib/executors/CodeFunctionExecutor.js +904 -0
  232. package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -0
  233. package/dist/lib/executors/GenerativeFunctionExecutor.js +904 -0
  234. package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -0
  235. package/dist/lib/executors/HumanFunctionExecutor.js +884 -0
  236. package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -0
  237. package/dist/lib/executors/ParallelStepExecutor.js +308 -0
  238. package/dist/lib/executors/ParallelStepExecutor.js.map +1 -0
  239. package/dist/lib/executors/types.js +12 -0
  240. package/dist/lib/executors/types.js.map +1 -0
  241. package/dist/lib/experiments.js +89 -0
  242. package/dist/lib/experiments.js.map +1 -0
  243. package/dist/lib/flags/store.js +262 -0
  244. package/dist/lib/flags/store.js.map +1 -0
  245. package/dist/lib/functions/FunctionComposition.js +467 -0
  246. package/dist/lib/functions/FunctionComposition.js.map +1 -0
  247. package/dist/lib/functions/FunctionMiddleware.js +457 -0
  248. package/dist/lib/functions/FunctionMiddleware.js.map +1 -0
  249. package/dist/lib/functions/FunctionRegistry.js +426 -0
  250. package/dist/lib/functions/FunctionRegistry.js.map +1 -0
  251. package/dist/lib/functions/createFunction.js +1048 -0
  252. package/dist/lib/functions/createFunction.js.map +1 -0
  253. package/dist/lib/humans/index.js +68 -0
  254. package/dist/lib/humans/index.js.map +1 -0
  255. package/dist/lib/humans/templates.js +117 -0
  256. package/dist/lib/humans/templates.js.map +1 -0
  257. package/dist/lib/identity.js +98 -0
  258. package/dist/lib/identity.js.map +1 -0
  259. package/dist/lib/index.js +9 -0
  260. package/dist/lib/index.js.map +1 -0
  261. package/dist/lib/logging/error-logger.js +163 -0
  262. package/dist/lib/logging/error-logger.js.map +1 -0
  263. package/dist/lib/logging/index.js +160 -0
  264. package/dist/lib/logging/index.js.map +1 -0
  265. package/dist/lib/mixins/bash.js +825 -0
  266. package/dist/lib/mixins/bash.js.map +1 -0
  267. package/dist/lib/mixins/fs.js +648 -0
  268. package/dist/lib/mixins/fs.js.map +1 -0
  269. package/dist/lib/mixins/git.js +1011 -0
  270. package/dist/lib/mixins/git.js.map +1 -0
  271. package/dist/lib/mixins/index.js +29 -0
  272. package/dist/lib/mixins/index.js.map +1 -0
  273. package/dist/lib/mixins/npm.js +662 -0
  274. package/dist/lib/mixins/npm.js.map +1 -0
  275. package/dist/lib/noun-id.js +278 -0
  276. package/dist/lib/noun-id.js.map +1 -0
  277. package/dist/lib/rate-limit/sliding-window.js +148 -0
  278. package/dist/lib/rate-limit/sliding-window.js.map +1 -0
  279. package/dist/lib/rate-limit.js +110 -0
  280. package/dist/lib/rate-limit.js.map +1 -0
  281. package/dist/lib/rpc/bindings.js +548 -0
  282. package/dist/lib/rpc/bindings.js.map +1 -0
  283. package/dist/lib/rpc/index.js +64 -0
  284. package/dist/lib/rpc/index.js.map +1 -0
  285. package/dist/lib/safe-stringify.js +223 -0
  286. package/dist/lib/safe-stringify.js.map +1 -0
  287. package/dist/lib/sandbox/miniflare-sandbox.js +1007 -0
  288. package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -0
  289. package/dist/lib/sqids.js +110 -0
  290. package/dist/lib/sqids.js.map +1 -0
  291. package/dist/lib/sql/adapters/index.js +10 -0
  292. package/dist/lib/sql/adapters/index.js.map +1 -0
  293. package/dist/lib/sql/adapters/node-sql-parser.js +552 -0
  294. package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -0
  295. package/dist/lib/sql/adapters/pgsql-parser.js +1189 -0
  296. package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -0
  297. package/dist/lib/sql/index.js +277 -0
  298. package/dist/lib/sql/index.js.map +1 -0
  299. package/dist/lib/sql/types.js +56 -0
  300. package/dist/lib/sql/types.js.map +1 -0
  301. package/dist/lib/type-classifier.js +126 -0
  302. package/dist/lib/type-classifier.js.map +1 -0
  303. package/dist/lib/utils/html.js +47 -0
  304. package/dist/lib/utils/html.js.map +1 -0
  305. package/dist/lib/validation.js +48 -0
  306. package/dist/lib/validation.js.map +1 -0
  307. package/dist/lib/vault/store.js +411 -0
  308. package/dist/lib/vault/store.js.map +1 -0
  309. package/dist/metrics/hunch.js +739 -0
  310. package/dist/metrics/hunch.js.map +1 -0
  311. package/dist/objects/API.js +302 -0
  312. package/dist/objects/API.js.map +1 -0
  313. package/dist/objects/Agent.js +179 -0
  314. package/dist/objects/Agent.js.map +1 -0
  315. package/dist/objects/AgenticFunctionExecutor.js +8 -0
  316. package/dist/objects/AgenticFunctionExecutor.js.map +1 -0
  317. package/dist/objects/App.js +83 -0
  318. package/dist/objects/App.js.map +1 -0
  319. package/dist/objects/Browser.js +884 -0
  320. package/dist/objects/Browser.js.map +1 -0
  321. package/dist/objects/Business.js +107 -0
  322. package/dist/objects/Business.js.map +1 -0
  323. package/dist/objects/CLI.js +221 -0
  324. package/dist/objects/CLI.js.map +1 -0
  325. package/dist/objects/CodeFunctionExecutor.js +8 -0
  326. package/dist/objects/CodeFunctionExecutor.js.map +1 -0
  327. package/dist/objects/Collection.js +161 -0
  328. package/dist/objects/Collection.js.map +1 -0
  329. package/dist/objects/DO.js +41 -0
  330. package/dist/objects/DO.js.map +1 -0
  331. package/dist/objects/DOBase.js +2309 -0
  332. package/dist/objects/DOBase.js.map +1 -0
  333. package/dist/objects/DOFull.js +1676 -0
  334. package/dist/objects/DOFull.js.map +1 -0
  335. package/dist/objects/DOTiny.js +207 -0
  336. package/dist/objects/DOTiny.js.map +1 -0
  337. package/dist/objects/Directory.js +199 -0
  338. package/dist/objects/Directory.js.map +1 -0
  339. package/dist/objects/Entity.js +413 -0
  340. package/dist/objects/Entity.js.map +1 -0
  341. package/dist/objects/Function.js +116 -0
  342. package/dist/objects/Function.js.map +1 -0
  343. package/dist/objects/Human.js +231 -0
  344. package/dist/objects/Human.js.map +1 -0
  345. package/dist/objects/HumanFunctionExecutor.js +8 -0
  346. package/dist/objects/HumanFunctionExecutor.js.map +1 -0
  347. package/dist/objects/IcebergMetadataDO.js +938 -0
  348. package/dist/objects/IcebergMetadataDO.js.map +1 -0
  349. package/dist/objects/IntegrationsDO.js +1174 -0
  350. package/dist/objects/IntegrationsDO.js.map +1 -0
  351. package/dist/objects/ObservabilityBroadcaster.js +149 -0
  352. package/dist/objects/ObservabilityBroadcaster.js.map +1 -0
  353. package/dist/objects/Package.js +154 -0
  354. package/dist/objects/Package.js.map +1 -0
  355. package/dist/objects/Product.js +193 -0
  356. package/dist/objects/Product.js.map +1 -0
  357. package/dist/objects/SDK.js +152 -0
  358. package/dist/objects/SDK.js.map +1 -0
  359. package/dist/objects/SaaS.js +235 -0
  360. package/dist/objects/SaaS.js.map +1 -0
  361. package/dist/objects/SandboxDO.js +759 -0
  362. package/dist/objects/SandboxDO.js.map +1 -0
  363. package/dist/objects/Service.js +337 -0
  364. package/dist/objects/Service.js.map +1 -0
  365. package/dist/objects/Site.js +80 -0
  366. package/dist/objects/Site.js.map +1 -0
  367. package/dist/objects/Startup.js +479 -0
  368. package/dist/objects/Startup.js.map +1 -0
  369. package/dist/objects/ThingsDO.js +170 -0
  370. package/dist/objects/ThingsDO.js.map +1 -0
  371. package/dist/objects/VectorShardDO.js +648 -0
  372. package/dist/objects/VectorShardDO.js.map +1 -0
  373. package/dist/objects/Worker.js +144 -0
  374. package/dist/objects/Worker.js.map +1 -0
  375. package/dist/objects/Workflow.js +196 -0
  376. package/dist/objects/Workflow.js.map +1 -0
  377. package/dist/objects/WorkflowFactory.js +313 -0
  378. package/dist/objects/WorkflowFactory.js.map +1 -0
  379. package/dist/objects/WorkflowRuntime.js +863 -0
  380. package/dist/objects/WorkflowRuntime.js.map +1 -0
  381. package/dist/objects/circuit-breaker-bulkhead.js +178 -0
  382. package/dist/objects/circuit-breaker-bulkhead.js.map +1 -0
  383. package/dist/objects/createFunction.js +934 -0
  384. package/dist/objects/createFunction.js.map +1 -0
  385. package/dist/objects/index.js +80 -0
  386. package/dist/objects/index.js.map +1 -0
  387. package/dist/objects/lifecycle/Branch.js +275 -0
  388. package/dist/objects/lifecycle/Branch.js.map +1 -0
  389. package/dist/objects/lifecycle/Clone.js +1499 -0
  390. package/dist/objects/lifecycle/Clone.js.map +1 -0
  391. package/dist/objects/lifecycle/Compact.js +237 -0
  392. package/dist/objects/lifecycle/Compact.js.map +1 -0
  393. package/dist/objects/lifecycle/Promote.js +476 -0
  394. package/dist/objects/lifecycle/Promote.js.map +1 -0
  395. package/dist/objects/lifecycle/Shard.js +560 -0
  396. package/dist/objects/lifecycle/Shard.js.map +1 -0
  397. package/dist/objects/lifecycle/index.js +15 -0
  398. package/dist/objects/lifecycle/index.js.map +1 -0
  399. package/dist/objects/lifecycle/types.js +33 -0
  400. package/dist/objects/lifecycle/types.js.map +1 -0
  401. package/dist/objects/mixins/infrastructure.js +171 -0
  402. package/dist/objects/mixins/infrastructure.js.map +1 -0
  403. package/dist/objects/modules/StoresModule.js +153 -0
  404. package/dist/objects/modules/StoresModule.js.map +1 -0
  405. package/dist/objects/persistence/checkpoint-manager.js +606 -0
  406. package/dist/objects/persistence/checkpoint-manager.js.map +1 -0
  407. package/dist/objects/persistence/index.js +72 -0
  408. package/dist/objects/persistence/index.js.map +1 -0
  409. package/dist/objects/persistence/migration-runner.js +562 -0
  410. package/dist/objects/persistence/migration-runner.js.map +1 -0
  411. package/dist/objects/persistence/replication-manager.js +501 -0
  412. package/dist/objects/persistence/replication-manager.js.map +1 -0
  413. package/dist/objects/persistence/tiered-storage-manager.js +595 -0
  414. package/dist/objects/persistence/tiered-storage-manager.js.map +1 -0
  415. package/dist/objects/persistence/types.js +14 -0
  416. package/dist/objects/persistence/types.js.map +1 -0
  417. package/dist/objects/persistence/wal-manager.js +653 -0
  418. package/dist/objects/persistence/wal-manager.js.map +1 -0
  419. package/dist/objects/presets/index.js +20 -0
  420. package/dist/objects/presets/index.js.map +1 -0
  421. package/dist/objects/presets/primitives.js +188 -0
  422. package/dist/objects/presets/primitives.js.map +1 -0
  423. package/dist/objects/primitives/alarm-adapter.js +141 -0
  424. package/dist/objects/primitives/alarm-adapter.js.map +1 -0
  425. package/dist/objects/primitives/index.js +337 -0
  426. package/dist/objects/primitives/index.js.map +1 -0
  427. package/dist/objects/primitives/storage-adapter.js +182 -0
  428. package/dist/objects/primitives/storage-adapter.js.map +1 -0
  429. package/dist/objects/primitives/with-primitives.js +102 -0
  430. package/dist/objects/primitives/with-primitives.js.map +1 -0
  431. package/dist/objects/services/StoreManager.js +227 -0
  432. package/dist/objects/services/StoreManager.js.map +1 -0
  433. package/dist/objects/services/index.js +13 -0
  434. package/dist/objects/services/index.js.map +1 -0
  435. package/dist/objects/transport/auth-layer.js +1451 -0
  436. package/dist/objects/transport/auth-layer.js.map +1 -0
  437. package/dist/objects/transport/capnweb-target.js +355 -0
  438. package/dist/objects/transport/capnweb-target.js.map +1 -0
  439. package/dist/objects/transport/chain.js +441 -0
  440. package/dist/objects/transport/chain.js.map +1 -0
  441. package/dist/objects/transport/handler.js +58 -0
  442. package/dist/objects/transport/handler.js.map +1 -0
  443. package/dist/objects/transport/index.js +53 -0
  444. package/dist/objects/transport/index.js.map +1 -0
  445. package/dist/objects/transport/mcp-server.js +690 -0
  446. package/dist/objects/transport/mcp-server.js.map +1 -0
  447. package/dist/objects/transport/rest-autowire.js +1507 -0
  448. package/dist/objects/transport/rest-autowire.js.map +1 -0
  449. package/dist/objects/transport/rest-router.js +440 -0
  450. package/dist/objects/transport/rest-router.js.map +1 -0
  451. package/dist/objects/transport/rpc-server.js +1536 -0
  452. package/dist/objects/transport/rpc-server.js.map +1 -0
  453. package/dist/objects/transport/shared.js +575 -0
  454. package/dist/objects/transport/shared.js.map +1 -0
  455. package/dist/objects/transport/sync-engine.js +291 -0
  456. package/dist/objects/transport/sync-engine.js.map +1 -0
  457. package/dist/objects/transport/types.js +8 -0
  458. package/dist/objects/transport/types.js.map +1 -0
  459. package/dist/primitives/bashx/src/ast/analyze.js +1472 -0
  460. package/dist/primitives/bashx/src/ast/analyze.js.map +1 -0
  461. package/dist/primitives/bashx/src/ast/parser.js +1488 -0
  462. package/dist/primitives/bashx/src/ast/parser.js.map +1 -0
  463. package/dist/primitives/bashx/src/do/commands/crypto.js +1954 -0
  464. package/dist/primitives/bashx/src/do/commands/crypto.js.map +1 -0
  465. package/dist/primitives/bashx/src/do/commands/data-processing.js +1812 -0
  466. package/dist/primitives/bashx/src/do/commands/data-processing.js.map +1 -0
  467. package/dist/primitives/bashx/src/do/commands/extended-utils.js +804 -0
  468. package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +1 -0
  469. package/dist/primitives/bashx/src/do/commands/math-control.js +1122 -0
  470. package/dist/primitives/bashx/src/do/commands/math-control.js.map +1 -0
  471. package/dist/primitives/bashx/src/do/commands/posix-utils.js +1015 -0
  472. package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +1 -0
  473. package/dist/primitives/bashx/src/do/commands/system-utils.js +687 -0
  474. package/dist/primitives/bashx/src/do/commands/system-utils.js.map +1 -0
  475. package/dist/primitives/bashx/src/do/commands/test-command.js +523 -0
  476. package/dist/primitives/bashx/src/do/commands/test-command.js.map +1 -0
  477. package/dist/primitives/bashx/src/do/commands/text-processing.js +1550 -0
  478. package/dist/primitives/bashx/src/do/commands/text-processing.js.map +1 -0
  479. package/dist/primitives/bashx/src/do/container-executor.js +429 -0
  480. package/dist/primitives/bashx/src/do/container-executor.js.map +1 -0
  481. package/dist/primitives/bashx/src/do/index.js +668 -0
  482. package/dist/primitives/bashx/src/do/index.js.map +1 -0
  483. package/dist/primitives/bashx/src/do/tiered-executor.js +2647 -0
  484. package/dist/primitives/bashx/src/do/tiered-executor.js.map +1 -0
  485. package/dist/primitives/bashx/src/do/worker.js +352 -0
  486. package/dist/primitives/bashx/src/do/worker.js.map +1 -0
  487. package/dist/primitives/bashx/src/types.js +10 -0
  488. package/dist/primitives/bashx/src/types.js.map +1 -0
  489. package/dist/primitives/fsx/core/backend.js +480 -0
  490. package/dist/primitives/fsx/core/backend.js.map +1 -0
  491. package/dist/primitives/fsx/core/constants.js +140 -0
  492. package/dist/primitives/fsx/core/constants.js.map +1 -0
  493. package/dist/primitives/fsx/core/fsx.js +1184 -0
  494. package/dist/primitives/fsx/core/fsx.js.map +1 -0
  495. package/dist/primitives/fsx/core/glob/glob.js +438 -0
  496. package/dist/primitives/fsx/core/glob/glob.js.map +1 -0
  497. package/dist/primitives/fsx/core/glob/index.js +8 -0
  498. package/dist/primitives/fsx/core/glob/index.js.map +1 -0
  499. package/dist/primitives/fsx/core/glob/match.js +392 -0
  500. package/dist/primitives/fsx/core/glob/match.js.map +1 -0
  501. package/dist/primitives/fsx/core/types.js +307 -0
  502. package/dist/primitives/fsx/core/types.js.map +1 -0
  503. package/dist/sandbox/index.js +258 -0
  504. package/dist/sandbox/index.js.map +1 -0
  505. package/dist/sdk/capnweb-compat.js +42 -0
  506. package/dist/sdk/capnweb-compat.js.map +1 -0
  507. package/dist/sdk/client.js +20 -0
  508. package/dist/sdk/client.js.map +1 -0
  509. package/dist/sdk/index.js +17 -0
  510. package/dist/sdk/index.js.map +1 -0
  511. package/dist/snippets/artifacts-config.js +241 -0
  512. package/dist/snippets/artifacts-config.js.map +1 -0
  513. package/dist/snippets/artifacts-ingest.js +832 -0
  514. package/dist/snippets/artifacts-ingest.js.map +1 -0
  515. package/dist/snippets/artifacts-serve.js +1035 -0
  516. package/dist/snippets/artifacts-serve.js.map +1 -0
  517. package/dist/snippets/artifacts-types.js +161 -0
  518. package/dist/snippets/artifacts-types.js.map +1 -0
  519. package/dist/snippets/cache-probe.js +376 -0
  520. package/dist/snippets/cache-probe.js.map +1 -0
  521. package/dist/snippets/cache.js +10 -0
  522. package/dist/snippets/cache.js.map +1 -0
  523. package/dist/snippets/events.js +469 -0
  524. package/dist/snippets/events.js.map +1 -0
  525. package/dist/snippets/index.js +7 -0
  526. package/dist/snippets/index.js.map +1 -0
  527. package/dist/snippets/proxy.js +495 -0
  528. package/dist/snippets/proxy.js.map +1 -0
  529. package/dist/snippets/search.js +1759 -0
  530. package/dist/snippets/search.js.map +1 -0
  531. package/dist/streams/index.js +30 -0
  532. package/dist/streams/index.js.map +1 -0
  533. package/dist/streams/observability.js +68 -0
  534. package/dist/streams/observability.js.map +1 -0
  535. package/dist/types/AI.js +92 -0
  536. package/dist/types/AI.js.map +1 -0
  537. package/dist/types/AIFunction.js +171 -0
  538. package/dist/types/AIFunction.js.map +1 -0
  539. package/dist/types/BrowseVerb.js +89 -0
  540. package/dist/types/BrowseVerb.js.map +1 -0
  541. package/dist/types/Browser.js +31 -0
  542. package/dist/types/Browser.js.map +1 -0
  543. package/dist/types/Chaos.js +15 -0
  544. package/dist/types/Chaos.js.map +1 -0
  545. package/dist/types/CloudflareBindings.js +109 -0
  546. package/dist/types/CloudflareBindings.js.map +1 -0
  547. package/dist/types/Collection.js +50 -0
  548. package/dist/types/Collection.js.map +1 -0
  549. package/dist/types/DO.js +2 -0
  550. package/dist/types/DO.js.map +1 -0
  551. package/dist/types/DOLocation.js +63 -0
  552. package/dist/types/DOLocation.js.map +1 -0
  553. package/dist/types/EventHandler.js +57 -0
  554. package/dist/types/EventHandler.js.map +1 -0
  555. package/dist/types/Experiment.js +33 -0
  556. package/dist/types/Experiment.js.map +1 -0
  557. package/dist/types/Flag.js +57 -0
  558. package/dist/types/Flag.js.map +1 -0
  559. package/dist/types/Lifecycle.js +13 -0
  560. package/dist/types/Lifecycle.js.map +1 -0
  561. package/dist/types/Location.js +169 -0
  562. package/dist/types/Location.js.map +1 -0
  563. package/dist/types/Noun.js +66 -0
  564. package/dist/types/Noun.js.map +1 -0
  565. package/dist/types/SessionEvent.js +194 -0
  566. package/dist/types/SessionEvent.js.map +1 -0
  567. package/dist/types/Thing.js +55 -0
  568. package/dist/types/Thing.js.map +1 -0
  569. package/dist/types/ThingDO.js +153 -0
  570. package/dist/types/ThingDO.js.map +1 -0
  571. package/dist/types/Things.js +2 -0
  572. package/dist/types/Things.js.map +1 -0
  573. package/dist/types/Verb.js +119 -0
  574. package/dist/types/Verb.js.map +1 -0
  575. package/dist/types/WorkflowContext.js +70 -0
  576. package/dist/types/WorkflowContext.js.map +1 -0
  577. package/dist/types/analytics-api.js +13 -0
  578. package/dist/types/analytics-api.js.map +1 -0
  579. package/dist/types/capabilities.js +135 -0
  580. package/dist/types/capabilities.js.map +1 -0
  581. package/dist/types/drizzle.js +12 -0
  582. package/dist/types/drizzle.js.map +1 -0
  583. package/dist/types/event.js +201 -0
  584. package/dist/types/event.js.map +1 -0
  585. package/dist/types/fn.js +12 -0
  586. package/dist/types/fn.js.map +1 -0
  587. package/dist/types/iceberg.js +48 -0
  588. package/dist/types/iceberg.js.map +1 -0
  589. package/dist/types/ids.js +170 -0
  590. package/dist/types/ids.js.map +1 -0
  591. package/dist/types/index.js +41 -0
  592. package/dist/types/index.js.map +1 -0
  593. package/dist/types/introspect.js +54 -0
  594. package/dist/types/introspect.js.map +1 -0
  595. package/dist/types/observability.js +124 -0
  596. package/dist/types/observability.js.map +1 -0
  597. package/dist/types/sync-protocol.js +175 -0
  598. package/dist/types/sync-protocol.js.map +1 -0
  599. package/dist/types/vector.js +13 -0
  600. package/dist/types/vector.js.map +1 -0
  601. package/dist/workflows/ScheduleManager.js +473 -0
  602. package/dist/workflows/ScheduleManager.js.map +1 -0
  603. package/dist/workflows/StepDOBridge.js +149 -0
  604. package/dist/workflows/StepDOBridge.js.map +1 -0
  605. package/dist/workflows/StepResultStorage.js +232 -0
  606. package/dist/workflows/StepResultStorage.js.map +1 -0
  607. package/dist/workflows/WaitForEventManager.js +461 -0
  608. package/dist/workflows/WaitForEventManager.js.map +1 -0
  609. package/dist/workflows/analyzer.js +332 -0
  610. package/dist/workflows/analyzer.js.map +1 -0
  611. package/dist/workflows/compat/activity-router.js +484 -0
  612. package/dist/workflows/compat/activity-router.js.map +1 -0
  613. package/dist/workflows/compat/backends/cloudflare-workflows.js +431 -0
  614. package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -0
  615. package/dist/workflows/compat/backends/index.js +14 -0
  616. package/dist/workflows/compat/backends/index.js.map +1 -0
  617. package/dist/workflows/compat/errors/index.js +375 -0
  618. package/dist/workflows/compat/errors/index.js.map +1 -0
  619. package/dist/workflows/compat/index.js +79 -0
  620. package/dist/workflows/compat/index.js.map +1 -0
  621. package/dist/workflows/compat/inngest/index.js +989 -0
  622. package/dist/workflows/compat/inngest/index.js.map +1 -0
  623. package/dist/workflows/compat/qstash/index.js +1263 -0
  624. package/dist/workflows/compat/qstash/index.js.map +1 -0
  625. package/dist/workflows/compat/temporal/activities.js +739 -0
  626. package/dist/workflows/compat/temporal/activities.js.map +1 -0
  627. package/dist/workflows/compat/temporal/child-workflows.js +154 -0
  628. package/dist/workflows/compat/temporal/child-workflows.js.map +1 -0
  629. package/dist/workflows/compat/temporal/client.js +381 -0
  630. package/dist/workflows/compat/temporal/client.js.map +1 -0
  631. package/dist/workflows/compat/temporal/context.js +309 -0
  632. package/dist/workflows/compat/temporal/context.js.map +1 -0
  633. package/dist/workflows/compat/temporal/determinism.js +216 -0
  634. package/dist/workflows/compat/temporal/determinism.js.map +1 -0
  635. package/dist/workflows/compat/temporal/errors.js +128 -0
  636. package/dist/workflows/compat/temporal/errors.js.map +1 -0
  637. package/dist/workflows/compat/temporal/index.js +2464 -0
  638. package/dist/workflows/compat/temporal/index.js.map +1 -0
  639. package/dist/workflows/compat/temporal/saga.js +504 -0
  640. package/dist/workflows/compat/temporal/saga.js.map +1 -0
  641. package/dist/workflows/compat/temporal/signals.js +364 -0
  642. package/dist/workflows/compat/temporal/signals.js.map +1 -0
  643. package/dist/workflows/compat/temporal/storage.js +271 -0
  644. package/dist/workflows/compat/temporal/storage.js.map +1 -0
  645. package/dist/workflows/compat/temporal/timers.js +347 -0
  646. package/dist/workflows/compat/temporal/timers.js.map +1 -0
  647. package/dist/workflows/compat/temporal/types.js +7 -0
  648. package/dist/workflows/compat/temporal/types.js.map +1 -0
  649. package/dist/workflows/compat/temporal/unified-primitives.js +339 -0
  650. package/dist/workflows/compat/temporal/unified-primitives.js.map +1 -0
  651. package/dist/workflows/compat/trigger/index.js +468 -0
  652. package/dist/workflows/compat/trigger/index.js.map +1 -0
  653. package/dist/workflows/compat/utils/index.js +69 -0
  654. package/dist/workflows/compat/utils/index.js.map +1 -0
  655. package/dist/workflows/context/correlation-capability.js +266 -0
  656. package/dist/workflows/context/correlation-capability.js.map +1 -0
  657. package/dist/workflows/context/correlation.js +484 -0
  658. package/dist/workflows/context/correlation.js.map +1 -0
  659. package/dist/workflows/context/experiment.js +289 -0
  660. package/dist/workflows/context/experiment.js.map +1 -0
  661. package/dist/workflows/context/flag.js +244 -0
  662. package/dist/workflows/context/flag.js.map +1 -0
  663. package/dist/workflows/context/foundation.js +648 -0
  664. package/dist/workflows/context/foundation.js.map +1 -0
  665. package/dist/workflows/context/human-base.js +106 -0
  666. package/dist/workflows/context/human-base.js.map +1 -0
  667. package/dist/workflows/context/human.js +368 -0
  668. package/dist/workflows/context/human.js.map +1 -0
  669. package/dist/workflows/context/measure.js +354 -0
  670. package/dist/workflows/context/measure.js.map +1 -0
  671. package/dist/workflows/context/rate-limit.js +358 -0
  672. package/dist/workflows/context/rate-limit.js.map +1 -0
  673. package/dist/workflows/context/user.js +117 -0
  674. package/dist/workflows/context/user.js.map +1 -0
  675. package/dist/workflows/context/vault.js +360 -0
  676. package/dist/workflows/context/vault.js.map +1 -0
  677. package/dist/workflows/data/entity-events/entity-events.js +489 -0
  678. package/dist/workflows/data/entity-events/entity-events.js.map +1 -0
  679. package/dist/workflows/data/experiment/index.js +599 -0
  680. package/dist/workflows/data/experiment/index.js.map +1 -0
  681. package/dist/workflows/data/goal/context.js +558 -0
  682. package/dist/workflows/data/goal/context.js.map +1 -0
  683. package/dist/workflows/data/goal/index.js +32 -0
  684. package/dist/workflows/data/goal/index.js.map +1 -0
  685. package/dist/workflows/data/measure/index.js +840 -0
  686. package/dist/workflows/data/measure/index.js.map +1 -0
  687. package/dist/workflows/data/stream/index.js +1215 -0
  688. package/dist/workflows/data/stream/index.js.map +1 -0
  689. package/dist/workflows/data/track/context.js +883 -0
  690. package/dist/workflows/data/track/context.js.map +1 -0
  691. package/dist/workflows/data/track/index.js +15 -0
  692. package/dist/workflows/data/track/index.js.map +1 -0
  693. package/dist/workflows/data/view/context.js +864 -0
  694. package/dist/workflows/data/view/context.js.map +1 -0
  695. package/dist/workflows/domain.js +93 -0
  696. package/dist/workflows/domain.js.map +1 -0
  697. package/dist/workflows/flag.js +176 -0
  698. package/dist/workflows/flag.js.map +1 -0
  699. package/dist/workflows/flags.js +217 -0
  700. package/dist/workflows/flags.js.map +1 -0
  701. package/dist/workflows/hash.js +209 -0
  702. package/dist/workflows/hash.js.map +1 -0
  703. package/dist/workflows/index.js +50 -0
  704. package/dist/workflows/index.js.map +1 -0
  705. package/dist/workflows/on.js +378 -0
  706. package/dist/workflows/on.js.map +1 -0
  707. package/dist/workflows/pipeline-promise.js +481 -0
  708. package/dist/workflows/pipeline-promise.js.map +1 -0
  709. package/dist/workflows/pipeline-types.js +20 -0
  710. package/dist/workflows/pipeline-types.js.map +1 -0
  711. package/dist/workflows/proxy.js +76 -0
  712. package/dist/workflows/proxy.js.map +1 -0
  713. package/dist/workflows/runtime.js +310 -0
  714. package/dist/workflows/runtime.js.map +1 -0
  715. package/dist/workflows/schedule-builder.js +327 -0
  716. package/dist/workflows/schedule-builder.js.map +1 -0
  717. package/dist/workflows/visibility/index.js +148 -0
  718. package/dist/workflows/visibility/index.js.map +1 -0
  719. package/dist/workflows/visibility/query-parser.js +150 -0
  720. package/dist/workflows/visibility/query-parser.js.map +1 -0
  721. package/dist/workflows/visibility/store.js +223 -0
  722. package/dist/workflows/visibility/store.js.map +1 -0
  723. package/dist/workflows/visibility/types.js +30 -0
  724. package/dist/workflows/visibility/types.js.map +1 -0
  725. package/dist/workflows/workflow.js +53 -0
  726. package/dist/workflows/workflow.js.map +1 -0
  727. package/package.json +279 -46
@@ -0,0 +1,1536 @@
1
+ /**
2
+ * RPC Server for DO - Legacy RPC Protocol Implementation
3
+ *
4
+ * @deprecated This module is deprecated in favor of the official capnweb library.
5
+ * Use the root endpoint (/) for Cap'n Web RPC via `objects/transport/capnweb-target.ts`.
6
+ *
7
+ * This module is kept for backward compatibility at the /rpc endpoint and supports:
8
+ * - JSON-RPC 2.0: Standard JSON-RPC protocol (still useful for many clients)
9
+ * - Chain RPC: Legacy chain-based format (deprecated, use capnweb)
10
+ * - Custom Cap'n Web emulation: (deprecated, use real capnweb at /)
11
+ *
12
+ * Migration guide:
13
+ * - For new clients: Use capnweb client connecting to root endpoint (/)
14
+ * - For JSON-RPC 2.0: Continue using /rpc endpoint
15
+ * - For Chain RPC: Migrate to capnweb protocol
16
+ *
17
+ * @see {@link ./capnweb-target.ts} for the new capnweb integration
18
+ */
19
+ // Standard JSON-RPC error codes
20
+ const JSON_RPC_ERRORS = {
21
+ PARSE_ERROR: { code: -32700, message: 'Parse error' },
22
+ INVALID_REQUEST: { code: -32600, message: 'Invalid Request' },
23
+ METHOD_NOT_FOUND: { code: -32601, message: 'Method not found' },
24
+ INVALID_PARAMS: { code: -32602, message: 'Invalid params' },
25
+ INTERNAL_ERROR: { code: -32603, message: 'Internal error' },
26
+ };
27
+ /**
28
+ * Chain execution error codes
29
+ */
30
+ const CHAIN_ERRORS = {
31
+ INVALID_CHAIN: { code: 'INVALID_CHAIN', message: 'Chain must be a non-empty array' },
32
+ INVALID_STEP: { code: 'INVALID_STEP', message: 'Invalid step type' },
33
+ NOT_FOUND: { code: 'NOT_FOUND', message: 'Property not found' },
34
+ NOT_CALLABLE: { code: 'NOT_CALLABLE', message: 'Value is not a function' },
35
+ NOT_INDEXABLE: { code: 'NOT_INDEXABLE', message: 'Value is not an array' },
36
+ INDEX_OUT_OF_BOUNDS: { code: 'INDEX_OUT_OF_BOUNDS', message: 'Array index out of bounds' },
37
+ EXECUTION_ERROR: { code: 'EXECUTION_ERROR', message: 'Chain execution failed' },
38
+ BLOCKED_ACCESS: { code: 'BLOCKED_ACCESS', message: 'Access to this property is blocked' },
39
+ };
40
+ // ============================================================================
41
+ // PROMISE STORE - Manages stored promise results for pipelining
42
+ // ============================================================================
43
+ class PromiseStore {
44
+ promises = new Map();
45
+ disposed = new Set();
46
+ depths = new Map();
47
+ set(id, value, depth = 0) {
48
+ this.promises.set(id, value);
49
+ this.depths.set(id, depth);
50
+ }
51
+ get(id) {
52
+ if (this.disposed.has(id)) {
53
+ throw { code: 'DISPOSED_REFERENCE', message: `Promise ${id} has been disposed` };
54
+ }
55
+ return this.promises.get(id);
56
+ }
57
+ getDepth(id) {
58
+ return this.depths.get(id) ?? 0;
59
+ }
60
+ has(id) {
61
+ return this.promises.has(id) && !this.disposed.has(id);
62
+ }
63
+ dispose(id) {
64
+ if (this.promises.has(id)) {
65
+ this.disposed.add(id);
66
+ this.promises.delete(id);
67
+ this.depths.delete(id);
68
+ return true;
69
+ }
70
+ return false;
71
+ }
72
+ isDisposed(id) {
73
+ return this.disposed.has(id);
74
+ }
75
+ clear() {
76
+ this.promises.clear();
77
+ this.disposed.clear();
78
+ this.depths.clear();
79
+ }
80
+ }
81
+ class SubscriptionManager {
82
+ subscriptions = new Map();
83
+ eventSubscriptions = new Map();
84
+ subscribe(event, callback) {
85
+ const id = `sub_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
86
+ this.subscriptions.set(id, { id, event, callback });
87
+ if (!this.eventSubscriptions.has(event)) {
88
+ this.eventSubscriptions.set(event, new Set());
89
+ }
90
+ this.eventSubscriptions.get(event).add(id);
91
+ return id;
92
+ }
93
+ unsubscribe(subscriptionId) {
94
+ const sub = this.subscriptions.get(subscriptionId);
95
+ if (!sub)
96
+ return false;
97
+ this.subscriptions.delete(subscriptionId);
98
+ this.eventSubscriptions.get(sub.event)?.delete(subscriptionId);
99
+ return true;
100
+ }
101
+ emit(event, data) {
102
+ const subIds = this.eventSubscriptions.get(event);
103
+ if (!subIds)
104
+ return;
105
+ for (const id of subIds) {
106
+ const sub = this.subscriptions.get(id);
107
+ if (sub) {
108
+ try {
109
+ sub.callback(data);
110
+ }
111
+ catch (error) {
112
+ // Log callback errors so broken subscriptions can be detected
113
+ console.error('[rpc] Subscription callback error:', {
114
+ subscriptionId: id,
115
+ event,
116
+ error: error instanceof Error ? error.message : 'unknown',
117
+ stack: error instanceof Error ? error.stack : undefined,
118
+ });
119
+ }
120
+ }
121
+ }
122
+ }
123
+ clear() {
124
+ this.subscriptions.clear();
125
+ this.eventSubscriptions.clear();
126
+ }
127
+ }
128
+ // Default blocked methods - internal DO methods that should never be exposed
129
+ const DEFAULT_BLOCKED_METHODS = new Set([
130
+ // Lifecycle methods
131
+ 'initialize',
132
+ 'fetch',
133
+ 'handleFetch',
134
+ 'alarm',
135
+ // Internal state
136
+ 'db',
137
+ 'ctx',
138
+ 'storage',
139
+ 'env',
140
+ // Private accessors
141
+ '_users',
142
+ '_posts',
143
+ '_things',
144
+ '_rels',
145
+ '_actions',
146
+ '_events',
147
+ '_search',
148
+ '_objects',
149
+ '_dlq',
150
+ '_typeCache',
151
+ '_eventHandlers',
152
+ '_scheduleHandlers',
153
+ '_scheduleManager',
154
+ '_currentActor',
155
+ '_stepCache',
156
+ // Constructor
157
+ 'constructor',
158
+ ]);
159
+ // ============================================================================
160
+ // COLLECTION RPC PATTERN MATCHING
161
+ // ============================================================================
162
+ /**
163
+ * Valid collection methods
164
+ */
165
+ const COLLECTION_METHODS = new Set(['create', 'update', 'delete', 'get', 'list', 'find']);
166
+ /**
167
+ * Pattern for valid PascalCase noun names (no numbers, no special chars)
168
+ */
169
+ const VALID_NOUN_PATTERN = /^[A-Z][a-zA-Z]*$/;
170
+ /**
171
+ * Pattern for {Noun}.{method} format (exactly one dot)
172
+ * Noun must be PascalCase, method can be any valid identifier starting with lowercase
173
+ */
174
+ const COLLECTION_RPC_PATTERN = /^([A-Z][a-zA-Z]*)\.([a-z][a-zA-Z]*)$/;
175
+ /**
176
+ * Check if a method name looks like a collection RPC call
177
+ */
178
+ function isCollectionRpcMethod(method) {
179
+ return method.includes('.') && !method.startsWith('_');
180
+ }
181
+ /**
182
+ * Parse a collection RPC method into noun and action
183
+ * Returns null if invalid format
184
+ */
185
+ function parseCollectionRpcMethod(method) {
186
+ // Check for multiple dots (invalid)
187
+ if ((method.match(/\./g) || []).length !== 1) {
188
+ return null;
189
+ }
190
+ const match = method.match(COLLECTION_RPC_PATTERN);
191
+ if (!match)
192
+ return null;
193
+ const [, noun, action] = match;
194
+ return { noun, action };
195
+ }
196
+ /**
197
+ * Validate noun name
198
+ * @returns error message if invalid, null if valid
199
+ */
200
+ function validateNounName(noun) {
201
+ if (!noun || noun.trim() === '') {
202
+ return 'Noun name cannot be empty';
203
+ }
204
+ if (!VALID_NOUN_PATTERN.test(noun)) {
205
+ return `Invalid noun '${noun}': must be PascalCase letters only`;
206
+ }
207
+ return null;
208
+ }
209
+ /**
210
+ * Validate collection method name
211
+ * @returns error message if invalid, null if valid
212
+ */
213
+ function validateCollectionMethod(noun, method) {
214
+ if (!COLLECTION_METHODS.has(method)) {
215
+ return `Unknown method '${method}' on ${noun}. Valid methods: ${Array.from(COLLECTION_METHODS).join(', ')}`;
216
+ }
217
+ return null;
218
+ }
219
+ /**
220
+ * RPC Server class that wraps a DO instance
221
+ */
222
+ export class RPCServer {
223
+ doInstance;
224
+ config;
225
+ exposedMethods;
226
+ blockedMethods;
227
+ sessions = new Map();
228
+ defaultHttpSession;
229
+ constructor(doInstance, config = {}) {
230
+ this.doInstance = doInstance;
231
+ this.config = {
232
+ maxPipelineDepth: config.maxPipelineDepth ?? 20,
233
+ ...config,
234
+ };
235
+ // Build blocked methods set
236
+ this.blockedMethods = new Set([
237
+ ...DEFAULT_BLOCKED_METHODS,
238
+ ...(config.blockedMethods ?? []),
239
+ ]);
240
+ // Build exposed methods set
241
+ this.exposedMethods = new Set();
242
+ if (config.exposedMethods && config.exposedMethods.length > 0) {
243
+ for (const method of config.exposedMethods) {
244
+ if (!this.blockedMethods.has(method)) {
245
+ this.exposedMethods.add(method);
246
+ }
247
+ }
248
+ }
249
+ else {
250
+ // Auto-discover methods from the DO instance
251
+ this.discoverMethods();
252
+ }
253
+ }
254
+ /**
255
+ * Discover exposed methods from the DO instance
256
+ */
257
+ discoverMethods() {
258
+ // Get own property names from instance and prototype chain
259
+ const visited = new Set();
260
+ let obj = this.doInstance;
261
+ while (obj && obj !== Object.prototype) {
262
+ for (const key of Object.getOwnPropertyNames(obj)) {
263
+ if (visited.has(key))
264
+ continue;
265
+ visited.add(key);
266
+ // Skip blocked methods
267
+ if (this.blockedMethods.has(key))
268
+ continue;
269
+ // Skip private methods (starting with _)
270
+ if (key.startsWith('_'))
271
+ continue;
272
+ // Skip getter/setter only properties
273
+ const descriptor = Object.getOwnPropertyDescriptor(obj, key);
274
+ if (descriptor && (descriptor.get || descriptor.set) && !descriptor.value) {
275
+ continue;
276
+ }
277
+ // Check if it's a function
278
+ const value = this.doInstance[key];
279
+ if (typeof value === 'function') {
280
+ this.exposedMethods.add(key);
281
+ }
282
+ }
283
+ obj = Object.getPrototypeOf(obj);
284
+ }
285
+ }
286
+ /**
287
+ * Get list of exposed methods
288
+ */
289
+ get methods() {
290
+ return Array.from(this.exposedMethods);
291
+ }
292
+ /**
293
+ * Check if a method is exposed
294
+ */
295
+ isRpcExposed(method) {
296
+ if (this.blockedMethods.has(method))
297
+ return false;
298
+ if (method.startsWith('_'))
299
+ return false;
300
+ return this.exposedMethods.has(method);
301
+ }
302
+ /**
303
+ * Check if a method requires authentication and return an error if auth is missing
304
+ */
305
+ checkMethodAuth(method, request) {
306
+ // Get the $auth config from the DO instance's constructor
307
+ const DOClass = this.doInstance.constructor;
308
+ const authConfig = DOClass.$auth?.[method];
309
+ if (!authConfig)
310
+ return null;
311
+ // If method is public, no auth needed
312
+ if (authConfig.public)
313
+ return null;
314
+ // If method requires auth, check for Authorization header
315
+ if (authConfig.requireAuth || authConfig.roles) {
316
+ const authHeader = request.headers.get('Authorization');
317
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
318
+ return {
319
+ code: -32001, // Custom auth error code
320
+ message: 'Authentication required',
321
+ };
322
+ }
323
+ // Basic token validation (could be extended to actually validate JWT)
324
+ const token = authHeader.slice(7);
325
+ if (!token || token.split('.').length !== 3) {
326
+ return {
327
+ code: -32001,
328
+ message: 'Invalid authentication token',
329
+ };
330
+ }
331
+ }
332
+ return null;
333
+ }
334
+ /**
335
+ * Handle collection RPC call pattern: {Noun}.{method}
336
+ * Routes to the DO's collection() method for typed data access.
337
+ *
338
+ * @param method - The method name (e.g., "Task.create")
339
+ * @param args - The resolved arguments
340
+ * @returns The result of the collection operation, or throws an error
341
+ */
342
+ async handleCollectionRpc(method, args) {
343
+ // Check if this looks like a collection RPC call
344
+ if (!isCollectionRpcMethod(method)) {
345
+ return null; // Not a collection RPC, let normal handling proceed
346
+ }
347
+ // Handle multiple dots (invalid pattern)
348
+ if ((method.match(/\./g) || []).length !== 1) {
349
+ throw { code: 'INVALID_METHOD', message: `Invalid method pattern: ${method}` };
350
+ }
351
+ // Parse the method
352
+ const parsed = parseCollectionRpcMethod(method);
353
+ // Check for invalid noun pattern (lowercase, special chars, etc.)
354
+ if (!parsed) {
355
+ // Extract noun part for better error message
356
+ const [nounPart] = method.split('.');
357
+ // Check if it's a lowercase noun issue
358
+ if (nounPart && /^[a-z]/.test(nounPart)) {
359
+ throw { code: 'INVALID_NOUN', message: `Invalid noun '${nounPart}': must start with uppercase letter` };
360
+ }
361
+ // Check for numbers or special chars
362
+ if (nounPart && !/^[A-Za-z]+$/.test(nounPart)) {
363
+ throw { code: 'INVALID_NOUN', message: `Invalid noun '${nounPart}': must contain only letters` };
364
+ }
365
+ // Empty noun
366
+ if (!nounPart || nounPart === '') {
367
+ throw { code: 'INVALID_NOUN', message: 'Noun name cannot be empty' };
368
+ }
369
+ throw { code: 'INVALID_METHOD', message: `Invalid method pattern: ${method}` };
370
+ }
371
+ const { noun, action } = parsed;
372
+ // Validate noun name
373
+ const nounError = validateNounName(noun);
374
+ if (nounError) {
375
+ throw { code: 'INVALID_NOUN', message: nounError };
376
+ }
377
+ // Validate collection method
378
+ const methodError = validateCollectionMethod(noun, action);
379
+ if (methodError) {
380
+ throw { code: 'UNKNOWN_METHOD', message: methodError };
381
+ }
382
+ // Get the collection method from the DO instance
383
+ // The collection method is protected, but we can access it via the instance
384
+ const collectionFn = this.doInstance['collection'];
385
+ if (typeof collectionFn !== 'function') {
386
+ // Fallback: the DO doesn't have a collection method, so we can't handle this
387
+ throw { code: 'NOT_SUPPORTED', message: 'This DO does not support collection operations' };
388
+ }
389
+ // Get the collection for this noun
390
+ const collection = collectionFn.call(this.doInstance, noun);
391
+ if (!collection || typeof collection !== 'object') {
392
+ throw { code: 'COLLECTION_ERROR', message: `Failed to get collection for '${noun}'` };
393
+ }
394
+ const actionFn = collection[action];
395
+ if (typeof actionFn !== 'function') {
396
+ throw { code: 'UNKNOWN_METHOD', message: `Method '${action}' not found on ${noun} collection` };
397
+ }
398
+ // Execute the collection method with the provided arguments
399
+ let result = await actionFn.apply(collection, args);
400
+ // For mutations (create, update, delete), ensure $rowid is included
401
+ if (action === 'create' || action === 'update' || action === 'delete') {
402
+ result = this.ensureRowidInResult(result, action);
403
+ }
404
+ return result;
405
+ }
406
+ /**
407
+ * Ensure $rowid is present in mutation results.
408
+ * If not present, generate a synthetic one for compatibility.
409
+ */
410
+ ensureRowidInResult(result, action) {
411
+ if (result === null || result === undefined) {
412
+ return result;
413
+ }
414
+ if (typeof result === 'object' && !Array.isArray(result)) {
415
+ const obj = result;
416
+ // If $rowid is already present, return as-is
417
+ if ('$rowid' in obj && typeof obj.$rowid === 'number') {
418
+ return result;
419
+ }
420
+ // For delete, also add 'deleted' flag if not present
421
+ if (action === 'delete') {
422
+ return {
423
+ ...obj,
424
+ deleted: obj.deleted ?? true,
425
+ $rowid: obj.$rowid ?? this.generateSyntheticRowid(),
426
+ };
427
+ }
428
+ // For create/update, add $rowid if missing
429
+ return {
430
+ ...obj,
431
+ $rowid: this.generateSyntheticRowid(),
432
+ };
433
+ }
434
+ return result;
435
+ }
436
+ /**
437
+ * Generate a synthetic rowid for collection operations.
438
+ * This is used when the underlying collection doesn't return a rowid.
439
+ */
440
+ syntheticRowidCounter = 1;
441
+ generateSyntheticRowid() {
442
+ return this.syntheticRowidCounter++;
443
+ }
444
+ /**
445
+ * Create a new RPC session
446
+ */
447
+ createSession() {
448
+ const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
449
+ const promiseStore = new PromiseStore();
450
+ const subscriptions = new SubscriptionManager();
451
+ const ctx = {
452
+ promiseStore,
453
+ subscriptions,
454
+ rootObject: this.doInstance,
455
+ sendNotification: () => { },
456
+ sessionId,
457
+ exposedMethods: this.exposedMethods,
458
+ blockedMethods: this.blockedMethods,
459
+ };
460
+ this.sessions.set(sessionId, ctx);
461
+ return ctx;
462
+ }
463
+ /**
464
+ * Get or create a session
465
+ */
466
+ getSession(sessionId) {
467
+ if (sessionId && this.sessions.has(sessionId)) {
468
+ return this.sessions.get(sessionId);
469
+ }
470
+ return this.createSession();
471
+ }
472
+ /**
473
+ * Get the default HTTP session (persists across HTTP requests to same DO)
474
+ */
475
+ getDefaultHttpSession() {
476
+ if (!this.defaultHttpSession) {
477
+ this.defaultHttpSession = this.createSession();
478
+ }
479
+ return this.defaultHttpSession;
480
+ }
481
+ /**
482
+ * Clean up a session
483
+ */
484
+ cleanupSession(sessionId) {
485
+ const ctx = this.sessions.get(sessionId);
486
+ if (ctx) {
487
+ ctx.promiseStore.clear();
488
+ ctx.subscriptions.clear();
489
+ this.sessions.delete(sessionId);
490
+ }
491
+ }
492
+ /**
493
+ * Handle an HTTP RPC request
494
+ */
495
+ async handleRpcRequest(request) {
496
+ // Use persistent session for HTTP requests (state persists across requests to same DO)
497
+ const ctx = this.getDefaultHttpSession();
498
+ // Parse request body
499
+ let body;
500
+ try {
501
+ body = await request.json();
502
+ }
503
+ catch {
504
+ return Response.json({
505
+ id: '',
506
+ type: 'error',
507
+ error: { code: 'PARSE_ERROR', message: 'Invalid JSON' },
508
+ }, { status: 400, headers: { 'Content-Type': 'application/json' } });
509
+ }
510
+ // Check if JSON-RPC 2.0
511
+ if (this.isJSONRPCRequest(body)) {
512
+ // Check if the method requires auth
513
+ const authError = this.checkMethodAuth(body.method, request);
514
+ if (authError) {
515
+ return Response.json({
516
+ jsonrpc: '2.0',
517
+ error: authError,
518
+ id: body.id ?? null,
519
+ }, { status: 401, headers: { 'Content-Type': 'application/json' } });
520
+ }
521
+ const response = await this.handleJSONRPCRequest(body, ctx);
522
+ if (!response) {
523
+ // Notification - no response
524
+ return new Response(null, { status: 204 });
525
+ }
526
+ return Response.json(response, { headers: { 'Content-Type': 'application/json' } });
527
+ }
528
+ // Check if JSON-RPC 2.0 batch
529
+ if (this.isJSONRPCBatch(body)) {
530
+ const responses = [];
531
+ for (const req of body) {
532
+ const response = await this.handleJSONRPCRequest(req, ctx);
533
+ if (response) {
534
+ responses.push(response);
535
+ }
536
+ }
537
+ if (responses.length === 0) {
538
+ return new Response(null, { status: 204 });
539
+ }
540
+ return Response.json(responses, { headers: { 'Content-Type': 'application/json' } });
541
+ }
542
+ // Cap'n Web RPC
543
+ if (this.isCapnWebRequest(body)) {
544
+ const response = await this.executeCapnWebRequest(body, ctx);
545
+ return Response.json(response, { headers: { 'Content-Type': 'application/json' } });
546
+ }
547
+ // Chain RPC - Check for chain request format
548
+ if (this.isChainRequest(body)) {
549
+ // Get the WorkflowContext if available on the DO instance
550
+ const workflowContext = this.doInstance.$;
551
+ return this.executeChainRequest(body, workflowContext);
552
+ }
553
+ // Check for invalid chain format (has 'chain' property but it's not an array)
554
+ if (body !== null && typeof body === 'object' && 'chain' in body) {
555
+ return Response.json({
556
+ error: { message: 'Chain must be a non-empty array', code: 'INVALID_CHAIN' },
557
+ }, { status: 400, headers: { 'Content-Type': 'application/json' } });
558
+ }
559
+ return Response.json({
560
+ id: '',
561
+ type: 'error',
562
+ error: { code: 'INVALID_REQUEST', message: 'Unknown request format' },
563
+ }, { status: 400, headers: { 'Content-Type': 'application/json' } });
564
+ }
565
+ /**
566
+ * Handle WebSocket RPC connection
567
+ */
568
+ handleWebSocketRpc() {
569
+ const pair = new WebSocketPair();
570
+ const [client, server] = Object.values(pair);
571
+ const ctx = this.createSession();
572
+ // Set up notification sender
573
+ ctx.sendNotification = (method, params) => {
574
+ try {
575
+ server.send(JSON.stringify({
576
+ jsonrpc: '2.0',
577
+ method,
578
+ params,
579
+ }));
580
+ }
581
+ catch (error) {
582
+ // Log send errors for debugging WebSocket connection issues
583
+ console.debug('[rpc] WebSocket notification send failed:', {
584
+ method,
585
+ readyState: server.readyState,
586
+ error: error instanceof Error ? error.message : 'unknown',
587
+ });
588
+ }
589
+ };
590
+ server.accept();
591
+ // Send connection acknowledgment
592
+ server.send(JSON.stringify({
593
+ type: 'connected',
594
+ sessionId: ctx.sessionId,
595
+ }));
596
+ server.addEventListener('message', async (event) => {
597
+ const rawData = event.data;
598
+ // Handle binary data
599
+ if (rawData instanceof ArrayBuffer) {
600
+ server.send(JSON.stringify({
601
+ type: 'binary_received',
602
+ size: rawData.byteLength,
603
+ }));
604
+ return;
605
+ }
606
+ // Parse message
607
+ let data;
608
+ try {
609
+ data = JSON.parse(rawData);
610
+ }
611
+ catch {
612
+ server.send(JSON.stringify({
613
+ jsonrpc: '2.0',
614
+ error: JSON_RPC_ERRORS.PARSE_ERROR,
615
+ id: null,
616
+ }));
617
+ return;
618
+ }
619
+ // Handle JSON-RPC 2.0 batch
620
+ if (this.isJSONRPCBatch(data)) {
621
+ const responses = [];
622
+ for (const req of data) {
623
+ const response = await this.handleJSONRPCRequest(req, ctx);
624
+ if (response) {
625
+ responses.push(response);
626
+ }
627
+ }
628
+ if (responses.length > 0) {
629
+ server.send(JSON.stringify(responses));
630
+ }
631
+ return;
632
+ }
633
+ // Handle single JSON-RPC 2.0 request
634
+ if (this.isJSONRPCRequest(data)) {
635
+ const response = await this.handleJSONRPCRequest(data, ctx);
636
+ if (response) {
637
+ server.send(JSON.stringify(response));
638
+ }
639
+ return;
640
+ }
641
+ // Handle Cap'n Web request
642
+ if (this.isCapnWebRequest(data)) {
643
+ const response = await this.executeCapnWebRequest(data, ctx);
644
+ server.send(JSON.stringify(response));
645
+ return;
646
+ }
647
+ // Invalid request format
648
+ server.send(JSON.stringify({
649
+ jsonrpc: '2.0',
650
+ error: JSON_RPC_ERRORS.INVALID_REQUEST,
651
+ id: null,
652
+ }));
653
+ });
654
+ server.addEventListener('close', () => {
655
+ this.cleanupSession(ctx.sessionId);
656
+ });
657
+ server.addEventListener('error', () => {
658
+ this.cleanupSession(ctx.sessionId);
659
+ server.close();
660
+ });
661
+ return new Response(null, {
662
+ status: 101,
663
+ webSocket: client,
664
+ });
665
+ }
666
+ // ============================================================================
667
+ // PROTOCOL DETECTION
668
+ // ============================================================================
669
+ isJSONRPCRequest(data) {
670
+ return (data !== null &&
671
+ typeof data === 'object' &&
672
+ 'jsonrpc' in data &&
673
+ data.jsonrpc === '2.0');
674
+ }
675
+ isJSONRPCBatch(data) {
676
+ return (Array.isArray(data) &&
677
+ data.length > 0 &&
678
+ data.every((item) => this.isJSONRPCRequest(item)));
679
+ }
680
+ isCapnWebRequest(data) {
681
+ return (data !== null &&
682
+ typeof data === 'object' &&
683
+ 'type' in data &&
684
+ typeof data.type === 'string');
685
+ }
686
+ /**
687
+ * Check if request is a Chain RPC request
688
+ */
689
+ isChainRequest(data) {
690
+ return (data !== null &&
691
+ typeof data === 'object' &&
692
+ 'chain' in data &&
693
+ Array.isArray(data.chain));
694
+ }
695
+ // ============================================================================
696
+ // CHAIN RPC HANDLER
697
+ // ============================================================================
698
+ /**
699
+ * Execute a chain-based RPC request.
700
+ *
701
+ * The chain starts from the root object (the DO instance) and executes
702
+ * each step in sequence. If a WorkflowContext ($) is available, the chain
703
+ * can access it via the 'chain' starting from root.
704
+ *
705
+ * @param request - The chain RPC request
706
+ * @param workflowContext - Optional WorkflowContext to use as $ root
707
+ * @returns Response with data or error
708
+ */
709
+ async executeChainRequest(request, workflowContext) {
710
+ const { chain } = request;
711
+ // Validate chain
712
+ if (!Array.isArray(chain) || chain.length === 0) {
713
+ return Response.json({
714
+ error: { message: 'Chain must be a non-empty array', code: 'INVALID_CHAIN' },
715
+ }, { status: 400, headers: { 'Content-Type': 'application/json' } });
716
+ }
717
+ try {
718
+ const result = await this.executeChain(chain, workflowContext);
719
+ return Response.json({
720
+ result,
721
+ }, { headers: { 'Content-Type': 'application/json' } });
722
+ }
723
+ catch (error) {
724
+ const chainError = error;
725
+ const status = chainError.status ?? 400;
726
+ return Response.json({
727
+ error: {
728
+ message: chainError.message ?? 'Chain execution failed',
729
+ code: chainError.code ?? 'EXECUTION_ERROR',
730
+ },
731
+ }, { status, headers: { 'Content-Type': 'application/json' } });
732
+ }
733
+ }
734
+ /**
735
+ * Execute a chain of steps starting from the DO instance.
736
+ *
737
+ * The chain can access:
738
+ * - DO instance properties and methods directly (e.g., config, getStatus)
739
+ * - WorkflowContext via the $ property (e.g., $.things, $.on)
740
+ *
741
+ * @param chain - Array of chain steps
742
+ * @param workflowContext - Optional WorkflowContext accessible via $ property
743
+ * @returns The final result of the chain
744
+ */
745
+ async executeChain(chain, workflowContext) {
746
+ // Always start from the DO instance
747
+ // WorkflowContext ($) is accessible as a property of the instance
748
+ let current = this.doInstance;
749
+ // If the first step is accessing '$', use the WorkflowContext directly
750
+ if (chain.length > 0 && chain[0].type === 'property' && chain[0].key === '$' && workflowContext) {
751
+ current = workflowContext;
752
+ chain = chain.slice(1); // Skip the '$' step
753
+ }
754
+ for (let i = 0; i < chain.length; i++) {
755
+ const step = chain[i];
756
+ switch (step.type) {
757
+ case 'property': {
758
+ // Validate the step
759
+ if (typeof step.key !== 'string') {
760
+ throw { code: 'INVALID_STEP', message: 'Property step requires a string key', status: 400 };
761
+ }
762
+ // Block access to private/internal properties
763
+ if (step.key.startsWith('_')) {
764
+ throw { code: 'BLOCKED_ACCESS', message: `Access to private property '${step.key}' is blocked`, status: 404 };
765
+ }
766
+ // Block access to internal DO methods on first step (from root)
767
+ if (i === 0 && this.blockedMethods.has(step.key)) {
768
+ throw { code: 'BLOCKED_ACCESS', message: `Access to '${step.key}' is blocked`, status: 404 };
769
+ }
770
+ if (current === null || current === undefined) {
771
+ throw { code: 'NOT_FOUND', message: `Cannot access property '${step.key}' of ${current}`, status: 404 };
772
+ }
773
+ // For objects with a Proxy get trap (like WorkflowContext), accessing the property triggers the proxy
774
+ const value = current[step.key];
775
+ if (value === undefined && !(step.key in current)) {
776
+ throw { code: 'NOT_FOUND', message: `Property '${step.key}' not found`, status: 404 };
777
+ }
778
+ current = value;
779
+ break;
780
+ }
781
+ case 'call': {
782
+ const args = step.args ?? [];
783
+ // SDK Combined Format: { type: 'call', key: 'methodName', args: [...] }
784
+ // This combines property access and method call in one step.
785
+ // When 'key' is present, first access the property, then call it.
786
+ const combinedKey = step.key;
787
+ if (combinedKey !== undefined) {
788
+ // Combined call step - first access the property, then call it
789
+ if (typeof combinedKey !== 'string') {
790
+ throw { code: 'INVALID_STEP', message: 'Combined call step requires a string key', status: 400 };
791
+ }
792
+ // Block access to private methods
793
+ if (combinedKey.startsWith('_')) {
794
+ throw { code: 'BLOCKED_ACCESS', message: `Access to private method '${combinedKey}' is blocked`, status: 404 };
795
+ }
796
+ // Block access to internal DO methods on first step (from root)
797
+ if (i === 0 && this.blockedMethods.has(combinedKey)) {
798
+ throw { code: 'BLOCKED_ACCESS', message: `Access to '${combinedKey}' is blocked`, status: 404 };
799
+ }
800
+ if (current === null || current === undefined) {
801
+ throw { code: 'NOT_FOUND', message: `Cannot access method '${combinedKey}' of ${current}`, status: 404 };
802
+ }
803
+ // Access the method
804
+ const method = current[combinedKey];
805
+ if (method === undefined && !(combinedKey in current)) {
806
+ throw { code: 'NOT_FOUND', message: `Method '${combinedKey}' not found`, status: 404 };
807
+ }
808
+ if (typeof method !== 'function') {
809
+ throw { code: 'NOT_CALLABLE', message: `'${combinedKey}' is not a function`, status: 400 };
810
+ }
811
+ // Execute the method with 'current' as 'this' context
812
+ const result = method.apply(current, args);
813
+ // Await if it's a promise
814
+ current = result instanceof Promise ? await result : result;
815
+ }
816
+ else {
817
+ // Traditional call step - 'current' should already be a function
818
+ if (typeof current !== 'function') {
819
+ throw { code: 'NOT_CALLABLE', message: 'Value is not a function, cannot call', status: 400 };
820
+ }
821
+ // Find the 'this' context for the call
822
+ // Look back for the last property access to get the parent object
823
+ let thisContext = this.doInstance;
824
+ if (i > 0) {
825
+ // Re-execute chain up to the previous step to get the parent context
826
+ const prevChain = chain.slice(0, i - 1);
827
+ if (prevChain.length > 0) {
828
+ thisContext = await this.executeChain(prevChain, workflowContext);
829
+ }
830
+ else if (i === 1) {
831
+ // First call after property access - use root
832
+ thisContext = workflowContext ?? this.doInstance;
833
+ }
834
+ }
835
+ // Execute the function
836
+ const result = current.apply(thisContext, args);
837
+ // Await if it's a promise
838
+ current = result instanceof Promise ? await result : result;
839
+ }
840
+ break;
841
+ }
842
+ case 'index': {
843
+ if (typeof step.index !== 'number') {
844
+ throw { code: 'INVALID_STEP', message: 'Index step requires a numeric index', status: 400 };
845
+ }
846
+ if (!Array.isArray(current)) {
847
+ throw { code: 'NOT_INDEXABLE', message: 'Value is not an array, cannot use index access', status: 400 };
848
+ }
849
+ if (step.index < 0 || step.index >= current.length) {
850
+ throw {
851
+ code: 'INDEX_OUT_OF_BOUNDS',
852
+ message: `Index ${step.index} is out of bounds (array length: ${current.length})`,
853
+ status: 404
854
+ };
855
+ }
856
+ current = current[step.index];
857
+ break;
858
+ }
859
+ default: {
860
+ throw {
861
+ code: 'INVALID_STEP',
862
+ message: `Invalid step type: ${step.type}`,
863
+ status: 400
864
+ };
865
+ }
866
+ }
867
+ }
868
+ return current;
869
+ }
870
+ // ============================================================================
871
+ // JSON-RPC 2.0 HANDLER
872
+ // ============================================================================
873
+ async handleJSONRPCRequest(request, ctx) {
874
+ const { method, params, id } = request;
875
+ const isNotification = id === undefined;
876
+ try {
877
+ // Handle subscription methods
878
+ if (method === 'subscribe') {
879
+ const p = params;
880
+ const subscriptionId = ctx.subscriptions.subscribe(p.event, (data) => {
881
+ ctx.sendNotification(p.event, data);
882
+ });
883
+ if (isNotification)
884
+ return null;
885
+ return {
886
+ jsonrpc: '2.0',
887
+ result: { subscriptionId },
888
+ id: id ?? null,
889
+ };
890
+ }
891
+ if (method === 'unsubscribe') {
892
+ const p = params;
893
+ const success = ctx.subscriptions.unsubscribe(p.subscriptionId);
894
+ if (isNotification)
895
+ return null;
896
+ return {
897
+ jsonrpc: '2.0',
898
+ result: { success },
899
+ id: id ?? null,
900
+ };
901
+ }
902
+ // Handle triggerEvent (for testing)
903
+ if (method === 'triggerEvent') {
904
+ const p = params;
905
+ ctx.subscriptions.emit(p.event, p.data);
906
+ if (isNotification)
907
+ return null;
908
+ return {
909
+ jsonrpc: '2.0',
910
+ result: { triggered: true },
911
+ id: id ?? null,
912
+ };
913
+ }
914
+ // Check for collection RPC pattern: {Noun}.{method}
915
+ if (isCollectionRpcMethod(method)) {
916
+ // Convert params to args array
917
+ const args = params === undefined
918
+ ? []
919
+ : Array.isArray(params)
920
+ ? params
921
+ : [params];
922
+ const result = await this.handleCollectionRpc(method, args);
923
+ if (isNotification)
924
+ return null;
925
+ return {
926
+ jsonrpc: '2.0',
927
+ result,
928
+ id: id ?? null,
929
+ };
930
+ }
931
+ // Check if method exists and is exposed
932
+ if (!this.isRpcExposed(method)) {
933
+ if (isNotification)
934
+ return null;
935
+ return {
936
+ jsonrpc: '2.0',
937
+ error: { ...JSON_RPC_ERRORS.METHOD_NOT_FOUND, message: `Method '${method}' not found` },
938
+ id: id ?? null,
939
+ };
940
+ }
941
+ const methodFn = ctx.rootObject[method];
942
+ if (typeof methodFn !== 'function') {
943
+ if (isNotification)
944
+ return null;
945
+ return {
946
+ jsonrpc: '2.0',
947
+ error: { ...JSON_RPC_ERRORS.METHOD_NOT_FOUND, message: `Method '${method}' not found` },
948
+ id: id ?? null,
949
+ };
950
+ }
951
+ // Execute method
952
+ let result;
953
+ if (params === undefined) {
954
+ result = await methodFn.call(ctx.rootObject);
955
+ }
956
+ else if (Array.isArray(params)) {
957
+ result = await methodFn.apply(ctx.rootObject, params);
958
+ }
959
+ else if (typeof params === 'object' && params !== null) {
960
+ // Named parameters - try to extract positional args from object
961
+ const namedParams = params;
962
+ const paramNames = this.extractParamNames(methodFn);
963
+ if (paramNames.length > 0 && paramNames.every((name) => name in namedParams)) {
964
+ // All parameter names found in the object - convert to positional args
965
+ const args = paramNames.map((name) => namedParams[name]);
966
+ result = await methodFn.apply(ctx.rootObject, args);
967
+ }
968
+ else {
969
+ // Fall back to passing the object as a single argument
970
+ result = await methodFn.call(ctx.rootObject, params);
971
+ }
972
+ }
973
+ else {
974
+ result = await methodFn.call(ctx.rootObject, params);
975
+ }
976
+ if (isNotification)
977
+ return null;
978
+ return {
979
+ jsonrpc: '2.0',
980
+ result,
981
+ id: id ?? null,
982
+ };
983
+ }
984
+ catch (error) {
985
+ if (isNotification)
986
+ return null;
987
+ const errorMessage = error instanceof Error ? error.message : String(error);
988
+ return {
989
+ jsonrpc: '2.0',
990
+ error: {
991
+ code: JSON_RPC_ERRORS.INTERNAL_ERROR.code,
992
+ message: errorMessage,
993
+ },
994
+ id: id ?? null,
995
+ };
996
+ }
997
+ }
998
+ // ============================================================================
999
+ // CAP'N WEB RPC HANDLER
1000
+ // ============================================================================
1001
+ async executeCapnWebRequest(request, ctx) {
1002
+ switch (request.type) {
1003
+ case 'call':
1004
+ case 'batch':
1005
+ return this.executeBatch(request, ctx);
1006
+ case 'resolve':
1007
+ return this.executeResolve(request, ctx);
1008
+ case 'dispose':
1009
+ return this.executeDispose(request, ctx);
1010
+ default:
1011
+ return {
1012
+ id: request.id,
1013
+ type: 'error',
1014
+ error: { code: 'INVALID_REQUEST', message: 'Unknown request type' },
1015
+ };
1016
+ }
1017
+ }
1018
+ async executeBatch(request, ctx) {
1019
+ if (!request.calls || request.calls.length === 0) {
1020
+ return {
1021
+ id: request.id,
1022
+ type: 'error',
1023
+ error: { code: 'INVALID_REQUEST', message: 'No calls provided' },
1024
+ };
1025
+ }
1026
+ const results = [];
1027
+ for (const call of request.calls) {
1028
+ const result = await this.executeCall(call, ctx);
1029
+ results.push(result);
1030
+ }
1031
+ return {
1032
+ id: request.id,
1033
+ type: 'batch',
1034
+ results,
1035
+ };
1036
+ }
1037
+ async executeResolve(request, ctx) {
1038
+ if (!request.resolve?.promiseId) {
1039
+ return {
1040
+ id: request.id,
1041
+ type: 'error',
1042
+ error: { code: 'INVALID_REQUEST', message: 'No promiseId provided' },
1043
+ };
1044
+ }
1045
+ const promiseId = request.resolve.promiseId;
1046
+ if (ctx.promiseStore.isDisposed(promiseId)) {
1047
+ return {
1048
+ id: request.id,
1049
+ type: 'error',
1050
+ error: { code: 'DISPOSED_REFERENCE', message: `Promise ${promiseId} has been disposed` },
1051
+ };
1052
+ }
1053
+ if (!ctx.promiseStore.has(promiseId)) {
1054
+ return {
1055
+ id: request.id,
1056
+ type: 'error',
1057
+ error: { code: 'INVALID_PROMISE', message: `Promise ${promiseId} not found` },
1058
+ };
1059
+ }
1060
+ const value = ctx.promiseStore.get(promiseId);
1061
+ return {
1062
+ id: request.id,
1063
+ type: 'result',
1064
+ results: [
1065
+ {
1066
+ promiseId,
1067
+ type: 'value',
1068
+ value,
1069
+ },
1070
+ ],
1071
+ };
1072
+ }
1073
+ async executeDispose(request, ctx) {
1074
+ if (!request.dispose?.promiseIds) {
1075
+ return {
1076
+ id: request.id,
1077
+ type: 'error',
1078
+ error: { code: 'INVALID_REQUEST', message: 'No promiseIds provided' },
1079
+ };
1080
+ }
1081
+ for (const promiseId of request.dispose.promiseIds) {
1082
+ ctx.promiseStore.dispose(promiseId);
1083
+ }
1084
+ return {
1085
+ id: request.id,
1086
+ type: 'result',
1087
+ results: [],
1088
+ };
1089
+ }
1090
+ async executeCall(call, ctx) {
1091
+ // Calculate depth for this call (outside try for catch access)
1092
+ let callDepth = 0;
1093
+ try {
1094
+ if (call.target.type === 'promise') {
1095
+ const baseDepth = ctx.promiseStore.getDepth(call.target.promiseId);
1096
+ callDepth = baseDepth + 1;
1097
+ // Check max pipeline depth
1098
+ const maxDepth = this.config.maxPipelineDepth ?? 20;
1099
+ if (callDepth >= maxDepth) {
1100
+ throw { code: 'MAX_PIPELINE_DEPTH', message: `Pipeline depth ${callDepth} exceeds maximum ${maxDepth}` };
1101
+ }
1102
+ }
1103
+ else if (call.target.type === 'property') {
1104
+ const base = call.target.base;
1105
+ if (base.type === 'promise') {
1106
+ const baseDepth = ctx.promiseStore.getDepth(base.promiseId);
1107
+ callDepth = baseDepth + 1;
1108
+ // Check max pipeline depth
1109
+ if (callDepth > (this.config.maxPipelineDepth ?? 20)) {
1110
+ throw { code: 'MAX_PIPELINE_DEPTH', message: `Pipeline depth ${callDepth} exceeds maximum ${this.config.maxPipelineDepth ?? 20}` };
1111
+ }
1112
+ }
1113
+ }
1114
+ const target = this.resolveTarget(call.target, ctx);
1115
+ const args = call.args.map((arg) => this.resolveArg(arg, ctx));
1116
+ let result;
1117
+ // Handle magic methods
1118
+ if (call.method === '__get__') {
1119
+ // Property getter - target is already the value from property access
1120
+ result = target;
1121
+ }
1122
+ else if (call.method === '__map__' && Array.isArray(target)) {
1123
+ // Magic map operation
1124
+ const mapSpec = args[0];
1125
+ if (mapSpec?.property) {
1126
+ result = target.map((item) => item[mapSpec.property]);
1127
+ }
1128
+ else {
1129
+ result = target;
1130
+ }
1131
+ }
1132
+ else if (call.method === '__filter__' && Array.isArray(target)) {
1133
+ // Magic filter operation
1134
+ const filterSpec = args[0];
1135
+ if (filterSpec?.property) {
1136
+ result = target.filter((item) => item[filterSpec.property] === filterSpec.equals);
1137
+ }
1138
+ else {
1139
+ result = target;
1140
+ }
1141
+ }
1142
+ else if (target === ctx.rootObject) {
1143
+ // Check for collection RPC pattern first: {Noun}.{method}
1144
+ if (isCollectionRpcMethod(call.method)) {
1145
+ result = await this.handleCollectionRpc(call.method, args);
1146
+ }
1147
+ else {
1148
+ // Regular root object method call - MUST check if exposed
1149
+ if (!this.isRpcExposed(call.method)) {
1150
+ throw { code: 'METHOD_NOT_FOUND', message: `Method ${call.method} not found` };
1151
+ }
1152
+ const method = target[call.method];
1153
+ if (typeof method !== 'function') {
1154
+ throw { code: 'METHOD_NOT_FOUND', message: `Method ${call.method} not found` };
1155
+ }
1156
+ result = await method.apply(target, args);
1157
+ }
1158
+ }
1159
+ else if (target && typeof target === 'object' && call.method in target) {
1160
+ // Method call on non-root object (from pipelining)
1161
+ const method = target[call.method];
1162
+ if (typeof method === 'function') {
1163
+ result = await method.apply(target, args);
1164
+ }
1165
+ else {
1166
+ result = method;
1167
+ }
1168
+ }
1169
+ else if (target && typeof target === 'object') {
1170
+ // Property access on object
1171
+ result = target[call.method];
1172
+ if (result === undefined && !(call.method in target)) {
1173
+ throw { code: 'METHOD_NOT_FOUND', message: `Method ${call.method} not found` };
1174
+ }
1175
+ }
1176
+ else {
1177
+ throw { code: 'INVALID_TARGET', message: 'Cannot call method on null or primitive' };
1178
+ }
1179
+ // Store result for pipelining (with depth tracking)
1180
+ ctx.promiseStore.set(call.promiseId, result, callDepth);
1181
+ return {
1182
+ promiseId: call.promiseId,
1183
+ type: 'value',
1184
+ value: result,
1185
+ };
1186
+ }
1187
+ catch (error) {
1188
+ const rpcError = error && typeof error === 'object' && 'code' in error
1189
+ ? error
1190
+ : {
1191
+ code: 'EXECUTION_ERROR',
1192
+ message: error instanceof Error ? error.message : String(error),
1193
+ };
1194
+ // Store error marker for pipeline propagation (with depth tracking)
1195
+ ctx.promiseStore.set(call.promiseId, { __error__: rpcError }, callDepth);
1196
+ return {
1197
+ promiseId: call.promiseId,
1198
+ type: 'error',
1199
+ error: rpcError,
1200
+ };
1201
+ }
1202
+ }
1203
+ resolveTarget(target, ctx) {
1204
+ switch (target.type) {
1205
+ case 'root':
1206
+ return ctx.rootObject;
1207
+ case 'promise': {
1208
+ if (ctx.promiseStore.isDisposed(target.promiseId)) {
1209
+ throw { code: 'DISPOSED_REFERENCE', message: `Promise ${target.promiseId} has been disposed` };
1210
+ }
1211
+ const value = ctx.promiseStore.get(target.promiseId);
1212
+ if (value === undefined && !ctx.promiseStore.has(target.promiseId)) {
1213
+ throw { code: 'INVALID_PROMISE', message: `Promise ${target.promiseId} not found` };
1214
+ }
1215
+ // Check if the value is an error marker (propagate errors through pipeline)
1216
+ if (value && typeof value === 'object' && '__error__' in value) {
1217
+ throw value.__error__;
1218
+ }
1219
+ // Check for null/undefined target
1220
+ if (value === null || value === undefined) {
1221
+ throw { code: 'INVALID_TARGET', message: 'Cannot access property of null or undefined' };
1222
+ }
1223
+ return value;
1224
+ }
1225
+ case 'property': {
1226
+ const base = this.resolveNestedTarget(target.base, ctx);
1227
+ if (base === null || typeof base !== 'object') {
1228
+ throw { code: 'INVALID_TARGET', message: 'Cannot access property of non-object' };
1229
+ }
1230
+ // Handle array index access
1231
+ if (Array.isArray(base) && /^\d+$/.test(target.property)) {
1232
+ return base[parseInt(target.property, 10)];
1233
+ }
1234
+ return base[target.property];
1235
+ }
1236
+ default:
1237
+ throw { code: 'INVALID_TARGET', message: 'Unknown target type' };
1238
+ }
1239
+ }
1240
+ resolveNestedTarget(target, ctx) {
1241
+ switch (target.type) {
1242
+ case 'root':
1243
+ return ctx.rootObject;
1244
+ case 'promise': {
1245
+ if (ctx.promiseStore.isDisposed(target.promiseId)) {
1246
+ throw { code: 'DISPOSED_REFERENCE', message: `Promise ${target.promiseId} has been disposed` };
1247
+ }
1248
+ const value = ctx.promiseStore.get(target.promiseId);
1249
+ if (value === undefined && !ctx.promiseStore.has(target.promiseId)) {
1250
+ throw { code: 'INVALID_PROMISE', message: `Promise ${target.promiseId} not found` };
1251
+ }
1252
+ // Check if the value is an error marker
1253
+ if (value && typeof value === 'object' && '__error__' in value) {
1254
+ throw value.__error__;
1255
+ }
1256
+ return value;
1257
+ }
1258
+ default:
1259
+ throw { code: 'INVALID_TARGET', message: 'Unknown nested target type' };
1260
+ }
1261
+ }
1262
+ resolveArg(arg, ctx) {
1263
+ switch (arg.type) {
1264
+ case 'value':
1265
+ return arg.value;
1266
+ case 'promise': {
1267
+ if (ctx.promiseStore.isDisposed(arg.promiseId)) {
1268
+ throw { code: 'DISPOSED_REFERENCE', message: `Promise ${arg.promiseId} has been disposed` };
1269
+ }
1270
+ const value = ctx.promiseStore.get(arg.promiseId);
1271
+ // If the value is an object with an id, extract it for method calls
1272
+ // This handles the case where we pass a user object to getUserPosts
1273
+ if (value && typeof value === 'object' && 'id' in value) {
1274
+ return value.id;
1275
+ }
1276
+ return value;
1277
+ }
1278
+ case 'callback':
1279
+ throw { code: 'NOT_IMPLEMENTED', message: 'Callbacks not yet supported' };
1280
+ default:
1281
+ throw { code: 'INVALID_ARG', message: 'Unknown argument type' };
1282
+ }
1283
+ }
1284
+ /**
1285
+ * Extract parameter names from a function.
1286
+ * Uses function.toString() parsing to extract parameter names.
1287
+ */
1288
+ extractParamNames(fn) {
1289
+ const fnStr = fn.toString();
1290
+ // Match function parameters - handles various function syntaxes
1291
+ const arrowMatch = fnStr.match(/^\s*\(?([^)=]*)\)?\s*=>/);
1292
+ const funcMatch = fnStr.match(/^(?:async\s+)?(?:function\s*)?\s*\w*\s*\(([^)]*)\)/);
1293
+ const paramsStr = arrowMatch?.[1] || funcMatch?.[1] || '';
1294
+ if (!paramsStr.trim()) {
1295
+ return [];
1296
+ }
1297
+ return paramsStr
1298
+ .split(',')
1299
+ .map((p) => {
1300
+ // Handle destructuring, default values, rest params
1301
+ const cleaned = p.trim()
1302
+ .replace(/\s*=\s*.*$/, '') // Remove default values
1303
+ .replace(/\.\.\.\s*/, '') // Remove rest operator
1304
+ .replace(/[{}[\]]/g, ''); // Remove destructuring braces
1305
+ // Extract the first identifier
1306
+ const match = cleaned.match(/^\s*(\w+)/);
1307
+ return match?.[1] || '';
1308
+ })
1309
+ .filter((p) => p.length > 0);
1310
+ }
1311
+ }
1312
+ // ============================================================================
1313
+ // FACTORY FUNCTIONS
1314
+ // ============================================================================
1315
+ /**
1316
+ * Create an RPC handler for a DO instance
1317
+ */
1318
+ export function createRpcHandler(doInstance, config) {
1319
+ return new RPCServer(doInstance, config);
1320
+ }
1321
+ /**
1322
+ * Handle an RPC request (HTTP)
1323
+ */
1324
+ export async function handleRpcRequest(request, doInstance, config) {
1325
+ const server = createRpcHandler(doInstance, config);
1326
+ return server.handleRpcRequest(request);
1327
+ }
1328
+ /**
1329
+ * Handle WebSocket RPC upgrade
1330
+ */
1331
+ export function handleWebSocketRpc(doInstance, config) {
1332
+ const server = createRpcHandler(doInstance, config);
1333
+ return server.handleWebSocketRpc();
1334
+ }
1335
+ export function withRpcServer(Base, config) {
1336
+ return class extends Base {
1337
+ _rpcServer;
1338
+ get rpcServer() {
1339
+ if (!this._rpcServer) {
1340
+ this._rpcServer = new RPCServer(this, config);
1341
+ }
1342
+ return this._rpcServer;
1343
+ }
1344
+ isRpcExposed(method) {
1345
+ return this.rpcServer.isRpcExposed(method);
1346
+ }
1347
+ /**
1348
+ * Override fetch to handle /rpc endpoint
1349
+ */
1350
+ async fetch(request) {
1351
+ const url = new URL(request.url);
1352
+ // Handle /rpc endpoint
1353
+ if (url.pathname === '/rpc') {
1354
+ // Check for WebSocket upgrade
1355
+ const upgradeHeader = request.headers.get('upgrade');
1356
+ const connectionHeader = request.headers.get('connection')?.toLowerCase() || '';
1357
+ const hasConnectionUpgrade = connectionHeader.includes('upgrade');
1358
+ if (upgradeHeader?.toLowerCase() === 'websocket' && hasConnectionUpgrade) {
1359
+ return this.rpcServer.handleWebSocketRpc();
1360
+ }
1361
+ // HTTP RPC request
1362
+ if (request.method === 'POST') {
1363
+ return this.rpcServer.handleRpcRequest(request);
1364
+ }
1365
+ // GET request - return RPC info
1366
+ return Response.json({
1367
+ message: 'RPC endpoint - use POST for HTTP batch mode or WebSocket for streaming',
1368
+ methods: this.rpcServer.methods,
1369
+ }, { headers: { 'Content-Type': 'application/json' } });
1370
+ }
1371
+ // Delegate to parent fetch
1372
+ return super.fetch(request);
1373
+ }
1374
+ };
1375
+ }
1376
+ /**
1377
+ * Apply RPC integration to an existing DO instance
1378
+ * This is useful when you can't use the mixin pattern
1379
+ */
1380
+ export function applyRpcIntegration(doInstance, config) {
1381
+ const rpcServer = new RPCServer(doInstance, config);
1382
+ // Add rpcServer property
1383
+ Object.defineProperty(doInstance, 'rpcServer', {
1384
+ get() {
1385
+ return rpcServer;
1386
+ },
1387
+ enumerable: true,
1388
+ configurable: false,
1389
+ });
1390
+ // Add isRpcExposed method
1391
+ doInstance.isRpcExposed = (method) => rpcServer.isRpcExposed(method);
1392
+ // Wrap the existing fetch method
1393
+ const originalFetch = doInstance.fetch.bind(doInstance);
1394
+ doInstance.fetch = async (request) => {
1395
+ const url = new URL(request.url);
1396
+ // Handle /rpc endpoint
1397
+ if (url.pathname === '/rpc') {
1398
+ // Check for WebSocket upgrade
1399
+ const upgradeHeader = request.headers.get('upgrade');
1400
+ const connectionHeader = request.headers.get('connection')?.toLowerCase() || '';
1401
+ const hasConnectionUpgrade = connectionHeader.includes('upgrade');
1402
+ if (upgradeHeader?.toLowerCase() === 'websocket' && hasConnectionUpgrade) {
1403
+ return rpcServer.handleWebSocketRpc();
1404
+ }
1405
+ // HTTP RPC request
1406
+ if (request.method === 'POST') {
1407
+ return rpcServer.handleRpcRequest(request);
1408
+ }
1409
+ // GET request - return RPC info
1410
+ return Response.json({
1411
+ message: 'RPC endpoint - use POST for HTTP batch mode or WebSocket for streaming',
1412
+ methods: rpcServer.methods,
1413
+ }, { headers: { 'Content-Type': 'application/json' } });
1414
+ }
1415
+ // Delegate to original fetch
1416
+ return originalFetch(request);
1417
+ };
1418
+ }
1419
+ export default RPCServer;
1420
+ import { buildJsonResponse, buildErrorResponse, } from './shared';
1421
+ /**
1422
+ * Cache for RPC servers per DO instance
1423
+ */
1424
+ const rpcServerCache = new WeakMap();
1425
+ /**
1426
+ * RPC Handler implementing TransportHandler interface
1427
+ *
1428
+ * Provides Cap'n Web RPC functionality:
1429
+ * - Promise pipelining
1430
+ * - JSON-RPC 2.0 support
1431
+ * - WebSocket streaming RPC
1432
+ * - Method discovery and invocation
1433
+ *
1434
+ * @example
1435
+ * ```typescript
1436
+ * const rpcHandler = new RpcHandler({
1437
+ * path: '/rpc',
1438
+ * maxPipelineDepth: 20,
1439
+ * })
1440
+ *
1441
+ * // Use in handler chain
1442
+ * chain.use(rpcHandler, 40)
1443
+ * ```
1444
+ */
1445
+ export class RpcHandler {
1446
+ name = 'rpc';
1447
+ options;
1448
+ server = null;
1449
+ constructor(options = {}) {
1450
+ this.options = {
1451
+ path: '/rpc',
1452
+ maxPipelineDepth: 20,
1453
+ ...options,
1454
+ };
1455
+ }
1456
+ /**
1457
+ * Check if this handler can process the request
1458
+ * RPC handler processes requests to the /rpc endpoint
1459
+ */
1460
+ canHandle(request) {
1461
+ const url = new URL(request.url);
1462
+ const rpcPath = this.options.path || '/rpc';
1463
+ // Check if request is to RPC endpoint
1464
+ if (url.pathname === rpcPath) {
1465
+ // RPC handler has medium-high priority
1466
+ return {
1467
+ canHandle: true,
1468
+ priority: 40,
1469
+ };
1470
+ }
1471
+ return { canHandle: false, reason: 'Path does not match RPC endpoint' };
1472
+ }
1473
+ /**
1474
+ * Handle the RPC request
1475
+ */
1476
+ async handle(request, context) {
1477
+ // Get or create RPC server for this instance
1478
+ const server = this.getOrCreateServer(context.instance);
1479
+ // Check for WebSocket upgrade
1480
+ const upgradeHeader = request.headers.get('upgrade');
1481
+ const connectionHeader = request.headers.get('connection')?.toLowerCase() || '';
1482
+ const hasConnectionUpgrade = connectionHeader.includes('upgrade');
1483
+ if (upgradeHeader?.toLowerCase() === 'websocket' && hasConnectionUpgrade) {
1484
+ return server.handleWebSocketRpc();
1485
+ }
1486
+ // Handle HTTP methods
1487
+ if (request.method === 'POST') {
1488
+ return server.handleRpcRequest(request);
1489
+ }
1490
+ if (request.method === 'GET') {
1491
+ // Return RPC info
1492
+ return buildJsonResponse({
1493
+ message: 'RPC endpoint - use POST for HTTP batch mode or WebSocket for streaming',
1494
+ methods: server.methods,
1495
+ });
1496
+ }
1497
+ return buildErrorResponse({ message: 'Method not allowed', code: 'METHOD_NOT_ALLOWED' }, 405, { headers: { 'Allow': 'GET, POST' } });
1498
+ }
1499
+ /**
1500
+ * Get or create RPC server for an instance
1501
+ */
1502
+ getOrCreateServer(instance) {
1503
+ // Check cache
1504
+ if (rpcServerCache.has(instance)) {
1505
+ return rpcServerCache.get(instance);
1506
+ }
1507
+ // Create new server
1508
+ const server = new RPCServer(instance, {
1509
+ maxPipelineDepth: this.options.maxPipelineDepth,
1510
+ exposedMethods: this.options.exposedMethods,
1511
+ blockedMethods: this.options.blockedMethods,
1512
+ });
1513
+ rpcServerCache.set(instance, server);
1514
+ this.server = server;
1515
+ return server;
1516
+ }
1517
+ /**
1518
+ * Get current RPC server
1519
+ */
1520
+ getServer() {
1521
+ return this.server;
1522
+ }
1523
+ /**
1524
+ * Clear server cache for an instance
1525
+ */
1526
+ static clearCache(instance) {
1527
+ rpcServerCache.delete(instance);
1528
+ }
1529
+ /**
1530
+ * Dispose handler resources
1531
+ */
1532
+ dispose() {
1533
+ this.server = null;
1534
+ }
1535
+ }
1536
+ //# sourceMappingURL=rpc-server.js.map