tapimo 0.11.0 → 0.13.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 (443) hide show
  1. package/dist/App.d.ts +6396 -4575
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +39 -4
  4. package/dist/App.js.map +1 -1
  5. package/dist/Assets.d.ts +15 -0
  6. package/dist/Assets.d.ts.map +1 -1
  7. package/dist/Assets.js +7 -0
  8. package/dist/Assets.js.map +1 -1
  9. package/dist/Scope.d.ts +2 -0
  10. package/dist/Scope.d.ts.map +1 -1
  11. package/dist/Scope.js +17 -0
  12. package/dist/Scope.js.map +1 -1
  13. package/dist/admin/App.d.ts +176 -78
  14. package/dist/admin/App.d.ts.map +1 -1
  15. package/dist/admin/apps/api-keys.d.ts +84 -4
  16. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  17. package/dist/admin/apps/api-keys.js +54 -0
  18. package/dist/admin/apps/api-keys.js.map +1 -1
  19. package/dist/admin/apps/earn-vaults.d.ts +123 -9
  20. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  21. package/dist/admin/apps/earn-vaults.js +60 -7
  22. package/dist/admin/apps/earn-vaults.js.map +1 -1
  23. package/dist/admin/apps/organizations.d.ts.map +1 -1
  24. package/dist/admin/apps/organizations.js +4 -2
  25. package/dist/admin/apps/organizations.js.map +1 -1
  26. package/dist/admin/apps/verified-tokens.d.ts +90 -90
  27. package/dist/admin/ui.generated.d.ts +1 -1
  28. package/dist/admin/ui.generated.js +71 -71
  29. package/dist/admin/ui.generated.js.map +1 -1
  30. package/dist/apps/Zones.d.ts +16 -16
  31. package/dist/apps/Zones.js +4 -4
  32. package/dist/apps/data/App.d.ts +1699 -749
  33. package/dist/apps/data/App.d.ts.map +1 -1
  34. package/dist/apps/data/App.js +58 -9
  35. package/dist/apps/data/App.js.map +1 -1
  36. package/dist/apps/data/ZoneSelection.d.ts +62 -0
  37. package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
  38. package/dist/apps/data/ZoneSelection.js +44 -0
  39. package/dist/apps/data/ZoneSelection.js.map +1 -0
  40. package/dist/apps/data/routes/activities.d.ts +2417 -50
  41. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  42. package/dist/apps/data/routes/activities.js +1896 -1293
  43. package/dist/apps/data/routes/activities.js.map +1 -1
  44. package/dist/apps/data/routes/addresses.d.ts +471 -340
  45. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  46. package/dist/apps/data/routes/balances.d.ts +12 -12
  47. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  48. package/dist/apps/data/routes/balances.js +44 -17
  49. package/dist/apps/data/routes/balances.js.map +1 -1
  50. package/dist/apps/data/routes/blocks.d.ts +42 -42
  51. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  52. package/dist/apps/data/routes/blocks.js +22 -12
  53. package/dist/apps/data/routes/blocks.js.map +1 -1
  54. package/dist/apps/data/routes/coingecko.d.ts +179 -179
  55. package/dist/apps/data/routes/earn.d.ts +144 -19
  56. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  57. package/dist/apps/data/routes/earn.js +160 -28
  58. package/dist/apps/data/routes/earn.js.map +1 -1
  59. package/dist/apps/data/routes/exchanges.d.ts +719 -13
  60. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  61. package/dist/apps/data/routes/exchanges.js +16 -13
  62. package/dist/apps/data/routes/exchanges.js.map +1 -1
  63. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  64. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  65. package/dist/apps/data/routes/fee-amm.js +9 -11
  66. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  67. package/dist/apps/data/routes/indexer.d.ts +34 -34
  68. package/dist/apps/data/routes/receipts.d.ts +363 -263
  69. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  70. package/dist/apps/data/routes/receipts.js +29 -11
  71. package/dist/apps/data/routes/receipts.js.map +1 -1
  72. package/dist/apps/data/routes/rpc.js +24 -10
  73. package/dist/apps/data/routes/rpc.js.map +1 -1
  74. package/dist/apps/data/routes/tokenlist.d.ts +13 -13
  75. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  76. package/dist/apps/data/routes/tokenlist.js +16 -15
  77. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  78. package/dist/apps/data/routes/tokens.d.ts +112 -98
  79. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  80. package/dist/apps/data/routes/tokens.js +85 -35
  81. package/dist/apps/data/routes/tokens.js.map +1 -1
  82. package/dist/apps/data/routes/transactions.d.ts +7 -2
  83. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  84. package/dist/apps/data/routes/transactions.js +38 -18
  85. package/dist/apps/data/routes/transactions.js.map +1 -1
  86. package/dist/apps/data/routes/transfers.d.ts +1 -1
  87. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  88. package/dist/apps/data/routes/transfers.js +25 -21
  89. package/dist/apps/data/routes/transfers.js.map +1 -1
  90. package/dist/apps/data/routes/valuation.d.ts +1 -1
  91. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  92. package/dist/apps/data/routes/valuation.js +12 -7
  93. package/dist/apps/data/routes/valuation.js.map +1 -1
  94. package/dist/apps/data/routes/verified-tokens.d.ts +3 -3
  95. package/dist/apps/data/routes/webhooks.d.ts +15 -15
  96. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  97. package/dist/apps/data/routes/webhooks.js +2 -2
  98. package/dist/apps/data/routes/webhooks.js.map +1 -1
  99. package/dist/apps/data/routes/zones.d.ts +32 -32
  100. package/dist/apps/data/routes/zones.js +1 -1
  101. package/dist/apps/funding/App.d.ts +38 -27
  102. package/dist/apps/funding/App.d.ts.map +1 -1
  103. package/dist/apps/funding/routes/chains.d.ts.map +1 -1
  104. package/dist/apps/funding/routes/chains.js +5 -4
  105. package/dist/apps/funding/routes/chains.js.map +1 -1
  106. package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
  107. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  108. package/dist/apps/funding/routes/deposit-addresses.js +24 -19
  109. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  110. package/dist/apps/funding/routes/providers.d.ts +13 -13
  111. package/dist/apps/funding/routes/providers.d.ts.map +1 -1
  112. package/dist/apps/funding/routes/providers.js +3 -2
  113. package/dist/apps/funding/routes/providers.js.map +1 -1
  114. package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
  115. package/dist/apps/funding/routes/quotes.js +2 -2
  116. package/dist/apps/funding/routes/quotes.js.map +1 -1
  117. package/dist/apps/funding/routes/transfers.d.ts +60 -48
  118. package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
  119. package/dist/apps/funding/routes/transfers.js +27 -19
  120. package/dist/apps/funding/routes/transfers.js.map +1 -1
  121. package/dist/apps/management/App.d.ts +4558 -3700
  122. package/dist/apps/management/App.d.ts.map +1 -1
  123. package/dist/apps/management/Billing.d.ts.map +1 -1
  124. package/dist/apps/management/Billing.js +19 -6
  125. package/dist/apps/management/Billing.js.map +1 -1
  126. package/dist/apps/management/routes/api-keys.d.ts +786 -175
  127. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  128. package/dist/apps/management/routes/api-keys.js +312 -34
  129. package/dist/apps/management/routes/api-keys.js.map +1 -1
  130. package/dist/apps/management/routes/billing.d.ts +103 -30
  131. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  132. package/dist/apps/management/routes/billing.js +91 -32
  133. package/dist/apps/management/routes/billing.js.map +1 -1
  134. package/dist/apps/management/routes/faucet.d.ts +35 -35
  135. package/dist/apps/management/routes/faucet.d.ts.map +1 -1
  136. package/dist/apps/management/routes/faucet.js +23 -12
  137. package/dist/apps/management/routes/faucet.js.map +1 -1
  138. package/dist/apps/management/routes/invitations.d.ts +46 -13
  139. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  140. package/dist/apps/management/routes/invitations.js +79 -29
  141. package/dist/apps/management/routes/invitations.js.map +1 -1
  142. package/dist/apps/management/routes/invite-links.d.ts +120 -75
  143. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  144. package/dist/apps/management/routes/invite-links.js +100 -41
  145. package/dist/apps/management/routes/invite-links.js.map +1 -1
  146. package/dist/apps/management/routes/me.d.ts +5 -5
  147. package/dist/apps/management/routes/me.d.ts.map +1 -1
  148. package/dist/apps/management/routes/me.js +14 -10
  149. package/dist/apps/management/routes/me.js.map +1 -1
  150. package/dist/apps/management/routes/members.d.ts +99 -78
  151. package/dist/apps/management/routes/members.d.ts.map +1 -1
  152. package/dist/apps/management/routes/members.js +37 -18
  153. package/dist/apps/management/routes/members.js.map +1 -1
  154. package/dist/apps/management/routes/orgs.d.ts +48 -8
  155. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  156. package/dist/apps/management/routes/orgs.js +48 -19
  157. package/dist/apps/management/routes/orgs.js.map +1 -1
  158. package/dist/apps/management/routes/projects.d.ts +108 -46
  159. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  160. package/dist/apps/management/routes/projects.js +72 -21
  161. package/dist/apps/management/routes/projects.js.map +1 -1
  162. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  163. package/dist/apps/management/routes/scopes.js +8 -5
  164. package/dist/apps/management/routes/scopes.js.map +1 -1
  165. package/dist/apps/management/routes/usage.d.ts +82 -82
  166. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  167. package/dist/apps/management/routes/usage.js +41 -31
  168. package/dist/apps/management/routes/usage.js.map +1 -1
  169. package/dist/apps/management/routes/verified-token-requests.d.ts +35 -7
  170. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  171. package/dist/apps/management/routes/verified-token-requests.js +36 -17
  172. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  173. package/dist/apps/management/routes/webhooks.d.ts +200 -183
  174. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  175. package/dist/apps/management/routes/webhooks.js +80 -35
  176. package/dist/apps/management/routes/webhooks.js.map +1 -1
  177. package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
  178. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  179. package/dist/apps/mpp/internal/Adapter.js +12 -0
  180. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  181. package/dist/db/Db.d.ts +2 -0
  182. package/dist/db/Db.d.ts.map +1 -1
  183. package/dist/db/Db.js +52 -1
  184. package/dist/db/Db.js.map +1 -1
  185. package/dist/db/Schema.d.ts +26 -3
  186. package/dist/db/Schema.d.ts.map +1 -1
  187. package/dist/db/Schema.js +24 -5
  188. package/dist/db/Schema.js.map +1 -1
  189. package/dist/db/tables/earnVaults.d.ts +5 -1
  190. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  191. package/dist/db/tables/earnVaults.js +5 -0
  192. package/dist/db/tables/earnVaults.js.map +1 -1
  193. package/dist/db/tables/fundingCatalog.d.ts +4 -2
  194. package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
  195. package/dist/db/tables/fundingCatalog.js +5 -1
  196. package/dist/db/tables/fundingCatalog.js.map +1 -1
  197. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
  198. package/dist/db/tables/webhookDeliveries.js +10 -0
  199. package/dist/db/tables/webhookDeliveries.js.map +1 -1
  200. package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
  201. package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
  202. package/dist/db/tables/webhookQueueCompletions.js +32 -0
  203. package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
  204. package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
  205. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  206. package/dist/db/tables/webhookQueueEvents.js +68 -47
  207. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  208. package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
  209. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  210. package/dist/db/tables/webhookSubscriptions.js +29 -5
  211. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  212. package/dist/handlers/internal/utils.d.ts.map +1 -1
  213. package/dist/handlers/internal/utils.js +9 -0
  214. package/dist/handlers/internal/utils.js.map +1 -1
  215. package/dist/internal/Auth.d.ts +11 -2
  216. package/dist/internal/Auth.d.ts.map +1 -1
  217. package/dist/internal/Auth.js +19 -6
  218. package/dist/internal/Auth.js.map +1 -1
  219. package/dist/internal/Cache.d.ts.map +1 -1
  220. package/dist/internal/Cache.js +11 -7
  221. package/dist/internal/Cache.js.map +1 -1
  222. package/dist/internal/EarnVaults.d.ts +43 -4
  223. package/dist/internal/EarnVaults.d.ts.map +1 -1
  224. package/dist/internal/EarnVaults.js +167 -0
  225. package/dist/internal/EarnVaults.js.map +1 -1
  226. package/dist/internal/Fetch.d.ts +23 -0
  227. package/dist/internal/Fetch.d.ts.map +1 -0
  228. package/dist/internal/Fetch.js +26 -0
  229. package/dist/internal/Fetch.js.map +1 -0
  230. package/dist/internal/Log.d.ts +3 -1
  231. package/dist/internal/Log.d.ts.map +1 -1
  232. package/dist/internal/Log.js +16 -3
  233. package/dist/internal/Log.js.map +1 -1
  234. package/dist/internal/OpenApi.d.ts +30 -24
  235. package/dist/internal/OpenApi.d.ts.map +1 -1
  236. package/dist/internal/OpenApi.js +140 -41
  237. package/dist/internal/OpenApi.js.map +1 -1
  238. package/dist/internal/Response.d.ts +14 -9
  239. package/dist/internal/Response.d.ts.map +1 -1
  240. package/dist/internal/Response.js +16 -5
  241. package/dist/internal/Response.js.map +1 -1
  242. package/dist/internal/Schema.d.ts +11 -10
  243. package/dist/internal/Schema.d.ts.map +1 -1
  244. package/dist/internal/Schema.js +14 -9
  245. package/dist/internal/Schema.js.map +1 -1
  246. package/dist/internal/Store.d.ts +28 -6
  247. package/dist/internal/Store.d.ts.map +1 -1
  248. package/dist/internal/Store.js +121 -25
  249. package/dist/internal/Store.js.map +1 -1
  250. package/dist/internal/Tidx.d.ts +2 -0
  251. package/dist/internal/Tidx.d.ts.map +1 -1
  252. package/dist/internal/Tidx.js +23 -6
  253. package/dist/internal/Tidx.js.map +1 -1
  254. package/dist/internal/Timeout.d.ts +36 -0
  255. package/dist/internal/Timeout.d.ts.map +1 -0
  256. package/dist/internal/Timeout.js +37 -0
  257. package/dist/internal/Timeout.js.map +1 -0
  258. package/dist/internal/Timing.d.ts +9 -0
  259. package/dist/internal/Timing.d.ts.map +1 -1
  260. package/dist/internal/Timing.js +7 -0
  261. package/dist/internal/Timing.js.map +1 -1
  262. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  263. package/dist/internal/WebhookDestination.js +3 -0
  264. package/dist/internal/WebhookDestination.js.map +1 -1
  265. package/dist/internal/Webhooks.d.ts +29 -12
  266. package/dist/internal/Webhooks.d.ts.map +1 -1
  267. package/dist/internal/Webhooks.js +37 -20
  268. package/dist/internal/Webhooks.js.map +1 -1
  269. package/dist/internal/funding/Action.d.ts +9 -0
  270. package/dist/internal/funding/Action.d.ts.map +1 -1
  271. package/dist/internal/funding/Action.js +16 -8
  272. package/dist/internal/funding/Action.js.map +1 -1
  273. package/dist/internal/funding/Catalog.d.ts +9 -2
  274. package/dist/internal/funding/Catalog.d.ts.map +1 -1
  275. package/dist/internal/funding/Catalog.js +19 -8
  276. package/dist/internal/funding/Catalog.js.map +1 -1
  277. package/dist/internal/funding/Deposit.d.ts +2 -2
  278. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  279. package/dist/internal/funding/Deposit.js +9 -8
  280. package/dist/internal/funding/Deposit.js.map +1 -1
  281. package/dist/internal/funding/DepositAddress.d.ts +4 -4
  282. package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
  283. package/dist/internal/funding/DepositAddress.js +9 -8
  284. package/dist/internal/funding/DepositAddress.js.map +1 -1
  285. package/dist/internal/funding/Provider.d.ts +68 -13
  286. package/dist/internal/funding/Provider.d.ts.map +1 -1
  287. package/dist/internal/funding/Provider.js +42 -20
  288. package/dist/internal/funding/Provider.js.map +1 -1
  289. package/dist/internal/funding/Transfer.d.ts +13 -12
  290. package/dist/internal/funding/Transfer.d.ts.map +1 -1
  291. package/dist/internal/funding/Transfer.js +23 -21
  292. package/dist/internal/funding/Transfer.js.map +1 -1
  293. package/dist/internal/funding/providers/stargate.d.ts +38 -0
  294. package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
  295. package/dist/internal/funding/providers/stargate.js +277 -0
  296. package/dist/internal/funding/providers/stargate.js.map +1 -0
  297. package/dist/internal/index.d.ts +1 -0
  298. package/dist/internal/index.d.ts.map +1 -1
  299. package/dist/internal/index.js +1 -0
  300. package/dist/internal/index.js.map +1 -1
  301. package/dist/providers/index.d.ts +7 -0
  302. package/dist/providers/index.d.ts.map +1 -1
  303. package/dist/providers/index.js +3 -0
  304. package/dist/providers/index.js.map +1 -1
  305. package/package.json +3 -3
  306. package/src/App.test.ts +148 -0
  307. package/src/App.ts +45 -4
  308. package/src/Assets.test.ts +18 -0
  309. package/src/Assets.ts +22 -0
  310. package/src/Client.test-d.ts +311 -16
  311. package/src/Scope.test.ts +20 -0
  312. package/src/Scope.ts +16 -0
  313. package/src/admin/apps/api-keys.test.ts +75 -0
  314. package/src/admin/apps/api-keys.ts +64 -0
  315. package/src/admin/apps/earn-vaults.test.ts +143 -0
  316. package/src/admin/apps/earn-vaults.ts +84 -7
  317. package/src/admin/apps/organizations.ts +6 -2
  318. package/src/admin/ui/src/lib/api-keys.ts +19 -0
  319. package/src/admin/ui/src/routes/api-keys.tsx +125 -2
  320. package/src/admin/ui.generated.ts +71 -71
  321. package/src/apps/Zones.test.ts +4 -4
  322. package/src/apps/Zones.ts +4 -4
  323. package/src/apps/composition.test.ts +1 -1
  324. package/src/apps/data/App.test.ts +72 -0
  325. package/src/apps/data/App.ts +58 -10
  326. package/src/apps/data/ZoneSelection.test.ts +196 -0
  327. package/src/apps/data/ZoneSelection.ts +108 -0
  328. package/src/apps/data/routes/activities.test.ts +1843 -2
  329. package/src/apps/data/routes/activities.ts +2211 -1388
  330. package/src/apps/data/routes/balances.ts +134 -98
  331. package/src/apps/data/routes/blocks.test.ts +533 -0
  332. package/src/apps/data/routes/blocks.ts +36 -17
  333. package/src/apps/data/routes/earn.test.ts +187 -25
  334. package/src/apps/data/routes/earn.ts +228 -32
  335. package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
  336. package/src/apps/data/routes/exchanges.test.ts +31 -1
  337. package/src/apps/data/routes/exchanges.ts +19 -15
  338. package/src/apps/data/routes/fee-amm.ts +18 -11
  339. package/src/apps/data/routes/receipts.ts +48 -17
  340. package/src/apps/data/routes/rpc.test.ts +75 -0
  341. package/src/apps/data/routes/rpc.ts +23 -9
  342. package/src/apps/data/routes/tokenlist.ts +21 -18
  343. package/src/apps/data/routes/tokens.test.ts +607 -0
  344. package/src/apps/data/routes/tokens.ts +312 -231
  345. package/src/apps/data/routes/transactions.ts +69 -30
  346. package/src/apps/data/routes/transfers.test.ts +424 -3
  347. package/src/apps/data/routes/transfers.ts +57 -36
  348. package/src/apps/data/routes/valuation.ts +94 -78
  349. package/src/apps/data/routes/webhooks.ts +6 -2
  350. package/src/apps/data/routes/zones.test.ts +21 -15
  351. package/src/apps/data/routes/zones.ts +1 -1
  352. package/src/apps/funding/routes/chains.test.ts +211 -7
  353. package/src/apps/funding/routes/chains.ts +19 -12
  354. package/src/apps/funding/routes/deposit-addresses.test.ts +416 -0
  355. package/src/apps/funding/routes/deposit-addresses.ts +101 -84
  356. package/src/apps/funding/routes/providers.ts +9 -5
  357. package/src/apps/funding/routes/quotes.test.ts +42 -0
  358. package/src/apps/funding/routes/quotes.ts +8 -5
  359. package/src/apps/funding/routes/transfers.test.ts +430 -40
  360. package/src/apps/funding/routes/transfers.ts +76 -59
  361. package/src/apps/management/Billing.test.ts +26 -0
  362. package/src/apps/management/Billing.ts +24 -7
  363. package/src/apps/management/routes/api-keys.test.ts +398 -0
  364. package/src/apps/management/routes/api-keys.ts +481 -145
  365. package/src/apps/management/routes/billing.test.ts +209 -0
  366. package/src/apps/management/routes/billing.ts +254 -177
  367. package/src/apps/management/routes/faucet.test.ts +39 -0
  368. package/src/apps/management/routes/faucet.ts +75 -41
  369. package/src/apps/management/routes/invitations.test.ts +216 -0
  370. package/src/apps/management/routes/invitations.ts +186 -109
  371. package/src/apps/management/routes/invite-links.test.ts +263 -1
  372. package/src/apps/management/routes/invite-links.ts +295 -214
  373. package/src/apps/management/routes/me.test.ts +49 -0
  374. package/src/apps/management/routes/me.ts +42 -32
  375. package/src/apps/management/routes/members.test.ts +124 -1
  376. package/src/apps/management/routes/members.ts +81 -51
  377. package/src/apps/management/routes/orgs.test.ts +176 -0
  378. package/src/apps/management/routes/orgs.ts +101 -59
  379. package/src/apps/management/routes/projects.test.ts +183 -0
  380. package/src/apps/management/routes/projects.ts +124 -60
  381. package/src/apps/management/routes/scopes.test.ts +44 -0
  382. package/src/apps/management/routes/scopes.ts +37 -28
  383. package/src/apps/management/routes/usage.test.ts +92 -0
  384. package/src/apps/management/routes/usage.ts +186 -151
  385. package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
  386. package/src/apps/management/routes/verified-token-requests.ts +166 -133
  387. package/src/apps/management/routes/webhooks.test.ts +234 -0
  388. package/src/apps/management/routes/webhooks.ts +191 -78
  389. package/src/apps/mpp/internal/Adapter.ts +13 -1
  390. package/src/db/Db.test.ts +41 -0
  391. package/src/db/Db.ts +75 -1
  392. package/src/db/Schema.ts +33 -5
  393. package/src/db/tables/earnVaults.test.ts +22 -0
  394. package/src/db/tables/earnVaults.ts +11 -1
  395. package/src/db/tables/fundingCatalog.test.ts +16 -2
  396. package/src/db/tables/fundingCatalog.ts +9 -3
  397. package/src/db/tables/webhookDeliveries.ts +13 -0
  398. package/src/db/tables/webhookQueueCompletions.ts +55 -0
  399. package/src/db/tables/webhookQueueEvents.ts +95 -61
  400. package/src/db/tables/webhookSubscriptions.ts +45 -6
  401. package/src/handlers/internal/utils.test.ts +53 -0
  402. package/src/handlers/internal/utils.ts +15 -0
  403. package/src/internal/Auth.ts +35 -9
  404. package/src/internal/Cache.ts +14 -7
  405. package/src/internal/EarnVaults.capabilities.test.ts +33 -0
  406. package/src/internal/EarnVaults.test.ts +79 -0
  407. package/src/internal/EarnVaults.ts +277 -0
  408. package/src/internal/Fetch.test.ts +46 -0
  409. package/src/internal/Fetch.ts +56 -0
  410. package/src/internal/Log.test.ts +21 -0
  411. package/src/internal/Log.ts +20 -5
  412. package/src/internal/OpenApi.ts +177 -51
  413. package/src/internal/Response.test.ts +95 -0
  414. package/src/internal/Response.ts +41 -3
  415. package/src/internal/Schema.test.ts +18 -0
  416. package/src/internal/Schema.ts +19 -9
  417. package/src/internal/Store.test.ts +364 -0
  418. package/src/internal/Store.ts +153 -27
  419. package/src/internal/Tidx.test.ts +21 -1
  420. package/src/internal/Tidx.ts +23 -6
  421. package/src/internal/Timeout.test.ts +35 -0
  422. package/src/internal/Timeout.ts +73 -0
  423. package/src/internal/Timing.ts +16 -0
  424. package/src/internal/WebhookDestination.ts +3 -0
  425. package/src/internal/Webhooks.test.ts +122 -8
  426. package/src/internal/Webhooks.ts +59 -29
  427. package/src/internal/funding/Action.test.ts +41 -1
  428. package/src/internal/funding/Action.ts +69 -41
  429. package/src/internal/funding/Catalog.test.ts +34 -0
  430. package/src/internal/funding/Catalog.ts +28 -11
  431. package/src/internal/funding/Deposit.ts +71 -64
  432. package/src/internal/funding/DepositAddress.ts +50 -43
  433. package/src/internal/funding/Provider.test.ts +73 -0
  434. package/src/internal/funding/Provider.ts +246 -170
  435. package/src/internal/funding/Transfer.ts +133 -110
  436. package/src/internal/funding/providers/index.test.ts +22 -0
  437. package/src/internal/funding/providers/relay.test.ts +2 -2
  438. package/src/internal/funding/providers/stargate.test.ts +163 -0
  439. package/src/internal/funding/providers/stargate.ts +409 -0
  440. package/src/internal/index.test.ts +1 -0
  441. package/src/internal/index.ts +1 -0
  442. package/src/providers/index.test.ts +1 -0
  443. package/src/providers/index.ts +9 -0
@@ -0,0 +1,56 @@
1
+ import * as Timeout from './Timeout.js'
2
+
3
+ /** Installs the default outbound fetch timeout once for this runtime. */
4
+ export function install(): void {
5
+ if (isInstalled(globalThis.fetch)) return
6
+
7
+ const fetch = withTimeout(globalThis.fetch.bind(globalThis), { timeout: Timeout.duration })
8
+ Object.defineProperty(fetch, timeoutMarker, { value: true })
9
+ globalThis.fetch = fetch
10
+ }
11
+
12
+ /** Adds a default maximum duration to fetch calls that do not carry a signal. */
13
+ export function withTimeout(
14
+ fetch: typeof globalThis.fetch,
15
+ options: withTimeout.Options,
16
+ ): typeof globalThis.fetch {
17
+ return ((input, init) => {
18
+ const signal = resolveSignal(input, { init, timeout: options.timeout })
19
+ return fetch(input, { ...init, signal })
20
+ }) as typeof globalThis.fetch
21
+ }
22
+
23
+ /** Resolves a caller signal or creates the default fetch deadline signal. */
24
+ export function resolveSignal(
25
+ input: Parameters<typeof globalThis.fetch>[0],
26
+ options: resolveSignal.Options,
27
+ ): AbortSignal {
28
+ return (
29
+ options.init?.signal ??
30
+ (input instanceof Request ? input.signal : Timeout.signal({ timeout: options.timeout }))
31
+ )
32
+ }
33
+
34
+ export declare namespace resolveSignal {
35
+ /** Options for {@link resolveSignal}. */
36
+ type Options = {
37
+ /** Optional fetch initialization carrying a caller signal. */
38
+ init?: Parameters<typeof globalThis.fetch>[1]
39
+ /** Default maximum duration in milliseconds. */
40
+ timeout: number
41
+ }
42
+ }
43
+
44
+ export declare namespace withTimeout {
45
+ /** Options for {@link withTimeout}. */
46
+ type Options = {
47
+ /** Maximum fetch duration in milliseconds. */
48
+ timeout: number
49
+ }
50
+ }
51
+
52
+ const timeoutMarker = Symbol.for('tempo.api.fetch.timeout')
53
+
54
+ function isInstalled(fetch: typeof globalThis.fetch): boolean {
55
+ return timeoutMarker in fetch
56
+ }
@@ -457,6 +457,27 @@ describe('middleware', () => {
457
457
  `)
458
458
  })
459
459
 
460
+ test('preserves the request error and unfinished stages', async () => {
461
+ const entries: Log.Entry[] = []
462
+ const causes: Error[] = []
463
+ const api = app({
464
+ emit: (entry, cause) => {
465
+ entries.push(entry)
466
+ if (cause) causes.push(cause)
467
+ },
468
+ })
469
+ const cause = new Error('Memoized cache-miss flight timed out after 15000ms.')
470
+ api.get('/activities', (c) => {
471
+ void Timing.time(c, 'transaction_activity_mpp', () => new Promise(() => {}))
472
+ return Response.upstream(c, cause)
473
+ })
474
+
475
+ await api.request('/activities')
476
+
477
+ expect(causes[0]).toBe(cause)
478
+ expect(entries[0]?.pendingTimings?.['transaction_activity_mpp']).toBeGreaterThanOrEqual(0)
479
+ })
480
+
460
481
  test('includes bounded funding provider attempts', async () => {
461
482
  const entries: Log.Entry[] = []
462
483
  const api = app({ emit: (entry) => void entries.push(entry) })
@@ -151,6 +151,8 @@ export type Entry = {
151
151
  path: string
152
152
  /** MPP payment reason when the request was paid per call. */
153
153
  payment?: Auth.Payment['reason'] | undefined
154
+ /** Operations still running when the response completed, with elapsed milliseconds. */
155
+ pendingTimings?: Record<string, number> | undefined
154
156
  /** Bounded outcome for an MPP relay operation. */
155
157
  mpp?: {
156
158
  /** Resolved Tempo chain selected by the credential. */
@@ -228,7 +230,7 @@ export type Entry = {
228
230
  }
229
231
 
230
232
  /** Sink receiving one {@link Entry} per request. */
231
- export type Emit = (entry: Entry) => Promise<void> | void
233
+ export type Emit = (entry: Entry, cause?: Error) => Promise<void> | void
232
234
 
233
235
  /**
234
236
  * Emits one canonical structured log entry per request, after the response is
@@ -258,7 +260,8 @@ export function middleware<environment extends Environment = Environment>(
258
260
  // Hono cannot resolve variable types through the generic `environment`,
259
261
  // so shared-variable reads are cast from the environment contract above
260
262
  // (the same pattern EdgeCache uses for its cross-layer reads).
261
- const error = c.error as ErrorMetadata | undefined
263
+ const cause = c.error
264
+ const error = cause as (Error & ErrorMetadata) | undefined
262
265
  const principal = c.get('principal' as never) as Auth.Principal | undefined
263
266
  const errorCaptured = c.get('errorCaptured' as never) as boolean | undefined
264
267
  const chainId = c.get('chainId' as never) as number | undefined
@@ -279,7 +282,6 @@ export function middleware<environment extends Environment = Environment>(
279
282
  error?.providerFailures ?? (c.get('providerFailures' as never) as Entry['providerFailures'])
280
283
  const rpc = c.get('rpcResponse' as never) as Entry['rpc']
281
284
  const sponsorship = c.get('sponsorship' as never) as Entry['sponsorship']
282
-
283
285
  // The `request` total metric duplicates `duration` (measured here, one
284
286
  // layer further out), so only operation timings are kept.
285
287
  const metrics = (c.get('serverTiming' as never) as Timing.Metric[] | undefined)?.filter(
@@ -295,6 +297,17 @@ export function middleware<environment extends Environment = Environment>(
295
297
  }, new Map<string, number>()),
296
298
  )
297
299
  : undefined
300
+ const activeTimings = c.get('activeTimings' as never) as Timing.Active[] | undefined
301
+ const pendingTimings = activeTimings?.length
302
+ ? Object.fromEntries(
303
+ activeTimings.reduce((result, timing) => {
304
+ const duration = round(performance.now() - timing.start)
305
+ const existing = result.get(timing.name)
306
+ if (existing === undefined || duration > existing) result.set(timing.name, duration)
307
+ return result
308
+ }, new Map<string, number>()),
309
+ )
310
+ : undefined
298
311
 
299
312
  const rateLimit = (() => {
300
313
  const limit = c.res.headers.get('RateLimit-Limit')
@@ -310,7 +323,7 @@ export function middleware<environment extends Environment = Environment>(
310
323
  }
311
324
  })()
312
325
 
313
- const result = fn({
326
+ const entry = {
314
327
  ...(c.get('edgeCacheStatus' as never) === 'hit' ? { cache: 'hit' as const } : {}),
315
328
  ...(chainId === undefined ? {} : { chainId }),
316
329
  duration: round(duration),
@@ -333,6 +346,7 @@ export function middleware<environment extends Environment = Environment>(
333
346
  ...(mpp === undefined ? {} : { mpp }),
334
347
  path: url.pathname,
335
348
  ...(principal?.payment === undefined ? {} : { payment: principal.payment.reason }),
349
+ ...(pendingTimings === undefined ? {} : { pendingTimings }),
336
350
  ...(principal === undefined
337
351
  ? {}
338
352
  : {
@@ -360,7 +374,8 @@ export function middleware<environment extends Environment = Environment>(
360
374
  ...(sponsorship === undefined ? {} : { sponsorship }),
361
375
  status,
362
376
  ...(timings === undefined ? {} : { timings }),
363
- })
377
+ } satisfies Entry
378
+ const result = fn(entry, cause)
364
379
 
365
380
  if (result instanceof Promise) {
366
381
  const promise = result.catch((error) => console.error('request log sink failed', error))
@@ -1,6 +1,13 @@
1
1
  import type { Context, Env, MiddlewareHandler, ValidationTargets } from 'hono'
2
2
  import type { HasRequiredKeys } from 'hono/utils/types'
3
- import { resolver, type ResponsesWithResolver, validator } from 'hono-openapi'
3
+ import {
4
+ describeRoute as core_describeRoute,
5
+ type DescribeRouteOptions,
6
+ resolver,
7
+ type ResponsesWithResolver,
8
+ uniqueSymbol,
9
+ validator,
10
+ } from 'hono-openapi'
4
11
  import * as z from 'zod/mini'
5
12
  import * as Response from './Response.js'
6
13
  import * as Schema from './Schema.js'
@@ -41,7 +48,6 @@ const schemaOptions = { options: { override: recoverExamples, unrepresentable: '
41
48
  // re-exports because `uniqueSymbol` is a `unique symbol` whose identity is
42
49
  // lost when copied through a `const` declaration.
43
50
  export {
44
- describeRoute,
45
51
  type HandlerUniqueProperty,
46
52
  resolver,
47
53
  type ResponsesWithResolver,
@@ -49,12 +55,53 @@ export {
49
55
  validator,
50
56
  } from 'hono-openapi'
51
57
 
58
+ function cloneResponseContainers(spec: DescribeRouteOptions): DescribeRouteOptions {
59
+ if (!spec.responses) return spec
60
+ return {
61
+ ...spec,
62
+ responses: Object.fromEntries(
63
+ Object.entries(spec.responses).map(([status, response]) => [
64
+ status,
65
+ !response || !('content' in response)
66
+ ? response
67
+ : {
68
+ ...response,
69
+ content: Object.fromEntries(
70
+ Object.entries(response.content ?? {}).map(([mediaType, media]) => [
71
+ mediaType,
72
+ { ...media },
73
+ ]),
74
+ ),
75
+ },
76
+ ]),
77
+ ),
78
+ }
79
+ }
80
+
81
+ /** Describes a route without allowing spec generation to mutate reusable response definitions. */
82
+ export function describeRoute(spec: DescribeRouteOptions): MiddlewareHandler {
83
+ const handler = core_describeRoute(spec)
84
+ Object.defineProperty(handler, uniqueSymbol, {
85
+ get: () => ({ spec: cloneResponseContainers(spec) }),
86
+ })
87
+ return handler
88
+ }
89
+
90
+ /** Emits a named OpenAPI component and uses its `$ref` wherever the schema appears. */
91
+ export function component<const schema extends z.ZodMiniType>(
92
+ schema: schema,
93
+ name: string,
94
+ ): schema {
95
+ const cloned = schema.clone()
96
+ z.globalRegistry.add(cloned, { ...z.globalRegistry.get(schema), ref: name })
97
+ return cloned as schema
98
+ }
99
+
52
100
  /**
53
101
  * Standard machine-readable `error.code` values per status, shared API-wide.
54
102
  * The reference enumerates `error.code` to these so generated clients narrow it
55
- * to a literal union instead of an open `string`. 400 and 404 vary per
56
- * operation; the values here are the API-wide supersets, narrowable per route
57
- * via the `codes` override in {@link responses.Options}.
103
+ * to a literal union instead of an open `string`. The values here are shared
104
+ * defaults; operation-specific codes are supplied through {@link responses.Options}.
58
105
  */
59
106
  export const errorCodes = {
60
107
  400: [
@@ -80,7 +127,7 @@ export const errorCodes = {
80
127
  'api_key_malformed',
81
128
  ],
82
129
  401: ['api_key_missing', 'api_key_invalid', 'unauthorized'],
83
- 403: ['api_key_forbidden', 'api_key_ip_forbidden', 'limit_exceeded'],
130
+ 403: ['api_key_forbidden', 'api_key_ip_forbidden', 'forbidden'],
84
131
  404: [
85
132
  'not_found',
86
133
  'token_not_found',
@@ -101,6 +148,7 @@ export const errorCodes = {
101
148
  500: ['internal_error'],
102
149
  501: ['billing_unconfigured'],
103
150
  502: ['upstream_error'],
151
+ 504: ['request_timeout'],
104
152
  } as const satisfies Record<number, readonly [string, ...string[]]>
105
153
 
106
154
  /**
@@ -164,11 +212,79 @@ export const rateLimitHeaders = {
164
212
  /** Representative `requestId` used in error-body examples. */
165
213
  const exampleRequestId = '0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9'
166
214
 
167
- /** Builds the `application/json` content for a standard error response: the enumerated-code envelope plus an example body. */
168
- function errorContent(codes: readonly [string, ...string[]] | undefined, message: string) {
215
+ const standardErrorNames = {
216
+ 400: 'InvalidRequestError',
217
+ 401: 'AuthenticationError',
218
+ 403: 'ForbiddenError',
219
+ 404: 'ResourceNotFoundError',
220
+ 429: 'RateLimitError',
221
+ 500: 'InternalError',
222
+ 501: 'NotImplementedError',
223
+ 502: 'UpstreamError',
224
+ 504: 'RequestTimeoutError',
225
+ } as const satisfies Record<keyof typeof errorCodes, string>
226
+
227
+ const reservedErrorNames = new Set<string>(Object.values(standardErrorNames))
228
+ const errorSchemas = new Map<string, z.ZodMiniType>()
229
+
230
+ function errorName(status: number, codes: readonly string[]) {
231
+ const standard = errorCodes[status as keyof typeof errorCodes]
232
+ if (
233
+ standard &&
234
+ standard.length === codes.length &&
235
+ [...standard].sort().every((code, index) => code === codes[index])
236
+ )
237
+ return standardErrorNames[status as keyof typeof standardErrorNames]
238
+ const name = `${codes
239
+ .map((code) =>
240
+ code
241
+ .split('_')
242
+ .map((part) => `${part[0]?.toUpperCase()}${part.slice(1)}`)
243
+ .join(''),
244
+ )
245
+ .join('Or')}Error`
246
+ if (reservedErrorNames.has(name)) return `${name.slice(0, -'Error'.length)}${status}Error`
247
+ return name
248
+ }
249
+
250
+ function errorSchema(status: number, codes: readonly [string, ...string[]] | undefined) {
251
+ const defaults = errorCodes[status as keyof typeof errorCodes]
252
+ if (!codes && !defaults) {
253
+ const cached = errorSchemas.get('*')
254
+ if (cached) return cached
255
+ const schema = component(Schema.errorResponse(), 'ErrorResponse')
256
+ errorSchemas.set('*', schema)
257
+ return schema
258
+ }
259
+ const normalized = [...(codes ?? defaults ?? [])].sort() as [string, ...string[]]
260
+ const key = normalized.join('\0')
261
+ const cached = errorSchemas.get(key)
262
+ if (cached) return cached
263
+ const schema = component(Schema.errorResponse(normalized), errorName(status, normalized))
264
+ errorSchemas.set(key, schema)
265
+ return schema
266
+ }
267
+
268
+ function mergeErrorCodes(
269
+ status: number,
270
+ codes: readonly string[] | undefined,
271
+ ): readonly [string, ...string[]] | undefined {
272
+ if (!codes) return errorCodes[status as keyof typeof errorCodes]
273
+ if (status !== 400 && status !== 403)
274
+ return codes.length ? (codes as [string, ...string[]]) : undefined
275
+ const baseline = status === 400 ? (['api_key_malformed'] as const) : errorCodes[403]
276
+ return [...new Set([...baseline, ...codes])] as [string, ...string[]]
277
+ }
278
+
279
+ /** Builds the `application/json` content for a standard error response: the named enumerated-code envelope plus an example body. */
280
+ function errorContent(
281
+ status: number,
282
+ codes: readonly [string, ...string[]] | undefined,
283
+ message: string,
284
+ ) {
169
285
  return {
170
286
  'application/json': {
171
- schema: resolver(Schema.errorResponse(codes), schemaOptions),
287
+ schema: resolver(errorSchema(status, codes), schemaOptions),
172
288
  example: { error: { code: codes?.[0] ?? 'error', message }, requestId: exampleRequestId },
173
289
  },
174
290
  }
@@ -186,32 +302,35 @@ export const paymentChallenge = {
186
302
  headers: { 'WWW-Authenticate': headerRef('WwwAuthenticate') },
187
303
  } as const
188
304
 
189
- /** Shared `429` rate-limit response, registered as `components.responses.RateLimited`. */
190
- const rateLimitedResponse = {
191
- content: errorContent(errorCodes[429], 'Rate limit exceeded.'),
192
- description:
193
- 'Rate limit exceeded. On endpoints that accept MPP, over-quota unpaid requests return `402 Payment Required` instead.',
194
- headers: { ...rateLimitHeaders },
195
- }
196
-
197
- /** Shared `500` internal-error response, registered as `components.responses.InternalError`. */
198
- const serverErrorResponse = {
199
- content: errorContent(errorCodes[500], 'Internal server error.'),
200
- description: 'Internal server error.',
201
- }
305
+ type ResponseComponentName = 'InternalError' | 'PaymentRequired' | 'RateLimited' | 'RequestTimeout'
202
306
 
203
307
  /**
204
308
  * Reusable responses registered under `components.responses` (see `App.create`)
205
- * and `$ref`-erenced from operations, so the uniform `402`/`429`/`500` responses
206
- * are defined once instead of inlined on every operation.
309
+ * and `$ref`-erenced from operations, so the uniform `402`/`429`/`500`/`504`
310
+ * responses are defined once instead of inlined on every operation.
207
311
  */
208
- export const responseComponents: ResponsesWithResolver = {
209
- InternalError: serverErrorResponse,
210
- PaymentRequired: paymentChallenge,
211
- RateLimited: rateLimitedResponse,
312
+ export function responseComponents(): ResponsesWithResolver {
313
+ return {
314
+ InternalError: {
315
+ content: errorContent(500, errorCodes[500], 'Internal server error.'),
316
+ description: 'Internal server error.',
317
+ },
318
+ PaymentRequired: paymentChallenge,
319
+ RateLimited: {
320
+ content: errorContent(429, errorCodes[429], 'Rate limit exceeded.'),
321
+ description:
322
+ 'Rate limit exceeded. On endpoints that accept MPP, over-quota unpaid requests return `402 Payment Required` instead.',
323
+ headers: { ...rateLimitHeaders },
324
+ },
325
+ RequestTimeout: {
326
+ content: errorContent(504, errorCodes[504], 'Request timed out'),
327
+ description:
328
+ 'Request timed out. The request did not complete within the 60-second deadline; retry it.',
329
+ },
330
+ }
212
331
  }
213
332
 
214
- const responseRef = (name: keyof typeof responseComponents) => ({
333
+ const responseRef = (name: ResponseComponentName) => ({
215
334
  $ref: `#/components/responses/${name}`,
216
335
  })
217
336
 
@@ -232,22 +351,24 @@ export function standardError(
232
351
  ): ResponsesWithResolver[string] {
233
352
  if (status === 429) return responseRef('RateLimited')
234
353
  if (status === 500) return responseRef('InternalError')
235
- return { content: errorContent(codes ?? errorCodes[status], description), description }
354
+ if (status === 504) return responseRef('RequestTimeout')
355
+ return { content: errorContent(status, mergeErrorCodes(status, codes), description), description }
236
356
  }
237
357
 
238
358
  /**
239
359
  * Builds an OpenAPI `responses` map with the API's standard error responses
240
360
  * pre-filled, plus the success response (with rate-limit headers):
241
361
  *
242
- * - `400` invalid request, `401` missing/invalid key, `429` rate limited,
243
- * `500` internal error, and `502` upstream failure on every operation;
244
- * - `403`/`404`/`409`/`412`/`413`/`415` only when an `errors` entry is set.
362
+ * - `400` invalid request, `401` missing/invalid key, `403` forbidden, `429`
363
+ * rate limited, `500` internal error, `502` upstream failure, and `504`
364
+ * request timeout on every operation;
365
+ * - `404`/`409`/`412`/`413`/`415` only when an `errors` entry is set.
245
366
  *
246
- * `error.code` is enumerated per status from {@link errorCodes}; narrow 400/404
247
- * to a route's exact codes by passing `{ description, codes }` for that status.
248
- * `429`/`500` `$ref` the shared {@link responseComponents}. `402` is not emitted
249
- * here it is injected per operation from the route's MPP policy during spec
250
- * generation (see `App.ts`).
367
+ * `error.code` is enumerated per status from {@link errorCodes}. Operation-level
368
+ * 400/403 codes merge with shared auth codes; other overrides replace defaults.
369
+ * The default `429` and `500` `$ref` shared {@link responseComponents}; an exact
370
+ * operation-level `429` override is emitted inline with the standard headers.
371
+ * `402` is injected per operation from the route's MPP policy in `App.ts`.
251
372
  */
252
373
  export function responses<schema extends z.ZodMiniType>(
253
374
  options: responses.Options<schema>,
@@ -257,10 +378,11 @@ export function responses<schema extends z.ZodMiniType>(
257
378
  const override = errors?.[status as 400]
258
379
  const description =
259
380
  typeof override === 'string' ? override : (override?.description ?? fallback)
260
- const codes =
261
- (typeof override === 'object' ? override.codes : undefined) ??
262
- errorCodes[status as keyof typeof errorCodes]
263
- return { content: errorContent(codes, description), description }
381
+ const codes = mergeErrorCodes(status, typeof override === 'object' ? override.codes : undefined)
382
+ return {
383
+ content: errorContent(status, codes, description),
384
+ description,
385
+ }
264
386
  }
265
387
  return {
266
388
  200: {
@@ -279,39 +401,41 @@ export function responses<schema extends z.ZodMiniType>(
279
401
  },
280
402
  400: error(400, 'Invalid request.'),
281
403
  401: error(401, 'Missing or invalid API key.'),
282
- ...(errors?.[403] && { 403: error(403, 'Forbidden.') }),
404
+ 403: error(403, 'Forbidden.'),
283
405
  ...(errors?.[404] && { 404: error(404, 'Not found.') }),
284
406
  ...(errors?.[409] && { 409: error(409, 'Conflict.') }),
285
407
  ...(errors?.[412] && { 412: error(412, 'Precondition failed.') }),
286
408
  ...(errors?.[413] && { 413: error(413, 'Payload too large.') }),
287
409
  ...(errors?.[415] && { 415: error(415, 'Unsupported media type.') }),
288
- 429: responseRef('RateLimited'),
410
+ 429: errors?.[429]
411
+ ? { ...error(429, 'Rate limit exceeded.'), headers: { ...rateLimitHeaders } }
412
+ : responseRef('RateLimited'),
289
413
  500: responseRef('InternalError'),
290
414
  ...(errors?.[501] && { 501: error(501, 'Not implemented.') }),
291
415
  502: error(502, 'Upstream data failure.'),
416
+ 504: responseRef('RequestTimeout'),
292
417
  }
293
418
  }
294
419
 
295
420
  export declare namespace responses {
296
421
  /**
297
422
  * Override for a standard error response: a description string, or an object
298
- * adding the exact `codes` that status can return (narrowing the enum).
423
+ * adding operation codes. Codes replace defaults except shared 400/403 auth codes.
299
424
  */
300
425
  type ErrorOverride =
301
426
  | string
302
427
  | {
303
428
  /** Human-readable description of the error response. */
304
429
  description?: string | undefined
305
- /** Exact `error.code` values this status returns for the operation. */
306
- codes?: readonly [string, ...string[]] | undefined
430
+ /** Operation-specific `error.code` values for this status. */
431
+ codes?: readonly string[] | undefined
307
432
  }
308
433
 
309
434
  /** Options for building a standard OpenAPI responses map. */
310
435
  type Options<schema> = {
311
436
  /**
312
- * Optional overrides for standard error responses (description and/or exact
313
- * `error.code` enum). Setting `403`/`404`/`409`/`412`/`413`/`415` also
314
- * includes that status in the map.
437
+ * Optional overrides for standard error responses. Setting
438
+ * `404`/`409`/`412`/`413`/`415` includes that status in the map.
315
439
  */
316
440
  errors?:
317
441
  | {
@@ -319,7 +443,7 @@ export declare namespace responses {
319
443
  400?: ErrorOverride | undefined
320
444
  /** Override for the 401 response. */
321
445
  401?: ErrorOverride | undefined
322
- /** Override for the 403 response. Setting this includes 403 in the map. */
446
+ /** Add operation-specific 403 codes or override its description. */
323
447
  403?: ErrorOverride | undefined
324
448
  /** Override for the 404 response. Setting this includes 404 in the map. */
325
449
  404?: ErrorOverride | undefined
@@ -331,6 +455,8 @@ export declare namespace responses {
331
455
  413?: ErrorOverride | undefined
332
456
  /** Override for the 415 response. Setting this includes 415 in the map. */
333
457
  415?: ErrorOverride | undefined
458
+ /** Override the shared 429 response with operation-specific rate-limit codes. */
459
+ 429?: ErrorOverride | undefined
334
460
  /** Override for the 501 response. Setting this includes 501 in the map. */
335
461
  501?: ErrorOverride | undefined
336
462
  /** Override for the 502 response. */
@@ -1,4 +1,5 @@
1
1
  import { Hono } from 'hono'
2
+ import { Tidx } from 'tidx.ts'
2
3
 
3
4
  import * as Response from './Response.js'
4
5
 
@@ -25,4 +26,98 @@ describe('upstream', () => {
25
26
  `)
26
27
  expect(captured).toBe(cause)
27
28
  })
29
+
30
+ test('returns a query error when a positional page times out', async () => {
31
+ const app = new Hono()
32
+ const cause = new Tidx.FetchRequestError(
33
+ 'Request timeout',
34
+ new globalThis.Response(null, { status: 408 }),
35
+ )
36
+ let captured: Error | undefined
37
+
38
+ app.use(async (c, next) => {
39
+ await next()
40
+ captured = c.error
41
+ })
42
+ app.get('/', (c) => Response.upstream(c, cause, { page: 2 }))
43
+
44
+ const response = await app.request('/')
45
+ expect(response.status).toMatchInlineSnapshot(`400`)
46
+ expect(await response.json()).toMatchInlineSnapshot(`
47
+ {
48
+ "error": {
49
+ "code": "query_invalid",
50
+ "message": "The requested page timed out. Use cursor pagination for deep traversal.",
51
+ },
52
+ }
53
+ `)
54
+ expect(captured).toBe(cause)
55
+ })
56
+
57
+ test('returns a query error when a positional page is rejected', async () => {
58
+ const app = new Hono()
59
+ const cause = new Tidx.FetchRequestError(
60
+ 'Query rejected',
61
+ new globalThis.Response(null, { status: 422 }),
62
+ )
63
+ let captured: Error | undefined
64
+
65
+ app.use(async (c, next) => {
66
+ await next()
67
+ captured = c.error
68
+ })
69
+ app.get('/', (c) => Response.upstream(c, cause, { page: 584 }))
70
+
71
+ const response = await app.request('/')
72
+ expect(response.status).toMatchInlineSnapshot(`400`)
73
+ expect(await response.json()).toMatchInlineSnapshot(`
74
+ {
75
+ "error": {
76
+ "code": "query_invalid",
77
+ "message": "The requested page was rejected. Use cursor pagination for deep traversal.",
78
+ },
79
+ }
80
+ `)
81
+ expect(captured).toBe(cause)
82
+ })
83
+
84
+ test('keeps timeouts without a deep positional page as upstream errors', async () => {
85
+ const app = new Hono()
86
+ const cause = new Tidx.FetchRequestError(
87
+ 'Request timeout',
88
+ new globalThis.Response(null, { status: 408 }),
89
+ )
90
+ app.get('/', (c) => Response.upstream(c, cause, { page: undefined }))
91
+
92
+ const response = await app.request('/')
93
+ expect(response.status).toMatchInlineSnapshot(`502`)
94
+ expect(await response.json()).toMatchInlineSnapshot(`
95
+ {
96
+ "error": {
97
+ "code": "upstream_error",
98
+ "message": "Upstream service could not complete the request",
99
+ },
100
+ }
101
+ `)
102
+ })
103
+
104
+ test('keeps query rejections without a deep positional page as upstream errors', async () => {
105
+ const app = new Hono()
106
+ const cause = new Tidx.FetchRequestError(
107
+ 'Query rejected',
108
+ new globalThis.Response(null, { status: 422 }),
109
+ )
110
+ app.get('/', (c) => Response.upstream(c, cause, { page: undefined }))
111
+
112
+ const response = await app.request('/')
113
+ expect(response.status).toMatchInlineSnapshot(`502`)
114
+ expect(await response.json()).toMatchInlineSnapshot(`
115
+ {
116
+ "error": {
117
+ "code": "upstream_error",
118
+ "message": "Upstream service could not complete the request",
119
+ },
120
+ }
121
+ `)
122
+ })
28
123
  })