@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
@@ -1,37 +1,20 @@
1
1
  import { schemaToIR } from "./codegen-ir.ts"
2
- import type { IRSchema } from "./codegen-ir.ts"
3
-
4
- export const GO_KEYWORDS = new Set([
5
- "break",
6
- "case",
7
- "chan",
8
- "const",
9
- "continue",
10
- "default",
11
- "defer",
12
- "else",
13
- "fallthrough",
14
- "for",
15
- "func",
16
- "go",
17
- "goto",
18
- "if",
19
- "import",
20
- "interface",
21
- "map",
22
- "package",
23
- "range",
24
- "return",
25
- "select",
26
- "struct",
27
- "switch",
28
- "type",
29
- "var",
30
- ])
31
-
32
- /** Converts a string to PascalCase from kebab-case, snake_case, dotted, or camelCase. */
2
+ import type { IRField, IRSchema } from "./codegen-ir.ts"
3
+ import {
4
+ GO_KEYWORDS,
5
+ cmpCodeUnit,
6
+ goExported,
7
+ goJsonTag,
8
+ goJsonTagNameValid,
9
+ goString,
10
+ NameScope,
11
+ } from "./codegen-lang.ts"
12
+
13
+ export { GO_KEYWORDS }
14
+
15
+ /** Exported Go identifier from kebab-case, snake_case, dotted, camelCase or arbitrary text. */
33
16
  export function goPascal(name: string): string {
34
- return name.replace(/[-_.](.)/g, (_, c: string) => c.toUpperCase()).replace(/^(.)/, (_, c: string) => c.toUpperCase())
17
+ return goExported(name)
35
18
  }
36
19
 
37
20
  /**
@@ -47,8 +30,47 @@ export function goIdent(name: string, exported = true): string {
47
30
  return name
48
31
  }
49
32
 
50
- export function goTag(jsonKey: string, omitempty: boolean): string {
51
- return omitempty ? `\`json:"${jsonKey},omitempty"\`` : `\`json:"${jsonKey}"\``
33
+ export function goTag(jsonKey: string, omit: boolean | "omitzero"): string {
34
+ return goJsonTag(jsonKey, omit)
35
+ }
36
+
37
+ /** An optional field that may also be null: absent, null and a value are three different requests. */
38
+ function isTriState(field: IRField): boolean {
39
+ return !field.required && field.schema.kind === "nullable"
40
+ }
41
+
42
+ /** Go type of a struct field: `Nullable[T]` for optional + nullable, else a pointer when optional. */
43
+ function structFieldType(field: IRField, render: (schema: IRSchema) => string): string {
44
+ if (isTriState(field) && field.schema.kind === "nullable") {
45
+ /* a cyclic ref stays a pointer: Nullable holds its value inline */
46
+ return `Nullable[${render(field.schema.inner)}]`
47
+ }
48
+ return fieldType(render(field.schema), field.required)
49
+ }
50
+
51
+ function fieldTag(field: IRField): string {
52
+ return goTag(field.name, isTriState(field) ? "omitzero" : !field.required)
53
+ }
54
+
55
+ /** Package-level naming shared by every type the SDK emits. */
56
+ export type GoTypeNames = {
57
+ /** Go type name for a component schema. */
58
+ ref: (schemaName: string) => string
59
+ /** Unique package-level name for a hoisted declaration; the same key always gets the same name. */
60
+ hoist: (key: string, base: string) => string
61
+ /** Unique package-level name for a constant. */
62
+ claimConst: (base: string) => string
63
+ /** Component schemas that reach themselves by value; references to them become pointers. */
64
+ cyclic: Set<string>
65
+ resolve: (schema: IRSchema) => IRSchema
66
+ }
67
+
68
+ const DEFAULT_NAMES: GoTypeNames = {
69
+ claimConst: (base) => base,
70
+ cyclic: new Set(),
71
+ hoist: (_key, base) => base,
72
+ ref: (name) => goPascal(name),
73
+ resolve: (s) => s,
52
74
  }
53
75
 
54
76
  export type RenderUseCtx = {
@@ -57,6 +79,7 @@ export type RenderUseCtx = {
57
79
  decls: Map<string, string>
58
80
  circularRefs?: Set<string>
59
81
  depth?: number
82
+ names?: GoTypeNames
60
83
  }
61
84
 
62
85
  export function isNullable(schema: Record<string, unknown>): boolean {
@@ -94,25 +117,35 @@ export function hoistEnumName(parentName: string, fieldName: string): string {
94
117
  return `${goPascal(parentName)}${goPascal(fieldName)}`
95
118
  }
96
119
 
97
- function renderHoistedStringEnum(typeName: string, enumVals: unknown[]): string {
120
+ function enumLabel(v: unknown): string {
121
+ if (typeof v === "string") return v === "" ? "Empty" : goExported(v)
122
+ if (typeof v === "number") return v < 0 ? `Neg${String(-v).replace(/\./g, "_")}` : String(v).replace(/\./g, "_")
123
+ return goExported(String(v))
124
+ }
125
+
126
+ function renderHoistedStringEnum(typeName: string, enumVals: unknown[], names: GoTypeNames): string {
98
127
  const l: string[] = []
99
128
  l.push(`type ${typeName} string`)
100
129
  l.push(`const (`)
130
+ const local = new NameScope()
101
131
  for (const v of enumVals) {
102
- const label = typeof v === "string" ? goPascal(v) : String(v)
103
- const val = typeof v === "string" ? JSON.stringify(v) : String(v)
104
- l.push(`\t${typeName}${label} ${typeName} = ${val}`)
132
+ if (v === null) continue
133
+ const constName = names.claimConst(local.claim(`${typeName}${enumLabel(v)}`))
134
+ l.push(`\t${constName} ${typeName} = ${goString(String(v))}`)
105
135
  }
106
136
  l.push(`)`)
107
137
  return l.join("\n")
108
138
  }
109
139
 
110
- function renderHoistedIntEnum(typeName: string, enumVals: unknown[]): string {
140
+ function renderHoistedIntEnum(typeName: string, enumVals: unknown[], names: GoTypeNames): string {
111
141
  const l: string[] = []
112
142
  l.push(`type ${typeName} int`)
113
143
  l.push(`const (`)
144
+ const local = new NameScope()
114
145
  for (const v of enumVals) {
115
- l.push(`\t${typeName}${String(v)} ${typeName} = ${String(v)}`)
146
+ if (typeof v !== "number" || !Number.isInteger(v)) continue
147
+ const constName = names.claimConst(local.claim(`${typeName}${enumLabel(v)}`))
148
+ l.push(`\t${constName} ${typeName} = ${String(v)}`)
116
149
  }
117
150
  l.push(`)`)
118
151
  return l.join("\n")
@@ -139,33 +172,48 @@ function constBaseType(val: unknown): string {
139
172
  return "string"
140
173
  }
141
174
 
175
+ function isNilable(t: string): boolean {
176
+ return (
177
+ t === "json.RawMessage" ||
178
+ t.startsWith("*") ||
179
+ t.startsWith("[]") ||
180
+ t.startsWith("map[") ||
181
+ t === "any" ||
182
+ t === "interface{}"
183
+ )
184
+ }
185
+
142
186
  /** Mutates `ctx.decls` when hoisting enums. */
143
187
  export function irRenderUse(ir: IRSchema, ctx: RenderUseCtx, depth = 0): string {
144
188
  if (depth > 12) return "json.RawMessage"
189
+ const names = ctx.names ?? DEFAULT_NAMES
145
190
 
146
191
  switch (ir.kind) {
147
192
  case "ref": {
148
- const goName = goPascal(ir.name)
149
- if (ctx.circularRefs?.has(goName)) return `*${goName}`
193
+ const goName = names.ref(ir.name)
194
+ if (ctx.circularRefs?.has(goName) || names.cyclic.has(ir.name)) return `*${goName}`
150
195
  return goName
151
196
  }
152
197
 
153
198
  case "allOf": {
154
199
  const firstRef = ir.parts.find((p) => p.kind === "ref")
155
- if (firstRef && firstRef.kind === "ref") return goPascal(firstRef.name)
200
+ if (ir.parts.length > 1 && ctx.names) {
201
+ /* several parts: hoist a struct that embeds/inlines them all */
202
+ const name = names.hoist(`${ctx.parentName}.${ctx.fieldName}`, hoistEnumName(ctx.parentName, ctx.fieldName))
203
+ if (!ctx.decls.has(name)) {
204
+ ctx.decls.set(name, "")
205
+ ctx.decls.set(name, irRenderTopLevel(name, ir, ctx.decls, undefined, names))
206
+ }
207
+ return name
208
+ }
209
+ if (firstRef && firstRef.kind === "ref") return names.ref(firstRef.name)
156
210
  return "json.RawMessage"
157
211
  }
158
212
 
159
213
  case "nullable": {
160
214
  const innerStr = irRenderUse(ir.inner, ctx, depth + 1)
161
215
  /* already-nilable forms need no pointer prefix */
162
- if (
163
- innerStr === "json.RawMessage" ||
164
- innerStr.startsWith("*") ||
165
- innerStr.startsWith("[]") ||
166
- innerStr.startsWith("map[")
167
- )
168
- return innerStr
216
+ if (isNilable(innerStr)) return innerStr
169
217
  return `*${innerStr}`
170
218
  }
171
219
 
@@ -176,12 +224,14 @@ export function irRenderUse(ir: IRSchema, ctx: RenderUseCtx, depth = 0): string
176
224
 
177
225
  case "scalar": {
178
226
  if (ir.enum) {
179
- const name = hoistEnumName(ctx.parentName, ctx.fieldName)
227
+ const name = names.hoist(`${ctx.parentName}.${ctx.fieldName}`, hoistEnumName(ctx.parentName, ctx.fieldName))
180
228
  if (!ctx.decls.has(name)) {
181
229
  if (ir.type === "string") {
182
- ctx.decls.set(name, renderHoistedStringEnum(name, ir.enum as unknown[]))
230
+ ctx.decls.set(name, renderHoistedStringEnum(name, ir.enum as unknown[], names))
231
+ } else if (ir.type === "integer") {
232
+ ctx.decls.set(name, renderHoistedIntEnum(name, ir.enum as unknown[], names))
183
233
  } else {
184
- ctx.decls.set(name, renderHoistedIntEnum(name, ir.enum as unknown[]))
234
+ return primitiveFor(ir.type) ?? "json.RawMessage"
185
235
  }
186
236
  }
187
237
  return name
@@ -196,8 +246,10 @@ export function irRenderUse(ir: IRSchema, ctx: RenderUseCtx, depth = 0): string
196
246
  }
197
247
 
198
248
  case "array": {
199
- const el = irRenderUse(ir.items, ctx, depth + 1)
200
- return `[]${el}`
249
+ const itemCtx = ctx.names ? { ...ctx, fieldName: `${ctx.fieldName}Item` } : ctx
250
+ const el = irRenderUse(ir.items, itemCtx, depth + 1)
251
+ /* a slice already breaks a recursive cycle */
252
+ return `[]${el.startsWith("*") && ir.items.kind === "ref" ? el.slice(1) : el}`
201
253
  }
202
254
 
203
255
  case "tuple": {
@@ -210,12 +262,21 @@ export function irRenderUse(ir: IRSchema, ctx: RenderUseCtx, depth = 0): string
210
262
  if (fields.length === 0) {
211
263
  if (additional) {
212
264
  const valType = irRenderUse(additional, ctx, depth + 1)
213
- return `map[string]${valType}`
265
+ return `map[string]${valType.startsWith("*") && additional.kind === "ref" ? valType.slice(1) : valType}`
214
266
  }
215
267
  if (additional === false) return "struct{}"
216
268
  return "map[string]interface{}"
217
269
  }
218
270
 
271
+ if (ctx.names) {
272
+ /* a named type: callers can construct it, and it can carry (un)marshal methods */
273
+ const name = names.hoist(`${ctx.parentName}.${ctx.fieldName}`, hoistEnumName(ctx.parentName, ctx.fieldName))
274
+ if (!ctx.decls.has(name)) {
275
+ ctx.decls.set(name, "")
276
+ ctx.decls.set(name, irRenderTopLevel(name, ir, ctx.decls, undefined, names))
277
+ }
278
+ return name
279
+ }
219
280
  return irRenderAnonStruct(ir, ctx, depth)
220
281
  }
221
282
 
@@ -234,30 +295,190 @@ export function irRenderUse(ir: IRSchema, ctx: RenderUseCtx, depth = 0): string
234
295
  }
235
296
  }
236
297
 
298
+ function sortFields(fields: IRField[]): IRField[] {
299
+ return fields.slice().sort((a, b) => cmpCodeUnit(a.name, b.name))
300
+ }
301
+
302
+ function fieldType(ft: string, required: boolean): string {
303
+ return !required && !isNilable(ft) ? `*${ft}` : ft
304
+ }
305
+
237
306
  function irRenderAnonStruct(ir: Extract<IRSchema, { kind: "object" }>, ctx: RenderUseCtx, depth: number): string {
238
- const sorted = ir.fields.slice().sort((a, b) => a.name.localeCompare(b.name))
239
307
  const lines: string[] = []
240
308
  lines.push(`struct {`)
241
- for (const field of sorted) {
242
- const fieldGoName = goPascal(field.name)
309
+ const scope = new NameScope()
310
+ for (const field of sortFields(ir.fields)) {
311
+ const fieldGoName = scope.claim(goPascal(field.name))
243
312
  const childParent = `${ctx.parentName}${goPascal(ctx.fieldName)}`
244
313
  const childCtx: RenderUseCtx = {
245
314
  circularRefs: ctx.circularRefs,
246
315
  decls: ctx.decls,
247
316
  depth: depth + 1,
248
317
  fieldName: field.name,
318
+ names: ctx.names,
249
319
  parentName: childParent,
250
320
  }
251
- const fieldType = irRenderUse(field.schema, childCtx, depth + 1)
252
- const alreadyNilable = fieldType.startsWith("*") || fieldType.startsWith("[]") || fieldType.startsWith("map[")
253
- const finalType = !field.required && !alreadyNilable ? `*${fieldType}` : fieldType
254
- const tag = goTag(field.name, !field.required)
255
- lines.push(`\t${fieldGoName} ${finalType} ${tag}`)
321
+ const type = structFieldType(field, (schema) => irRenderUse(schema, childCtx, depth + 1))
322
+ lines.push(`\t${fieldGoName} ${type} ${fieldTag(field)}`)
256
323
  }
257
324
  lines.push(`}`)
258
325
  return lines.join("\n")
259
326
  }
260
327
 
328
+ type StructField = {
329
+ goName: string
330
+ key: string
331
+ type: string
332
+ required: boolean
333
+ tagged: boolean
334
+ /** Optional + nullable: `Nullable[T]` under `omitzero`. */
335
+ triState: boolean
336
+ }
337
+
338
+ /** A struct plus, when needed, (un)marshal methods for keys encoding/json cannot tag and for extra keys. */
339
+ function renderStruct(
340
+ typeName: string,
341
+ embeds: string[],
342
+ fields: StructField[],
343
+ extra: { goName: string; valueType: string } | undefined,
344
+ ): string {
345
+ const l: string[] = []
346
+ l.push(`type ${typeName} struct {`)
347
+ for (const e of embeds) l.push(`\t${e}`)
348
+ for (const f of fields) {
349
+ const tag = f.tagged ? goTag(f.key, f.triState ? "omitzero" : !f.required) : '`json:"-"`'
350
+ l.push(`\t${f.goName} ${f.type} ${tag}`)
351
+ }
352
+ if (extra) l.push(`\t${extra.goName} map[string]${extra.valueType} \`json:"-"\``)
353
+ l.push(`}`)
354
+
355
+ const untagged = fields.filter((f) => !f.tagged)
356
+ /* a required slice or map left nil would encode as null, which the schema does not allow */
357
+ const emptyWhenNil = fields.filter(
358
+ (f) => f.required && !f.triState && (f.type.startsWith("[]") || f.type.startsWith("map[")),
359
+ )
360
+ const fillNil = (target: string): void => {
361
+ for (const f of emptyWhenNil) {
362
+ l.push(`\tif ${target}.${f.goName} == nil {`)
363
+ l.push(`\t\t${target}.${f.goName} = ${f.type}{}`)
364
+ l.push(`\t}`)
365
+ }
366
+ }
367
+ if (untagged.length === 0 && !extra) {
368
+ if (emptyWhenNil.length === 0) return l.join("\n")
369
+ l.push(``)
370
+ l.push(`func (s ${typeName}) MarshalJSON() ([]byte, error) {`)
371
+ l.push(`\ttype plain ${typeName}`)
372
+ l.push(`\tp := plain(s)`)
373
+ fillNil("p")
374
+ l.push(`\treturn json.Marshal(p)`)
375
+ l.push(`}`)
376
+ return l.join("\n")
377
+ }
378
+ const known = fields.map((f) => goString(f.key))
379
+ l.push(``)
380
+ l.push(`func (s *${typeName}) UnmarshalJSON(data []byte) error {`)
381
+ l.push(`\ttype plain ${typeName}`)
382
+ l.push(`\tvar base plain`)
383
+ l.push(`\tif err := json.Unmarshal(data, &base); err != nil {`)
384
+ l.push(`\t\treturn err`)
385
+ l.push(`\t}`)
386
+ l.push(`\tvar raw map[string]json.RawMessage`)
387
+ l.push(`\tif err := json.Unmarshal(data, &raw); err != nil {`)
388
+ l.push(`\t\treturn err`)
389
+ l.push(`\t}`)
390
+ for (const f of untagged) {
391
+ l.push(`\tif v, ok := raw[${goString(f.key)}]; ok {`)
392
+ l.push(`\t\tif err := json.Unmarshal(v, &base.${f.goName}); err != nil {`)
393
+ l.push(`\t\t\treturn err`)
394
+ l.push(`\t\t}`)
395
+ l.push(`\t}`)
396
+ }
397
+ if (extra) {
398
+ l.push(`\tknown := map[string]bool{${known.map((k) => `${k}: true`).join(", ")}}`)
399
+ l.push(`\tfor k, v := range raw {`)
400
+ l.push(`\t\tif known[k] {`)
401
+ l.push(`\t\t\tcontinue`)
402
+ l.push(`\t\t}`)
403
+ l.push(`\t\tvar item ${extra.valueType}`)
404
+ l.push(`\t\tif err := json.Unmarshal(v, &item); err != nil {`)
405
+ l.push(`\t\t\treturn err`)
406
+ l.push(`\t\t}`)
407
+ l.push(`\t\tif base.${extra.goName} == nil {`)
408
+ l.push(`\t\t\tbase.${extra.goName} = map[string]${extra.valueType}{}`)
409
+ l.push(`\t\t}`)
410
+ l.push(`\t\tbase.${extra.goName}[k] = item`)
411
+ l.push(`\t}`)
412
+ }
413
+ l.push(`\t*s = ${typeName}(base)`)
414
+ l.push(`\treturn nil`)
415
+ l.push(`}`)
416
+ l.push(``)
417
+ l.push(`func (s ${typeName}) MarshalJSON() ([]byte, error) {`)
418
+ l.push(`\ttype plain ${typeName}`)
419
+ l.push(`\tp := plain(s)`)
420
+ fillNil("p")
421
+ l.push(`\tencoded, err := json.Marshal(p)`)
422
+ l.push(`\tif err != nil {`)
423
+ l.push(`\t\treturn nil, err`)
424
+ l.push(`\t}`)
425
+ l.push(`\tvar out map[string]json.RawMessage`)
426
+ l.push(`\tif err := json.Unmarshal(encoded, &out); err != nil {`)
427
+ l.push(`\t\treturn nil, err`)
428
+ l.push(`\t}`)
429
+ if (extra) {
430
+ l.push(`\tfor k, v := range p.${extra.goName} {`)
431
+ l.push(`\t\tif _, taken := out[k]; taken {`)
432
+ l.push(`\t\t\tcontinue`)
433
+ l.push(`\t\t}`)
434
+ l.push(`\t\tb, err := json.Marshal(v)`)
435
+ l.push(`\t\tif err != nil {`)
436
+ l.push(`\t\t\treturn nil, err`)
437
+ l.push(`\t\t}`)
438
+ l.push(`\t\tout[k] = b`)
439
+ l.push(`\t}`)
440
+ }
441
+ for (const f of untagged) {
442
+ const nilable = isNilable(f.type)
443
+ const guarded = nilable || f.triState
444
+ const indent = guarded ? "\t\t" : "\t"
445
+ if (f.triState) l.push(`\tif !p.${f.goName}.IsZero() {`)
446
+ else if (nilable) l.push(`\tif p.${f.goName} != nil {`)
447
+ l.push(`${indent}b, err := json.Marshal(p.${f.goName})`)
448
+ l.push(`${indent}if err != nil {`)
449
+ l.push(`${indent}\treturn nil, err`)
450
+ l.push(`${indent}}`)
451
+ l.push(`${indent}out[${goString(f.key)}] = b`)
452
+ if (guarded) l.push(`\t}`)
453
+ }
454
+ l.push(`\treturn json.Marshal(out)`)
455
+ l.push(`}`)
456
+ return l.join("\n")
457
+ }
458
+
459
+ function discriminatorValues(
460
+ variant: IRSchema,
461
+ propertyName: string,
462
+ mapping: Record<string, string> | undefined,
463
+ names: GoTypeNames,
464
+ ): string[] {
465
+ if (variant.kind === "ref") {
466
+ const mapped = mapping
467
+ ? Object.entries(mapping)
468
+ .filter(([, target]) => target === variant.name)
469
+ .map(([k]) => k)
470
+ : []
471
+ if (mapped.length > 0) return mapped
472
+ }
473
+ const resolved = names.resolve(variant)
474
+ if (resolved.kind === "object") {
475
+ const f = resolved.fields.find((x) => x.name === propertyName)
476
+ if (f?.schema.kind === "const" && typeof f.schema.value === "string") return [f.schema.value]
477
+ if (f?.schema.kind === "scalar" && f.schema.enum) return f.schema.enum.map(String)
478
+ }
479
+ return variant.kind === "ref" ? [variant.name] : []
480
+ }
481
+
261
482
  /**
262
483
  * `raw` 4th arg is for the const-with-declared-type branch only: IR `const` kind
263
484
  * strips the type field; `raw.type` provides the override.
@@ -267,71 +488,131 @@ export function irRenderTopLevel(
267
488
  ir: IRSchema,
268
489
  decls: Map<string, string>,
269
490
  raw?: Record<string, unknown>,
491
+ names?: GoTypeNames,
270
492
  ): string {
271
- const typeName = goPascal(name)
493
+ const n = names ?? DEFAULT_NAMES
494
+ /* the schema name is already a Go identifier when the caller passes `names` */
495
+ const typeName = names ? name : goPascal(name)
272
496
  const circularRefs = new Set([typeName])
497
+ const useCtx = (fieldName: string): RenderUseCtx => ({
498
+ circularRefs,
499
+ decls,
500
+ fieldName,
501
+ names,
502
+ parentName: typeName,
503
+ })
273
504
 
274
505
  if (ir.kind === "scalar" && ir.enum) {
275
- if (ir.type === "string") {
276
- return renderHoistedStringEnum(typeName, ir.enum as unknown[])
277
- }
278
- return renderHoistedIntEnum(typeName, ir.enum as unknown[])
506
+ if (ir.type === "string") return renderHoistedStringEnum(typeName, ir.enum as unknown[], n)
507
+ if (ir.type === "integer") return renderHoistedIntEnum(typeName, ir.enum as unknown[], n)
279
508
  }
280
509
 
281
510
  if (ir.kind === "const") {
282
- const rawType = raw?.type as string | undefined
511
+ const rawType = ir.type ?? (raw?.type as string | undefined)
283
512
  const base = rawType ? (primitiveFor(rawType) ?? "string") : constBaseType(ir.value)
284
- const val = typeof ir.value === "string" ? JSON.stringify(ir.value) : String(ir.value)
285
- return [`type ${typeName} ${base}`, `const ${typeName}Value ${typeName} = ${val}`].join("\n")
513
+ const val = typeof ir.value === "string" ? goString(ir.value) : String(ir.value)
514
+ return [`type ${typeName} ${base}`, `const ${n.claimConst(`${typeName}Value`)} ${typeName} = ${val}`].join("\n")
286
515
  }
287
516
 
288
517
  if (ir.kind === "allOf") {
289
- const l: string[] = []
290
- l.push(`type ${typeName} struct {`)
518
+ const embeds: string[] = []
519
+ const fields: StructField[] = []
520
+ const scope = new NameScope(["UnmarshalJSON", "MarshalJSON"])
291
521
  for (const part of ir.parts) {
292
522
  if (part.kind === "ref") {
293
- l.push(`\t${goPascal(part.name)}`)
294
- continue
523
+ const embedded = n.ref(part.name)
524
+ scope.reserve(embedded)
525
+ embeds.push(n.cyclic.has(part.name) ? `*${embedded}` : embedded)
295
526
  }
296
- if (part.kind !== "object") continue
297
- const sorted = part.fields.slice().sort((a, b) => a.name.localeCompare(b.name))
298
- for (const field of sorted) {
299
- const fieldGoName = goPascal(field.name)
300
- const ft = irRenderUse(field.schema, {
301
- circularRefs,
302
- decls,
303
- fieldName: field.name,
304
- parentName: typeName,
527
+ }
528
+ for (const part of ir.parts) {
529
+ const obj = part.kind === "object" ? part : undefined
530
+ if (!obj) continue
531
+ for (const field of sortFields(obj.fields)) {
532
+ if (fields.some((f) => f.key === field.name)) continue
533
+ fields.push({
534
+ goName: scope.claim(goPascal(field.name)),
535
+ key: field.name,
536
+ required: field.required,
537
+ tagged: goJsonTagNameValid(field.name),
538
+ triState: isTriState(field),
539
+ type: structFieldType(field, (schema) => irRenderUse(schema, useCtx(field.name))),
305
540
  })
306
- const alreadyNilable = ft.startsWith("*") || ft.startsWith("[]") || ft.startsWith("map[")
307
- const finalType = !field.required && !alreadyNilable ? `*${ft}` : ft
308
- l.push(`\t${fieldGoName} ${finalType} ${goTag(field.name, !field.required)}`)
309
541
  }
310
542
  }
311
- l.push(`}`)
312
- return l.join("\n")
543
+ return renderStruct(typeName, embeds, fields, undefined)
313
544
  }
314
545
 
315
546
  if (ir.kind === "union" && ir.discriminator) {
316
- const discProp = ir.discriminator.propertyName
317
- return [
318
- `type ${typeName} struct {`,
319
- `\tType string ${goTag(discProp, false)}`,
320
- `\tPayload json.RawMessage ${goTag("payload", false)}`,
321
- `}`,
322
- ].join("\n")
547
+ const prop = ir.discriminator.propertyName
548
+ const scope = new NameScope(["Raw", "UnmarshalJSON", "MarshalJSON"])
549
+ const variants: Array<{ field: string; type: string; values: string[] }> = []
550
+ ir.variants.forEach((v, i) => {
551
+ const values = discriminatorValues(v, prop, ir.discriminator?.mapping, n)
552
+ let type: string
553
+ if (v.kind === "ref") {
554
+ type = n.ref(v.name)
555
+ } else if (v.kind === "object") {
556
+ const hoisted = n.hoist(`${typeName}.variant${i}`, `${typeName}${goPascal(values[0] ?? `Variant${i}`)}`)
557
+ if (!decls.has(hoisted)) {
558
+ decls.set(hoisted, "")
559
+ decls.set(hoisted, irRenderTopLevel(hoisted, v, decls, undefined, names))
560
+ }
561
+ type = hoisted
562
+ } else {
563
+ return
564
+ }
565
+ variants.push({ field: scope.claim(goPascal(values[0] ?? type)), type, values })
566
+ })
567
+ const l: string[] = []
568
+ l.push(`// ${typeName} holds exactly one variant, selected by the ${goString(prop)} property.`)
569
+ l.push(`type ${typeName} struct {`)
570
+ for (const v of variants) l.push(`\t${v.field} *${v.type}`)
571
+ l.push(`\t// Raw keeps a payload whose discriminator matches no known variant.`)
572
+ l.push(`\tRaw json.RawMessage`)
573
+ l.push(`}`)
574
+ l.push(``)
575
+ l.push(`func (u *${typeName}) UnmarshalJSON(data []byte) error {`)
576
+ l.push(`\tvar probe map[string]json.RawMessage`)
577
+ l.push(`\tif err := json.Unmarshal(data, &probe); err != nil {`)
578
+ l.push(`\t\treturn err`)
579
+ l.push(`\t}`)
580
+ l.push(`\tvar tag string`)
581
+ l.push(`\tif v, ok := probe[${goString(prop)}]; ok {`)
582
+ l.push(`\t\t_ = json.Unmarshal(v, &tag)`)
583
+ l.push(`\t}`)
584
+ l.push(`\t*u = ${typeName}{}`)
585
+ l.push(`\tswitch tag {`)
586
+ for (const v of variants) {
587
+ if (v.values.length === 0) continue
588
+ l.push(`\tcase ${v.values.map(goString).join(", ")}:`)
589
+ l.push(`\t\tu.${v.field} = new(${v.type})`)
590
+ l.push(`\t\treturn json.Unmarshal(data, u.${v.field})`)
591
+ }
592
+ l.push(`\t}`)
593
+ l.push(`\tu.Raw = append(json.RawMessage(nil), data...)`)
594
+ l.push(`\treturn nil`)
595
+ l.push(`}`)
596
+ l.push(``)
597
+ l.push(`func (u ${typeName}) MarshalJSON() ([]byte, error) {`)
598
+ for (const v of variants) {
599
+ l.push(`\tif u.${v.field} != nil {`)
600
+ l.push(`\t\treturn json.Marshal(u.${v.field})`)
601
+ l.push(`\t}`)
602
+ }
603
+ l.push(`\tif u.Raw != nil {`)
604
+ l.push(`\t\treturn u.Raw, nil`)
605
+ l.push(`\t}`)
606
+ l.push(`\treturn []byte("null"), nil`)
607
+ l.push(`}`)
608
+ return l.join("\n")
323
609
  }
324
610
 
325
611
  if (ir.kind === "object") {
326
612
  const { fields, additional } = ir
327
613
 
328
614
  if (fields.length === 0 && additional) {
329
- const valType = irRenderUse(additional, {
330
- circularRefs,
331
- decls,
332
- fieldName: "Value",
333
- parentName: typeName,
334
- })
615
+ const valType = irRenderUse(additional, useCtx("Value"))
335
616
  return `type ${typeName} map[string]${valType}`
336
617
  }
337
618
 
@@ -340,63 +621,33 @@ export function irRenderTopLevel(
340
621
  return `type ${typeName} map[string]interface{}`
341
622
  }
342
623
 
343
- const sorted = fields.slice().sort((a, b) => a.name.localeCompare(b.name))
344
- const l: string[] = []
345
- l.push(`type ${typeName} struct {`)
346
- for (const field of sorted) {
347
- const fieldGoName = goPascal(field.name)
348
- const ft = irRenderUse(field.schema, {
349
- circularRefs,
350
- decls,
351
- fieldName: field.name,
352
- parentName: typeName,
353
- })
354
- const alreadyNilable = ft.startsWith("*") || ft.startsWith("[]") || ft.startsWith("map[")
355
- let finalType = !field.required && !alreadyNilable ? `*${ft}` : ft
356
- /* self-ref → pointer (circular) */
357
- if (circularRefs.has(ft.replace(/^\*/, "")) && !finalType.startsWith("*")) {
358
- finalType = `*${ft}`
624
+ const scope = new NameScope(["UnmarshalJSON", "MarshalJSON"])
625
+ const extraName = additional ? scope.claim("Extra") : ""
626
+ const out: StructField[] = []
627
+ for (const field of sortFields(fields)) {
628
+ let finalType: string
629
+ if (isTriState(field)) {
630
+ finalType = structFieldType(field, (schema) => irRenderUse(schema, useCtx(field.name)))
631
+ } else {
632
+ const ft = irRenderUse(field.schema, useCtx(field.name))
633
+ finalType = fieldType(ft, field.required)
634
+ /* self-ref → pointer (circular) */
635
+ if (circularRefs.has(ft.replace(/^\*/, "")) && !finalType.startsWith("*")) finalType = `*${ft}`
359
636
  }
360
- l.push(`\t${fieldGoName} ${finalType} ${goTag(field.name, !field.required)}`)
361
- }
362
-
363
- if (additional) {
364
- const valType = irRenderUse(additional, {
365
- circularRefs,
366
- decls,
367
- fieldName: "Extra",
368
- parentName: typeName,
637
+ out.push({
638
+ goName: scope.claim(goPascal(field.name)),
639
+ key: field.name,
640
+ required: field.required,
641
+ tagged: goJsonTagNameValid(field.name),
642
+ triState: isTriState(field),
643
+ type: finalType,
369
644
  })
370
- l.push(`\tExtra map[string]${valType} \`json:"-"\``)
371
- l.push(`}`)
372
- l.push(``)
373
- l.push(`func (s *${typeName}) UnmarshalJSON(data []byte) error {`)
374
- l.push(`\ttype plain ${typeName}`)
375
- l.push(`\tvar base plain`)
376
- l.push(`\tif err := json.Unmarshal(data, &base); err != nil {`)
377
- l.push(`\t\treturn err`)
378
- l.push(`\t}`)
379
- l.push(`\t*s = ${typeName}(base)`)
380
- l.push(`\treturn nil`)
381
- l.push(`}`)
382
- l.push(``)
383
- l.push(`func (s ${typeName}) MarshalJSON() ([]byte, error) {`)
384
- l.push(`\ttype plain ${typeName}`)
385
- l.push(`\treturn json.Marshal(plain(s))`)
386
- l.push(`}`)
387
- return l.join("\n")
388
645
  }
389
-
390
- l.push(`}`)
391
- return l.join("\n")
646
+ const extra = additional ? { goName: extraName, valueType: irRenderUse(additional, useCtx("Extra")) } : undefined
647
+ return renderStruct(typeName, [], out, extra)
392
648
  }
393
649
 
394
- const aliased = irRenderUse(ir, {
395
- circularRefs,
396
- decls,
397
- fieldName: "Value",
398
- parentName: typeName,
399
- })
650
+ const aliased = irRenderUse(ir, useCtx("Value"))
400
651
  return `type ${typeName} = ${aliased}`
401
652
  }
402
653