@procedures/client 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (762) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +832 -2
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/adapters/http/client/index.d.ts +11 -0
  6. package/dist/adapters/http/client/index.d.ts.map +1 -0
  7. package/dist/adapters/http/client/index.js +18 -0
  8. package/dist/adapters/http/client/index.js.map +1 -0
  9. package/dist/adapters/http/client/transport.d.ts +72 -0
  10. package/dist/adapters/http/client/transport.d.ts.map +1 -0
  11. package/dist/adapters/http/client/transport.js +282 -0
  12. package/dist/adapters/http/client/transport.js.map +1 -0
  13. package/dist/adapters/http/client/types.d.ts +27 -0
  14. package/dist/adapters/http/client/types.d.ts.map +1 -0
  15. package/dist/adapters/http/client/types.js +8 -0
  16. package/dist/adapters/http/client/types.js.map +1 -0
  17. package/dist/adapters/http/index.d.ts +7 -0
  18. package/dist/adapters/http/index.d.ts.map +1 -0
  19. package/dist/adapters/http/index.js +7 -0
  20. package/dist/adapters/http/index.js.map +1 -0
  21. package/dist/adapters/http/server/index.d.ts +9 -0
  22. package/dist/adapters/http/server/index.d.ts.map +1 -0
  23. package/dist/adapters/http/server/index.js +10 -0
  24. package/dist/adapters/http/server/index.js.map +1 -0
  25. package/dist/adapters/http/server/strategies.d.ts +39 -0
  26. package/dist/adapters/http/server/strategies.d.ts.map +1 -0
  27. package/dist/adapters/http/server/strategies.js +90 -0
  28. package/dist/adapters/http/server/strategies.js.map +1 -0
  29. package/dist/adapters/http/server/transport.d.ts +66 -0
  30. package/dist/adapters/http/server/transport.d.ts.map +1 -0
  31. package/dist/adapters/http/server/transport.js +561 -0
  32. package/dist/adapters/http/server/transport.js.map +1 -0
  33. package/dist/adapters/http/server/types.d.ts +71 -0
  34. package/dist/adapters/http/server/types.d.ts.map +1 -0
  35. package/dist/adapters/http/server/types.js +7 -0
  36. package/dist/adapters/http/server/types.js.map +1 -0
  37. package/dist/adapters/http/shared/constants.d.ts +95 -0
  38. package/dist/adapters/http/shared/constants.d.ts.map +1 -0
  39. package/dist/adapters/http/shared/constants.js +102 -0
  40. package/dist/adapters/http/shared/constants.js.map +1 -0
  41. package/dist/adapters/http/shared/errors.d.ts +78 -0
  42. package/dist/adapters/http/shared/errors.d.ts.map +1 -0
  43. package/dist/adapters/http/shared/errors.js +151 -0
  44. package/dist/adapters/http/shared/errors.js.map +1 -0
  45. package/dist/adapters/http/shared/headers.d.ts +122 -0
  46. package/dist/adapters/http/shared/headers.d.ts.map +1 -0
  47. package/dist/adapters/http/shared/headers.js +216 -0
  48. package/dist/adapters/http/shared/headers.js.map +1 -0
  49. package/dist/adapters/http/shared/index.d.ts +12 -0
  50. package/dist/adapters/http/shared/index.d.ts.map +1 -0
  51. package/dist/adapters/http/shared/index.js +17 -0
  52. package/dist/adapters/http/shared/index.js.map +1 -0
  53. package/dist/adapters/http/shared/status-codes.d.ts +92 -0
  54. package/dist/adapters/http/shared/status-codes.d.ts.map +1 -0
  55. package/dist/adapters/http/shared/status-codes.js +189 -0
  56. package/dist/adapters/http/shared/status-codes.js.map +1 -0
  57. package/dist/adapters/http/shared/strategies.d.ts +90 -0
  58. package/dist/adapters/http/shared/strategies.d.ts.map +1 -0
  59. package/dist/adapters/http/shared/strategies.js +180 -0
  60. package/dist/adapters/http/shared/strategies.js.map +1 -0
  61. package/dist/adapters/local/client/index.d.ts +8 -0
  62. package/dist/adapters/local/client/index.d.ts.map +1 -0
  63. package/dist/adapters/local/client/index.js +8 -0
  64. package/dist/adapters/local/client/index.js.map +1 -0
  65. package/dist/adapters/local/client/transport.d.ts +81 -0
  66. package/dist/adapters/local/client/transport.d.ts.map +1 -0
  67. package/dist/adapters/local/client/transport.js +172 -0
  68. package/dist/adapters/local/client/transport.js.map +1 -0
  69. package/dist/adapters/local/client/types.d.ts +39 -0
  70. package/dist/adapters/local/client/types.d.ts.map +1 -0
  71. package/dist/adapters/local/client/types.js +13 -0
  72. package/dist/adapters/local/client/types.js.map +1 -0
  73. package/dist/adapters/metadata.d.ts +10 -0
  74. package/dist/adapters/metadata.d.ts.map +1 -0
  75. package/dist/adapters/metadata.js +19 -0
  76. package/dist/adapters/metadata.js.map +1 -0
  77. package/dist/adapters/mock/client/builder.d.ts +35 -0
  78. package/dist/adapters/mock/client/builder.d.ts.map +1 -0
  79. package/dist/adapters/mock/client/builder.js +58 -0
  80. package/dist/adapters/mock/client/builder.js.map +1 -0
  81. package/dist/adapters/mock/client/index.d.ts +9 -0
  82. package/dist/adapters/mock/client/index.d.ts.map +1 -0
  83. package/dist/adapters/mock/client/index.js +10 -0
  84. package/dist/adapters/mock/client/index.js.map +1 -0
  85. package/dist/adapters/mock/client/transport.d.ts +149 -0
  86. package/dist/adapters/mock/client/transport.d.ts.map +1 -0
  87. package/dist/adapters/mock/client/transport.js +289 -0
  88. package/dist/adapters/mock/client/transport.js.map +1 -0
  89. package/dist/adapters/mock/client/types.d.ts +86 -0
  90. package/dist/adapters/mock/client/types.d.ts.map +1 -0
  91. package/dist/adapters/mock/client/types.js +7 -0
  92. package/dist/adapters/mock/client/types.js.map +1 -0
  93. package/dist/adapters/websocket/client/index.d.ts +9 -0
  94. package/dist/adapters/websocket/client/index.d.ts.map +1 -0
  95. package/dist/adapters/websocket/client/index.js +9 -0
  96. package/dist/adapters/websocket/client/index.js.map +1 -0
  97. package/dist/adapters/websocket/client/transport.d.ts +106 -0
  98. package/dist/adapters/websocket/client/transport.d.ts.map +1 -0
  99. package/dist/adapters/websocket/client/transport.js +647 -0
  100. package/dist/adapters/websocket/client/transport.js.map +1 -0
  101. package/dist/adapters/websocket/client/types.d.ts +192 -0
  102. package/dist/adapters/websocket/client/types.d.ts.map +1 -0
  103. package/dist/adapters/websocket/client/types.js +17 -0
  104. package/dist/adapters/websocket/client/types.js.map +1 -0
  105. package/dist/adapters/websocket/index.d.ts +8 -0
  106. package/dist/adapters/websocket/index.d.ts.map +1 -0
  107. package/dist/adapters/websocket/index.js +8 -0
  108. package/dist/adapters/websocket/index.js.map +1 -0
  109. package/dist/adapters/websocket/server/index.d.ts +8 -0
  110. package/dist/adapters/websocket/server/index.d.ts.map +1 -0
  111. package/dist/adapters/websocket/server/index.js +8 -0
  112. package/dist/adapters/websocket/server/index.js.map +1 -0
  113. package/dist/adapters/websocket/server/transport.d.ts +112 -0
  114. package/dist/adapters/websocket/server/transport.d.ts.map +1 -0
  115. package/dist/adapters/websocket/server/transport.js +619 -0
  116. package/dist/adapters/websocket/server/transport.js.map +1 -0
  117. package/dist/adapters/websocket/server/types.d.ts +140 -0
  118. package/dist/adapters/websocket/server/types.d.ts.map +1 -0
  119. package/dist/adapters/websocket/server/types.js +7 -0
  120. package/dist/adapters/websocket/server/types.js.map +1 -0
  121. package/dist/browser.d.ts +48 -0
  122. package/dist/browser.d.ts.map +1 -0
  123. package/dist/browser.js +86 -0
  124. package/dist/browser.js.map +1 -0
  125. package/dist/client/batch-executor.d.ts +160 -0
  126. package/dist/client/batch-executor.d.ts.map +1 -0
  127. package/dist/client/batch-executor.js +397 -0
  128. package/dist/client/batch-executor.js.map +1 -0
  129. package/dist/client/call-types.d.ts +271 -0
  130. package/dist/client/call-types.d.ts.map +1 -0
  131. package/dist/client/call-types.js +208 -0
  132. package/dist/client/call-types.js.map +1 -0
  133. package/dist/client/client.d.ts +517 -0
  134. package/dist/client/client.d.ts.map +1 -0
  135. package/dist/client/client.js +990 -0
  136. package/dist/client/client.js.map +1 -0
  137. package/dist/client/consumption.d.ts +191 -0
  138. package/dist/client/consumption.d.ts.map +1 -0
  139. package/dist/client/consumption.js +98 -0
  140. package/dist/client/consumption.js.map +1 -0
  141. package/dist/client/context.d.ts +116 -0
  142. package/dist/client/context.d.ts.map +1 -0
  143. package/dist/client/context.js +111 -0
  144. package/dist/client/context.js.map +1 -0
  145. package/dist/client/errors/codes.d.ts +71 -0
  146. package/dist/client/errors/codes.d.ts.map +1 -0
  147. package/dist/client/errors/codes.js +81 -0
  148. package/dist/client/errors/codes.js.map +1 -0
  149. package/dist/client/errors/factory.d.ts +102 -0
  150. package/dist/client/errors/factory.d.ts.map +1 -0
  151. package/dist/client/errors/factory.js +210 -0
  152. package/dist/client/errors/factory.js.map +1 -0
  153. package/dist/client/errors/http-errors.d.ts +47 -0
  154. package/dist/client/errors/http-errors.d.ts.map +1 -0
  155. package/dist/client/errors/http-errors.js +548 -0
  156. package/dist/client/errors/http-errors.js.map +1 -0
  157. package/dist/client/errors/http-status.d.ts +73 -0
  158. package/dist/client/errors/http-status.d.ts.map +1 -0
  159. package/dist/client/errors/http-status.js +79 -0
  160. package/dist/client/errors/http-status.js.map +1 -0
  161. package/dist/client/errors/index.d.ts +36 -0
  162. package/dist/client/errors/index.d.ts.map +1 -0
  163. package/dist/client/errors/index.js +40 -0
  164. package/dist/client/errors/index.js.map +1 -0
  165. package/dist/client/errors/registry.d.ts +38 -0
  166. package/dist/client/errors/registry.d.ts.map +1 -0
  167. package/dist/client/errors/registry.js +535 -0
  168. package/dist/client/errors/registry.js.map +1 -0
  169. package/dist/client/errors/types.d.ts +112 -0
  170. package/dist/client/errors/types.d.ts.map +1 -0
  171. package/dist/client/errors/types.js +45 -0
  172. package/dist/client/errors/types.js.map +1 -0
  173. package/dist/client/index.d.ts +44 -0
  174. package/dist/client/index.d.ts.map +1 -0
  175. package/dist/client/index.js +36 -0
  176. package/dist/client/index.js.map +1 -0
  177. package/dist/client/middleware/auth.d.ts +90 -0
  178. package/dist/client/middleware/auth.d.ts.map +1 -0
  179. package/dist/client/middleware/auth.js +98 -0
  180. package/dist/client/middleware/auth.js.map +1 -0
  181. package/dist/client/middleware/batching.d.ts +102 -0
  182. package/dist/client/middleware/batching.d.ts.map +1 -0
  183. package/dist/client/middleware/batching.js +245 -0
  184. package/dist/client/middleware/batching.js.map +1 -0
  185. package/dist/client/middleware/cache.d.ts +124 -0
  186. package/dist/client/middleware/cache.d.ts.map +1 -0
  187. package/dist/client/middleware/cache.js +208 -0
  188. package/dist/client/middleware/cache.js.map +1 -0
  189. package/dist/client/middleware/circuit-breaker.d.ts +113 -0
  190. package/dist/client/middleware/circuit-breaker.d.ts.map +1 -0
  191. package/dist/client/middleware/circuit-breaker.js +236 -0
  192. package/dist/client/middleware/circuit-breaker.js.map +1 -0
  193. package/dist/client/middleware/contexts.d.ts +199 -0
  194. package/dist/client/middleware/contexts.d.ts.map +1 -0
  195. package/dist/client/middleware/contexts.js +74 -0
  196. package/dist/client/middleware/contexts.js.map +1 -0
  197. package/dist/client/middleware/items.d.ts +37 -0
  198. package/dist/client/middleware/items.d.ts.map +1 -0
  199. package/dist/client/middleware/items.js +100 -0
  200. package/dist/client/middleware/items.js.map +1 -0
  201. package/dist/client/middleware/lru.d.ts +32 -0
  202. package/dist/client/middleware/lru.d.ts.map +1 -0
  203. package/dist/client/middleware/lru.js +62 -0
  204. package/dist/client/middleware/lru.js.map +1 -0
  205. package/dist/client/middleware/pagination.d.ts +114 -0
  206. package/dist/client/middleware/pagination.d.ts.map +1 -0
  207. package/dist/client/middleware/pagination.js +148 -0
  208. package/dist/client/middleware/pagination.js.map +1 -0
  209. package/dist/client/middleware/rate-limit.d.ts +105 -0
  210. package/dist/client/middleware/rate-limit.d.ts.map +1 -0
  211. package/dist/client/middleware/rate-limit.js +222 -0
  212. package/dist/client/middleware/rate-limit.js.map +1 -0
  213. package/dist/client/middleware/retry.d.ts +100 -0
  214. package/dist/client/middleware/retry.d.ts.map +1 -0
  215. package/dist/client/middleware/retry.js +150 -0
  216. package/dist/client/middleware/retry.js.map +1 -0
  217. package/dist/client/middleware/timeout.d.ts +91 -0
  218. package/dist/client/middleware/timeout.d.ts.map +1 -0
  219. package/dist/client/middleware/timeout.js +253 -0
  220. package/dist/client/middleware/timeout.js.map +1 -0
  221. package/dist/client/middleware/tracing.d.ts +118 -0
  222. package/dist/client/middleware/tracing.d.ts.map +1 -0
  223. package/dist/client/middleware/tracing.js +152 -0
  224. package/dist/client/middleware/tracing.js.map +1 -0
  225. package/dist/client/route-resolver.d.ts +181 -0
  226. package/dist/client/route-resolver.d.ts.map +1 -0
  227. package/dist/client/route-resolver.js +300 -0
  228. package/dist/client/route-resolver.js.map +1 -0
  229. package/dist/client/typed-method.d.ts +29 -0
  230. package/dist/client/typed-method.d.ts.map +1 -0
  231. package/dist/client/typed-method.js +36 -0
  232. package/dist/client/typed-method.js.map +1 -0
  233. package/dist/client/typed.d.ts +102 -0
  234. package/dist/client/typed.d.ts.map +1 -0
  235. package/dist/client/typed.js +52 -0
  236. package/dist/client/typed.js.map +1 -0
  237. package/dist/client/types.d.ts +296 -0
  238. package/dist/client/types.d.ts.map +1 -0
  239. package/dist/client/types.js +26 -0
  240. package/dist/client/types.js.map +1 -0
  241. package/dist/client/validation/index.d.ts +34 -0
  242. package/dist/client/validation/index.d.ts.map +1 -0
  243. package/dist/client/validation/index.js +36 -0
  244. package/dist/client/validation/index.js.map +1 -0
  245. package/dist/client/validation/middleware.d.ts +82 -0
  246. package/dist/client/validation/middleware.d.ts.map +1 -0
  247. package/dist/client/validation/middleware.js +138 -0
  248. package/dist/client/validation/middleware.js.map +1 -0
  249. package/dist/client/validation/types.d.ts +118 -0
  250. package/dist/client/validation/types.d.ts.map +1 -0
  251. package/dist/client/validation/types.js +59 -0
  252. package/dist/client/validation/types.js.map +1 -0
  253. package/dist/collections/async/async-queue.d.ts +144 -0
  254. package/dist/collections/async/async-queue.d.ts.map +1 -0
  255. package/dist/collections/async/async-queue.js +347 -0
  256. package/dist/collections/async/async-queue.js.map +1 -0
  257. package/dist/collections/async/channels.d.ts +188 -0
  258. package/dist/collections/async/channels.d.ts.map +1 -0
  259. package/dist/collections/async/channels.js +312 -0
  260. package/dist/collections/async/channels.js.map +1 -0
  261. package/dist/collections/behaviors/bounded.d.ts +79 -0
  262. package/dist/collections/behaviors/bounded.d.ts.map +1 -0
  263. package/dist/collections/behaviors/bounded.js +384 -0
  264. package/dist/collections/behaviors/bounded.js.map +1 -0
  265. package/dist/collections/behaviors/evented.d.ts +154 -0
  266. package/dist/collections/behaviors/evented.d.ts.map +1 -0
  267. package/dist/collections/behaviors/evented.js +299 -0
  268. package/dist/collections/behaviors/evented.js.map +1 -0
  269. package/dist/collections/behaviors/lru.d.ts +84 -0
  270. package/dist/collections/behaviors/lru.d.ts.map +1 -0
  271. package/dist/collections/behaviors/lru.js +330 -0
  272. package/dist/collections/behaviors/lru.js.map +1 -0
  273. package/dist/collections/behaviors/readonly.d.ts +73 -0
  274. package/dist/collections/behaviors/readonly.d.ts.map +1 -0
  275. package/dist/collections/behaviors/readonly.js +158 -0
  276. package/dist/collections/behaviors/readonly.js.map +1 -0
  277. package/dist/collections/behaviors/safe.d.ts +163 -0
  278. package/dist/collections/behaviors/safe.d.ts.map +1 -0
  279. package/dist/collections/behaviors/safe.js +172 -0
  280. package/dist/collections/behaviors/safe.js.map +1 -0
  281. package/dist/collections/behaviors/synchronized.d.ts +88 -0
  282. package/dist/collections/behaviors/synchronized.d.ts.map +1 -0
  283. package/dist/collections/behaviors/synchronized.js +294 -0
  284. package/dist/collections/behaviors/synchronized.js.map +1 -0
  285. package/dist/collections/behaviors/ttl.d.ts +118 -0
  286. package/dist/collections/behaviors/ttl.d.ts.map +1 -0
  287. package/dist/collections/behaviors/ttl.js +338 -0
  288. package/dist/collections/behaviors/ttl.js.map +1 -0
  289. package/dist/collections/core/effects.d.ts +176 -0
  290. package/dist/collections/core/effects.d.ts.map +1 -0
  291. package/dist/collections/core/effects.js +180 -0
  292. package/dist/collections/core/effects.js.map +1 -0
  293. package/dist/collections/core/events.d.ts +192 -0
  294. package/dist/collections/core/events.d.ts.map +1 -0
  295. package/dist/collections/core/events.js +291 -0
  296. package/dist/collections/core/events.js.map +1 -0
  297. package/dist/collections/core/middleware.d.ts +231 -0
  298. package/dist/collections/core/middleware.d.ts.map +1 -0
  299. package/dist/collections/core/middleware.js +161 -0
  300. package/dist/collections/core/middleware.js.map +1 -0
  301. package/dist/collections/core/policies.d.ts +220 -0
  302. package/dist/collections/core/policies.d.ts.map +1 -0
  303. package/dist/collections/core/policies.js +48 -0
  304. package/dist/collections/core/policies.js.map +1 -0
  305. package/dist/collections/core/traits.d.ts +142 -0
  306. package/dist/collections/core/traits.d.ts.map +1 -0
  307. package/dist/collections/core/traits.js +8 -0
  308. package/dist/collections/core/traits.js.map +1 -0
  309. package/dist/collections/examples.d.ts +13 -0
  310. package/dist/collections/examples.d.ts.map +1 -0
  311. package/dist/collections/examples.js +302 -0
  312. package/dist/collections/examples.js.map +1 -0
  313. package/dist/collections/fx/collectors.d.ts +190 -0
  314. package/dist/collections/fx/collectors.d.ts.map +1 -0
  315. package/dist/collections/fx/collectors.js +369 -0
  316. package/dist/collections/fx/collectors.js.map +1 -0
  317. package/dist/collections/fx/iter.d.ts +166 -0
  318. package/dist/collections/fx/iter.d.ts.map +1 -0
  319. package/dist/collections/fx/iter.js +421 -0
  320. package/dist/collections/fx/iter.js.map +1 -0
  321. package/dist/collections/impl/array-deque.d.ts +107 -0
  322. package/dist/collections/impl/array-deque.d.ts.map +1 -0
  323. package/dist/collections/impl/array-deque.js +381 -0
  324. package/dist/collections/impl/array-deque.js.map +1 -0
  325. package/dist/collections/impl/array-list.d.ts +101 -0
  326. package/dist/collections/impl/array-list.d.ts.map +1 -0
  327. package/dist/collections/impl/array-list.js +387 -0
  328. package/dist/collections/impl/array-list.js.map +1 -0
  329. package/dist/collections/impl/hash-map.d.ts +141 -0
  330. package/dist/collections/impl/hash-map.d.ts.map +1 -0
  331. package/dist/collections/impl/hash-map.js +450 -0
  332. package/dist/collections/impl/hash-map.js.map +1 -0
  333. package/dist/collections/impl/hash-set.d.ts +125 -0
  334. package/dist/collections/impl/hash-set.d.ts.map +1 -0
  335. package/dist/collections/impl/hash-set.js +264 -0
  336. package/dist/collections/impl/hash-set.js.map +1 -0
  337. package/dist/collections/impl/linked-hash-map.d.ts +141 -0
  338. package/dist/collections/impl/linked-hash-map.d.ts.map +1 -0
  339. package/dist/collections/impl/linked-hash-map.js +472 -0
  340. package/dist/collections/impl/linked-hash-map.js.map +1 -0
  341. package/dist/collections/impl/linked-list.d.ts +109 -0
  342. package/dist/collections/impl/linked-list.d.ts.map +1 -0
  343. package/dist/collections/impl/linked-list.js +491 -0
  344. package/dist/collections/impl/linked-list.js.map +1 -0
  345. package/dist/collections/impl/priority-queue.d.ts +134 -0
  346. package/dist/collections/impl/priority-queue.d.ts.map +1 -0
  347. package/dist/collections/impl/priority-queue.js +336 -0
  348. package/dist/collections/impl/priority-queue.js.map +1 -0
  349. package/dist/collections/impl/tree-map.d.ts +146 -0
  350. package/dist/collections/impl/tree-map.d.ts.map +1 -0
  351. package/dist/collections/impl/tree-map.js +781 -0
  352. package/dist/collections/impl/tree-map.js.map +1 -0
  353. package/dist/collections/impl/tree-set.d.ts +112 -0
  354. package/dist/collections/impl/tree-set.d.ts.map +1 -0
  355. package/dist/collections/impl/tree-set.js +374 -0
  356. package/dist/collections/impl/tree-set.js.map +1 -0
  357. package/dist/collections/index.d.ts +105 -0
  358. package/dist/collections/index.d.ts.map +1 -0
  359. package/dist/collections/index.js +135 -0
  360. package/dist/collections/index.js.map +1 -0
  361. package/dist/collections/interfaces/collection.d.ts +119 -0
  362. package/dist/collections/interfaces/collection.d.ts.map +1 -0
  363. package/dist/collections/interfaces/collection.js +8 -0
  364. package/dist/collections/interfaces/collection.js.map +1 -0
  365. package/dist/collections/interfaces/list.d.ts +247 -0
  366. package/dist/collections/interfaces/list.d.ts.map +1 -0
  367. package/dist/collections/interfaces/list.js +8 -0
  368. package/dist/collections/interfaces/list.js.map +1 -0
  369. package/dist/collections/interfaces/map.d.ts +344 -0
  370. package/dist/collections/interfaces/map.d.ts.map +1 -0
  371. package/dist/collections/interfaces/map.js +8 -0
  372. package/dist/collections/interfaces/map.js.map +1 -0
  373. package/dist/collections/interfaces/queue.d.ts +304 -0
  374. package/dist/collections/interfaces/queue.d.ts.map +1 -0
  375. package/dist/collections/interfaces/queue.js +8 -0
  376. package/dist/collections/interfaces/queue.js.map +1 -0
  377. package/dist/collections/interfaces/set.d.ts +137 -0
  378. package/dist/collections/interfaces/set.d.ts.map +1 -0
  379. package/dist/collections/interfaces/set.js +8 -0
  380. package/dist/collections/interfaces/set.js.map +1 -0
  381. package/dist/collections/storage/api.d.ts +109 -0
  382. package/dist/collections/storage/api.d.ts.map +1 -0
  383. package/dist/collections/storage/api.js +182 -0
  384. package/dist/collections/storage/api.js.map +1 -0
  385. package/dist/collections/storage/hybrid.d.ts +164 -0
  386. package/dist/collections/storage/hybrid.d.ts.map +1 -0
  387. package/dist/collections/storage/hybrid.js +416 -0
  388. package/dist/collections/storage/hybrid.js.map +1 -0
  389. package/dist/collections/storage/index.d.ts +16 -0
  390. package/dist/collections/storage/index.d.ts.map +1 -0
  391. package/dist/collections/storage/index.js +13 -0
  392. package/dist/collections/storage/index.js.map +1 -0
  393. package/dist/collections/storage/interface.d.ts +141 -0
  394. package/dist/collections/storage/interface.d.ts.map +1 -0
  395. package/dist/collections/storage/interface.js +23 -0
  396. package/dist/collections/storage/interface.js.map +1 -0
  397. package/dist/collections/storage/memory.d.ts +68 -0
  398. package/dist/collections/storage/memory.d.ts.map +1 -0
  399. package/dist/collections/storage/memory.js +154 -0
  400. package/dist/collections/storage/memory.js.map +1 -0
  401. package/dist/collections/utils/defaults.d.ts +135 -0
  402. package/dist/collections/utils/defaults.d.ts.map +1 -0
  403. package/dist/collections/utils/defaults.js +322 -0
  404. package/dist/collections/utils/defaults.js.map +1 -0
  405. package/dist/collections/utils/factories.d.ts +144 -0
  406. package/dist/collections/utils/factories.d.ts.map +1 -0
  407. package/dist/collections/utils/factories.js +293 -0
  408. package/dist/collections/utils/factories.js.map +1 -0
  409. package/dist/collections/utils/helpers.d.ts +137 -0
  410. package/dist/collections/utils/helpers.d.ts.map +1 -0
  411. package/dist/collections/utils/helpers.js +221 -0
  412. package/dist/collections/utils/helpers.js.map +1 -0
  413. package/dist/collections.d.ts +12 -0
  414. package/dist/collections.d.ts.map +1 -0
  415. package/dist/collections.js +10 -0
  416. package/dist/collections.js.map +1 -0
  417. package/dist/components/define.d.ts +134 -0
  418. package/dist/components/define.d.ts.map +1 -0
  419. package/dist/components/define.js +486 -0
  420. package/dist/components/define.js.map +1 -0
  421. package/dist/components/index.d.ts +39 -0
  422. package/dist/components/index.d.ts.map +1 -0
  423. package/dist/components/index.js +38 -0
  424. package/dist/components/index.js.map +1 -0
  425. package/dist/components/types.d.ts +264 -0
  426. package/dist/components/types.d.ts.map +1 -0
  427. package/dist/components/types.js +46 -0
  428. package/dist/components/types.js.map +1 -0
  429. package/dist/events/bus.d.ts +193 -0
  430. package/dist/events/bus.d.ts.map +1 -0
  431. package/dist/events/bus.js +511 -0
  432. package/dist/events/bus.js.map +1 -0
  433. package/dist/events/index.d.ts +34 -0
  434. package/dist/events/index.d.ts.map +1 -0
  435. package/dist/events/index.js +36 -0
  436. package/dist/events/index.js.map +1 -0
  437. package/dist/events/types.d.ts +242 -0
  438. package/dist/events/types.d.ts.map +1 -0
  439. package/dist/events/types.js +8 -0
  440. package/dist/events/types.js.map +1 -0
  441. package/dist/index.d.ts +17 -0
  442. package/dist/index.d.ts.map +1 -0
  443. package/dist/index.js +17 -0
  444. package/dist/index.js.map +1 -0
  445. package/dist/middleware/compose.d.ts +88 -0
  446. package/dist/middleware/compose.d.ts.map +1 -0
  447. package/dist/middleware/compose.js +108 -0
  448. package/dist/middleware/compose.js.map +1 -0
  449. package/dist/middleware/index.d.ts +12 -0
  450. package/dist/middleware/index.d.ts.map +1 -0
  451. package/dist/middleware/index.js +11 -0
  452. package/dist/middleware/index.js.map +1 -0
  453. package/dist/middleware/types.d.ts +112 -0
  454. package/dist/middleware/types.d.ts.map +1 -0
  455. package/dist/middleware/types.js +14 -0
  456. package/dist/middleware/types.js.map +1 -0
  457. package/dist/procedures/cli/announce.d.ts +67 -0
  458. package/dist/procedures/cli/announce.d.ts.map +1 -0
  459. package/dist/procedures/cli/announce.js +392 -0
  460. package/dist/procedures/cli/announce.js.map +1 -0
  461. package/dist/procedures/cli/discover.d.ts +66 -0
  462. package/dist/procedures/cli/discover.d.ts.map +1 -0
  463. package/dist/procedures/cli/discover.js +310 -0
  464. package/dist/procedures/cli/discover.js.map +1 -0
  465. package/dist/procedures/cli/index.d.ts +13 -0
  466. package/dist/procedures/cli/index.d.ts.map +1 -0
  467. package/dist/procedures/cli/index.js +201 -0
  468. package/dist/procedures/cli/index.js.map +1 -0
  469. package/dist/procedures/cli/init.d.ts +17 -0
  470. package/dist/procedures/cli/init.d.ts.map +1 -0
  471. package/dist/procedures/cli/init.js +336 -0
  472. package/dist/procedures/cli/init.js.map +1 -0
  473. package/dist/procedures/collection/index.d.ts +10 -0
  474. package/dist/procedures/collection/index.d.ts.map +1 -0
  475. package/dist/procedures/collection/index.js +10 -0
  476. package/dist/procedures/collection/index.js.map +1 -0
  477. package/dist/procedures/collection/procedures.d.ts +21 -0
  478. package/dist/procedures/collection/procedures.d.ts.map +1 -0
  479. package/dist/procedures/collection/procedures.js +198 -0
  480. package/dist/procedures/collection/procedures.js.map +1 -0
  481. package/dist/procedures/collection/schemas.d.ts +131 -0
  482. package/dist/procedures/collection/schemas.d.ts.map +1 -0
  483. package/dist/procedures/collection/schemas.js +422 -0
  484. package/dist/procedures/collection/schemas.js.map +1 -0
  485. package/dist/procedures/collection/storage.d.ts +53 -0
  486. package/dist/procedures/collection/storage.d.ts.map +1 -0
  487. package/dist/procedures/collection/storage.js +2 -0
  488. package/dist/procedures/collection/storage.js.map +1 -0
  489. package/dist/procedures/core/array.d.ts +276 -0
  490. package/dist/procedures/core/array.d.ts.map +1 -0
  491. package/dist/procedures/core/array.js +637 -0
  492. package/dist/procedures/core/array.js.map +1 -0
  493. package/dist/procedures/core/comparison.d.ts +85 -0
  494. package/dist/procedures/core/comparison.d.ts.map +1 -0
  495. package/dist/procedures/core/comparison.js +156 -0
  496. package/dist/procedures/core/comparison.js.map +1 -0
  497. package/dist/procedures/core/index.d.ts +261 -0
  498. package/dist/procedures/core/index.d.ts.map +1 -0
  499. package/dist/procedures/core/index.js +585 -0
  500. package/dist/procedures/core/index.js.map +1 -0
  501. package/dist/procedures/core/logic.d.ts +144 -0
  502. package/dist/procedures/core/logic.d.ts.map +1 -0
  503. package/dist/procedures/core/logic.js +169 -0
  504. package/dist/procedures/core/logic.js.map +1 -0
  505. package/dist/procedures/core/math.d.ts +139 -0
  506. package/dist/procedures/core/math.d.ts.map +1 -0
  507. package/dist/procedures/core/math.js +273 -0
  508. package/dist/procedures/core/math.js.map +1 -0
  509. package/dist/procedures/core/meta.d.ts +111 -0
  510. package/dist/procedures/core/meta.d.ts.map +1 -0
  511. package/dist/procedures/core/meta.js +239 -0
  512. package/dist/procedures/core/meta.js.map +1 -0
  513. package/dist/procedures/core/object.d.ts +109 -0
  514. package/dist/procedures/core/object.d.ts.map +1 -0
  515. package/dist/procedures/core/object.js +270 -0
  516. package/dist/procedures/core/object.js.map +1 -0
  517. package/dist/procedures/core/operands.d.ts +51 -0
  518. package/dist/procedures/core/operands.d.ts.map +1 -0
  519. package/dist/procedures/core/operands.js +90 -0
  520. package/dist/procedures/core/operands.js.map +1 -0
  521. package/dist/procedures/core/outputs.d.ts +28 -0
  522. package/dist/procedures/core/outputs.d.ts.map +1 -0
  523. package/dist/procedures/core/outputs.js +42 -0
  524. package/dist/procedures/core/outputs.js.map +1 -0
  525. package/dist/procedures/core/results.d.ts +202 -0
  526. package/dist/procedures/core/results.d.ts.map +1 -0
  527. package/dist/procedures/core/results.js +106 -0
  528. package/dist/procedures/core/results.js.map +1 -0
  529. package/dist/procedures/core/schemas.d.ts +48 -0
  530. package/dist/procedures/core/schemas.d.ts.map +1 -0
  531. package/dist/procedures/core/schemas.js +102 -0
  532. package/dist/procedures/core/schemas.js.map +1 -0
  533. package/dist/procedures/core/string.d.ts +138 -0
  534. package/dist/procedures/core/string.d.ts.map +1 -0
  535. package/dist/procedures/core/string.js +268 -0
  536. package/dist/procedures/core/string.js.map +1 -0
  537. package/dist/procedures/core/type.d.ts +101 -0
  538. package/dist/procedures/core/type.d.ts.map +1 -0
  539. package/dist/procedures/core/type.js +208 -0
  540. package/dist/procedures/core/type.js.map +1 -0
  541. package/dist/procedures/define-procedure.d.ts +187 -0
  542. package/dist/procedures/define-procedure.d.ts.map +1 -0
  543. package/dist/procedures/define-procedure.js +356 -0
  544. package/dist/procedures/define-procedure.js.map +1 -0
  545. package/dist/procedures/define.d.ts +228 -0
  546. package/dist/procedures/define.d.ts.map +1 -0
  547. package/dist/procedures/define.js +300 -0
  548. package/dist/procedures/define.js.map +1 -0
  549. package/dist/procedures/discovery.d.ts +57 -0
  550. package/dist/procedures/discovery.d.ts.map +1 -0
  551. package/dist/procedures/discovery.js +68 -0
  552. package/dist/procedures/discovery.js.map +1 -0
  553. package/dist/procedures/index.d.ts +24 -0
  554. package/dist/procedures/index.d.ts.map +1 -0
  555. package/dist/procedures/index.js +69 -0
  556. package/dist/procedures/index.js.map +1 -0
  557. package/dist/procedures/interceptors.d.ts +82 -0
  558. package/dist/procedures/interceptors.d.ts.map +1 -0
  559. package/dist/procedures/interceptors.js +193 -0
  560. package/dist/procedures/interceptors.js.map +1 -0
  561. package/dist/procedures/invoke.d.ts +127 -0
  562. package/dist/procedures/invoke.d.ts.map +1 -0
  563. package/dist/procedures/invoke.js +277 -0
  564. package/dist/procedures/invoke.js.map +1 -0
  565. package/dist/procedures/module.d.ts +49 -0
  566. package/dist/procedures/module.d.ts.map +1 -0
  567. package/dist/procedures/module.js +93 -0
  568. package/dist/procedures/module.js.map +1 -0
  569. package/dist/procedures/policy.d.ts +70 -0
  570. package/dist/procedures/policy.d.ts.map +1 -0
  571. package/dist/procedures/policy.js +138 -0
  572. package/dist/procedures/policy.js.map +1 -0
  573. package/dist/procedures/ref.d.ts +606 -0
  574. package/dist/procedures/ref.d.ts.map +1 -0
  575. package/dist/procedures/ref.js +895 -0
  576. package/dist/procedures/ref.js.map +1 -0
  577. package/dist/procedures/registry.d.ts +208 -0
  578. package/dist/procedures/registry.d.ts.map +1 -0
  579. package/dist/procedures/registry.js +402 -0
  580. package/dist/procedures/registry.js.map +1 -0
  581. package/dist/procedures/schema.d.ts +126 -0
  582. package/dist/procedures/schema.d.ts.map +1 -0
  583. package/dist/procedures/schema.js +108 -0
  584. package/dist/procedures/schema.js.map +1 -0
  585. package/dist/procedures/storage/adapter.d.ts +148 -0
  586. package/dist/procedures/storage/adapter.d.ts.map +1 -0
  587. package/dist/procedures/storage/adapter.js +214 -0
  588. package/dist/procedures/storage/adapter.js.map +1 -0
  589. package/dist/procedures/storage/api.d.ts +125 -0
  590. package/dist/procedures/storage/api.d.ts.map +1 -0
  591. package/dist/procedures/storage/api.js +220 -0
  592. package/dist/procedures/storage/api.js.map +1 -0
  593. package/dist/procedures/storage/factory.d.ts +134 -0
  594. package/dist/procedures/storage/factory.d.ts.map +1 -0
  595. package/dist/procedures/storage/factory.js +166 -0
  596. package/dist/procedures/storage/factory.js.map +1 -0
  597. package/dist/procedures/storage/hybrid.d.ts +193 -0
  598. package/dist/procedures/storage/hybrid.d.ts.map +1 -0
  599. package/dist/procedures/storage/hybrid.js +519 -0
  600. package/dist/procedures/storage/hybrid.js.map +1 -0
  601. package/dist/procedures/storage/index.d.ts +17 -0
  602. package/dist/procedures/storage/index.d.ts.map +1 -0
  603. package/dist/procedures/storage/index.js +17 -0
  604. package/dist/procedures/storage/index.js.map +1 -0
  605. package/dist/procedures/storage/procedures.d.ts +39 -0
  606. package/dist/procedures/storage/procedures.d.ts.map +1 -0
  607. package/dist/procedures/storage/procedures.js +261 -0
  608. package/dist/procedures/storage/procedures.js.map +1 -0
  609. package/dist/procedures/storage/serialization.d.ts +123 -0
  610. package/dist/procedures/storage/serialization.d.ts.map +1 -0
  611. package/dist/procedures/storage/serialization.js +216 -0
  612. package/dist/procedures/storage/serialization.js.map +1 -0
  613. package/dist/procedures/storage/synced-registry.d.ts +246 -0
  614. package/dist/procedures/storage/synced-registry.d.ts.map +1 -0
  615. package/dist/procedures/storage/synced-registry.js +575 -0
  616. package/dist/procedures/storage/synced-registry.js.map +1 -0
  617. package/dist/procedures/storage/types.d.ts +130 -0
  618. package/dist/procedures/storage/types.d.ts.map +1 -0
  619. package/dist/procedures/storage/types.js +8 -0
  620. package/dist/procedures/storage/types.js.map +1 -0
  621. package/dist/procedures/types.d.ts +370 -0
  622. package/dist/procedures/types.d.ts.map +1 -0
  623. package/dist/procedures/types.js +23 -0
  624. package/dist/procedures/types.js.map +1 -0
  625. package/dist/server/browser-guard.d.ts +69 -0
  626. package/dist/server/browser-guard.d.ts.map +1 -0
  627. package/dist/server/browser-guard.js +103 -0
  628. package/dist/server/browser-guard.js.map +1 -0
  629. package/dist/server/host-policy.d.ts +59 -0
  630. package/dist/server/host-policy.d.ts.map +1 -0
  631. package/dist/server/host-policy.js +82 -0
  632. package/dist/server/host-policy.js.map +1 -0
  633. package/dist/server/index.d.ts +46 -0
  634. package/dist/server/index.d.ts.map +1 -0
  635. package/dist/server/index.js +42 -0
  636. package/dist/server/index.js.map +1 -0
  637. package/dist/server/method.d.ts +24 -0
  638. package/dist/server/method.d.ts.map +1 -0
  639. package/dist/server/method.js +29 -0
  640. package/dist/server/method.js.map +1 -0
  641. package/dist/server/procedure-server.d.ts +212 -0
  642. package/dist/server/procedure-server.d.ts.map +1 -0
  643. package/dist/server/procedure-server.js +323 -0
  644. package/dist/server/procedure-server.js.map +1 -0
  645. package/dist/server/server.d.ts +161 -0
  646. package/dist/server/server.d.ts.map +1 -0
  647. package/dist/server/server.js +279 -0
  648. package/dist/server/server.js.map +1 -0
  649. package/dist/server/types.d.ts +106 -0
  650. package/dist/server/types.d.ts.map +1 -0
  651. package/dist/server/types.js +29 -0
  652. package/dist/server/types.js.map +1 -0
  653. package/package.json +115 -3
  654. package/src/adapters/http/client/index.ts +51 -0
  655. package/src/adapters/http/client/transport.ts +338 -0
  656. package/src/adapters/http/client/types.ts +33 -0
  657. package/src/adapters/http/index.ts +7 -0
  658. package/src/adapters/http/server/index.ts +14 -0
  659. package/src/adapters/http/server/strategies.ts +105 -0
  660. package/src/adapters/http/server/transport.ts +622 -0
  661. package/src/adapters/http/server/types.ts +81 -0
  662. package/src/adapters/http/shared/constants.ts +108 -0
  663. package/src/adapters/http/shared/errors.ts +199 -0
  664. package/src/adapters/http/shared/headers.ts +291 -0
  665. package/src/adapters/http/shared/index.ts +21 -0
  666. package/src/adapters/http/shared/status-codes.ts +212 -0
  667. package/src/adapters/http/shared/strategies.ts +255 -0
  668. package/src/adapters/local/client/index.ts +11 -0
  669. package/src/adapters/local/client/transport.ts +188 -0
  670. package/src/adapters/local/client/types.ts +50 -0
  671. package/src/adapters/metadata.ts +17 -0
  672. package/src/adapters/mock/client/builder.ts +64 -0
  673. package/src/adapters/mock/client/index.ts +19 -0
  674. package/src/adapters/mock/client/transport.ts +352 -0
  675. package/src/adapters/mock/client/types.ts +99 -0
  676. package/src/adapters/websocket/client/index.ts +18 -0
  677. package/src/adapters/websocket/client/transport.ts +733 -0
  678. package/src/adapters/websocket/client/types.ts +235 -0
  679. package/src/adapters/websocket/index.ts +24 -0
  680. package/src/adapters/websocket/server/index.ts +18 -0
  681. package/src/adapters/websocket/server/transport.ts +705 -0
  682. package/src/adapters/websocket/server/types.ts +169 -0
  683. package/src/browser.ts +373 -0
  684. package/src/client/batch-executor.ts +514 -0
  685. package/src/client/call-types.ts +491 -0
  686. package/src/client/client.ts +1202 -0
  687. package/src/client/consumption.ts +288 -0
  688. package/src/client/context.ts +228 -0
  689. package/src/client/errors/README.md +279 -0
  690. package/src/client/errors/codes.ts +88 -0
  691. package/src/client/errors/factory.ts +263 -0
  692. package/src/client/errors/http-errors.ts +601 -0
  693. package/src/client/errors/http-status.ts +82 -0
  694. package/src/client/errors/index.ts +72 -0
  695. package/src/client/errors/registry.ts +595 -0
  696. package/src/client/errors/types.ts +139 -0
  697. package/src/client/index.ts +124 -0
  698. package/src/client/middleware/auth.ts +132 -0
  699. package/src/client/middleware/cache.ts +316 -0
  700. package/src/client/middleware/circuit-breaker.ts +339 -0
  701. package/src/client/middleware/contexts.ts +319 -0
  702. package/src/client/middleware/items.ts +114 -0
  703. package/src/client/middleware/lru.ts +66 -0
  704. package/src/client/middleware/pagination.ts +213 -0
  705. package/src/client/middleware/rate-limit.ts +315 -0
  706. package/src/client/middleware/retry.ts +236 -0
  707. package/src/client/middleware/timeout.ts +308 -0
  708. package/src/client/middleware/tracing.ts +191 -0
  709. package/src/client/route-resolver.ts +407 -0
  710. package/src/client/typed-method.ts +65 -0
  711. package/src/client/typed.ts +140 -0
  712. package/src/client/types.ts +361 -0
  713. package/src/client/validation/index.ts +56 -0
  714. package/src/client/validation/middleware.ts +254 -0
  715. package/src/client/validation/types.ts +162 -0
  716. package/src/events/bus.ts +594 -0
  717. package/src/events/index.ts +67 -0
  718. package/src/events/types.ts +263 -0
  719. package/src/index.ts +33 -0
  720. package/src/middleware/compose.ts +159 -0
  721. package/src/middleware/index.ts +28 -0
  722. package/src/middleware/types.ts +166 -0
  723. package/src/procedures/cli/announce.ts +470 -0
  724. package/src/procedures/cli/discover.ts +390 -0
  725. package/src/procedures/cli/index.ts +229 -0
  726. package/src/procedures/cli/init.ts +370 -0
  727. package/src/procedures/collection/index.ts +51 -0
  728. package/src/procedures/collection/procedures.ts +245 -0
  729. package/src/procedures/collection/schemas.ts +550 -0
  730. package/src/procedures/collection/storage.ts +53 -0
  731. package/src/procedures/core/array.ts +1024 -0
  732. package/src/procedures/core/comparison.ts +263 -0
  733. package/src/procedures/core/index.ts +895 -0
  734. package/src/procedures/core/logic.ts +225 -0
  735. package/src/procedures/core/math.ts +469 -0
  736. package/src/procedures/core/meta.ts +384 -0
  737. package/src/procedures/core/object.ts +427 -0
  738. package/src/procedures/core/operands.ts +119 -0
  739. package/src/procedures/core/outputs.ts +48 -0
  740. package/src/procedures/core/results.ts +296 -0
  741. package/src/procedures/core/schemas.ts +123 -0
  742. package/src/procedures/core/string.ts +458 -0
  743. package/src/procedures/core/type.ts +344 -0
  744. package/src/procedures/define-procedure.ts +531 -0
  745. package/src/procedures/define.ts +387 -0
  746. package/src/procedures/discovery.ts +76 -0
  747. package/src/procedures/index.ts +228 -0
  748. package/src/procedures/interceptors.ts +272 -0
  749. package/src/procedures/invoke.ts +413 -0
  750. package/src/procedures/module.ts +107 -0
  751. package/src/procedures/policy.ts +171 -0
  752. package/src/procedures/ref.ts +1305 -0
  753. package/src/procedures/registry.ts +473 -0
  754. package/src/procedures/schema.ts +225 -0
  755. package/src/procedures/types.ts +485 -0
  756. package/src/server/browser-guard.ts +147 -0
  757. package/src/server/host-policy.ts +121 -0
  758. package/src/server/index.ts +70 -0
  759. package/src/server/method.ts +33 -0
  760. package/src/server/procedure-server.ts +417 -0
  761. package/src/server/server.ts +364 -0
  762. package/src/server/types.ts +147 -0
@@ -0,0 +1,1202 @@
1
+ /**
2
+ * Universal Client
3
+ *
4
+ * Protocol-agnostic RPC client with middleware composition.
5
+ * Works with any transport: HTTP, gRPC, WebSocket, or local.
6
+ *
7
+ * The Client class is generic over its accumulated context type, enabling
8
+ * compile-time validation of middleware chains. Each call to `use()` returns
9
+ * a new type that includes the middleware's provided context.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Type accumulates as middleware is added
14
+ * const client = new Client(transport)
15
+ * .use(createRetryMiddleware()) // Client<BaseContext & RetryContext>
16
+ * .use(createCacheMiddleware({ methods: ["users.get"] })) // Client<... & CacheContext>
17
+ * .use(createAuthMiddleware(...)) // Client<... & AuthContext>
18
+ *
19
+ * // Middleware requiring context validates at compile time
20
+ * client.use(middlewareThatRequiresAuth); // OK if AuthContext is in chain
21
+ *
22
+ * // Context passing via withContext() and per-call options
23
+ * const authedClient = client.withContext({ auth: { token: "user-token" } });
24
+ * await authedClient.call(method, payload, { context: { retry: { maxAttempts: 5 } } });
25
+ * ```
26
+ */
27
+
28
+ import type {
29
+ Transport,
30
+ Method,
31
+ Metadata,
32
+ Message,
33
+ ClientMiddleware,
34
+ ClientContext,
35
+ ClientRunner,
36
+ ClientOptions,
37
+ TypedClientMiddleware,
38
+ } from "./types.js";
39
+ import { ClientError } from "./types.js";
40
+ import { compose } from "../middleware/compose.js";
41
+ import { pathToMethod } from "../server/method.js";
42
+ import type { CallOptions, ClientContextInput } from "./context.js";
43
+ import { mergeContext, normalizeCallOptions } from "./context.js";
44
+ import type { SchemaDefinition, ZodLike } from "./validation/types.js";
45
+ import { methodToKey } from "./validation/types.js";
46
+ import { SCHEMA_REGISTRY, type ZodMiddleware } from "./validation/middleware.js";
47
+ import type {
48
+ Route,
49
+ CallRequest,
50
+ CallResponse,
51
+ StreamingCallResponse,
52
+ ProcedureCallResult,
53
+ } from "./call-types.js";
54
+ import { buildResponse, toMiddlewareContext } from "./call-types.js";
55
+ import { RouteResolver, type ResolvedRoute, type RouteResolutionResult } from "./route-resolver.js";
56
+ import { BatchExecutor, type ExecutionContext } from "./batch-executor.js";
57
+ import type { ProcedureRegistry } from "../procedures/registry.js";
58
+ import type { EventBus } from "../events/types.js";
59
+ import { PROCEDURE_REGISTRY } from "../procedures/registry.js";
60
+ import { validateSchema } from "../procedures/schema.js";
61
+ import type { AnyProcedure, ProcedureClient, ProcedurePath } from "../procedures/types.js";
62
+ import {
63
+ InvocationError,
64
+ invokeProcedure,
65
+ outputItems,
66
+ outputValue,
67
+ type InvokeOptions,
68
+ type Invocation,
69
+ type Interceptor,
70
+ } from "../procedures/invoke.js";
71
+ import { isHandlerConfig, isStreamConfig, type HandlerCallback, type OutputConfig } from "./consumption.js";
72
+ import {
73
+ isAnyProcedureRef,
74
+ isPlainObject,
75
+ normalizeRef,
76
+ prepareRootCall,
77
+ rawInputRule,
78
+ type ProcedureRef,
79
+ type AnyProcedureRef,
80
+ type HydrationEvent,
81
+ } from "../procedures/ref.js";
82
+
83
+ /** Each element of each array item: the stream form of an `outputMode: "batch"` procedure. */
84
+ async function* batchElements(items: AsyncIterable<unknown>): AsyncGenerator<unknown, void, undefined> {
85
+ for await (const item of items) {
86
+ if (Array.isArray(item)) {
87
+ yield* item;
88
+ } else {
89
+ yield item;
90
+ }
91
+ }
92
+ }
93
+
94
+ /**
95
+ * The items of a source, with up to `size` items read ahead of the reader. With size 0, the
96
+ * source runs only when the reader reads (the source itself is returned).
97
+ */
98
+ function readAhead<T>(source: AsyncIterable<T>, size: number): AsyncIterable<T> {
99
+ if (size <= 0) return source;
100
+ return (async function* () {
101
+ const iterator = source[Symbol.asyncIterator]();
102
+ const buffer: Array<Promise<IteratorResult<T>>> = [];
103
+ let ended = false;
104
+ const pull = (): void => {
105
+ while (!ended && buffer.length < size + 1) {
106
+ const next = iterator.next();
107
+ buffer.push(next);
108
+ // The handler marks the end, and keeps a failure from being unhandled until it is read
109
+ next.then(
110
+ (result) => {
111
+ if (result.done) ended = true;
112
+ },
113
+ () => {
114
+ ended = true;
115
+ }
116
+ );
117
+ }
118
+ };
119
+ let finished = false;
120
+ try {
121
+ // Before each read: the item for the reader, and `size` items ahead
122
+ for (pull(); buffer.length > 0; pull()) {
123
+ const result = await buffer.shift()!;
124
+ if (result.done) break;
125
+ yield result.value;
126
+ }
127
+ finished = true;
128
+ } finally {
129
+ if (!finished) await iterator.return?.();
130
+ }
131
+ })();
132
+ }
133
+
134
+ /** The metadata and the signal of a procedure, for the nested calls that it makes. */
135
+ interface CallerContext {
136
+ metadata?: Record<string, unknown> | undefined;
137
+ signal?: AbortSignal | undefined;
138
+ /** The invocation whose handler makes the call: the interceptors link a nested call to it. */
139
+ parent?: Invocation | undefined;
140
+ /** The hydration observer of the program (`exec(ref, input, { onRef })`). */
141
+ onRef?: ((event: HydrationEvent) => void) | undefined;
142
+ }
143
+
144
+ /** The options of `exec()` and `execStream()`. */
145
+ export interface ExecOptions {
146
+ /**
147
+ * This function gets the hydration events of this program only: the refs that hydration runs,
148
+ * also inside control flow and runners, with the call that gets each result. A trace uses it.
149
+ * (`observeHydration()` gets the events of every program in the process.)
150
+ */
151
+ onRef?: ((event: HydrationEvent) => void) | undefined;
152
+ }
153
+
154
+ /**
155
+ * Generate a unique message ID.
156
+ */
157
+ function generateId(): string {
158
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
159
+ }
160
+
161
+ /**
162
+ * Universal Client for protocol-agnostic RPC.
163
+ *
164
+ * Features:
165
+ * - Works with any transport (HTTP, gRPC, WebSocket, local)
166
+ * - Middleware composition (retry, cache, timeout, custom)
167
+ * - Stream-first API (single response = stream with 1 item)
168
+ * - Type-safe request/response handling
169
+ * - **Type-accumulating middleware**: Context types build through `use()` calls
170
+ *
171
+ * @typeParam TContext - Accumulated context type from applied middleware.
172
+ * Starts as `{}` and grows as middleware is added via `use()`.
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * // HTTP client with type-accumulating middleware
177
+ * const client = new Client({ transport: new HttpTransport({ baseUrl: "/api" }) })
178
+ * .use(createRetryMiddleware()) // Client<{} & RetryContext>
179
+ * .use(createCacheMiddleware({ methods: ["users.get"] })) // Client<{} & RetryContext & CacheContext>
180
+ * .use(createAuthMiddleware({ // Client<... & AuthContext>
181
+ * token: "abc123"
182
+ * }));
183
+ *
184
+ * // The client type now carries all middleware context
185
+ * const user = await client.call(
186
+ * { service: "users", operation: "get" },
187
+ * { id: 123 }
188
+ * );
189
+ *
190
+ * // Streaming
191
+ * for await (const event of client.stream(
192
+ * { service: "events", operation: "watch" },
193
+ * { topic: "orders" }
194
+ * )) {
195
+ * console.log(event);
196
+ * }
197
+ * ```
198
+ */
199
+ export class Client<TContext = {}> {
200
+ private readonly transport: Transport;
201
+ private readonly middleware: ClientMiddleware[] = [];
202
+ private readonly defaultMetadata: Metadata;
203
+ private readonly throwOnError: boolean;
204
+ /** The bus of the local procedures. Undefined: the global bus. */
205
+ private bus: EventBus | undefined;
206
+ /** The interceptors of the local invocations (roadmap 1.2) */
207
+ private interceptors: readonly Interceptor[] = [];
208
+
209
+ /**
210
+ * Context values set via withContext().
211
+ * Merged with parent context when creating child clients.
212
+ */
213
+ private readonly clientContext: Partial<TContext>;
214
+
215
+ /**
216
+ * Parent client reference (for context inheritance).
217
+ * When set, middleware and transport are shared, only context differs.
218
+ */
219
+ private readonly parent?: Client<any>;
220
+
221
+ constructor(options: ClientOptions | Transport) {
222
+ // Support both new Client(transport) and new Client({ transport, ... })
223
+ if ("send" in options && typeof options.send === "function") {
224
+ // Direct transport passed - narrow to Transport type
225
+ const transport = options as Transport;
226
+ this.transport = transport;
227
+ this.defaultMetadata = {};
228
+ this.throwOnError = true;
229
+ } else {
230
+ // Options object - narrow to ClientOptions type
231
+ const opts = options as ClientOptions;
232
+ this.transport = opts.transport;
233
+ this.defaultMetadata = opts.defaultMetadata || {};
234
+ this.throwOnError = opts.throwOnError !== false;
235
+ this.bus = opts.bus;
236
+ this.interceptors = opts.interceptors ?? [];
237
+ }
238
+
239
+ // Initialize empty context (child clients override this)
240
+ this.clientContext = {};
241
+ }
242
+
243
+ /**
244
+ * Create a child client from this client (private, for withContext).
245
+ */
246
+ private static createChild<TParentContext, TChildContext extends TParentContext>(
247
+ parent: Client<TParentContext>,
248
+ additionalContext: Partial<TChildContext>,
249
+ ): Client<TChildContext> {
250
+ // Create a child with shared middleware chain
251
+ const child = Object.create(Client.prototype) as Client<TChildContext>;
252
+
253
+ // Share immutable references (no copying)
254
+ (child as any).transport = parent.transport;
255
+ (child as any).middleware = parent.middleware;
256
+ (child as any).defaultMetadata = parent.defaultMetadata;
257
+ (child as any).throwOnError = parent.throwOnError;
258
+ (child as any).bus = parent.bus;
259
+ (child as any).interceptors = parent.interceptors;
260
+
261
+ // Object.create() bypasses class-field initializers, so procedureRegistry (which normally
262
+ // defaults to PROCEDURE_REGISTRY via a field initializer) would be undefined on the child
263
+ // and exec()/route() would throw "Cannot read properties of undefined (reading 'get')".
264
+ // Inherit the parent's registry; leave the lazy resolver/executor undefined so the child
265
+ // builds its own (batchExecutor binds this.executeProcedure, which must be the child's).
266
+ // See documentation/BUGS-2026-07.md (H1).
267
+ (child as any).procedureRegistry = parent.procedureRegistry;
268
+ (child as any).routeResolver = undefined;
269
+ (child as any).batchExecutor = undefined;
270
+
271
+ // Set parent and additional context
272
+ (child as any).parent = parent;
273
+ (child as any).clientContext = additionalContext;
274
+
275
+ return child;
276
+ }
277
+
278
+ /**
279
+ * Create a child client with additional context.
280
+ *
281
+ * Child clients:
282
+ * - Share the middleware chain (cheap to create)
283
+ * - Inherit parent context (merged recursively)
284
+ * - Can override specific context fields
285
+ *
286
+ * Context priority (lowest to highest):
287
+ * 1. Middleware defaults (e.g., maxRetries: 3 from createRetryMiddleware)
288
+ * 2. Parent client context (full inheritance chain)
289
+ * 3. This client's context
290
+ * 4. Per-call context override
291
+ *
292
+ * @param context - Context to set/override on the child client
293
+ * @returns New client with accumulated context
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * // Create authenticated child client
298
+ * const authedClient = client.withContext({
299
+ * auth: { token: "user-token" },
300
+ * timeout: { overall: 5000 }
301
+ * });
302
+ *
303
+ * // Nested children inherit and can override
304
+ * const adminClient = authedClient.withContext({
305
+ * auth: { token: "admin-token" }, // Overrides parent token
306
+ * // timeout inherited from parent
307
+ * });
308
+ * ```
309
+ */
310
+ withContext<TAdditional extends object = {}>(
311
+ context: TAdditional & ClientContextInput<TContext>,
312
+ ): Client<TContext & TAdditional> {
313
+ return Client.createChild(this, context) as Client<TContext & TAdditional>;
314
+ }
315
+
316
+ /**
317
+ * Get effective context by merging entire parent chain.
318
+ *
319
+ * @returns Merged context from all ancestors plus this client
320
+ */
321
+ private getEffectiveContext(): Partial<TContext> {
322
+ if (this.parent) {
323
+ return mergeContext(this.parent.getEffectiveContext(), this.clientContext);
324
+ }
325
+ return this.clientContext;
326
+ }
327
+
328
+ /**
329
+ * Add middleware to the client.
330
+ *
331
+ * Middleware is composed in the order added (onion model):
332
+ * - First added = outermost layer
333
+ * - Last added = innermost layer (closest to transport)
334
+ *
335
+ * **Type Accumulation**: When using `TypedClientMiddleware`, the return type
336
+ * accumulates the middleware's provided context. This enables compile-time
337
+ * validation of middleware chains.
338
+ *
339
+ * @typeParam TProvides - Context type this middleware provides
340
+ * @typeParam TRequires - Context type this middleware requires (must be subset of TContext)
341
+ * @param middleware - Middleware function (typed or untyped)
342
+ * @returns Client with accumulated context type
343
+ *
344
+ * @example
345
+ * ```typescript
346
+ * // Type accumulation example
347
+ * const client = new Client(transport)
348
+ * .use(createTimeoutMiddleware({ overall: 5000 })) // Client<TimeoutContext>
349
+ * .use(createRetryMiddleware()) // Client<TimeoutContext & RetryContext>
350
+ * .use(createCacheMiddleware({ methods: ["users.get"] })); // Client<... & CacheContext>
351
+ *
352
+ * // Middleware ordering (onion model)
353
+ * client
354
+ * .use(timeoutMiddleware()) // Outer: handles timeouts
355
+ * .use(retryMiddleware()) // Middle: handles retries
356
+ * .use(cacheMiddleware()); // Inner: handles caching
357
+ * ```
358
+ */
359
+ use<TProvides = {}, TRequires extends TContext = TContext>(
360
+ middleware: TypedClientMiddleware<TProvides, TRequires> | ClientMiddleware,
361
+ ): Client<TContext & TProvides> {
362
+ this.middleware.push(middleware as ClientMiddleware);
363
+ // Cast is safe because we're just adding type information
364
+ // Runtime behavior is unchanged
365
+ return this as unknown as Client<TContext & TProvides>;
366
+ }
367
+
368
+ /**
369
+ * Make a single RPC call (request/response).
370
+ *
371
+ * The result is the last item of the response stream: the one item of a request/response
372
+ * call, or the final item of a streaming procedure. To read each item, use `stream()`.
373
+ *
374
+ * @param method - Method to invoke
375
+ * @param payload - Request payload
376
+ * @param options - Call options (context override, metadata, signal, schema)
377
+ * OR legacy Metadata object for backward compatibility
378
+ * @returns Response payload
379
+ * @throws {ClientError} if response has error status (when throwOnError=true)
380
+ *
381
+ * @example
382
+ * ```typescript
383
+ * // Simple call
384
+ * const user = await client.call(
385
+ * { service: "users", operation: "get" },
386
+ * { id: 123 }
387
+ * );
388
+ *
389
+ * // With context override
390
+ * const user = await client.call(
391
+ * { service: "users", operation: "get" },
392
+ * { id: 123 },
393
+ * { context: { timeout: { overall: 10000 } } }
394
+ * );
395
+ * ```
396
+ */
397
+ async call<TReq, TRes>(
398
+ method: Method,
399
+ payload: TReq,
400
+ options?: CallOptions<TContext> | Metadata,
401
+ ): Promise<TRes> {
402
+ // The result of a stream is its last item (the "sponge" mode of procedures/types.ts). Every
403
+ // request/response transport yields one item, so its result does not change. (Before, the
404
+ // result was the first item, and a falsy first item - 0, false, "" - threw "No response".)
405
+ let last: { value: TRes } | undefined;
406
+ for await (const item of this.stream<TReq, TRes>(method, payload, options)) {
407
+ last = { value: item };
408
+ }
409
+ if (!last) {
410
+ throw new Error("No response received from stream");
411
+ }
412
+ return last.value;
413
+ }
414
+
415
+ // ===========================================================================
416
+ // Procedure Reference Execution (Procedure-as-Data)
417
+ // ===========================================================================
418
+
419
+ /**
420
+ * Execute a procedure reference with automatic input hydration.
421
+ *
422
+ * This method supports procedure-as-data: procedures can be passed as inputs
423
+ * to other procedures, composed declaratively via JSON, or imperatively via TypeScript.
424
+ *
425
+ * **Input Hydration**: Any ProcedureRef or `$proc` objects in the input tree
426
+ * are automatically executed and replaced with their results before the
427
+ * main procedure runs.
428
+ *
429
+ * @param refOrPath - Procedure reference, JSON procedure ref, or procedure path
430
+ * @param input - Input for the procedure. With a reference, its fields go over the fields of the reference's input.
431
+ * @returns Output of the procedure
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * import { proc } from "@procedures/client";
436
+ *
437
+ * // Using proc() builder
438
+ * const result = await client.exec(
439
+ * proc(["git", "add"]).input({ all: true }).build()
440
+ * );
441
+ *
442
+ * // Using JSON format
443
+ * const result = await client.exec({
444
+ * $proc: ["git", "add"],
445
+ * input: { all: true },
446
+ * });
447
+ *
448
+ * // Using path + input (simple form)
449
+ * const result = await client.exec(["git", "add"], { all: true });
450
+ *
451
+ * // Nested procedure refs (hydrated automatically)
452
+ * const result = await client.exec(
453
+ * proc(["dag", "traverse"]).input({
454
+ * visit: proc(["client", "chain"]).input({
455
+ * steps: [
456
+ * proc(["git", "add"]).input({ all: true }).ref,
457
+ * proc(["git", "commit"]).input({ message: "auto" }).ref,
458
+ * ],
459
+ * }).ref,
460
+ * }).build()
461
+ * );
462
+ * ```
463
+ */
464
+ async exec<TOutput = unknown>(
465
+ refOrPath: AnyProcedureRef | ProcedurePath,
466
+ input?: unknown,
467
+ options: ExecOptions = {}
468
+ ): Promise<TOutput> {
469
+ const caller: CallerContext = options.onRef ? { onRef: options.onRef } : {};
470
+ const { path, input: hydratedInput } = await this.prepareRef(refOrPath, input, caller);
471
+ return this.execInternal<TOutput>(path, hydratedInput, caller);
472
+ }
473
+
474
+ /**
475
+ * Execute a procedure reference and read each output: each item of a streaming procedure, or
476
+ * the one value of another procedure. The input refs run as in `exec()`. Nothing runs until
477
+ * the caller reads the first item.
478
+ *
479
+ * @example
480
+ * ```typescript
481
+ * for await (const line of client.execStream(["logs", "tail"], { file: "app.log" })) {
482
+ * console.log(line);
483
+ * }
484
+ * ```
485
+ */
486
+ execStream<TOutput = unknown>(
487
+ refOrPath: AnyProcedureRef | ProcedurePath,
488
+ input?: unknown,
489
+ options: ExecOptions = {}
490
+ ): AsyncIterable<TOutput> {
491
+ const self = this;
492
+ const caller: CallerContext = options.onRef ? { onRef: options.onRef } : {};
493
+ return (async function* () {
494
+ const { path, input: hydratedInput } = await self.prepareRef(refOrPath, input, caller);
495
+ yield* self.execStreamInternal<TOutput>(path, hydratedInput, caller);
496
+ })();
497
+ }
498
+
499
+ /**
500
+ * The path and the input of a reference, with the refs of the input run (hydrated).
501
+ */
502
+ private async prepareRef(
503
+ refOrPath: AnyProcedureRef | ProcedurePath,
504
+ input: unknown,
505
+ caller: CallerContext = {}
506
+ ): Promise<{ path: ProcedurePath; input: unknown }> {
507
+ // Normalize to ProcedureRef
508
+ let ref: ProcedureRef;
509
+
510
+ if (isAnyProcedureRef(refOrPath)) {
511
+ ref = normalizeRef(refOrPath);
512
+ // The fields of `input` go over the fields of the ref's input (before, `input` was ignored)
513
+ if (input !== undefined) {
514
+ ref = {
515
+ ...ref,
516
+ input: isPlainObject(ref.input) && isPlainObject(input) ? { ...ref.input, ...input } : input,
517
+ };
518
+ }
519
+ } else if (Array.isArray(refOrPath) && refOrPath.every((s) => typeof s === "string")) {
520
+ // Path array provided, use second argument as input
521
+ ref = {
522
+ [Symbol.for("@mark/procedure") as typeof import("../procedures/ref.js").PROCEDURE_SYMBOL]: true,
523
+ path: refOrPath as ProcedurePath,
524
+ input: input ?? {},
525
+ } as ProcedureRef;
526
+ } else {
527
+ throw new Error("exec() requires a ProcedureRef, $proc JSON, or procedure path array");
528
+ }
529
+
530
+ // Create executor function for hydration
531
+ const executor = async <TIn, TOut>(path: ProcedurePath, inp: TIn): Promise<TOut> => {
532
+ return this.execInternal<TOut>(path, inp, caller);
533
+ };
534
+
535
+ // A procedure that takes its input raw (control flow, the `runs-refs` and `raw-input` tags,
536
+ // `procedure.define`) gets its operand refs RAW: it runs them itself, with correct
537
+ // ordering/laziness/error-scoping. Eagerly hydrating here would run the operands up-front
538
+ // and can hijack an all-refs array into an implicit chain that clobbers `steps`. See
539
+ // documentation/BUGS-2026-07.md (C2, H2, H3, M35). The procedure in the registry decides,
540
+ // also for the refs nested in the input (deep dive CORE-5: before, the last path segment did).
541
+ // The body of a defined procedure starts its root call the same way (prepareRootCall, DOC-3)
542
+ return prepareRootCall(ref, executor, { rawInput: rawInputRule(this.procedureRegistry), onRef: caller.onRef });
543
+ }
544
+
545
+ /**
546
+ * The options of a local invocation. The nested calls of the procedure go through this
547
+ * client, so a path without a local handler goes to the transport. The nested calls get the
548
+ * metadata and the signal of the caller: when the caller aborts, its nested work stops. (Before,
549
+ * each nested call started again with no metadata and no signal: deep dive CORE-10.)
550
+ */
551
+ private invokeOptions(caller: CallerContext = {}): InvokeOptions {
552
+ const self = this;
553
+ // The nested calls get the metadata and the signal of the invocation (an interceptor can
554
+ // change them), and name it as their parent
555
+ const client = (invocation: Invocation): ProcedureClient => {
556
+ const nested: CallerContext = {
557
+ metadata: invocation.metadata,
558
+ signal: invocation.signal,
559
+ parent: invocation,
560
+ onRef: caller.onRef,
561
+ };
562
+ return {
563
+ call: <TInput, TOutput>(path: ProcedurePath, input: TInput) => self.execInternal<TOutput>(path, input, nested),
564
+ stream: <TInput, TOutput>(path: ProcedurePath, input: TInput) => self.execStreamInternal<TOutput>(path, input, nested),
565
+ };
566
+ };
567
+ return {
568
+ registry: this.procedureRegistry,
569
+ metadata: caller.metadata ?? {},
570
+ signal: caller.signal,
571
+ client,
572
+ bus: this.bus,
573
+ interceptors: this.interceptors,
574
+ parent: caller.parent,
575
+ onRef: caller.onRef,
576
+ };
577
+ }
578
+
579
+ /** The call options of a remote call for a caller: its metadata as context, and its signal. */
580
+ private remoteCallOptions(caller: CallerContext): CallOptions<TContext> {
581
+ const options: CallOptions<TContext> = { context: (caller.metadata ?? {}) as ClientContextInput<TContext> };
582
+ if (caller.signal) {
583
+ options.signal = caller.signal;
584
+ }
585
+ return options;
586
+ }
587
+
588
+ /**
589
+ * The input for a procedure without a local handler: validated with the local schema when
590
+ * the registry has the procedure, then sent to the transport.
591
+ */
592
+ private async remoteInput(procedure: AnyProcedure | undefined, path: ProcedurePath, input: unknown): Promise<unknown> {
593
+ if (!procedure) return input;
594
+ const result = await validateSchema(procedure.input, input);
595
+ if (!result.ok) {
596
+ throw new InvocationError(
597
+ "VALIDATION_ERROR",
598
+ `Input validation failed for ${path.join(".")}: ${result.message}`,
599
+ path
600
+ );
601
+ }
602
+ return result.value;
603
+ }
604
+
605
+ /**
606
+ * Internal procedure execution (no hydration of the top-level input).
607
+ */
608
+ private async execInternal<TOutput>(
609
+ path: ProcedurePath,
610
+ input: unknown,
611
+ caller: CallerContext = {}
612
+ ): Promise<TOutput> {
613
+ const procedure = this.procedureRegistry.get(path);
614
+ if (procedure?.handler) {
615
+ const options = this.invokeOptions(caller);
616
+ return outputValue(await invokeProcedure<TOutput>(procedure, input, options), path);
617
+ }
618
+ // No local handler: the transport runs it (a remote procedure)
619
+ return this.call(
620
+ this.pathToMethod(path),
621
+ await this.remoteInput(procedure, path, input),
622
+ this.remoteCallOptions(caller)
623
+ ) as Promise<TOutput>;
624
+ }
625
+
626
+ /**
627
+ * Internal streaming execution (no hydration of the top-level input).
628
+ */
629
+ private execStreamInternal<TOutput>(
630
+ path: ProcedurePath,
631
+ input: unknown,
632
+ caller: CallerContext = {}
633
+ ): AsyncIterable<TOutput> {
634
+ const self = this;
635
+ return (async function* () {
636
+ const procedure = self.procedureRegistry.get(path);
637
+ if (procedure?.handler) {
638
+ const options = self.invokeOptions(caller);
639
+ yield* outputItems(await invokeProcedure<TOutput>(procedure, input, options));
640
+ return;
641
+ }
642
+ yield* self.stream<unknown, TOutput>(
643
+ self.pathToMethod(path),
644
+ await self.remoteInput(procedure, path, input),
645
+ self.remoteCallOptions(caller)
646
+ );
647
+ })();
648
+ }
649
+
650
+ /**
651
+ * Make a streaming RPC call.
652
+ *
653
+ * Returns an async iterable that yields response payloads.
654
+ * For single request/response, yields exactly one item.
655
+ *
656
+ * @param method - Method to invoke
657
+ * @param payload - Request payload
658
+ * @param options - Call options (context override, metadata, signal, schema)
659
+ * OR legacy Metadata object for backward compatibility
660
+ * @returns Async iterable of response payloads
661
+ * @throws {ClientError} if any response item has error status (when throwOnError=true)
662
+ *
663
+ * @example
664
+ * ```typescript
665
+ * // Streaming response
666
+ * for await (const event of client.stream(
667
+ * { service: "events", operation: "watch" },
668
+ * { topic: "orders" }
669
+ * )) {
670
+ * console.log(event);
671
+ * }
672
+ *
673
+ * // With context and signal
674
+ * const controller = new AbortController();
675
+ * for await (const event of client.stream(
676
+ * { service: "events", operation: "watch" },
677
+ * { topic: "orders" },
678
+ * { context: { timeout: { overall: 30000 } }, signal: controller.signal }
679
+ * )) {
680
+ * console.log(event);
681
+ * }
682
+ * ```
683
+ */
684
+ async *stream<TReq, TRes>(
685
+ method: Method,
686
+ payload: TReq,
687
+ options?: CallOptions<TContext> | Metadata,
688
+ ): AsyncIterable<TRes> {
689
+ // Normalize options (backward compatible with legacy Metadata parameter)
690
+ const opts = normalizeCallOptions(options);
691
+
692
+ // Merge context: parent chain -> client context -> per-call context
693
+ const effectiveContext = mergeContext(
694
+ this.getEffectiveContext() as object,
695
+ (opts.context ?? {}) as object,
696
+ );
697
+
698
+ // Create message with merged context in metadata
699
+ const message: Message<TReq> = {
700
+ id: generateId(),
701
+ method,
702
+ payload,
703
+ metadata: {
704
+ ...this.defaultMetadata,
705
+ ...effectiveContext, // Context flows into metadata
706
+ ...opts.metadata, // Raw metadata last (highest priority)
707
+ },
708
+ };
709
+
710
+ // Set signal if provided
711
+ if (opts.signal) {
712
+ message.signal = opts.signal;
713
+ }
714
+
715
+ // Store schema override in metadata for Zod middleware
716
+ if (opts.schema) {
717
+ (message.metadata as any).__schema = opts.schema;
718
+ }
719
+
720
+ // Compose middleware chain
721
+ const runner = this.composeMiddleware<TReq, TRes>();
722
+
723
+ // Execute through middleware chain
724
+ const context: ClientContext<TReq> = { message };
725
+ const responseStream = runner(context);
726
+
727
+ // Yield payloads, handling errors
728
+ for await (const item of responseStream) {
729
+ if (item.status.type === "error" && this.throwOnError) {
730
+ throw new ClientError(item.status, item.id);
731
+ }
732
+
733
+ yield item.payload;
734
+ }
735
+ }
736
+
737
+ /**
738
+ * Compose middleware chain using universal middleware composition.
739
+ *
740
+ * @returns Composed runner function
741
+ * @private
742
+ */
743
+ private composeMiddleware<TReq, TRes>(): ClientRunner<TReq, TRes> {
744
+ // Innermost function: call transport
745
+ const self = this;
746
+ const transportRunner: ClientRunner<TReq, TRes> = async function* (context: ClientContext<TReq>) {
747
+ yield* self.transport.send<TReq, TRes>(context.message);
748
+ };
749
+
750
+ // Use universal middleware composition
751
+ // compose(...middleware, finalRunner) applies middleware in order (onion model)
752
+ return compose<false>(...(this.middleware as any[]), transportRunner) as ClientRunner<TReq, TRes>;
753
+ }
754
+
755
+ /**
756
+ * Get transport name.
757
+ */
758
+ get transportName(): string {
759
+ return this.transport.name;
760
+ }
761
+
762
+ /**
763
+ * Close client and cleanup transport resources.
764
+ */
765
+ async close(): Promise<void> {
766
+ await this.transport.close();
767
+ }
768
+
769
+ // ===========================================================================
770
+ // Schema Registration (Zod Validation)
771
+ // ===========================================================================
772
+
773
+ /**
774
+ * Cached reference to Zod middleware for schema registration.
775
+ */
776
+ private zodMiddleware: ZodMiddleware | undefined;
777
+
778
+ /**
779
+ * Register a validation schema for a specific method.
780
+ *
781
+ * Requires `createZodMiddleware()` to be added via `.use()` first.
782
+ * Schemas are used to validate request payloads before sending and
783
+ * response payloads after receiving.
784
+ *
785
+ * @param method - Method to register schema for
786
+ * @param schemas - Input and/or output Zod schemas
787
+ * @returns this (for chaining)
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * import { z } from "zod";
792
+ *
793
+ * const client = new Client({ transport })
794
+ * .use(createZodMiddleware())
795
+ * .schema({ service: "users", operation: "get" }, {
796
+ * input: z.object({ id: z.string() }),
797
+ * output: z.object({ id: z.string(), name: z.string() }),
798
+ * })
799
+ * .schema({ service: "users", operation: "create" }, {
800
+ * input: UserCreateSchema,
801
+ * output: UserSchema,
802
+ * });
803
+ *
804
+ * // Validation happens automatically on call
805
+ * const user = await client.call(
806
+ * { service: "users", operation: "get" },
807
+ * { id: "123" } // Validated against input schema
808
+ * );
809
+ * // Response validated against output schema
810
+ * ```
811
+ */
812
+ schema<TInput extends ZodLike = ZodLike, TOutput extends ZodLike = ZodLike>(
813
+ method: Method,
814
+ schemas: {
815
+ input?: TInput;
816
+ output?: TOutput;
817
+ },
818
+ ): this {
819
+ // Find Zod middleware (lazy lookup, cached)
820
+ if (!this.zodMiddleware) {
821
+ this.zodMiddleware = this.findZodMiddleware();
822
+ }
823
+
824
+ if (!this.zodMiddleware) {
825
+ throw new Error(
826
+ "Cannot register schema: createZodMiddleware() must be added via .use() first",
827
+ );
828
+ }
829
+
830
+ const key = methodToKey(method);
831
+ this.zodMiddleware[SCHEMA_REGISTRY].set(key, schemas as SchemaDefinition);
832
+
833
+ return this;
834
+ }
835
+
836
+ /**
837
+ * Find Zod middleware in the middleware chain.
838
+ */
839
+ private findZodMiddleware(): ZodMiddleware | undefined {
840
+ // Check parent chain first (child clients share middleware)
841
+ if (this.parent) {
842
+ return this.parent.findZodMiddleware();
843
+ }
844
+
845
+ return this.middleware.find(
846
+ (m): m is ZodMiddleware => SCHEMA_REGISTRY in m,
847
+ );
848
+ }
849
+
850
+ // ===========================================================================
851
+ // Nested Route API
852
+ // ===========================================================================
853
+
854
+ /**
855
+ * Procedure registry for route resolution.
856
+ * Uses global registry by default.
857
+ */
858
+ private procedureRegistry: ProcedureRegistry = PROCEDURE_REGISTRY;
859
+
860
+ /**
861
+ * Route resolver instance (lazy initialized).
862
+ */
863
+ private routeResolver: RouteResolver | undefined;
864
+
865
+ /**
866
+ * Batch executor instance (lazy initialized).
867
+ */
868
+ private batchExecutor: BatchExecutor | undefined;
869
+
870
+ /**
871
+ * Set a custom procedure registry for this client.
872
+ *
873
+ * @param registry - Procedure registry to use
874
+ * @returns this (for chaining)
875
+ */
876
+ useRegistry(registry: ProcedureRegistry): this {
877
+ this.procedureRegistry = registry;
878
+ this.routeResolver = undefined; // Reset resolver
879
+ return this;
880
+ }
881
+
882
+ /**
883
+ * Set the event bus of the local procedures of this client (`ctx.bus`).
884
+ *
885
+ * @param bus - Event bus for the procedures
886
+ * @returns this (for chaining)
887
+ */
888
+ useBus(bus: EventBus): this {
889
+ this.bus = bus;
890
+ return this;
891
+ }
892
+
893
+ /**
894
+ * Make a call using the nested route API.
895
+ *
896
+ * This method supports:
897
+ * - Per-call middleware overrides
898
+ * - Batch execution with configurable strategies
899
+ * - Type-safe nested route structures
900
+ *
901
+ * @param request - Call request with route and options
902
+ * @returns Response mirroring the route structure
903
+ *
904
+ * @example
905
+ * ```typescript
906
+ * // Single route call
907
+ * const result = await client.route({
908
+ * route: {
909
+ * collections: {
910
+ * users: {
911
+ * get: { id: "123" }
912
+ * }
913
+ * }
914
+ * }
915
+ * });
916
+ * // result.collections.users.get.data = { id: "123", name: "John" }
917
+ *
918
+ * // Batched call with middleware overrides
919
+ * const results = await client.route({
920
+ * middlewares: {
921
+ * retry: { attempts: 3 },
922
+ * timeout: { ms: 5000 }
923
+ * },
924
+ * batch: { strategy: 'all' },
925
+ * route: {
926
+ * collections: {
927
+ * users: { get: { id: "123" } },
928
+ * orders: { list: { userId: "123" } }
929
+ * },
930
+ * weather: {
931
+ * forecast: { city: "NYC", days: 5 }
932
+ * }
933
+ * }
934
+ * });
935
+ * ```
936
+ */
937
+ async route<TRoute extends Route>(
938
+ request: CallRequest<TRoute>
939
+ ): Promise<CallResponse<TRoute>> {
940
+ const resolver = this.getRouteResolver();
941
+ const executor = this.getBatchExecutor();
942
+
943
+ // Resolve routes to procedures
944
+ const resolution = resolver.resolve(request.route);
945
+
946
+ if (!resolution.success) {
947
+ return buildResponse<TRoute>(this.resolutionFailure(resolution));
948
+ }
949
+
950
+ // Create execution context
951
+ const context = this.createExecutionContext(request);
952
+
953
+ // Execute routes
954
+ const batchConfig = request.batch ?? { strategy: "all" };
955
+ const result = await executor.executeBatch<TRoute>(
956
+ resolution.resolved,
957
+ context,
958
+ batchConfig
959
+ );
960
+
961
+ return result.response;
962
+ }
963
+
964
+ /**
965
+ * Make a streaming call using the nested route API.
966
+ *
967
+ * Returns an async iterator that yields results as they complete,
968
+ * plus a promise for the final complete response.
969
+ *
970
+ * @param request - Call request (batch.strategy should be 'stream')
971
+ * @returns Streaming response with iterator and completion promise
972
+ */
973
+ routeStream<TRoute extends Route>(
974
+ request: CallRequest<TRoute>
975
+ ): StreamingCallResponse<TRoute> {
976
+ const resolver = this.getRouteResolver();
977
+ const executor = this.getBatchExecutor();
978
+
979
+ const resolution = resolver.resolve(request.route);
980
+
981
+ if (!resolution.success) {
982
+ // Return error response immediately
983
+ const errorResults = this.resolutionFailure(resolution);
984
+
985
+ return {
986
+ results: (async function* () {
987
+ for (const [path, result] of errorResults) {
988
+ yield { path, result };
989
+ }
990
+ })(),
991
+ complete: Promise.resolve(buildResponse<TRoute>(errorResults)),
992
+ };
993
+ }
994
+
995
+ const context = this.createExecutionContext(request);
996
+ const streamConfig = request.batch ?? { strategy: "stream" };
997
+
998
+ return executor.getStreamingResponse<TRoute>(
999
+ resolution.resolved,
1000
+ context,
1001
+ streamConfig
1002
+ );
1003
+ }
1004
+
1005
+ /**
1006
+ * The results of a route that did not resolve: an error for each leaf that failed, and
1007
+ * `SKIPPED` for every other leaf, also the leaves after a validation error. (Before, the leaves
1008
+ * after a validation error were missing: deep dive CORE-14.)
1009
+ */
1010
+ private resolutionFailure(resolution: RouteResolutionResult): Array<[ProcedurePath, ProcedureCallResult]> {
1011
+ const skipped = (path: ProcedurePath): ProcedureCallResult => ({
1012
+ success: false,
1013
+ error: { code: "SKIPPED", message: "Skipped due to other route errors", retryable: false, path },
1014
+ });
1015
+ const results: Array<[ProcedurePath, ProcedureCallResult]> = resolution.errors.map((error) => [
1016
+ error.path,
1017
+ {
1018
+ success: false,
1019
+ error: {
1020
+ code: error.type === "not_found" ? "NOT_FOUND" : "VALIDATION_ERROR",
1021
+ message: error.message,
1022
+ retryable: false,
1023
+ path: error.path,
1024
+ },
1025
+ },
1026
+ ]);
1027
+ for (const resolved of resolution.resolved) results.push([resolved.path, skipped(resolved.path)]);
1028
+ for (const path of resolution.skipped) results.push([path, skipped(path)]);
1029
+ return results;
1030
+ }
1031
+
1032
+ /**
1033
+ * Get the route resolver (lazy initialization).
1034
+ */
1035
+ private getRouteResolver(): RouteResolver {
1036
+ if (!this.routeResolver) {
1037
+ this.routeResolver = new RouteResolver(this.procedureRegistry);
1038
+ }
1039
+ return this.routeResolver;
1040
+ }
1041
+
1042
+ /**
1043
+ * Get the batch executor (lazy initialization).
1044
+ */
1045
+ private getBatchExecutor(): BatchExecutor {
1046
+ if (!this.batchExecutor) {
1047
+ this.batchExecutor = new BatchExecutor(this.executeProcedure.bind(this));
1048
+ }
1049
+ return this.batchExecutor;
1050
+ }
1051
+
1052
+ /**
1053
+ * Create execution context from call request.
1054
+ */
1055
+ private createExecutionContext<TRoute extends Route>(
1056
+ request: CallRequest<TRoute>
1057
+ ): ExecutionContext {
1058
+ // Merge context: parent chain -> client context -> middleware overrides. The override keys
1059
+ // become the keys that the middleware reads (deep dive CORE-14). No internal key goes into
1060
+ // the metadata: a handler sees it as ctx.metadata (deep dive CORE-10).
1061
+ const effectiveContext = mergeContext(
1062
+ this.getEffectiveContext() as object,
1063
+ toMiddlewareContext(request.middlewares)
1064
+ );
1065
+
1066
+ const context: ExecutionContext = {
1067
+ metadata: {
1068
+ ...this.defaultMetadata,
1069
+ ...effectiveContext,
1070
+ },
1071
+ };
1072
+
1073
+ // Only set signal if provided (exactOptionalPropertyTypes)
1074
+ if (request.signal) {
1075
+ context.signal = request.signal;
1076
+ }
1077
+
1078
+ return context;
1079
+ }
1080
+
1081
+ /**
1082
+ * Execute a single procedure call.
1083
+ * Used by BatchExecutor.
1084
+ *
1085
+ * The `out` config of the route leaf chooses the result (BUGS-2026-07 H8):
1086
+ * - sponge (the default): the value, or the last item of a stream (or `accumulate` of all items);
1087
+ * - stream: `data` is an AsyncIterable of the items. The procedure starts when the reader reads.
1088
+ * With `bufferSize`, that many items are read ahead of the reader;
1089
+ * - handlers: `progress` gets each item but the last, `complete` gets the last, `error` gets the error.
1090
+ *
1091
+ * A procedure with `outputMode: "batch"` returns an array: sponge gives the array, and stream
1092
+ * gives each element.
1093
+ */
1094
+ private async executeProcedure(
1095
+ resolved: ResolvedRoute,
1096
+ context: ExecutionContext
1097
+ ): Promise<ProcedureCallResult> {
1098
+ const { path, outputConfig } = resolved;
1099
+
1100
+ try {
1101
+ const items = this.routeItems(resolved, context);
1102
+ if (isStreamConfig(outputConfig)) {
1103
+ const elements = resolved.procedure.outputMode === "batch" ? batchElements(items) : items;
1104
+ return { success: true, data: readAhead(elements, outputConfig.bufferSize ?? 0) };
1105
+ }
1106
+ if (isHandlerConfig(outputConfig)) {
1107
+ return { success: true, data: await this.consumeWithHandlers(items, outputConfig, path) };
1108
+ }
1109
+ return { success: true, data: await this.sponge(items, outputConfig, path) };
1110
+ } catch (error) {
1111
+ return {
1112
+ success: false,
1113
+ error: {
1114
+ code: error instanceof ClientError || error instanceof InvocationError ? error.code : "EXECUTION_ERROR",
1115
+ message: error instanceof Error ? error.message : String(error),
1116
+ retryable: error instanceof ClientError ? error.retryable : false,
1117
+ path,
1118
+ },
1119
+ };
1120
+ }
1121
+ }
1122
+
1123
+ /**
1124
+ * The output items of a resolved route: from the local handler, or from the transport.
1125
+ */
1126
+ private routeItems(resolved: ResolvedRoute, context: ExecutionContext): AsyncGenerator<unknown, void, undefined> {
1127
+ const self = this;
1128
+ const { path, procedure, input } = resolved;
1129
+ return (async function* () {
1130
+ if (procedure.handler) {
1131
+ // The resolver validated the input already (not an asynchronous schema: see ResolvedRoute)
1132
+ const options = {
1133
+ ...self.invokeOptions({ metadata: context.metadata, signal: context.signal }),
1134
+ inputValidated: resolved.inputValidated !== false,
1135
+ };
1136
+ yield* outputItems(await invokeProcedure(procedure, input, options));
1137
+ return;
1138
+ }
1139
+ const callOptions: CallOptions<TContext> = { context: context.metadata as ClientContextInput<TContext> };
1140
+ if (context.signal) {
1141
+ callOptions.signal = context.signal;
1142
+ }
1143
+ yield* self.stream(self.pathToMethod(path), input, callOptions);
1144
+ })();
1145
+ }
1146
+
1147
+ /** The sponge mode: the last item, or `accumulate` of all items. */
1148
+ private async sponge(items: AsyncIterable<unknown>, config: OutputConfig, path: ProcedurePath): Promise<unknown> {
1149
+ const accumulate = "type" in config && config.type === "sponge" ? config.accumulate : undefined;
1150
+ const all: unknown[] = [];
1151
+ let last: { value: unknown } | undefined;
1152
+ for await (const item of items) {
1153
+ last = { value: item };
1154
+ if (accumulate) all.push(item);
1155
+ }
1156
+ if (!last) {
1157
+ throw new InvocationError("NO_OUTPUT", `Procedure gave no output: ${path.join(".")}`, path);
1158
+ }
1159
+ return accumulate ? accumulate(all.slice(0, -1), last.value) : last.value;
1160
+ }
1161
+
1162
+ /** The handlers mode: `progress` for each item but the last, then `complete`, or `error`. */
1163
+ private async consumeWithHandlers(
1164
+ items: AsyncIterable<unknown>,
1165
+ config: { progress?: HandlerCallback; complete?: HandlerCallback; error?: HandlerCallback<Error> },
1166
+ path: ProcedurePath
1167
+ ): Promise<unknown> {
1168
+ let previous: { value: unknown } | undefined;
1169
+ try {
1170
+ for await (const item of items) {
1171
+ if (previous) await this.deliver(config.progress, previous.value);
1172
+ previous = { value: item };
1173
+ }
1174
+ } catch (error) {
1175
+ await this.deliver(config.error, error instanceof Error ? error : new Error(String(error)));
1176
+ throw error;
1177
+ }
1178
+ if (!previous) {
1179
+ throw new InvocationError("NO_OUTPUT", `Procedure gave no output: ${path.join(".")}`, path);
1180
+ }
1181
+ await this.deliver(config.complete, previous.value);
1182
+ return previous.value;
1183
+ }
1184
+
1185
+ /** A handler callback gets the data: a function, or a procedure path (the data is its input). */
1186
+ private async deliver<T>(callback: HandlerCallback<T> | undefined, data: T): Promise<void> {
1187
+ if (callback === undefined) return;
1188
+ if (Array.isArray(callback)) {
1189
+ await this.execInternal(callback, data);
1190
+ return;
1191
+ }
1192
+ await callback(data);
1193
+ }
1194
+
1195
+ /**
1196
+ * Convert procedure path to Method object.
1197
+ */
1198
+ private pathToMethod(path: ProcedurePath): Method {
1199
+ // The one mapping of every host (deep dive architecture review 3.3)
1200
+ return pathToMethod(path);
1201
+ }
1202
+ }