@lovrozagar/honey 0.6.8 → 0.7.1

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 +408 -148
  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 +819 -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 +1887 -1756
  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 +253 -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 +603 -423
  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
package/src/client/ws.ts CHANGED
@@ -1,54 +1,81 @@
1
1
  export type TypedWebSocket = {
2
2
  close(code?: number, reason?: string): void
3
- off(event: "close" | "error" | "message" | "open", handler: (...args: never[]) => void): void
3
+ off(event: "binary" | "close" | "error" | "message" | "open", handler: (...args: never[]) => void): void
4
+ /** Binary frames, as `ArrayBuffer`. Text frames go to `"message"`. */
5
+ on(event: "binary", handler: (data: ArrayBuffer) => void): void
4
6
  on(event: "close", handler: (code: number, reason: string) => void): void
5
7
  on(event: "error", handler: (error: unknown) => void): void
8
+ /** Text frames. */
6
9
  on(event: "message", handler: (data: string) => void): void
7
10
  on(event: "open", handler: () => void): void
8
11
  readonly readyState: number
9
- send(data: ArrayBuffer | ArrayBufferView | object | string): void
12
+ /**
13
+ * Strings, `ArrayBuffer`, typed arrays and `Blob` are sent as-is; any other value is
14
+ * JSON-encoded. Sends before the socket opens are queued; after it closes they are dropped.
15
+ */
16
+ send(data: ArrayBuffer | ArrayBufferView | Blob | object | string): void
10
17
  }
11
18
 
12
19
  export type WSOptions = {
13
20
  protocols?: string | string[]
14
21
  }
15
22
 
23
+ type Payload = Blob | string | Uint8Array<ArrayBuffer>
24
+
25
+ const EVENTS = new Set(["binary", "close", "error", "message", "open"])
26
+
16
27
  export function createTypedWebSocket(
17
28
  url: string,
18
29
  opts?: WSOptions,
19
30
  WebSocketImpl: typeof WebSocket = WebSocket,
20
31
  ): TypedWebSocket {
21
32
  const ws = opts?.protocols ? new WebSocketImpl(url, opts.protocols) : new WebSocketImpl(url)
33
+ ws.binaryType = "arraybuffer"
22
34
 
23
- /* map user handlers → wrapped listeners for proper removal */
24
- const listenerMap = new WeakMap<(...args: never[]) => void, EventListener>()
25
- /* buffer sends until OPEN */
26
- const sendBuffer: Array<string | Uint8Array<ArrayBuffer>> = []
27
- let buffering = true
35
+ /* user handler → wrapped listener, per event, so one handler can be registered for several events */
36
+ const listeners = new Map<string, WeakMap<(...args: never[]) => void, EventListener>>()
37
+ /* queue sends until OPEN; stop queueing for good once the socket closes or fails */
38
+ const sendBuffer: Payload[] = []
39
+ let state: "closed" | "connecting" | "open" = "connecting"
28
40
 
29
41
  ws.addEventListener("open", () => {
30
- buffering = false
42
+ state = "open"
31
43
  for (const msg of sendBuffer) {
32
44
  ws.send(msg)
33
45
  }
34
46
  sendBuffer.length = 0
35
47
  })
48
+ ws.addEventListener("close", () => {
49
+ state = "closed"
50
+ sendBuffer.length = 0
51
+ })
36
52
 
37
53
  function close(code?: number, reason?: string) {
38
- buffering = false
54
+ state = "closed"
39
55
  sendBuffer.length = 0
40
56
  ws.close(code, reason)
41
57
  }
42
58
 
59
+ function on(event: "binary", handler: (data: ArrayBuffer) => void): void
43
60
  function on(event: "close", handler: (code: number, reason: string) => void): void
44
61
  function on(event: "error", handler: (error: unknown) => void): void
45
62
  function on(event: "message", handler: (data: string) => void): void
46
63
  function on(event: "open", handler: () => void): void
47
64
  function on(event: string, handler: (...args: never[]) => void): void {
65
+ if (!EVENTS.has(event)) return
48
66
  let wrapped: EventListener
49
67
  switch (event) {
50
68
  case "message":
51
- wrapped = (e: Event) => (handler as (data: string) => void)((e as MessageEvent).data)
69
+ wrapped = (e: Event) => {
70
+ const data = (e as MessageEvent).data
71
+ if (typeof data === "string") (handler as (data: string) => void)(data)
72
+ }
73
+ break
74
+ case "binary":
75
+ wrapped = (e: Event) => {
76
+ const data = (e as MessageEvent).data
77
+ if (data instanceof ArrayBuffer) (handler as (data: ArrayBuffer) => void)(data)
78
+ }
52
79
  break
53
80
  case "open":
54
81
  wrapped = () => (handler as () => void)()
@@ -57,40 +84,49 @@ export function createTypedWebSocket(
57
84
  wrapped = (e: Event) =>
58
85
  (handler as (code: number, reason: string) => void)((e as CloseEvent).code, (e as CloseEvent).reason)
59
86
  break
60
- case "error":
87
+ default:
61
88
  wrapped = (e: Event) => (handler as (error: unknown) => void)(e)
62
89
  break
63
- default:
64
- return
65
90
  }
66
- listenerMap.set(handler, wrapped)
67
- ws.addEventListener(event, wrapped)
91
+ let byHandler = listeners.get(event)
92
+ if (byHandler === undefined) {
93
+ byHandler = new WeakMap()
94
+ listeners.set(event, byHandler)
95
+ }
96
+ const previous = byHandler.get(handler)
97
+ if (previous) ws.removeEventListener(event === "binary" ? "message" : event, previous)
98
+ byHandler.set(handler, wrapped)
99
+ ws.addEventListener(event === "binary" ? "message" : event, wrapped)
68
100
  }
69
101
 
70
102
  function off(event: string, handler: (...args: never[]) => void): void {
71
- const wrapped = listenerMap.get(handler)
103
+ const byHandler = listeners.get(event)
104
+ const wrapped = byHandler?.get(handler)
72
105
  if (wrapped) {
73
- ws.removeEventListener(event, wrapped)
74
- listenerMap.delete(handler)
106
+ ws.removeEventListener(event === "binary" ? "message" : event, wrapped)
107
+ byHandler?.delete(handler)
75
108
  }
76
109
  }
77
110
 
78
- function toWsData(data: ArrayBuffer | ArrayBufferView | string): string | Uint8Array<ArrayBuffer> {
111
+ function toPayload(data: ArrayBuffer | ArrayBufferView | Blob | object | string): Payload {
79
112
  if (typeof data === "string") return data
80
- const view =
81
- data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
82
- const copy = new Uint8Array(view.byteLength)
83
- copy.set(view)
84
- return copy
113
+ if (typeof Blob !== "undefined" && data instanceof Blob) return data
114
+ if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
115
+ const view =
116
+ data instanceof ArrayBuffer
117
+ ? new Uint8Array(data)
118
+ : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
119
+ const copy = new Uint8Array(view.byteLength)
120
+ copy.set(view)
121
+ return copy
122
+ }
123
+ return JSON.stringify(data)
85
124
  }
86
125
 
87
- function send(data: ArrayBuffer | ArrayBufferView | object | string) {
88
- const payload =
89
- typeof data === "string" || data instanceof ArrayBuffer || ArrayBuffer.isView(data)
90
- ? toWsData(data)
91
- : JSON.stringify(data)
92
-
93
- if (buffering) {
126
+ function send(data: ArrayBuffer | ArrayBufferView | Blob | object | string) {
127
+ if (state === "closed") return
128
+ const payload = toPayload(data)
129
+ if (state === "connecting") {
94
130
  sendBuffer.push(payload)
95
131
  } else {
96
132
  ws.send(payload)
@@ -6,6 +6,9 @@ import (
6
6
  "encoding/json"
7
7
  "fmt"
8
8
  "net/http"
9
+ "strings"
10
+ "unicode"
11
+ "unicode/utf8"
9
12
  )
10
13
 
11
14
  // APIError is the interface implemented by all SDK error types.
@@ -155,37 +158,37 @@ type StatusErrorMeta struct {
155
158
 
156
159
  var statusErrorMap = map[int]func(status int, body []byte, data any, resp *http.Response) APIError{
157
160
  400: func(s int, b []byte, d any, r *http.Response) APIError {
158
- return &BadRequestError{Body: b, Data: d, Response: r, Message: string(b)}
161
+ return &BadRequestError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
159
162
  },
160
163
  401: func(s int, b []byte, d any, r *http.Response) APIError {
161
- return &UnauthorizedError{Body: b, Data: d, Response: r, Message: string(b)}
164
+ return &UnauthorizedError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
162
165
  },
163
166
  403: func(s int, b []byte, d any, r *http.Response) APIError {
164
- return &ForbiddenError{Body: b, Data: d, Response: r, Message: string(b)}
167
+ return &ForbiddenError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
165
168
  },
166
169
  404: func(s int, b []byte, d any, r *http.Response) APIError {
167
- return &NotFoundError{Body: b, Data: d, Response: r, Message: string(b)}
170
+ return &NotFoundError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
168
171
  },
169
172
  409: func(s int, b []byte, d any, r *http.Response) APIError {
170
- return &ConflictError{Body: b, Data: d, Response: r, Message: string(b)}
173
+ return &ConflictError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
171
174
  },
172
175
  422: func(s int, b []byte, d any, r *http.Response) APIError {
173
- return &UnprocessableEntityError{Body: b, Data: d, Response: r, Message: string(b)}
176
+ return &UnprocessableEntityError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
174
177
  },
175
178
  429: func(s int, b []byte, d any, r *http.Response) APIError {
176
- return &RateLimitError{Body: b, Data: d, Response: r, Message: string(b)}
179
+ return &RateLimitError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
177
180
  },
178
181
  500: func(s int, b []byte, d any, r *http.Response) APIError {
179
- return &InternalServerError{Body: b, Data: d, Response: r, Message: string(b)}
182
+ return &InternalServerError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
180
183
  },
181
184
  502: func(s int, b []byte, d any, r *http.Response) APIError {
182
- return &BadGatewayError{Body: b, Data: d, Response: r, Message: string(b)}
185
+ return &BadGatewayError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
183
186
  },
184
187
  503: func(s int, b []byte, d any, r *http.Response) APIError {
185
- return &ServiceUnavailableError{Body: b, Data: d, Response: r, Message: string(b)}
188
+ return &ServiceUnavailableError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
186
189
  },
187
190
  504: func(s int, b []byte, d any, r *http.Response) APIError {
188
- return &GatewayTimeoutError{Body: b, Data: d, Response: r, Message: string(b)}
191
+ return &GatewayTimeoutError{Body: b, Data: d, Response: r, Message: errorMessage(b, d)}
189
192
  },
190
193
  }
191
194
 
@@ -203,5 +206,31 @@ func raiseForStatus(resp *http.Response, body []byte) error {
203
206
  if fn, ok := statusErrorMap[resp.StatusCode]; ok {
204
207
  return fn(resp.StatusCode, body, data, resp)
205
208
  }
206
- return &StatusError{StatusCode: resp.StatusCode, Body: body, Data: data, Response: resp, Message: string(body)}
209
+ return &StatusError{StatusCode: resp.StatusCode, Body: body, Data: data, Response: resp, Message: errorMessage(body, data)}
210
+ }
211
+
212
+ // errorMessage is the server's `message` field when the body is a JSON object
213
+ // carrying one, else the body text. Control characters are dropped and the
214
+ // result is capped, so a hostile server cannot fill logs or drive a terminal.
215
+ func errorMessage(body []byte, data any) string {
216
+ text := string(body)
217
+ if m, ok := data.(map[string]any); ok {
218
+ if msg, ok := m["message"].(string); ok {
219
+ text = msg
220
+ }
221
+ }
222
+ var b strings.Builder
223
+ n := 0
224
+ for _, r := range text {
225
+ if n >= maxErrorMessageRunes {
226
+ b.WriteString("…")
227
+ break
228
+ }
229
+ if r == utf8.RuneError || unicode.IsControl(r) {
230
+ continue
231
+ }
232
+ b.WriteRune(r)
233
+ n++
234
+ }
235
+ return b.String()
207
236
  }
@@ -0,0 +1,44 @@
1
+ // Code generated by honey. DO NOT EDIT.
2
+
3
+ package sdk
4
+
5
+ import (
6
+ "context"
7
+ "iter"
8
+ "net/http"
9
+ )
10
+
11
+ // The Honey* functions expose the SDK's URL, SSE and error handling to the
12
+ // generated CLI, so both send byte-identical requests.
13
+
14
+ // HoneyExpandPath fills `{name}` placeholders with escaped values and rejects
15
+ // "", "." and "..".
16
+ func HoneyExpandPath(template string, params map[string]string) (string, error) {
17
+ return expandPath(template, params)
18
+ }
19
+
20
+ // HoneyBuildURL joins base and an escaped path (keeping the base path) and
21
+ // appends the query pairs in order.
22
+ func HoneyBuildURL(baseURL, path string, query [][2]string) (string, error) {
23
+ q := make(queryList, 0, len(query))
24
+ for _, p := range query {
25
+ q = append(q, queryPair{key: p[0], value: p[1]})
26
+ }
27
+ return buildURL(baseURL, path, q)
28
+ }
29
+
30
+ // HoneyParseSSEStream yields the events of an SSE response and closes its body.
31
+ func HoneyParseSSEStream(ctx context.Context, resp *http.Response) iter.Seq2[SSEEvent, error] {
32
+ return parseSSEStream(ctx, resp)
33
+ }
34
+
35
+ // HoneyRaiseForStatus returns the typed error for a non-2xx response, or nil.
36
+ func HoneyRaiseForStatus(resp *http.Response, body []byte) error {
37
+ return raiseForStatus(resp, body)
38
+ }
39
+
40
+ // HoneyFormatQueryValue renders a query or header value the way every SDK
41
+ // language does.
42
+ func HoneyFormatQueryValue(v any) string {
43
+ return formatQueryValue(v)
44
+ }
@@ -3,16 +3,17 @@
3
3
  package sdk
4
4
 
5
5
  import (
6
+ "container/list"
6
7
  "fmt"
7
- "net/url"
8
8
  "regexp"
9
9
  "strings"
10
10
  "sync"
11
11
  "time"
12
12
  )
13
13
 
14
- /* placeholderRe matches `{name}` and `:name` placeholders. */
15
- var placeholderRe = regexp.MustCompile(`\{([a-zA-Z_][a-zA-Z0-9_]*)\}|:([a-zA-Z_][a-zA-Z0-9_]*)`)
14
+ /* placeholderRe matches `{name}` (any name without braces or slashes) and a
15
+ * `:name` segment. A colon inside a segment (`/ops/1:cancel`) is literal. */
16
+ var placeholderRe = regexp.MustCompile(`\{([^{}/]+)\}|(^|/):([a-zA-Z_][a-zA-Z0-9_]*)`)
16
17
 
17
18
  /* patternRegexCache caches compiled placeholder→`[^/]+` regexps per pattern key. */
18
19
  var patternRegexCache sync.Map /* map[string]*regexp.Regexp */
@@ -24,6 +25,8 @@ type staleEntry struct {
24
25
  by []string
25
26
  seq uint64
26
27
  until time.Time
28
+ /* position in the tracker's LRU list */
29
+ elem *list.Element
27
30
  }
28
31
 
29
32
  // RequestMeta is the per-request invalidation snapshot consumers see on hook
@@ -44,7 +47,11 @@ func compilePattern(pattern string) *regexp.Regexp {
44
47
  b.WriteByte('^')
45
48
  last := 0
46
49
  for _, m := range matches {
47
- b.WriteString(regexp.QuoteMeta(pattern[last:m[0]]))
50
+ start := m[0]
51
+ if pattern[start] == '/' {
52
+ start++ /* keep the segment slash literal */
53
+ }
54
+ b.WriteString(regexp.QuoteMeta(pattern[last:start]))
48
55
  b.WriteString(`[^/]+`)
49
56
  last = m[1]
50
57
  }
@@ -78,8 +85,10 @@ func interpolatePath(template string, params map[string]string) (string, error)
78
85
  out := placeholderRe.ReplaceAllStringFunc(template, func(match string) string {
79
86
  groups := placeholderRe.FindStringSubmatch(match)
80
87
  key := groups[1]
88
+ prefix := ""
81
89
  if key == "" {
82
- key = groups[2]
90
+ prefix = groups[2]
91
+ key = groups[3]
83
92
  }
84
93
  val, ok := params[key]
85
94
  if !ok {
@@ -88,7 +97,7 @@ func interpolatePath(template string, params map[string]string) (string, error)
88
97
  }
89
98
  return match
90
99
  }
91
- return url.PathEscape(val)
100
+ return prefix + escapePathSegment(val)
92
101
  })
93
102
  if missing != "" {
94
103
  return "", fmt.Errorf("interpolatePath: missing path param %q", missing)
@@ -98,8 +107,8 @@ func interpolatePath(template string, params map[string]string) (string, error)
98
107
 
99
108
  // resolveInvalidationTargetsForMutation expands templated `METHOD /path/{x}`
100
109
  // invalidation entries to concrete `METHOD /path/abc` selectors using params.
101
- // Pattern-only entries (no params provided) pass through; entries whose
102
- // placeholders cannot be resolved are dropped.
110
+ // An entry whose placeholders cannot all be resolved stays a pattern, so it
111
+ // marks every instance stale (TS parity).
103
112
  func resolveInvalidationTargetsForMutation(targets []string, params map[string]string) []string {
104
113
  out := make([]string, 0, len(targets))
105
114
  for _, entry := range targets {
@@ -116,6 +125,7 @@ func resolveInvalidationTargetsForMutation(targets []string, params map[string]s
116
125
  }
117
126
  concrete, err := interpolatePath(template, params)
118
127
  if err != nil {
128
+ out = append(out, entry)
119
129
  continue
120
130
  }
121
131
  out = append(out, method+" "+concrete)
@@ -126,11 +136,14 @@ func resolveInvalidationTargetsForMutation(targets []string, params map[string]s
126
136
  // StaleTracker tracks invalidation state per `METHOD /path` selector with TS-
127
137
  // parity semantics: exact-key + pattern-key two-tier lookup, TTL stale window,
128
138
  // LRU eviction at cap, monotonic seq for clear-after-mutate ordering.
129
- // All public methods are safe for concurrent use.
139
+ // All public methods are safe for concurrent use. A lookup costs one map read plus a scan of
140
+ // the pattern keys of its method; touch and eviction are O(1).
130
141
  type StaleTracker struct {
131
- mu sync.Mutex
132
- entries map[string]*staleEntry
133
- order []string /* insertion order; oldest at index 0 */
142
+ mu sync.Mutex
143
+ entries map[string]*staleEntry
144
+ order *list.List /* of string keys; oldest at the front */
145
+ /* method → keys whose path still holds placeholders */
146
+ patterns map[string]map[string]struct{}
134
147
  enabled bool
135
148
  staleTime time.Duration
136
149
  maxEntries int
@@ -141,7 +154,7 @@ type StaleTracker struct {
141
154
  // NewStaleTracker constructs a tracker from an InvalidationConfig.
142
155
  // Tracker is disabled (cheap no-op) when cfg is nil or StaleTime ≤ 0.
143
156
  func NewStaleTracker(cfg *InvalidationConfig) *StaleTracker {
144
- t := &StaleTracker{entries: map[string]*staleEntry{}}
157
+ t := &StaleTracker{entries: map[string]*staleEntry{}, order: list.New(), patterns: map[string]map[string]struct{}{}}
145
158
  if cfg == nil || cfg.StaleTime <= 0 {
146
159
  return t
147
160
  }
@@ -203,21 +216,11 @@ func (t *StaleTracker) ClearStale(concreteSelector, concretePath, method string,
203
216
  t.deleteLocked(concreteSelector)
204
217
  }
205
218
  toDelete := make([]string, 0)
206
- for key, entry := range t.entries {
207
- if entry.seq > seqSnapshot {
219
+ for key := range t.patterns[method] {
220
+ if t.entries[key].seq > seqSnapshot {
208
221
  continue
209
222
  }
210
- if !strings.Contains(key, "{") && !strings.Contains(key, ":") {
211
- continue
212
- }
213
- spaceIdx := strings.IndexByte(key, ' ')
214
- if spaceIdx == -1 {
215
- continue
216
- }
217
- if key[:spaceIdx] != method {
218
- continue
219
- }
220
- if pathMatchesPattern(concretePath, key[spaceIdx+1:]) {
223
+ if pathMatchesPattern(concretePath, key[strings.IndexByte(key, ' ')+1:]) {
221
224
  toDelete = append(toDelete, key)
222
225
  }
223
226
  }
@@ -278,29 +281,34 @@ func (t *StaleTracker) upsertLocked(key string, until time.Time, seq uint64, mut
278
281
  if mutationSelector != "" {
279
282
  by = append(by, mutationSelector)
280
283
  }
281
- t.entries[key] = &staleEntry{by: by, seq: seq, until: until}
282
- t.order = append(t.order, key)
284
+ t.entries[key] = &staleEntry{by: by, elem: t.order.PushBack(key), seq: seq, until: until}
285
+ if method, path, ok := strings.Cut(key, " "); ok && pathHasPlaceholders(path) {
286
+ if t.patterns[method] == nil {
287
+ t.patterns[method] = map[string]struct{}{}
288
+ }
289
+ t.patterns[method][key] = struct{}{}
290
+ }
283
291
  }
284
292
 
285
293
  func (t *StaleTracker) touchOrderLocked(key string) {
286
- for i, k := range t.order {
287
- if k == key {
288
- t.order = append(t.order[:i], t.order[i+1:]...)
289
- break
290
- }
294
+ if entry, ok := t.entries[key]; ok {
295
+ t.order.MoveToBack(entry.elem)
291
296
  }
292
- t.order = append(t.order, key)
293
297
  }
294
298
 
295
299
  func (t *StaleTracker) deleteLocked(key string) {
296
- if _, ok := t.entries[key]; !ok {
300
+ entry, ok := t.entries[key]
301
+ if !ok {
297
302
  return
298
303
  }
299
304
  delete(t.entries, key)
300
- for i, k := range t.order {
301
- if k == key {
302
- t.order = append(t.order[:i], t.order[i+1:]...)
303
- return
305
+ t.order.Remove(entry.elem)
306
+ if method, _, ok := strings.Cut(key, " "); ok {
307
+ if bucket := t.patterns[method]; bucket != nil {
308
+ delete(bucket, key)
309
+ if len(bucket) == 0 {
310
+ delete(t.patterns, method)
311
+ }
304
312
  }
305
313
  }
306
314
  }
@@ -315,7 +323,8 @@ func (t *StaleTracker) lookupLocked(concreteSelector, concretePath, method strin
315
323
  }
316
324
  }
317
325
  expired := make([]string, 0)
318
- for key, entry := range t.entries {
326
+ for key := range t.patterns[method] {
327
+ entry := t.entries[key]
319
328
  if !entry.until.After(now) {
320
329
  expired = append(expired, key)
321
330
  continue
@@ -323,17 +332,7 @@ func (t *StaleTracker) lookupLocked(concreteSelector, concretePath, method strin
323
332
  if key == concreteSelector {
324
333
  continue
325
334
  }
326
- if !strings.Contains(key, "{") && !strings.Contains(key, ":") {
327
- continue
328
- }
329
- spaceIdx := strings.IndexByte(key, ' ')
330
- if spaceIdx == -1 {
331
- continue
332
- }
333
- if key[:spaceIdx] != method {
334
- continue
335
- }
336
- if pathMatchesPattern(concretePath, key[spaceIdx+1:]) {
335
+ if pathMatchesPattern(concretePath, key[strings.IndexByte(key, ' ')+1:]) {
337
336
  allBy = append(allBy, entry.by...)
338
337
  }
339
338
  }
@@ -366,8 +365,7 @@ func (t *StaleTracker) enforceCapacityLocked() {
366
365
  if target < 1 {
367
366
  target = 1
368
367
  }
369
- for len(t.entries) > target && len(t.order) > 0 {
370
- oldest := t.order[0]
371
- t.deleteLocked(oldest)
368
+ for len(t.entries) > target && t.order.Len() > 0 {
369
+ t.deleteLocked(t.order.Front().Value.(string))
372
370
  }
373
371
  }
@@ -0,0 +1,62 @@
1
+ // Code generated by honey. DO NOT EDIT.
2
+
3
+ package sdk
4
+
5
+ import (
6
+ "bytes"
7
+ "encoding/json"
8
+ )
9
+
10
+ // Nullable is an optional field that may also be null. Its zero value is "absent": the key is
11
+ // left out of the request (the field carries `omitzero`). NullOf sends an explicit null, Some a
12
+ // value. Decoding sets it from the response: absent stays absent, null becomes null.
13
+ type Nullable[T any] struct {
14
+ value T
15
+ set bool
16
+ null bool
17
+ }
18
+
19
+ // Some is a present, non-null value.
20
+ func Some[T any](v T) Nullable[T] {
21
+ return Nullable[T]{value: v, set: true}
22
+ }
23
+
24
+ // NullOf is an explicit null.
25
+ func NullOf[T any]() Nullable[T] {
26
+ return Nullable[T]{set: true, null: true}
27
+ }
28
+
29
+ // IsZero reports an absent field; encoding/json leaves it out under `omitzero`.
30
+ func (n Nullable[T]) IsZero() bool {
31
+ return !n.set
32
+ }
33
+
34
+ // IsNull reports an explicit null.
35
+ func (n Nullable[T]) IsNull() bool {
36
+ return n.set && n.null
37
+ }
38
+
39
+ // Get returns the value and whether there is one (false for absent and for null).
40
+ func (n Nullable[T]) Get() (T, bool) {
41
+ return n.value, n.set && !n.null
42
+ }
43
+
44
+ func (n Nullable[T]) MarshalJSON() ([]byte, error) {
45
+ if !n.set || n.null {
46
+ return []byte("null"), nil
47
+ }
48
+ return json.Marshal(n.value)
49
+ }
50
+
51
+ func (n *Nullable[T]) UnmarshalJSON(data []byte) error {
52
+ if bytes.Equal(bytes.TrimSpace(data), []byte("null")) {
53
+ *n = NullOf[T]()
54
+ return nil
55
+ }
56
+ var v T
57
+ if err := json.Unmarshal(data, &v); err != nil {
58
+ return err
59
+ }
60
+ *n = Some(v)
61
+ return nil
62
+ }