@lovrozagar/honey 0.6.5 → 0.7.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 (674) hide show
  1. package/README.md +514 -192
  2. package/bin/honey.js +25 -0
  3. package/dist/accepts.d.ts +7 -1
  4. package/dist/accepts.d.ts.map +1 -1
  5. package/dist/accepts.js +126 -0
  6. package/dist/accepts.js.map +1 -0
  7. package/dist/body-kind.d.ts +26 -0
  8. package/dist/body-kind.d.ts.map +1 -0
  9. package/dist/body-kind.js +70 -0
  10. package/dist/body-kind.js.map +1 -0
  11. package/dist/body-limit.d.ts +5 -1
  12. package/dist/body-limit.d.ts.map +1 -1
  13. package/dist/body-limit.js +126 -0
  14. package/dist/body-limit.js.map +1 -0
  15. package/dist/build/index.d.ts +19 -3
  16. package/dist/build/index.d.ts.map +1 -1
  17. package/dist/build/index.js +173 -0
  18. package/dist/build/index.js.map +1 -0
  19. package/dist/cli-args.d.ts +33 -0
  20. package/dist/cli-args.d.ts.map +1 -0
  21. package/dist/cli-args.js +102 -0
  22. package/dist/cli-args.js.map +1 -0
  23. package/dist/cli-go/auth.go +26 -0
  24. package/dist/cli-go/config.go +192 -0
  25. package/dist/cli-go/errors.go +75 -0
  26. package/dist/cli-go/multipart.go +79 -0
  27. package/dist/cli-go/output.go +163 -0
  28. package/dist/cli-go/root.go +30 -0
  29. package/dist/cli-go/stream.go +88 -0
  30. package/dist/cli-go/version.go +5 -0
  31. package/dist/cli.d.ts +1 -1
  32. package/dist/cli.js +209 -0
  33. package/dist/cli.js.map +1 -0
  34. package/dist/client/defaults.js +48 -0
  35. package/dist/client/defaults.js.map +1 -0
  36. package/dist/client/error.d.ts +35 -0
  37. package/dist/client/error.d.ts.map +1 -1
  38. package/dist/client/error.js +71 -0
  39. package/dist/client/error.js.map +1 -0
  40. package/dist/client/http.d.ts +67 -8
  41. package/dist/client/http.d.ts.map +1 -1
  42. package/dist/client/http.js +571 -0
  43. package/dist/client/http.js.map +1 -0
  44. package/dist/client/index.d.ts +3 -2
  45. package/dist/client/index.d.ts.map +1 -1
  46. package/dist/client/index.js +95 -0
  47. package/dist/client/index.js.map +1 -0
  48. package/dist/client/path.d.ts +26 -0
  49. package/dist/client/path.d.ts.map +1 -0
  50. package/dist/client/path.js +163 -0
  51. package/dist/client/path.js.map +1 -0
  52. package/dist/client/redirect-policy.d.ts +12 -0
  53. package/dist/client/redirect-policy.d.ts.map +1 -0
  54. package/dist/client/redirect-policy.js +20 -0
  55. package/dist/client/redirect-policy.js.map +1 -0
  56. package/dist/client/sdk.d.ts +36 -0
  57. package/dist/client/sdk.d.ts.map +1 -1
  58. package/dist/client/sdk.js +292 -0
  59. package/dist/client/sdk.js.map +1 -0
  60. package/dist/client/sse.d.ts +13 -0
  61. package/dist/client/sse.d.ts.map +1 -1
  62. package/dist/client/sse.js +129 -0
  63. package/dist/client/sse.js.map +1 -0
  64. package/dist/client/types.js +2 -0
  65. package/dist/client/types.js.map +1 -0
  66. package/dist/client/ws.d.ts +9 -2
  67. package/dist/client/ws.d.ts.map +1 -1
  68. package/dist/client/ws.js +112 -0
  69. package/dist/client/ws.js.map +1 -0
  70. package/dist/client-go/errors.go +236 -0
  71. package/dist/client-go/export.go +44 -0
  72. package/dist/client-go/invalidation.go +371 -0
  73. package/dist/client-go/nullable.go +62 -0
  74. package/dist/client-go/realtime.go +354 -0
  75. package/dist/client-go/result.go +20 -0
  76. package/dist/client-go/runtime.go +975 -0
  77. package/dist/client-go/sse.go +159 -0
  78. package/dist/client-go/transport.go +495 -0
  79. package/dist/client-go/ws.go +128 -0
  80. package/dist/client-info.d.ts +36 -0
  81. package/dist/client-info.d.ts.map +1 -0
  82. package/dist/client-info.js +53 -0
  83. package/dist/client-info.js.map +1 -0
  84. package/dist/client-mcp/README.md +10 -0
  85. package/dist/client-mcp/server.ts +221 -0
  86. package/dist/client-mcp/types.ts +19 -0
  87. package/dist/client-python/_errors.py +115 -0
  88. package/dist/client-python/_invalidation.py +494 -0
  89. package/dist/client-python/_realtime.py +179 -0
  90. package/dist/client-python/_runtime.py +860 -0
  91. package/dist/client-python/_sse.py +155 -0
  92. package/dist/client-python/_transport.py +366 -0
  93. package/dist/client-python/_ws.py +159 -0
  94. package/dist/client-python/py.typed +0 -0
  95. package/dist/client-rust/errors.rs +220 -0
  96. package/dist/client-rust/invalidation.rs +412 -0
  97. package/dist/client-rust/invalidation_sync.rs +93 -0
  98. package/dist/client-rust/nullable.rs +17 -0
  99. package/dist/client-rust/realtime.rs +702 -0
  100. package/dist/client-rust/result.rs +22 -0
  101. package/dist/client-rust/runtime.rs +980 -0
  102. package/dist/client-rust/runtime_sync.rs +484 -0
  103. package/dist/client-rust/sse.rs +188 -0
  104. package/dist/client-rust/ws.rs +167 -0
  105. package/dist/codegen-go-cli.d.ts.map +1 -1
  106. package/dist/codegen-go-cli.js +964 -0
  107. package/dist/codegen-go-cli.js.map +1 -0
  108. package/dist/codegen-go.d.ts +15 -3
  109. package/dist/codegen-go.d.ts.map +1 -1
  110. package/dist/codegen-go.js +872 -0
  111. package/dist/codegen-go.js.map +1 -0
  112. package/dist/codegen-hash.js +9 -0
  113. package/dist/codegen-hash.js.map +1 -0
  114. package/dist/codegen-ir.d.ts +69 -2
  115. package/dist/codegen-ir.d.ts.map +1 -1
  116. package/dist/codegen-ir.js +661 -0
  117. package/dist/codegen-ir.js.map +1 -0
  118. package/dist/codegen-lang.d.ts +65 -0
  119. package/dist/codegen-lang.d.ts.map +1 -0
  120. package/dist/codegen-lang.js +526 -0
  121. package/dist/codegen-lang.js.map +1 -0
  122. package/dist/codegen-load.d.ts +31 -0
  123. package/dist/codegen-load.d.ts.map +1 -0
  124. package/dist/codegen-load.js +138 -0
  125. package/dist/codegen-load.js.map +1 -0
  126. package/dist/codegen-loaders.js +55 -0
  127. package/dist/codegen-loaders.js.map +1 -0
  128. package/dist/codegen-mcp.d.ts.map +1 -1
  129. package/dist/codegen-mcp.js +368 -0
  130. package/dist/codegen-mcp.js.map +1 -0
  131. package/dist/codegen-python.d.ts +13 -1
  132. package/dist/codegen-python.d.ts.map +1 -1
  133. package/dist/codegen-python.js +828 -0
  134. package/dist/codegen-python.js.map +1 -0
  135. package/dist/codegen-route-tree-intern.d.ts +15 -5
  136. package/dist/codegen-route-tree-intern.d.ts.map +1 -1
  137. package/dist/codegen-route-tree-intern.js +221 -0
  138. package/dist/codegen-route-tree-intern.js.map +1 -0
  139. package/dist/codegen-rust.d.ts.map +1 -1
  140. package/dist/codegen-rust.js +1293 -0
  141. package/dist/codegen-rust.js.map +1 -0
  142. package/dist/codegen-sanitize.d.ts.map +1 -1
  143. package/dist/codegen-sanitize.js +56 -0
  144. package/dist/codegen-sanitize.js.map +1 -0
  145. package/dist/codegen-schema-naming.d.ts +5 -0
  146. package/dist/codegen-schema-naming.d.ts.map +1 -1
  147. package/dist/codegen-schema-naming.js +150 -0
  148. package/dist/codegen-schema-naming.js.map +1 -0
  149. package/dist/codegen-sdk-model.d.ts +71 -0
  150. package/dist/codegen-sdk-model.d.ts.map +1 -0
  151. package/dist/codegen-sdk-model.js +179 -0
  152. package/dist/codegen-sdk-model.js.map +1 -0
  153. package/dist/codegen.d.ts +41 -23
  154. package/dist/codegen.d.ts.map +1 -1
  155. package/dist/codegen.js +4610 -0
  156. package/dist/codegen.js.map +1 -0
  157. package/dist/context.d.ts +36 -6
  158. package/dist/context.d.ts.map +1 -1
  159. package/dist/context.js +242 -0
  160. package/dist/context.js.map +1 -0
  161. package/dist/cookie-sign.d.ts +16 -2
  162. package/dist/cookie-sign.d.ts.map +1 -1
  163. package/dist/cookie-sign.js +104 -0
  164. package/dist/cookie-sign.js.map +1 -0
  165. package/dist/cookie.d.ts +12 -0
  166. package/dist/cookie.d.ts.map +1 -1
  167. package/dist/cookie.js +138 -0
  168. package/dist/cookie.js.map +1 -0
  169. package/dist/cors.d.ts +1 -0
  170. package/dist/cors.d.ts.map +1 -1
  171. package/dist/cors.js +87 -0
  172. package/dist/cors.js.map +1 -0
  173. package/dist/crypto.d.ts +6 -1
  174. package/dist/crypto.d.ts.map +1 -1
  175. package/dist/crypto.js +38 -0
  176. package/dist/crypto.js.map +1 -0
  177. package/dist/csrf.d.ts +19 -0
  178. package/dist/csrf.d.ts.map +1 -1
  179. package/dist/csrf.js +79 -0
  180. package/dist/csrf.js.map +1 -0
  181. package/dist/curl-logger.d.ts +14 -3
  182. package/dist/curl-logger.d.ts.map +1 -1
  183. package/dist/curl-logger.js +199 -0
  184. package/dist/curl-logger.js.map +1 -0
  185. package/dist/detect-runtime.js +13 -0
  186. package/dist/detect-runtime.js.map +1 -0
  187. package/dist/dict.d.ts +11 -0
  188. package/dist/dict.d.ts.map +1 -0
  189. package/dist/dict.js +13 -0
  190. package/dist/dict.js.map +1 -0
  191. package/dist/error.d.ts.map +1 -1
  192. package/dist/error.js +44 -0
  193. package/dist/error.js.map +1 -0
  194. package/dist/errors.js +39 -0
  195. package/dist/errors.js.map +1 -0
  196. package/dist/etag.d.ts +2 -0
  197. package/dist/etag.d.ts.map +1 -1
  198. package/dist/etag.js +82 -0
  199. package/dist/etag.js.map +1 -0
  200. package/dist/feature-detect.d.ts +25 -0
  201. package/dist/feature-detect.d.ts.map +1 -0
  202. package/dist/feature-detect.js +144 -0
  203. package/dist/feature-detect.js.map +1 -0
  204. package/dist/feature-load.js +36 -0
  205. package/dist/feature-load.js.map +1 -0
  206. package/dist/feature-slots.d.ts +44 -0
  207. package/dist/feature-slots.d.ts.map +1 -0
  208. package/dist/feature-slots.js +48 -0
  209. package/dist/feature-slots.js.map +1 -0
  210. package/dist/fetch-request.d.ts +10 -0
  211. package/dist/fetch-request.d.ts.map +1 -0
  212. package/dist/fetch-request.js +13 -0
  213. package/dist/fetch-request.js.map +1 -0
  214. package/dist/gen-process.d.ts +15 -0
  215. package/dist/gen-process.d.ts.map +1 -0
  216. package/dist/gen-process.js +43 -0
  217. package/dist/gen-process.js.map +1 -0
  218. package/dist/gen-write.d.ts +19 -0
  219. package/dist/gen-write.d.ts.map +1 -0
  220. package/dist/gen-write.js +120 -0
  221. package/dist/gen-write.js.map +1 -0
  222. package/dist/glob.d.ts +21 -0
  223. package/dist/glob.d.ts.map +1 -0
  224. package/dist/glob.js +115 -0
  225. package/dist/glob.js.map +1 -0
  226. package/dist/go-type-emitter.d.ts +18 -4
  227. package/dist/go-type-emitter.d.ts.map +1 -1
  228. package/dist/go-type-emitter.js +594 -0
  229. package/dist/go-type-emitter.js.map +1 -0
  230. package/dist/honey-response.d.ts.map +1 -1
  231. package/dist/honey-response.js +338 -0
  232. package/dist/honey-response.js.map +1 -0
  233. package/dist/i18n-slot.d.ts +8 -0
  234. package/dist/i18n-slot.d.ts.map +1 -1
  235. package/dist/i18n-slot.js +14 -0
  236. package/dist/i18n-slot.js.map +1 -0
  237. package/dist/i18n.d.ts +3 -0
  238. package/dist/i18n.d.ts.map +1 -1
  239. package/dist/i18n.js +250 -0
  240. package/dist/i18n.js.map +1 -0
  241. package/dist/index.d.ts +410 -149
  242. package/dist/index.d.ts.map +1 -1
  243. package/dist/index.js +2324 -0
  244. package/dist/index.js.map +1 -0
  245. package/dist/init.d.ts +3 -5
  246. package/dist/init.d.ts.map +1 -1
  247. package/dist/init.js +140 -0
  248. package/dist/init.js.map +1 -0
  249. package/dist/input.js +4 -0
  250. package/dist/input.js.map +1 -0
  251. package/dist/invalidate-check.d.ts +11 -0
  252. package/dist/invalidate-check.d.ts.map +1 -1
  253. package/dist/invalidate-check.js +163 -0
  254. package/dist/invalidate-check.js.map +1 -0
  255. package/dist/invoke-user.d.ts +35 -0
  256. package/dist/invoke-user.d.ts.map +1 -0
  257. package/dist/invoke-user.js +73 -0
  258. package/dist/invoke-user.js.map +1 -0
  259. package/dist/ip-restrict.d.ts +13 -1
  260. package/dist/ip-restrict.d.ts.map +1 -1
  261. package/dist/ip-restrict.js +60 -0
  262. package/dist/ip-restrict.js.map +1 -0
  263. package/dist/ip.d.ts +39 -0
  264. package/dist/ip.d.ts.map +1 -0
  265. package/dist/ip.js +209 -0
  266. package/dist/ip.js.map +1 -0
  267. package/dist/logger.d.ts.map +1 -1
  268. package/dist/logger.js +113 -0
  269. package/dist/logger.js.map +1 -0
  270. package/dist/media-type.d.ts +30 -0
  271. package/dist/media-type.d.ts.map +1 -0
  272. package/dist/media-type.js +97 -0
  273. package/dist/media-type.js.map +1 -0
  274. package/dist/meta-spec-merge.d.ts +32 -0
  275. package/dist/meta-spec-merge.d.ts.map +1 -0
  276. package/dist/meta-spec-merge.js +68 -0
  277. package/dist/meta-spec-merge.js.map +1 -0
  278. package/dist/meta-spec.d.ts +16 -3
  279. package/dist/meta-spec.d.ts.map +1 -1
  280. package/dist/meta-spec.js +535 -0
  281. package/dist/meta-spec.js.map +1 -0
  282. package/dist/middleware.d.ts +23 -6
  283. package/dist/middleware.d.ts.map +1 -1
  284. package/dist/middleware.js +253 -0
  285. package/dist/middleware.js.map +1 -0
  286. package/dist/node-request.d.ts +57 -12
  287. package/dist/node-request.d.ts.map +1 -1
  288. package/dist/node-request.js +407 -0
  289. package/dist/node-request.js.map +1 -0
  290. package/dist/node.d.ts +20 -3
  291. package/dist/node.d.ts.map +1 -1
  292. package/dist/node.js +396 -0
  293. package/dist/node.js.map +1 -0
  294. package/dist/openapi/collect.d.ts +6 -3
  295. package/dist/openapi/collect.d.ts.map +1 -1
  296. package/dist/openapi/collect.js +30 -0
  297. package/dist/openapi/collect.js.map +1 -0
  298. package/dist/openapi/docs-page.d.ts +42 -0
  299. package/dist/openapi/docs-page.d.ts.map +1 -0
  300. package/dist/openapi/docs-page.js +80 -0
  301. package/dist/openapi/docs-page.js.map +1 -0
  302. package/dist/openapi/document.d.ts +4 -0
  303. package/dist/openapi/document.d.ts.map +1 -1
  304. package/dist/openapi/document.js +785 -0
  305. package/dist/openapi/document.js.map +1 -0
  306. package/dist/openapi/json-schema-slot.d.ts +7 -0
  307. package/dist/openapi/json-schema-slot.d.ts.map +1 -1
  308. package/dist/openapi/json-schema-slot.js +38 -0
  309. package/dist/openapi/json-schema-slot.js.map +1 -0
  310. package/dist/openapi/register.d.ts.map +1 -1
  311. package/dist/openapi/register.js +20 -0
  312. package/dist/openapi/register.js.map +1 -0
  313. package/dist/openapi/scalar.d.ts +3 -1
  314. package/dist/openapi/scalar.d.ts.map +1 -1
  315. package/dist/openapi/scalar.js +21 -0
  316. package/dist/openapi/scalar.js.map +1 -0
  317. package/dist/openapi/serve.d.ts +9 -0
  318. package/dist/openapi/serve.d.ts.map +1 -0
  319. package/dist/openapi/serve.js +36 -0
  320. package/dist/openapi/serve.js.map +1 -0
  321. package/dist/openapi/spec-factory.d.ts +30 -1
  322. package/dist/openapi/spec-factory.d.ts.map +1 -1
  323. package/dist/openapi/spec-factory.js +52 -0
  324. package/dist/openapi/spec-factory.js.map +1 -0
  325. package/dist/openapi/spec.d.ts +14 -5
  326. package/dist/openapi/spec.d.ts.map +1 -1
  327. package/dist/openapi/spec.js +50 -0
  328. package/dist/openapi/spec.js.map +1 -0
  329. package/dist/openapi/swagger.d.ts +3 -1
  330. package/dist/openapi/swagger.d.ts.map +1 -1
  331. package/dist/openapi/swagger.js +22 -0
  332. package/dist/openapi/swagger.js.map +1 -0
  333. package/dist/pattern.d.ts +71 -0
  334. package/dist/pattern.d.ts.map +1 -0
  335. package/dist/pattern.js +239 -0
  336. package/dist/pattern.js.map +1 -0
  337. package/dist/peer.d.ts +17 -0
  338. package/dist/peer.d.ts.map +1 -0
  339. package/dist/peer.js +50 -0
  340. package/dist/peer.js.map +1 -0
  341. package/dist/plugin.d.ts +67 -16
  342. package/dist/plugin.d.ts.map +1 -1
  343. package/dist/plugin.js +649 -0
  344. package/dist/plugin.js.map +1 -0
  345. package/dist/powered-by.d.ts.map +1 -1
  346. package/dist/powered-by.js +11 -0
  347. package/dist/powered-by.js.map +1 -0
  348. package/dist/pretty-json.d.ts.map +1 -1
  349. package/dist/pretty-json.js +47 -0
  350. package/dist/pretty-json.js.map +1 -0
  351. package/dist/producer-stream.d.ts +47 -0
  352. package/dist/producer-stream.d.ts.map +1 -0
  353. package/dist/producer-stream.js +267 -0
  354. package/dist/producer-stream.js.map +1 -0
  355. package/dist/proxy.d.ts +47 -8
  356. package/dist/proxy.d.ts.map +1 -1
  357. package/dist/proxy.js +274 -0
  358. package/dist/proxy.js.map +1 -0
  359. package/dist/python-type-emitter.d.ts +14 -1
  360. package/dist/python-type-emitter.d.ts.map +1 -1
  361. package/dist/python-type-emitter.js +157 -0
  362. package/dist/python-type-emitter.js.map +1 -0
  363. package/dist/realtime/bus.d.ts +17 -1
  364. package/dist/realtime/bus.d.ts.map +1 -1
  365. package/dist/realtime/bus.js +112 -0
  366. package/dist/realtime/bus.js.map +1 -0
  367. package/dist/realtime/register.d.ts +3 -0
  368. package/dist/realtime/register.d.ts.map +1 -0
  369. package/dist/realtime/register.js +10 -0
  370. package/dist/realtime/register.js.map +1 -0
  371. package/dist/realtime/route.d.ts +65 -26
  372. package/dist/realtime/route.d.ts.map +1 -1
  373. package/dist/realtime/route.js +72 -0
  374. package/dist/realtime/route.js.map +1 -0
  375. package/dist/realtime/server.d.ts +43 -0
  376. package/dist/realtime/server.d.ts.map +1 -0
  377. package/dist/realtime/server.js +255 -0
  378. package/dist/realtime/server.js.map +1 -0
  379. package/dist/request-id.d.ts +7 -0
  380. package/dist/request-id.d.ts.map +1 -1
  381. package/dist/request-id.js +16 -0
  382. package/dist/request-id.js.map +1 -0
  383. package/dist/request-limits.d.ts +3 -0
  384. package/dist/request-limits.d.ts.map +1 -0
  385. package/dist/request-limits.js +3 -0
  386. package/dist/request-limits.js.map +1 -0
  387. package/dist/request-path.d.ts +33 -0
  388. package/dist/request-path.d.ts.map +1 -0
  389. package/dist/request-path.js +178 -0
  390. package/dist/request-path.js.map +1 -0
  391. package/dist/request-to-curl.d.ts +7 -1
  392. package/dist/request-to-curl.d.ts.map +1 -1
  393. package/dist/request-to-curl.js +48 -0
  394. package/dist/request-to-curl.js.map +1 -0
  395. package/dist/response.d.ts +25 -2
  396. package/dist/response.d.ts.map +1 -1
  397. package/dist/response.js +313 -0
  398. package/dist/response.js.map +1 -0
  399. package/dist/rust-type-emitter.d.ts +14 -2
  400. package/dist/rust-type-emitter.d.ts.map +1 -1
  401. package/dist/rust-type-emitter.js +463 -0
  402. package/dist/rust-type-emitter.js.map +1 -0
  403. package/dist/secure-headers.d.ts.map +1 -1
  404. package/dist/secure-headers.js +53 -0
  405. package/dist/secure-headers.js.map +1 -0
  406. package/dist/serve-register.d.ts +4 -0
  407. package/dist/serve-register.d.ts.map +1 -1
  408. package/dist/serve-register.js +9 -0
  409. package/dist/serve-register.js.map +1 -0
  410. package/dist/serve-slot.d.ts +3 -0
  411. package/dist/serve-slot.d.ts.map +1 -1
  412. package/dist/serve-slot.js +52 -0
  413. package/dist/serve-slot.js.map +1 -0
  414. package/dist/serve.d.ts +18 -1
  415. package/dist/serve.d.ts.map +1 -1
  416. package/dist/serve.js +157 -0
  417. package/dist/serve.js.map +1 -0
  418. package/dist/server-timing.d.ts.map +1 -1
  419. package/dist/server-timing.js +51 -0
  420. package/dist/server-timing.js.map +1 -0
  421. package/dist/static.d.ts +9 -0
  422. package/dist/static.d.ts.map +1 -1
  423. package/dist/static.js +102 -0
  424. package/dist/static.js.map +1 -0
  425. package/dist/telemetry/otel.d.ts +2 -0
  426. package/dist/telemetry/otel.d.ts.map +1 -1
  427. package/dist/telemetry/otel.js +135 -0
  428. package/dist/telemetry/otel.js.map +1 -0
  429. package/dist/testing.d.ts +12 -0
  430. package/dist/testing.d.ts.map +1 -1
  431. package/dist/testing.js +124 -0
  432. package/dist/testing.js.map +1 -0
  433. package/dist/timeout.d.ts +6 -0
  434. package/dist/timeout.d.ts.map +1 -1
  435. package/dist/timeout.js +36 -0
  436. package/dist/timeout.js.map +1 -0
  437. package/dist/tree.d.ts +133 -36
  438. package/dist/tree.d.ts.map +1 -1
  439. package/dist/tree.js +437 -0
  440. package/dist/tree.js.map +1 -0
  441. package/dist/trust.d.ts +21 -0
  442. package/dist/trust.d.ts.map +1 -0
  443. package/dist/trust.js +100 -0
  444. package/dist/trust.js.map +1 -0
  445. package/dist/ts-type-emitter.d.ts.map +1 -1
  446. package/dist/ts-type-emitter.js +150 -0
  447. package/dist/ts-type-emitter.js.map +1 -0
  448. package/dist/type-emitter.d.ts +16 -2
  449. package/dist/type-emitter.d.ts.map +1 -1
  450. package/dist/type-emitter.js +729 -0
  451. package/dist/type-emitter.js.map +1 -0
  452. package/dist/type-extractor.d.ts +8 -4
  453. package/dist/type-extractor.d.ts.map +1 -1
  454. package/dist/type-extractor.js +776 -0
  455. package/dist/type-extractor.js.map +1 -0
  456. package/dist/types.d.ts +7 -0
  457. package/dist/types.d.ts.map +1 -1
  458. package/dist/types.js +96 -0
  459. package/dist/types.js.map +1 -0
  460. package/dist/validation.d.ts +14 -2
  461. package/dist/validation.d.ts.map +1 -1
  462. package/dist/validation.js +335 -0
  463. package/dist/validation.js.map +1 -0
  464. package/dist/with-headers.d.ts +15 -0
  465. package/dist/with-headers.d.ts.map +1 -0
  466. package/dist/with-headers.js +45 -0
  467. package/dist/with-headers.js.map +1 -0
  468. package/dist/ws/bun.d.ts +11 -5
  469. package/dist/ws/bun.d.ts.map +1 -1
  470. package/dist/ws/bun.js +82 -0
  471. package/dist/ws/bun.js.map +1 -0
  472. package/dist/ws/cloudflare.d.ts +25 -3
  473. package/dist/ws/cloudflare.d.ts.map +1 -1
  474. package/dist/ws/cloudflare.js +117 -0
  475. package/dist/ws/cloudflare.js.map +1 -0
  476. package/dist/ws/deno.d.ts +4 -4
  477. package/dist/ws/deno.d.ts.map +1 -1
  478. package/dist/ws/deno.js +133 -0
  479. package/dist/ws/deno.js.map +1 -0
  480. package/dist/ws/node.d.ts +20 -3
  481. package/dist/ws/node.d.ts.map +1 -1
  482. package/dist/ws/node.js +173 -0
  483. package/dist/ws/node.js.map +1 -0
  484. package/dist/ws/session.d.ts +11 -0
  485. package/dist/ws/session.d.ts.map +1 -0
  486. package/dist/ws/session.js +60 -0
  487. package/dist/ws/session.js.map +1 -0
  488. package/dist/ws/shared.d.ts +65 -0
  489. package/dist/ws/shared.d.ts.map +1 -0
  490. package/dist/ws/shared.js +103 -0
  491. package/dist/ws/shared.js.map +1 -0
  492. package/dist/ws-origin.d.ts +20 -0
  493. package/dist/ws-origin.d.ts.map +1 -0
  494. package/dist/ws-origin.js +41 -0
  495. package/dist/ws-origin.js.map +1 -0
  496. package/dist/yaml.d.ts +15 -1
  497. package/dist/yaml.d.ts.map +1 -1
  498. package/dist/yaml.js +101 -0
  499. package/dist/yaml.js.map +1 -0
  500. package/docs/invalidate-spec.md +13 -1
  501. package/docs/meta-spec.md +36 -12
  502. package/docs/packaging.md +43 -24
  503. package/docs/regression-matrix/README.md +32 -0
  504. package/docs/regression-matrix/review.md +44 -0
  505. package/docs/regression-matrix/ws1-3.md +97 -0
  506. package/docs/regression-matrix/ws4-8.md +107 -0
  507. package/docs/regression-matrix/ws9-12.md +266 -0
  508. package/docs/sdk.md +102 -52
  509. package/package.json +183 -52
  510. package/src/accepts.ts +91 -33
  511. package/src/body-kind.ts +67 -0
  512. package/src/body-limit.ts +102 -87
  513. package/src/build/index.ts +104 -54
  514. package/src/cli-args.ts +123 -0
  515. package/src/cli-go/auth.go +12 -1
  516. package/src/cli-go/config.go +29 -2
  517. package/src/cli-go/errors.go +28 -10
  518. package/src/cli-go/multipart.go +51 -27
  519. package/src/cli-go/output.go +58 -4
  520. package/src/cli-go/root.go +1 -1
  521. package/src/cli-go/version.go +2 -2
  522. package/src/cli.ts +154 -148
  523. package/src/client/error.ts +56 -1
  524. package/src/client/http.ts +479 -256
  525. package/src/client/index.ts +55 -17
  526. package/src/client/path.ts +169 -0
  527. package/src/client/redirect-policy.ts +19 -0
  528. package/src/client/sdk.ts +180 -101
  529. package/src/client/sse.ts +92 -66
  530. package/src/client/ws.ts +67 -31
  531. package/src/client-go/errors.go +41 -12
  532. package/src/client-go/export.go +44 -0
  533. package/src/client-go/invalidation.go +52 -54
  534. package/src/client-go/nullable.go +62 -0
  535. package/src/client-go/realtime.go +147 -110
  536. package/src/client-go/runtime.go +646 -88
  537. package/src/client-go/sse.go +104 -94
  538. package/src/client-go/transport.go +67 -27
  539. package/src/client-go/ws.go +49 -25
  540. package/src/client-info.ts +79 -0
  541. package/src/client-mcp/server.ts +133 -3
  542. package/src/client-python/_invalidation.py +207 -291
  543. package/src/client-python/_realtime.py +63 -40
  544. package/src/client-python/_runtime.py +501 -119
  545. package/src/client-python/_sse.py +130 -74
  546. package/src/client-python/_transport.py +37 -9
  547. package/src/client-python/_ws.py +50 -22
  548. package/src/client-rust/errors.rs +21 -1
  549. package/src/client-rust/invalidation.rs +202 -231
  550. package/src/client-rust/invalidation_sync.rs +16 -229
  551. package/src/client-rust/nullable.rs +17 -0
  552. package/src/client-rust/realtime.rs +217 -217
  553. package/src/client-rust/runtime.rs +602 -177
  554. package/src/client-rust/runtime_sync.rs +169 -145
  555. package/src/client-rust/sse.rs +142 -121
  556. package/src/client-rust/ws.rs +61 -37
  557. package/src/codegen-go-cli.ts +607 -728
  558. package/src/codegen-go.ts +710 -770
  559. package/src/codegen-ir.ts +381 -75
  560. package/src/codegen-lang.ts +517 -0
  561. package/src/codegen-load.ts +150 -0
  562. package/src/codegen-mcp.ts +207 -108
  563. package/src/codegen-python.ts +684 -816
  564. package/src/codegen-route-tree-intern.ts +51 -25
  565. package/src/codegen-rust.ts +946 -1240
  566. package/src/codegen-sanitize.ts +0 -4
  567. package/src/codegen-schema-naming.ts +19 -6
  568. package/src/codegen-sdk-model.ts +228 -0
  569. package/src/codegen.ts +1488 -1140
  570. package/src/context.ts +130 -11
  571. package/src/cookie-sign.ts +85 -16
  572. package/src/cookie.ts +66 -11
  573. package/src/cors.ts +55 -54
  574. package/src/crypto.ts +27 -5
  575. package/src/csrf.ts +57 -25
  576. package/src/curl-logger.ts +155 -114
  577. package/src/dict.ts +12 -0
  578. package/src/error.ts +4 -2
  579. package/src/etag.ts +58 -34
  580. package/src/feature-detect.ts +147 -0
  581. package/src/feature-slots.ts +70 -0
  582. package/src/fetch-request.ts +13 -0
  583. package/src/gen-process.ts +42 -0
  584. package/src/gen-write.ts +127 -0
  585. package/src/glob.ts +109 -0
  586. package/src/go-type-emitter.ts +406 -155
  587. package/src/honey-response.ts +36 -9
  588. package/src/i18n-slot.ts +10 -0
  589. package/src/i18n.ts +98 -23
  590. package/src/index.ts +1893 -1761
  591. package/src/init.ts +40 -28
  592. package/src/invalidate-check.ts +42 -4
  593. package/src/invoke-user.ts +95 -0
  594. package/src/ip-restrict.ts +47 -161
  595. package/src/ip.ts +194 -0
  596. package/src/logger.ts +65 -36
  597. package/src/media-type.ts +104 -0
  598. package/src/meta-spec-merge.ts +80 -0
  599. package/src/meta-spec.ts +0 -0
  600. package/src/middleware.ts +112 -12
  601. package/src/node-request.ts +242 -52
  602. package/src/node.ts +318 -75
  603. package/src/openapi/collect.ts +19 -44
  604. package/src/openapi/docs-page.ts +89 -0
  605. package/src/openapi/document.ts +503 -224
  606. package/src/openapi/json-schema-slot.ts +40 -0
  607. package/src/openapi/register.ts +7 -2
  608. package/src/openapi/scalar.ts +11 -10
  609. package/src/openapi/serve.ts +39 -0
  610. package/src/openapi/spec-factory.ts +50 -1
  611. package/src/openapi/spec.ts +53 -30
  612. package/src/openapi/swagger.ts +12 -11
  613. package/src/pattern.ts +245 -0
  614. package/src/peer.ts +53 -0
  615. package/src/plugin.ts +270 -185
  616. package/src/powered-by.ts +2 -2
  617. package/src/pretty-json.ts +25 -9
  618. package/src/producer-stream.ts +296 -0
  619. package/src/proxy.ts +271 -55
  620. package/src/python-type-emitter.ts +68 -56
  621. package/src/realtime/bus.ts +56 -9
  622. package/src/realtime/register.ts +13 -0
  623. package/src/realtime/route.ts +129 -80
  624. package/src/realtime/server.ts +298 -0
  625. package/src/request-id.ts +13 -3
  626. package/src/request-limits.ts +2 -0
  627. package/src/request-path.ts +165 -0
  628. package/src/request-to-curl.ts +28 -7
  629. package/src/response.ts +143 -103
  630. package/src/rust-type-emitter.ts +265 -170
  631. package/src/secure-headers.ts +8 -4
  632. package/src/serve-register.ts +4 -0
  633. package/src/serve-slot.ts +38 -0
  634. package/src/serve.ts +113 -25
  635. package/src/server-timing.ts +11 -7
  636. package/src/static.ts +85 -32
  637. package/src/telemetry/otel.ts +29 -7
  638. package/src/testing.ts +76 -14
  639. package/src/timeout.ts +15 -7
  640. package/src/tree.ts +405 -333
  641. package/src/trust.ts +117 -0
  642. package/src/ts-type-emitter.ts +18 -12
  643. package/src/type-emitter.ts +227 -89
  644. package/src/type-extractor.ts +562 -424
  645. package/src/types.ts +8 -0
  646. package/src/validation.ts +221 -96
  647. package/src/with-headers.ts +45 -0
  648. package/src/ws/bun.ts +53 -15
  649. package/src/ws/cloudflare.ts +81 -19
  650. package/src/ws/deno.ts +124 -36
  651. package/src/ws/node.ts +173 -79
  652. package/src/ws/session.ts +73 -0
  653. package/src/ws/shared.ts +140 -0
  654. package/src/ws-origin.ts +53 -0
  655. package/src/yaml.ts +45 -22
  656. package/dist/client-mcp/server.d.ts +0 -10
  657. package/dist/client-mcp/server.d.ts.map +0 -1
  658. package/dist/client-mcp/types.d.ts +0 -16
  659. package/dist/client-mcp/types.d.ts.map +0 -1
  660. package/dist/cloudflare/realtime.d.ts +0 -30
  661. package/dist/cloudflare/realtime.d.ts.map +0 -1
  662. package/dist/realtime/buffer.d.ts +0 -18
  663. package/dist/realtime/buffer.d.ts.map +0 -1
  664. package/dist/realtime/longpoll.d.ts +0 -23
  665. package/dist/realtime/longpoll.d.ts.map +0 -1
  666. package/dist/realtime/protocol.d.ts +0 -50
  667. package/dist/realtime/protocol.d.ts.map +0 -1
  668. package/dist/realtime/runtime.d.ts +0 -74
  669. package/dist/realtime/runtime.d.ts.map +0 -1
  670. package/src/cloudflare/realtime.ts +0 -234
  671. package/src/realtime/buffer.ts +0 -101
  672. package/src/realtime/longpoll.ts +0 -148
  673. package/src/realtime/protocol.ts +0 -128
  674. package/src/realtime/runtime.ts +0 -427
@@ -7,12 +7,11 @@
7
7
  test harnesses, CLI tools). Never call blocking methods from within an async runtime. */
8
8
 
9
9
  use crate::errors::{raise_for_status, Error};
10
- use crate::runtime::{LogEntry, OnLogHook};
10
+ use crate::runtime::{build_url, encode_query, merged_headers, set_header, LogEntry, OnLogHook};
11
11
  use std::collections::HashMap;
12
- use std::sync::Arc;
13
12
  use std::sync::atomic::{AtomicBool, Ordering};
13
+ use std::sync::{Arc, Mutex};
14
14
  use std::time::Duration;
15
- use uuid::Uuid;
16
15
 
17
16
  /// SyncOnRequestHook is a synchronous (non-async) request hook.
18
17
  /// Returns Result<(), Error> directly — no Future, no Pin<Box<...>>.
@@ -30,6 +29,8 @@ pub struct SyncRequestContext {
30
29
  pub url: String,
31
30
  pub path: String,
32
31
  pub headers: HashMap<String, String>,
32
+ /// `SyncClientConfig::state`, shared by every hook of every call; a fresh map per call when unset.
33
+ pub state: Arc<std::sync::Mutex<HashMap<String, serde_json::Value>>>,
33
34
  pub is_retry: bool,
34
35
  pub selector: String,
35
36
  pub is_stale: bool,
@@ -41,6 +42,8 @@ pub struct SyncResponseContext {
41
42
  pub status: u16,
42
43
  pub response: Vec<u8>,
43
44
  pub headers: reqwest::header::HeaderMap,
45
+ /// The same map the request hooks saw.
46
+ pub state: Arc<std::sync::Mutex<HashMap<String, serde_json::Value>>>,
44
47
  pub is_retry: bool,
45
48
  pub selector: String,
46
49
  pub is_stale: bool,
@@ -48,28 +51,31 @@ pub struct SyncResponseContext {
48
51
  }
49
52
 
50
53
  /// SyncRequestBody represents the different body types a blocking request can carry.
51
- /// `Stream` carries an owned, single-shot `reqwest::blocking::Body` (built via
52
- /// `reqwest::blocking::Body::new` over any `impl Read + Send + 'static`); like
53
- /// `Multipart`, it cannot be retried on 401 because the underlying body is not
54
- /// `Clone`.
54
+ /// `Multipart` and `Stream` own single-shot bodies and are not retried on 401.
55
55
  pub enum SyncRequestBody<'a> {
56
56
  None,
57
57
  Json(&'a serde_json::Value),
58
- FormUrl(&'a HashMap<String, String>),
58
+ FormUrl(Vec<(String, String)>),
59
+ Raw(&'static str, bytes::Bytes),
59
60
  Multipart(reqwest::blocking::multipart::Form),
60
61
  Stream(reqwest::blocking::Body),
61
62
  }
62
63
 
63
64
  /// SyncClientConfig holds all configuration for the blocking SDK client.
65
+ /// Same semantics as [`crate::runtime::ClientConfig`].
64
66
  #[derive(Clone)]
65
67
  pub struct SyncClientConfig {
66
68
  pub base_url: String,
67
69
  pub bearer_token: Option<String>,
68
70
  pub headers: HashMap<String, String>,
69
71
  pub timeout: Duration,
72
+ /// Ignored at runtime: whether methods return `SdkResult` is fixed when the SDK is generated.
73
+ #[deprecated(note = "has no effect; generate with `throwOnError: false` for SdkResult methods")]
70
74
  pub throw_on_error: bool,
75
+ /// Fallback for `InvalidationConfig::stale_max_entries` when that is 0.
71
76
  pub stale_max_entries: usize,
72
77
  pub invalidation: Option<crate::runtime::InvalidationConfig>,
78
+ /// Returns the new token; an empty string means "give up".
73
79
  pub on_auth_expired:
74
80
  Option<Arc<dyn Fn() -> Result<String, Error> + Send + Sync>>,
75
81
  pub http_client: Option<reqwest::blocking::Client>,
@@ -78,9 +84,12 @@ pub struct SyncClientConfig {
78
84
  pub on_request: Vec<SyncOnRequestHook>,
79
85
  pub on_response: Vec<SyncOnResponseHook>,
80
86
  pub on_log: Option<OnLogHook>,
87
+ /// Shared state handed to every `on_request` / `on_response` hook (`ctx.state`).
81
88
  pub state: Option<Arc<std::sync::Mutex<HashMap<String, serde_json::Value>>>>,
89
+ pub max_response_bytes: usize,
82
90
  }
83
91
 
92
+ #[allow(deprecated)]
84
93
  impl Default for SyncClientConfig {
85
94
  fn default() -> Self {
86
95
  SyncClientConfig {
@@ -99,10 +108,51 @@ impl Default for SyncClientConfig {
99
108
  on_response: Vec::new(),
100
109
  on_log: None,
101
110
  state: None,
111
+ max_response_bytes: crate::runtime::DEFAULT_MAX_RESPONSE_BYTES,
102
112
  }
103
113
  }
104
114
  }
105
115
 
116
+ /// SyncAuthState is the blocking twin of [`crate::runtime::AuthState`].
117
+ pub struct SyncAuthState {
118
+ token: Mutex<Option<String>>,
119
+ }
120
+
121
+ impl SyncAuthState {
122
+ pub fn new(token: Option<String>) -> Self {
123
+ SyncAuthState { token: Mutex::new(token) }
124
+ }
125
+
126
+ pub fn current(&self) -> Option<String> {
127
+ self.token.lock().unwrap_or_else(|p| p.into_inner()).clone()
128
+ }
129
+
130
+ fn refresh(
131
+ &self,
132
+ hook: &Arc<dyn Fn() -> Result<String, Error> + Send + Sync>,
133
+ rejected: Option<&str>,
134
+ ) -> Result<Option<String>, Error> {
135
+ let mut guard = self.token.lock().unwrap_or_else(|p| p.into_inner());
136
+ if guard.as_deref() != rejected {
137
+ return Ok(guard.clone());
138
+ }
139
+ let token = hook().map_err(|e| Error::AuthExpired(e.to_string()))?;
140
+ if token.is_empty() {
141
+ return Ok(None);
142
+ }
143
+ *guard = Some(token.clone());
144
+ Ok(Some(token))
145
+ }
146
+ }
147
+
148
+ /// default_http_client_blocking follows redirects on the same origin only.
149
+ pub fn default_http_client_blocking() -> reqwest::blocking::Client {
150
+ reqwest::blocking::Client::builder()
151
+ .redirect(crate::runtime::same_host_redirects())
152
+ .build()
153
+ .unwrap_or_default()
154
+ }
155
+
106
156
  /* emit_log invokes the on_log callback if configured, swallowing any panic so a
107
157
  faulty logger cannot break the request path. Mirrors runtime.rs sibling. */
108
158
  fn emit_log(cfg: &SyncClientConfig, entry: LogEntry) {
@@ -121,6 +171,14 @@ fn err_status(err: &Error) -> Option<i32> {
121
171
  }
122
172
  }
123
173
 
174
+ fn map_err(e: reqwest::Error) -> Error {
175
+ if e.is_timeout() {
176
+ Error::Timeout
177
+ } else {
178
+ Error::Transport(e)
179
+ }
180
+ }
181
+
124
182
  /// SyncRequestResult carries the raw bytes, status, headers, and final URL from a blocking request.
125
183
  #[allow(dead_code)]
126
184
  pub(crate) struct SyncRequestResult {
@@ -138,6 +196,7 @@ pub(crate) struct SyncRequestResult {
138
196
  pub(crate) fn do_request_blocking(
139
197
  client: &reqwest::blocking::Client,
140
198
  cfg: &SyncClientConfig,
199
+ auth: &SyncAuthState,
141
200
  method: reqwest::Method,
142
201
  raw_url: &str,
143
202
  query: &[(String, String)],
@@ -149,21 +208,25 @@ pub(crate) fn do_request_blocking(
149
208
  request_meta: Option<&crate::invalidation::RequestMeta>,
150
209
  ) -> Result<SyncRequestResult, Error> {
151
210
  let start = std::time::Instant::now();
211
+ let log_error = |e: &Error| {
212
+ emit_log(
213
+ cfg,
214
+ LogEntry {
215
+ level: "error".to_string(),
216
+ event: "error".to_string(),
217
+ operation: operation.to_string(),
218
+ duration_ms: start.elapsed().as_millis() as i64,
219
+ status: err_status(e),
220
+ error: Some(format!("{:?}", e)),
221
+ },
222
+ )
223
+ };
152
224
 
153
- /* Pre-flight cancellation check — short-circuit before any work. */
225
+ /* Pre-flight cancellation check — short-circuit before any work. Blocking
226
+ sends cannot be interrupted once started. */
154
227
  if let Some(ref tok) = cancel_token {
155
228
  if tok.load(Ordering::Acquire) {
156
- emit_log(
157
- cfg,
158
- LogEntry {
159
- level: "error".to_string(),
160
- event: "error".to_string(),
161
- operation: operation.to_string(),
162
- duration_ms: start.elapsed().as_millis() as i64,
163
- status: None,
164
- error: Some("Canceled".to_string()),
165
- },
166
- );
229
+ log_error(&Error::Canceled);
167
230
  return Err(Error::Canceled);
168
231
  }
169
232
  }
@@ -180,15 +243,16 @@ pub(crate) fn do_request_blocking(
180
243
  },
181
244
  );
182
245
 
183
- /* Reborrow body for retry path; Multipart + Stream are not Clone so cannot retry 401 */
184
246
  let retry_body: Option<SyncRequestBody<'_>> = match &body {
185
247
  SyncRequestBody::None => Some(SyncRequestBody::None),
186
248
  SyncRequestBody::Json(v) => Some(SyncRequestBody::Json(v)),
187
- SyncRequestBody::FormUrl(m) => Some(SyncRequestBody::FormUrl(m)),
249
+ SyncRequestBody::FormUrl(m) => Some(SyncRequestBody::FormUrl(m.clone())),
250
+ SyncRequestBody::Raw(ct, b) => Some(SyncRequestBody::Raw(ct, b.clone())),
188
251
  SyncRequestBody::Multipart(_) => None,
189
252
  SyncRequestBody::Stream(_) => None,
190
253
  };
191
254
 
255
+ let token = auth.current();
192
256
  let mut result = match execute_request_blocking(
193
257
  client,
194
258
  cfg,
@@ -197,7 +261,7 @@ pub(crate) fn do_request_blocking(
197
261
  query,
198
262
  body,
199
263
  call_headers,
200
- cfg.bearer_token.as_deref(),
264
+ token.as_deref(),
201
265
  false,
202
266
  timeout,
203
267
  cancel_token.clone(),
@@ -205,42 +269,21 @@ pub(crate) fn do_request_blocking(
205
269
  ) {
206
270
  Ok(r) => r,
207
271
  Err(e) => {
208
- emit_log(
209
- cfg,
210
- LogEntry {
211
- level: "error".to_string(),
212
- event: "error".to_string(),
213
- operation: operation.to_string(),
214
- duration_ms: start.elapsed().as_millis() as i64,
215
- status: err_status(&e),
216
- error: Some(format!("{:?}", e)),
217
- },
218
- );
272
+ log_error(&e);
219
273
  return Err(e);
220
274
  }
221
275
  };
222
276
 
223
277
  if result.status == 401 {
224
- if let Some(ref hook) = cfg.on_auth_expired {
225
- if let Some(retry) = retry_body {
226
- let new_token = match hook() {
227
- Ok(t) => t,
228
- Err(e) => {
229
- let mapped = Error::AuthExpired(e.to_string());
230
- emit_log(
231
- cfg,
232
- LogEntry {
233
- level: "error".to_string(),
234
- event: "error".to_string(),
235
- operation: operation.to_string(),
236
- duration_ms: start.elapsed().as_millis() as i64,
237
- status: err_status(&mapped),
238
- error: Some(format!("{:?}", mapped)),
239
- },
240
- );
241
- return Err(mapped);
242
- }
243
- };
278
+ if let (Some(hook), Some(retry)) = (cfg.on_auth_expired.as_ref(), retry_body) {
279
+ let new_token = match auth.refresh(hook, token.as_deref()) {
280
+ Ok(t) => t,
281
+ Err(e) => {
282
+ log_error(&e);
283
+ return Err(e);
284
+ }
285
+ };
286
+ if let Some(new_token) = new_token {
244
287
  result = match execute_request_blocking(
245
288
  client,
246
289
  cfg,
@@ -257,22 +300,11 @@ pub(crate) fn do_request_blocking(
257
300
  ) {
258
301
  Ok(r) => r,
259
302
  Err(e) => {
260
- emit_log(
261
- cfg,
262
- LogEntry {
263
- level: "error".to_string(),
264
- event: "error".to_string(),
265
- operation: operation.to_string(),
266
- duration_ms: start.elapsed().as_millis() as i64,
267
- status: err_status(&e),
268
- error: Some(format!("{:?}", e)),
269
- },
270
- );
303
+ log_error(&e);
271
304
  return Err(e);
272
305
  }
273
306
  };
274
307
  }
275
- /* Multipart/Stream 401: Form/Body is not Clone, cannot retry; fall through */
276
308
  }
277
309
  }
278
310
 
@@ -290,19 +322,11 @@ pub(crate) fn do_request_blocking(
290
322
  },
291
323
  );
292
324
 
293
- if let Some(err) = raise_for_status(result.status, result.body.clone()) {
294
- emit_log(
295
- cfg,
296
- LogEntry {
297
- level: "error".to_string(),
298
- event: "error".to_string(),
299
- operation: operation.to_string(),
300
- duration_ms: start.elapsed().as_millis() as i64,
301
- status: Some(status_i32),
302
- error: Some(format!("{:?}", err)),
303
- },
304
- );
305
- return Err(err);
325
+ if !(200..300).contains(&result.status) {
326
+ if let Some(err) = raise_for_status(result.status, std::mem::take(&mut result.body)) {
327
+ log_error(&err);
328
+ return Err(err);
329
+ }
306
330
  }
307
331
 
308
332
  Ok(result)
@@ -323,30 +347,35 @@ fn execute_request_blocking(
323
347
  cancel_token: Option<Arc<AtomicBool>>,
324
348
  request_meta: Option<&crate::invalidation::RequestMeta>,
325
349
  ) -> Result<SyncRequestResult, Error> {
326
- let url = build_url_sync(&cfg.base_url, raw_url, query)?;
327
- let url_str = url.to_string();
328
-
329
- /* build merged headers map for hook inspection */
330
- let mut hook_headers: HashMap<String, String> = cfg.headers.clone();
331
- if let Some(ch) = call_headers {
332
- for (k, v) in ch {
333
- hook_headers.insert(k.clone(), v.clone());
334
- }
335
- }
336
- if let Some(token) = bearer_token {
337
- if !token.is_empty() {
338
- let name = cfg.auth_header_name.as_deref().unwrap_or("Authorization");
339
- let prefix = cfg.auth_header_prefix.as_deref().unwrap_or("Bearer ");
340
- hook_headers.insert(name.to_string(), format!("{}{}", prefix, token));
350
+ let url = build_url(&cfg.base_url, raw_url, query)?;
351
+
352
+ let mut hook_headers = merged_headers(
353
+ &cfg.headers,
354
+ call_headers,
355
+ cfg.auth_header_name.as_deref(),
356
+ cfg.auth_header_prefix.as_deref(),
357
+ bearer_token,
358
+ );
359
+ match &body {
360
+ SyncRequestBody::Json(_) => set_header(&mut hook_headers, "Content-Type", "application/json".into()),
361
+ SyncRequestBody::FormUrl(_) => set_header(
362
+ &mut hook_headers,
363
+ "Content-Type",
364
+ "application/x-www-form-urlencoded".into(),
365
+ ),
366
+ SyncRequestBody::Raw(ct, _) => set_header(&mut hook_headers, "Content-Type", ct.to_string()),
367
+ SyncRequestBody::Stream(_) => {
368
+ if !hook_headers.keys().any(|k| k.eq_ignore_ascii_case("content-type")) {
369
+ set_header(&mut hook_headers, "Content-Type", "application/octet-stream".into());
370
+ }
341
371
  }
372
+ SyncRequestBody::Multipart(_) | SyncRequestBody::None => {}
342
373
  }
343
- /* auto correlation id — config/call win; on_request hooks may overwrite */
344
- if !hook_headers
345
- .keys()
346
- .any(|k| k.eq_ignore_ascii_case("x-request-id"))
347
- {
348
- hook_headers.insert("x-request-id".to_string(), Uuid::new_v4().to_string());
349
- }
374
+
375
+ let state = cfg
376
+ .state
377
+ .clone()
378
+ .unwrap_or_else(|| Arc::new(std::sync::Mutex::new(HashMap::new())));
350
379
 
351
380
  let (meta_selector, meta_is_stale, meta_by) = match request_meta {
352
381
  Some(m) => (m.selector.clone(), m.is_stale, m.invalidated_by.clone()),
@@ -355,88 +384,92 @@ fn execute_request_blocking(
355
384
 
356
385
  let mut req_ctx = SyncRequestContext {
357
386
  method: method.clone(),
358
- url: url_str.clone(),
387
+ url: url.to_string(),
359
388
  path: raw_url.to_string(),
360
389
  headers: hook_headers,
390
+ state: Arc::clone(&state),
361
391
  is_retry,
362
392
  selector: meta_selector.clone(),
363
393
  is_stale: meta_is_stale,
364
394
  invalidated_by: meta_by.clone(),
365
395
  };
366
396
 
367
- /* fire on_request hooks */
368
397
  for hook in cfg.on_request.iter() {
369
398
  hook(&mut req_ctx)?;
370
399
  }
371
400
 
372
401
  let mut req = client.request(req_ctx.method.clone(), &req_ctx.url);
373
-
374
- /* apply headers from context */
375
402
  for (k, v) in &req_ctx.headers {
376
403
  req = req.header(k.as_str(), v.as_str());
377
404
  }
378
-
379
- /* apply body and content-type */
380
405
  req = match body {
381
- SyncRequestBody::Json(v) => {
382
- req = req.header("Content-Type", "application/json");
383
- req.json(v)
384
- }
385
- SyncRequestBody::FormUrl(m) => req.form(m),
406
+ SyncRequestBody::Json(v) => req.body(serde_json::to_vec(v)?),
407
+ SyncRequestBody::FormUrl(pairs) => req.body(encode_query(&pairs)),
408
+ SyncRequestBody::Raw(_, b) => req.body(b.to_vec()),
386
409
  SyncRequestBody::Multipart(f) => req.multipart(f),
387
- SyncRequestBody::Stream(b) => {
388
- req = req.header("Content-Type", "application/octet-stream");
389
- req.body(b)
390
- }
410
+ SyncRequestBody::Stream(b) => req.body(b),
391
411
  SyncRequestBody::None => req,
392
412
  };
393
413
 
394
- /* apply per-call timeout (overrides cfg.timeout) */
414
+ /* per-call timeout overrides cfg.timeout; ZERO means no timeout */
395
415
  let effective_timeout = per_call_timeout.unwrap_or(cfg.timeout);
396
- req = req.timeout(effective_timeout);
416
+ if !effective_timeout.is_zero() {
417
+ req = req.timeout(effective_timeout);
418
+ }
397
419
 
398
- /* Re-check cancellation just before the blocking send (covers the window
399
- between do_request_blocking pre-flight check and actual send). */
400
420
  if let Some(ref tok) = cancel_token {
401
421
  if tok.load(Ordering::Acquire) {
402
422
  return Err(Error::Canceled);
403
423
  }
404
424
  }
405
425
 
406
- let resp = req.send().map_err(|e| {
407
- if e.is_timeout() {
408
- Error::Timeout
409
- } else if e.is_request() {
410
- Error::Canceled
411
- } else {
412
- Error::Transport(e)
413
- }
414
- })?;
426
+ let mut resp = req.send().map_err(map_err)?;
415
427
 
416
428
  let status = resp.status().as_u16();
417
429
  let resp_headers = resp.headers().clone();
418
430
  let resp_url = resp.url().to_string();
419
- let body_bytes = resp.bytes().map_err(Error::Transport)?.to_vec();
431
+ let mut body_bytes = Vec::new();
432
+ let limit = cfg.max_response_bytes;
433
+ {
434
+ use std::io::Read;
435
+ let mut buf = [0u8; 16 * 1024];
436
+ loop {
437
+ let n = resp.read(&mut buf).map_err(|e| {
438
+ if e.kind() == std::io::ErrorKind::TimedOut {
439
+ Error::Timeout
440
+ } else {
441
+ Error::Other(e.to_string())
442
+ }
443
+ })?;
444
+ if n == 0 {
445
+ break;
446
+ }
447
+ if limit > 0 && body_bytes.len() + n > limit {
448
+ return Err(Error::Other(format!("response body exceeds {} bytes", limit)));
449
+ }
450
+ body_bytes.extend_from_slice(&buf[..n]);
451
+ }
452
+ }
420
453
 
421
454
  let mut resp_ctx = SyncResponseContext {
422
455
  status,
423
- response: body_bytes.clone(),
424
- headers: resp_headers.clone(),
456
+ response: body_bytes,
457
+ headers: resp_headers,
458
+ state,
425
459
  is_retry,
426
460
  selector: meta_selector,
427
461
  is_stale: meta_is_stale,
428
462
  invalidated_by: meta_by,
429
463
  };
430
464
 
431
- /* fire on_response hooks */
432
465
  for hook in cfg.on_response.iter() {
433
466
  hook(&mut resp_ctx)?;
434
467
  }
435
468
 
436
469
  Ok(SyncRequestResult {
437
- body: body_bytes,
470
+ body: resp_ctx.response,
438
471
  status,
439
- headers: resp_headers,
472
+ headers: resp_ctx.headers,
440
473
  url: resp_url,
441
474
  })
442
475
  }
@@ -447,14 +480,5 @@ pub(crate) fn build_url_sync(
447
480
  path: &str,
448
481
  query: &[(String, String)],
449
482
  ) -> Result<url::Url, Error> {
450
- let base = url::Url::parse(base_url)?;
451
- let joined = base.join(path)?;
452
- let mut url = joined;
453
- if !query.is_empty() {
454
- let mut pairs = url.query_pairs_mut();
455
- for (k, v) in query {
456
- pairs.append_pair(k, v);
457
- }
458
- }
459
- Ok(url)
483
+ build_url(base_url, path, query)
460
484
  }