@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
package/src/plugin.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { createHash } from "node:crypto"
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
3
- import { dirname, extname, resolve } from "node:path"
1
+ import { existsSync, readFileSync } from "node:fs"
2
+ import { dirname, resolve, sep } from "node:path"
3
+ import { createModuleLoader, honeyConfigOf, type ModuleLoader } from "./codegen-load.ts"
4
4
  import {
5
5
  generateManifest,
6
6
  generateOpenApi,
@@ -14,9 +14,13 @@ import {
14
14
  import type { OpenApiRouteInfo, OpenApiSanitizeOptions, OpenApiSpecInput } from "./codegen.ts"
15
15
  import type { Honey } from "./index.ts"
16
16
  import type { InvalidateCheckConfig } from "./invalidate-check.ts"
17
- import { overlaySchemas } from "./tree.ts"
17
+ import { detectFeaturesInSource, featurePrelude, importsFeatureEntry } from "./feature-detect.ts"
18
+ import { runCli } from "./gen-process.ts"
19
+ import { writeGenFile, writeGenJsonFile, writeGenYamlFile, writeOutputDir } from "./gen-write.ts"
20
+ import { WATCH_IGNORE_RE, compileGlobs } from "./glob.ts"
21
+ import { overlaySchemas, type RouteTree } from "./tree.ts"
18
22
  import type { ExtractedChainTypes } from "./type-extractor.ts"
19
- import { toYaml, yamlSiblingPath } from "./yaml.ts"
23
+ import { openApiOutputPaths, toYaml } from "./yaml.ts"
20
24
 
21
25
  export type { InvalidateCheckConfig, InvalidateCheckLevel } from "./invalidate-check.ts"
22
26
 
@@ -281,86 +285,69 @@ export function resolveHoneyConfig(raw: HoneyVitePluginConfig): ResolvedHoneyCon
281
285
  }
282
286
  }
283
287
 
284
- /* ---- Config stash for CLI ---- */
288
+ /* ---- Config stash ---- */
285
289
 
286
290
  let _lastConfig: HoneyVitePluginConfig | undefined
287
291
 
292
+ /**
293
+ * Config of the most recent `honey()` call in this module instance.
294
+ * @deprecated Read the config off the plugin object (`plugin.api.honeyConfig`); this is a single
295
+ * global and does not survive a second module instance.
296
+ */
288
297
  export function getLastHoneyConfig(): HoneyVitePluginConfig | undefined {
289
298
  return _lastConfig
290
299
  }
291
300
 
292
- /* ---- writeGenFile / writeGenJsonFile ---- */
301
+ /* ---- Outputs ---- */
293
302
 
294
- function writeGenFile(filePath: string, body: string, generator: string): boolean {
295
- const normalized = body.replace(/\n*$/, "\n")
296
- const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 12)
303
+ const TS_SDK_FILES = [
304
+ "sdk.types.gen.ts",
305
+ "sdk.map.gen.ts",
306
+ "sdk.client.gen.ts",
307
+ "sdk.index.gen.ts",
308
+ "sdk.runtime.gen.ts",
309
+ ]
297
310
 
298
- const ext = filePath.endsWith(".d.ts") ? ".d.ts" : extname(filePath)
299
- const header =
300
- ext === ".sql"
301
- ? `-- @generated by ${generator} — do not edit. checksum: ${hash}`
302
- : `/* @generated by ${generator} — do not edit. checksum: ${hash} */`
303
- const fullContent = `${header}\n${normalized}`
304
-
305
- if (existsSync(filePath)) {
306
- const existing = readFileSync(filePath, "utf-8")
307
- const firstLine = existing.split("\n")[0] ?? ""
308
- const match = firstLine.match(/checksum: ([0-9a-f]{12})/)
309
- if (match?.[1] === hash) return false
311
+ /** Every file and directory a generation writes, as absolute paths. Watchers must ignore these. */
312
+ export function generatedOutputs(config: ResolvedHoneyConfig, root: string): { dirs: string[]; files: string[] } {
313
+ const cg = config.codegen
314
+ const files: string[] = []
315
+ const dirs: string[] = []
316
+ if (cg.tree) files.push(resolve(root, cg.tree))
317
+ if (cg.types) files.push(resolve(root, cg.types.path))
318
+ if (cg.manifest) files.push(resolve(root, cg.manifest))
319
+ for (const entry of cg.openApi || []) {
320
+ const out = openApiOutputPaths(resolve(root, entry.path))
321
+ if (out.json) files.push(out.json)
322
+ files.push(out.yaml)
310
323
  }
311
-
312
- mkdirSync(dirname(filePath), { recursive: true })
313
- writeFileSync(filePath, fullContent, "utf-8")
314
- return true
315
- }
316
-
317
- function writeGenJsonFile(filePath: string, data: unknown, generator: string): boolean {
318
- const json = JSON.stringify(data, null, 2)
319
- const hash = createHash("sha256").update(json).digest("hex").slice(0, 12)
320
- const marker = `${generator} checksum:${hash}`
321
-
322
- if (existsSync(filePath)) {
323
- try {
324
- const existing = readFileSync(filePath, "utf-8")
325
- const parsed = JSON.parse(existing) as Record<string, unknown>
326
- if (parsed._generated === marker) return false
327
- } catch {
328
- /* invalid JSON — proceed to write */
324
+ if (cg.sdk) {
325
+ const ports = cg.sdk.ports
326
+ if (ports.typescript) {
327
+ const outDir = resolve(root, ports.typescript.outDir)
328
+ files.push(...TS_SDK_FILES.map((name) => resolve(outDir, name)))
329
329
  }
330
+ if (ports.python) dirs.push(resolve(root, ports.python.outDir))
331
+ if (ports.go) dirs.push(resolve(root, ports.go.outDir))
332
+ if (ports.rust) dirs.push(resolve(root, ports.rust.outDir))
330
333
  }
331
-
332
- const output = { _generated: marker, ...(data as Record<string, unknown>) }
333
- mkdirSync(dirname(filePath), { recursive: true })
334
- writeFileSync(filePath, `${JSON.stringify(output, null, 2)}\n`, "utf-8")
335
- return true
334
+ if (cg.cli) dirs.push(resolve(root, cg.cli.out))
335
+ return { dirs, files }
336
336
  }
337
337
 
338
- function writeGenYamlFile(filePath: string, data: unknown, generator: string): boolean {
339
- const json = JSON.stringify(data, null, 2)
340
- const hash = createHash("sha256").update(json).digest("hex").slice(0, 12)
341
- const marker = `${generator} checksum:${hash}`
342
- const output = { _generated: marker, ...(data as Record<string, unknown>) }
343
- const yaml = toYaml(output)
344
-
345
- if (existsSync(filePath)) {
346
- const existing = readFileSync(filePath, "utf-8")
347
- if (existing.includes(marker)) return false
348
- }
349
-
350
- mkdirSync(dirname(filePath), { recursive: true })
351
- writeFileSync(filePath, yaml, "utf-8")
352
- return true
338
+ export function isGeneratedOutput(file: string, outputs: { dirs: string[]; files: string[] }): boolean {
339
+ const abs = resolve(file)
340
+ if (outputs.files.includes(abs)) return true
341
+ return outputs.dirs.some((dir) => abs === dir || abs.startsWith(dir + sep))
353
342
  }
354
343
 
355
344
  /* ---- Loaders ---- */
356
345
 
357
346
  type HoneyApp = Honey<unknown, unknown, unknown, unknown, unknown, string, string>
358
- type TreeResult = { root: import("./tree.ts").TreeNode }
347
+ type TreeResult = RouteTree
359
348
 
360
- async function loadDefaultWithJiti(entryPath: string): Promise<unknown> {
361
- const { createJiti } = await import("jiti")
362
- const jiti = createJiti(entryPath, { fsCache: false, interopDefault: true, moduleCache: false })
363
- const mod = (await jiti.import(entryPath)) as Record<string, unknown>
349
+ async function loadAppOrTree(load: ModuleLoader, entryPath: string): Promise<unknown> {
350
+ const mod = await load(entryPath)
364
351
 
365
352
  /* prefer named exports, then unwrap interop default */
366
353
  if (mod.app && isHoneyApp(mod.app)) return mod.app
@@ -389,21 +376,60 @@ function isRouteTree(val: unknown): val is TreeResult {
389
376
 
390
377
  /* ---- Generation ---- */
391
378
 
392
- export async function generateAndWrite(config: ResolvedHoneyConfig, root: string): Promise<void> {
379
+ /**
380
+ * The tree a `codegen.mergeTree` gateway serves: the merged downstream tree plus the routes
381
+ * the gateway app registers itself. Its root wildcard stays out — the downstream leaves
382
+ * delegate to it. Without a configured app the merged tree is served as is.
383
+ */
384
+ async function gatewayTree(load: ModuleLoader, source: RouteTree, appPath: string | undefined): Promise<RouteTree> {
385
+ if (appPath === undefined) return source
386
+ const exported = await loadAppOrTree(load, appPath)
387
+ if (!isHoneyApp(exported)) throw new Error(`Expected Honey app default export in ${appPath}`)
388
+ return exported._gatewayTree(source)
389
+ }
390
+
391
+ export type GenerateOptions = {
392
+ /**
393
+ * Loads the app, merge tree and type sources. Defaults to a fresh jiti loader per call. Modules
394
+ * imported transitively may still come from the runtime's cache under Bun — run generation in
395
+ * its own process (`honey generate`) when that matters.
396
+ */
397
+ load?: ModuleLoader
398
+ }
399
+
400
+ export async function generateAndWrite(
401
+ config: ResolvedHoneyConfig,
402
+ root: string,
403
+ options: GenerateOptions = {},
404
+ ): Promise<void> {
393
405
  await prepareCodegen()
394
406
  const cg = config.codegen
407
+ let load = options.load ?? (await createModuleLoader({ fresh: true, from: resolve(root, "index.ts") }))
395
408
 
396
409
  /* phase 1: route tree — from mergeTree source or app */
397
410
  let mergeSource: TreeResult | undefined
398
411
  if (cg.tree && (cg.mergeTree || config.app)) {
399
412
  const treeSrc = resolve(root, cg.mergeTree ?? config.app ?? "")
400
- const exported = await loadDefaultWithJiti(treeSrc)
413
+ const exported = await loadAppOrTree(load, treeSrc)
401
414
 
402
415
  let treeCode: string
403
416
  if (isHoneyApp(exported)) {
404
417
  treeCode = generateRouteTreeFromApp(exported)
405
418
  } else if (isRouteTree(exported)) {
406
- treeCode = generateRouteTreeFromRouteTree(exported)
419
+ const appPath = cg.mergeTree && config.app ? resolve(root, config.app) : undefined
420
+ const treePath = resolve(root, cg.tree)
421
+ let tree: RouteTree
422
+ try {
423
+ tree = await gatewayTree(load, exported, appPath)
424
+ } catch (err) {
425
+ /* first run: the gateway app imports the tree this pass writes. Write the merged
426
+ downstream tree, then load the app again over it to add its own routes. */
427
+ if (appPath === undefined || existsSync(treePath)) throw err
428
+ writeGenFile(treePath, generateRouteTreeFromRouteTree(exported), "honey")
429
+ load = await createModuleLoader({ fresh: true, from: resolve(root, "index.ts") })
430
+ tree = await gatewayTree(load, exported, appPath)
431
+ }
432
+ treeCode = generateRouteTreeFromRouteTree(tree)
407
433
  mergeSource = exported
408
434
  } else {
409
435
  throw new Error(`Expected Honey app or RouteTree default export in ${treeSrc}`)
@@ -411,7 +437,7 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
411
437
 
412
438
  writeGenFile(resolve(root, cg.tree), treeCode, "honey")
413
439
  } else if (cg.mergeTree && cg.openApi) {
414
- const exported = await loadDefaultWithJiti(resolve(root, cg.mergeTree))
440
+ const exported = await loadAppOrTree(load, resolve(root, cg.mergeTree))
415
441
  if (isRouteTree(exported)) mergeSource = exported
416
442
  }
417
443
 
@@ -426,13 +452,14 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
426
452
  throw new Error("No app configured — required for types/manifest/openapi/sdk without specs/cli")
427
453
  }
428
454
  appPath = resolve(root, config.app)
429
- const appExported = await loadDefaultWithJiti(appPath)
455
+ /* the loader evaluates each file once, so the tree pass above did not cost a second load */
456
+ const appExported = await loadAppOrTree(load, appPath)
430
457
  if (!isHoneyApp(appExported)) {
431
458
  throw new Error(`Expected Honey app default export in ${appPath}`)
432
459
  }
433
460
  app = appExported
434
461
  /* the app serves the intern tree (no schemas); document merged routes from their source */
435
- if (mergeSource) overlaySchemas(app.toRouteTree().root, mergeSource.root)
462
+ if (mergeSource) overlaySchemas(app, mergeSource)
436
463
  }
437
464
 
438
465
  /* manifest */
@@ -461,9 +488,9 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
461
488
  if (entry.sanitize) {
462
489
  spec = sanitizeOpenApiSpec(spec, entry.sanitize)
463
490
  }
464
- const jsonPath = resolve(root, entry.path)
465
- writeGenJsonFile(jsonPath, spec, "honey")
466
- writeGenYamlFile(yamlSiblingPath(jsonPath), spec, "honey")
491
+ const out = openApiOutputPaths(resolve(root, entry.path))
492
+ if (out.json) writeGenJsonFile(out.json, spec, "honey")
493
+ writeGenYamlFile(out.yaml, spec, "honey")
467
494
  }
468
495
  }
469
496
 
@@ -480,20 +507,13 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
480
507
  })
481
508
 
482
509
  /* prefer appBase (middleware-only, simpler type) over app (with routes) */
483
- let extracted: ExtractedChainTypes
484
- try {
485
- extracted = await extractChainTypes({
486
- entryPath: appPath,
487
- exportName: "appBase",
488
- outputDir: typesDir,
489
- })
490
- } catch {
491
- extracted = await extractChainTypes({
492
- entryPath: appPath,
493
- exportName: "app",
494
- outputDir: typesDir,
495
- })
496
- }
510
+ const appModule = await load(appPath)
511
+ const exportName = "appBase" in appModule ? "appBase" : "app"
512
+ const extracted: ExtractedChainTypes = await extractChainTypes({
513
+ entryPath: appPath,
514
+ exportName,
515
+ outputDir: typesDir,
516
+ })
497
517
 
498
518
  if (!app) throw new Error("Type generation requires a configured app")
499
519
  const typesCode = generateTypes(app, {
@@ -507,9 +527,22 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
507
527
  writeGenFile(typesPath, typesCode, "honey")
508
528
  }
509
529
 
530
+ /* The SDK and Go CLI share one unfiltered document. With openApi outputs the invalidate check
531
+ * already ran on the first of them, so it is not reported again; without, it runs here once. */
532
+ let unfiltered: Promise<OpenApiSpecInput> | undefined
533
+ const unfilteredSpec = (what: string): Promise<OpenApiSpecInput> => {
534
+ if (!app) throw new Error(`${what} generation requires a configured app`)
535
+ const primaryOA = cg.openApi && cg.openApi.length > 0 ? cg.openApi[0] : null
536
+ unfiltered ??= generateOpenApi(app, {
537
+ info: primaryOA ? { title: primaryOA.title, version: primaryOA.version } : { title: "API", version: "1.0.0" },
538
+ invalidate: primaryOA ? "off" : cg.invalidate,
539
+ })
540
+ return unfiltered
541
+ }
542
+
510
543
  /* sdk */
511
544
  if (cg.sdk) {
512
- const { generateOpenApi: genOA, generateSDK: genSDK, mergeSpecs } = await import("./codegen.ts")
545
+ const { generateSDK: genSDK, mergeSpecs } = await import("./codegen.ts")
513
546
 
514
547
  let spec: OpenApiSpecInput
515
548
  if (cg.sdk.specs && cg.sdk.specs.length > 0) {
@@ -519,12 +552,7 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
519
552
  })
520
553
  spec = mergeSpecs(...specs)
521
554
  } else {
522
- if (!app) throw new Error("SDK generation requires a configured app or specs")
523
- const primaryOA = cg.openApi && cg.openApi.length > 0 ? cg.openApi[0] : null
524
- const info = primaryOA
525
- ? { title: primaryOA.title, version: primaryOA.version }
526
- : { title: "API", version: "1.0.0" }
527
- spec = await genOA(app, { info })
555
+ spec = await unfilteredSpec("SDK")
528
556
  }
529
557
 
530
558
  const ports = cg.sdk.ports
@@ -544,34 +572,19 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
544
572
  if (ports.python) {
545
573
  const { generatePythonSDK } = await import("./codegen-python.ts")
546
574
  const { files } = generatePythonSDK(spec, { name: cg.sdk.name })
547
- const outDir = resolve(root, ports.python.outDir)
548
- for (const [filename, content] of Object.entries(files)) {
549
- const absPath = resolve(outDir, filename)
550
- mkdirSync(dirname(absPath), { recursive: true })
551
- writeFileSync(absPath, content, "utf-8")
552
- }
575
+ writeOutputDir(resolve(root, ports.python.outDir), files)
553
576
  }
554
577
 
555
578
  if (ports.go) {
556
579
  const { generateGoSDK } = await import("./codegen-go.ts")
557
580
  const { files } = generateGoSDK(spec, { modulePath: ports.go.modulePath })
558
- const outDir = resolve(root, ports.go.outDir)
559
- for (const [filename, content] of Object.entries(files)) {
560
- const absPath = resolve(outDir, filename)
561
- mkdirSync(dirname(absPath), { recursive: true })
562
- writeFileSync(absPath, content, "utf-8")
563
- }
581
+ writeOutputDir(resolve(root, ports.go.outDir), files)
564
582
  }
565
583
 
566
584
  if (ports.rust) {
567
585
  const { generateRustSDK } = await import("./codegen-rust.ts")
568
586
  const { files } = generateRustSDK(spec, { crateName: ports.rust.crateName })
569
- const outDir = resolve(root, ports.rust.outDir)
570
- for (const [relPath, content] of Object.entries(files)) {
571
- const absPath = resolve(outDir, relPath)
572
- mkdirSync(dirname(absPath), { recursive: true })
573
- writeFileSync(absPath, content, "utf-8")
574
- }
587
+ writeOutputDir(resolve(root, ports.rust.outDir), files)
575
588
  }
576
589
  }
577
590
 
@@ -579,10 +592,7 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
579
592
  if (cg.cli) {
580
593
  const { generateGoCLI } = await import("./codegen-go-cli.ts")
581
594
 
582
- const primaryOA = cg.openApi && cg.openApi.length > 0 ? cg.openApi[0] : null
583
- const info = primaryOA ? { title: primaryOA.title, version: primaryOA.version } : { title: "API", version: "1.0.0" }
584
- if (!app) throw new Error("CLI generation requires a configured app")
585
- const spec = await generateOpenApi(app, { info })
595
+ const spec = await unfilteredSpec("CLI")
586
596
 
587
597
  const { files } = generateGoCLI(spec, {
588
598
  binaryName: cg.cli.binaryName,
@@ -592,13 +602,7 @@ export async function generateAndWrite(config: ResolvedHoneyConfig, root: string
592
602
  modulePath: cg.cli.modulePath,
593
603
  sdkModulePath: cg.cli.sdkModulePath,
594
604
  })
595
-
596
- const outDir = resolve(root, cg.cli.out)
597
- for (const [relPath, content] of Object.entries(files)) {
598
- const absPath = resolve(outDir, relPath)
599
- mkdirSync(dirname(absPath), { recursive: true })
600
- writeFileSync(absPath, content, "utf-8")
601
- }
605
+ writeOutputDir(resolve(root, cg.cli.out), files)
602
606
  }
603
607
  }
604
608
 
@@ -611,67 +615,141 @@ const RESOLVED_ROUTES = `\0${VIRTUAL_ROUTES}`
611
615
  const RESOLVED_MANIFEST = `\0${VIRTUAL_MANIFEST}`
612
616
  const RESOLVED_OPENAPI = `\0${VIRTUAL_OPENAPI}`
613
617
 
614
- function matchesGlob(filePath: string, patterns: string[]): boolean {
615
- for (const pattern of patterns) {
616
- const re = pattern
617
- .replace(/[.+^${}()|[\]\\]/g, "\\$&")
618
- .replace(/\*\*\//g, "(.+/)?")
619
- .replace(/\*/g, "[^/]*")
620
- if (new RegExp(`(^|/)${re}$`).test(filePath)) return true
618
+ type ModuleGraphLike = { getModuleById(id: string): unknown }
619
+
620
+ type PluginThis = {
621
+ environment?: { config?: { consumer?: string }; moduleGraph?: ModuleGraphLike }
622
+ }
623
+
624
+ type ResolvedViteConfigLike = {
625
+ command?: "build" | "serve"
626
+ configFile?: string
627
+ mode?: string
628
+ plugins?: readonly unknown[]
629
+ root: string
630
+ }
631
+
632
+ type HotUpdateContext = {
633
+ file: string
634
+ modules: unknown[]
635
+ server: { moduleGraph: ModuleGraphLike }
636
+ timestamp?: number
637
+ }
638
+
639
+ /* the route tree codegen emits TypeScript; a virtual module must be JavaScript in dev */
640
+ async function toJavaScript(code: string): Promise<{ code: string; moduleType: string }> {
641
+ try {
642
+ const vite = (await import("vite")) as {
643
+ transformWithOxc?: (code: string, file: string, options: Record<string, unknown>) => Promise<{ code: string }>
644
+ }
645
+ if (vite.transformWithOxc) {
646
+ const out = await vite.transformWithOxc(code, "routes.gen.ts", { lang: "ts", sourcemap: false })
647
+ return { code: out.code, moduleType: "js" }
648
+ }
649
+ } catch {
650
+ /* no Vite 8 transform available — let the bundler strip types */
621
651
  }
622
- return false
652
+ return { code, moduleType: "ts" }
623
653
  }
624
654
 
625
655
  export function honey(config: HoneyVitePluginConfig) {
626
656
  _lastConfig = config
627
657
 
628
658
  const resolved = resolveHoneyConfig(config)
659
+ const watchPatterns = config.watch ?? []
660
+ const matchesWatch = compileGlobs(watchPatterns)
629
661
 
630
662
  let root = ""
663
+ let configFile: string | undefined
664
+ let pluginIndex = -1
665
+ let command: "build" | "serve" = "build"
666
+ let mode = "production"
667
+ let outputs: { dirs: string[]; files: string[] } = { dirs: [], files: [] }
668
+
669
+ /* one generation at a time; any request during a run schedules exactly one more */
670
+ let running: Promise<void> | undefined
671
+ let rerun: Promise<void> | undefined
672
+ let starting: Promise<void> | undefined
673
+ const savesSeen = new Map<string, Promise<void>>()
674
+
675
+ async function generateOnce(): Promise<void> {
676
+ if (configFile && pluginIndex >= 0) {
677
+ /* a child process: fresh module graph, and the app's side effects die with it */
678
+ await runCli(["generate", "--config", configFile, "--plugin", String(pluginIndex)], {
679
+ cwd: root,
680
+ env: { HONEY_VITE_COMMAND: command, HONEY_VITE_MODE: mode },
681
+ })
682
+ return
683
+ }
684
+ await generateAndWrite(resolved, root)
685
+ }
631
686
 
632
- const plugin: {
633
- buildStart(): Promise<void>
634
- configResolved(cfg: { root: string }): void
635
- hotUpdate(ctx: {
636
- file: string
637
- modules: unknown[]
638
- server: {
639
- moduleGraph: { getModuleById(id: string): unknown }
640
- reloadModule(mod: unknown): void
641
- }
642
- }): Promise<unknown[] | undefined>
643
- load(id: string): Promise<{ code: string; moduleType: string } | undefined>
644
- name: string
645
- resolveId(id: string): string | undefined
646
- transform(code: string, id: string): { code: string; map: null } | undefined
647
- } = {
687
+ function regenerate(): Promise<void> {
688
+ if (!running) {
689
+ running = generateOnce().finally(() => {
690
+ running = undefined
691
+ })
692
+ return running
693
+ }
694
+ if (!rerun) {
695
+ rerun = running
696
+ .catch(() => undefined)
697
+ .then(() => {
698
+ rerun = undefined
699
+ return regenerate()
700
+ })
701
+ }
702
+ return rerun
703
+ }
704
+
705
+ const plugin = {
706
+ /** Read by `honey generate` to find this plugin's config in a loaded Vite config. */
707
+ api: { honeyConfig: config },
708
+
709
+ /* Vite calls this once per environment, back to back: the second joins the running
710
+ * generation instead of queueing another. A later buildStart (a watch rebuild) runs anew. */
648
711
  async buildStart() {
649
- await generateAndWrite(resolved, root)
712
+ starting ??= regenerate().finally(() => {
713
+ starting = undefined
714
+ })
715
+ await starting
650
716
  },
651
717
 
652
- configResolved(cfg: { root: string }) {
718
+ configResolved(cfg: ResolvedViteConfigLike) {
653
719
  root = cfg.root
720
+ configFile = cfg.configFile
721
+ command = cfg.command ?? "build"
722
+ mode = cfg.mode ?? (command === "serve" ? "development" : "production")
723
+ outputs = generatedOutputs(resolved, root)
724
+ const honeyPlugins = (cfg.plugins ?? []).filter((p) => honeyConfigOf(p) !== undefined)
725
+ pluginIndex = honeyPlugins.findIndex((p) => p === plugin || honeyConfigOf(p) === config)
654
726
  },
655
727
 
656
- async hotUpdate(ctx: {
657
- file: string
658
- modules: unknown[]
659
- server: {
660
- moduleGraph: { getModuleById(id: string): unknown }
661
- reloadModule(mod: unknown): void
728
+ /**
729
+ * Regenerates when a watched file changes, then lets Vite's normal HMR proceed, adding the
730
+ * virtual route tree to the update. Vite calls this once per environment; the generation
731
+ * runs once per save.
732
+ */
733
+ async hotUpdate(this: PluginThis | void, ctx: HotUpdateContext): Promise<unknown[] | undefined> {
734
+ if (watchPatterns.length === 0) return undefined
735
+ if (WATCH_IGNORE_RE.test(ctx.file) || isGeneratedOutput(ctx.file, outputs)) return undefined
736
+ if (!matchesWatch(ctx.file, root)) return undefined
737
+
738
+ const key = `${ctx.file}\0${ctx.timestamp ?? Date.now()}`
739
+ let run = savesSeen.get(key)
740
+ if (!run) {
741
+ run = regenerate().catch((err: unknown) => {
742
+ console.error("honey: generation failed", err)
743
+ })
744
+ savesSeen.set(key, run)
745
+ if (savesSeen.size > 64) savesSeen.delete(savesSeen.keys().next().value as string)
662
746
  }
663
- }) {
664
- const patterns = config.watch
665
- if (!patterns || patterns.length === 0) return
666
- if (!matchesGlob(ctx.file, patterns)) return
667
-
668
- await generateAndWrite(resolved, root)
747
+ await run
669
748
 
670
- const mod = ctx.server.moduleGraph.getModuleById(RESOLVED_ROUTES)
671
- if (mod) {
672
- ctx.server.reloadModule(mod)
673
- }
674
- return []
749
+ const graph = (this && this.environment?.moduleGraph) || ctx.server.moduleGraph
750
+ const routes = graph.getModuleById(RESOLVED_ROUTES)
751
+ if (!routes || ctx.modules.includes(routes)) return undefined
752
+ return [...ctx.modules, routes]
675
753
  },
676
754
 
677
755
  async load(id: string): Promise<{ code: string; moduleType: string } | undefined> {
@@ -682,21 +760,23 @@ export function honey(config: HoneyVitePluginConfig) {
682
760
  const treeSrc = resolved.codegen.mergeTree
683
761
  ? resolve(root, resolved.codegen.mergeTree)
684
762
  : resolve(root, config.app ?? "")
685
- const exported = await loadDefaultWithJiti(treeSrc)
763
+ const load = await createModuleLoader({ fresh: true, from: treeSrc })
764
+ const exported = await loadAppOrTree(load, treeSrc)
686
765
  let code: string
687
766
  if (isHoneyApp(exported)) {
688
767
  code = generateRouteTreeFromApp(exported)
689
768
  } else if (isRouteTree(exported)) {
690
- code = generateRouteTreeFromRouteTree(exported)
769
+ const appPath = resolved.codegen.mergeTree && config.app ? resolve(root, config.app) : undefined
770
+ code = generateRouteTreeFromRouteTree(await gatewayTree(load, exported, appPath))
691
771
  } else {
692
772
  throw new Error(`Expected Honey app or RouteTree in ${treeSrc}`)
693
773
  }
694
- return { code, moduleType: "js" }
774
+ return toJavaScript(code)
695
775
  }
696
776
  if (id === RESOLVED_MANIFEST && resolved.codegen.manifest) {
697
777
  if (!config.app) throw new Error("Manifest virtual module requires app")
698
778
  const appPath = resolve(root, config.app)
699
- const exported = await loadDefaultWithJiti(appPath)
779
+ const exported = await loadAppOrTree(await createModuleLoader({ fresh: true, from: appPath }), appPath)
700
780
  if (isHoneyApp(exported)) {
701
781
  const manifest = generateManifest(exported)
702
782
  return {
@@ -706,10 +786,10 @@ export function honey(config: HoneyVitePluginConfig) {
706
786
  }
707
787
  }
708
788
  if (id === RESOLVED_OPENAPI && resolved.codegen.openApi) {
709
- const primary = resolved.codegen.openApi[0]
789
+ const primary = resolved.codegen.openApi[0] as ResolvedOpenApiOutput
710
790
  if (!config.app) throw new Error("OpenAPI virtual module requires app")
711
791
  const appPath = resolve(root, config.app)
712
- const exported = await loadDefaultWithJiti(appPath)
792
+ const exported = await loadAppOrTree(await createModuleLoader({ fresh: true, from: appPath }), appPath)
713
793
  if (isHoneyApp(exported)) {
714
794
  let spec = await generateOpenApi(exported, {
715
795
  filterRoutes: primary.filterRoutes,
@@ -718,6 +798,9 @@ export function honey(config: HoneyVitePluginConfig) {
718
798
  title: primary.title,
719
799
  version: primary.version,
720
800
  },
801
+ /* generation already reported; a virtual module load must not repeat it */
802
+ invalidate: "off",
803
+ profile: primary.profile,
721
804
  securitySchemes: primary.securitySchemes,
722
805
  })
723
806
  if (primary.sanitize) {
@@ -734,20 +817,22 @@ export function honey(config: HoneyVitePluginConfig) {
734
817
 
735
818
  name: "honey",
736
819
 
737
- transform(code: string, id: string): { code: string; map: null } | undefined {
820
+ /**
821
+ * Imports the entries of optional features a module uses, ahead of its code, on the same
822
+ * line so line numbers stay put. Server environments only: browser code never serves.
823
+ */
824
+ transform(this: PluginThis | void, code: string, id: string): { code: string; map: null } | undefined {
825
+ if (this && this.environment?.config?.consumer === "client") return undefined
738
826
  if (id.includes("\0") || id.includes("node_modules")) return undefined
739
- const inject: string[] = []
740
- if (/\.openapi\s*\(|\.manifest\s*\(/.test(code) && !code.includes("@lovrozagar/honey/openapi")) {
741
- inject.push('import { enableOpenApi } from "@lovrozagar/honey/openapi"', "enableOpenApi()")
742
- }
743
- if (/(?<!Bun)(?<!Deno)\.serve\s*\(/.test(code) && !code.includes("@lovrozagar/honey/serve")) {
744
- inject.push('import { enableServe } from "@lovrozagar/honey/serve"', "enableServe()")
745
- }
746
- if (/\.errorI18n\s*\(/.test(code) && !code.includes("@lovrozagar/honey/i18n")) {
747
- inject.push('import { enableI18n } from "@lovrozagar/honey/i18n"', "enableI18n()")
827
+ const features = [...detectFeaturesInSource(code)].filter((f) => !importsFeatureEntry(code, f))
828
+ if (features.length === 0) return undefined
829
+ const prelude = featurePrelude(features)
830
+ if (code.startsWith("#!")) {
831
+ const eol = code.indexOf("\n")
832
+ if (eol === -1) return { code: `${code}\n${prelude}`, map: null }
833
+ return { code: `${code.slice(0, eol + 1)}${prelude} ${code.slice(eol + 1)}`, map: null }
748
834
  }
749
- if (inject.length === 0) return undefined
750
- return { code: `${inject.join("\n")}\n${code}`, map: null }
835
+ return { code: `${prelude} ${code}`, map: null }
751
836
  },
752
837
 
753
838
  resolveId(id: string): string | undefined {