tapimo 0.0.0 → 0.0.2

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 (422) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/ApiKey.d.ts +65 -0
  4. package/dist/ApiKey.d.ts.map +1 -0
  5. package/dist/ApiKey.js +105 -0
  6. package/dist/ApiKey.js.map +1 -0
  7. package/dist/ApiKeySource.d.ts +166 -0
  8. package/dist/ApiKeySource.d.ts.map +1 -0
  9. package/dist/ApiKeySource.js +234 -0
  10. package/dist/ApiKeySource.js.map +1 -0
  11. package/dist/App.d.ts +19317 -0
  12. package/dist/App.d.ts.map +1 -0
  13. package/dist/App.js +612 -0
  14. package/dist/App.js.map +1 -0
  15. package/dist/Assets.d.ts +44 -0
  16. package/dist/Assets.d.ts.map +1 -0
  17. package/dist/Assets.js +23 -0
  18. package/dist/Assets.js.map +1 -0
  19. package/dist/Auth.d.ts +2 -0
  20. package/dist/Auth.d.ts.map +1 -0
  21. package/dist/Auth.js +2 -0
  22. package/dist/Auth.js.map +1 -0
  23. package/dist/Cli.d.ts +21 -0
  24. package/dist/Cli.d.ts.map +1 -0
  25. package/dist/Cli.js +13 -0
  26. package/dist/Cli.js.map +1 -0
  27. package/dist/Client.d.ts +20 -0
  28. package/dist/Client.d.ts.map +1 -0
  29. package/dist/Client.js +24 -0
  30. package/dist/Client.js.map +1 -0
  31. package/dist/Metrics.d.ts +70 -0
  32. package/dist/Metrics.d.ts.map +1 -0
  33. package/dist/Metrics.js +91 -0
  34. package/dist/Metrics.js.map +1 -0
  35. package/dist/Scope.d.ts +35 -0
  36. package/dist/Scope.d.ts.map +1 -0
  37. package/dist/Scope.js +38 -0
  38. package/dist/Scope.js.map +1 -0
  39. package/dist/Webhooks.d.ts +79 -0
  40. package/dist/Webhooks.d.ts.map +1 -0
  41. package/dist/Webhooks.js +107 -0
  42. package/dist/Webhooks.js.map +1 -0
  43. package/dist/admin/Access.d.ts +41 -0
  44. package/dist/admin/Access.d.ts.map +1 -0
  45. package/dist/admin/Access.js +75 -0
  46. package/dist/admin/Access.js.map +1 -0
  47. package/dist/admin/App.d.ts +1221 -0
  48. package/dist/admin/App.d.ts.map +1 -0
  49. package/dist/admin/App.js +113 -0
  50. package/dist/admin/App.js.map +1 -0
  51. package/dist/admin/apps/api-keys.d.ts +209 -0
  52. package/dist/admin/apps/api-keys.d.ts.map +1 -0
  53. package/dist/admin/apps/api-keys.js +129 -0
  54. package/dist/admin/apps/api-keys.js.map +1 -0
  55. package/dist/admin/apps/scopes.d.ts +46 -0
  56. package/dist/admin/apps/scopes.d.ts.map +1 -0
  57. package/dist/admin/apps/scopes.js +41 -0
  58. package/dist/admin/apps/scopes.js.map +1 -0
  59. package/dist/admin/apps/verified-tokens.d.ts +1206 -0
  60. package/dist/admin/apps/verified-tokens.d.ts.map +1 -0
  61. package/dist/admin/apps/verified-tokens.js +485 -0
  62. package/dist/admin/apps/verified-tokens.js.map +1 -0
  63. package/dist/admin/index.d.ts +3 -0
  64. package/dist/admin/index.d.ts.map +1 -0
  65. package/dist/admin/index.js +3 -0
  66. package/dist/admin/index.js.map +1 -0
  67. package/dist/admin/ui.generated.d.ts +11 -0
  68. package/dist/admin/ui.generated.d.ts.map +1 -0
  69. package/dist/admin/ui.generated.js +43 -0
  70. package/dist/admin/ui.generated.js.map +1 -0
  71. package/dist/apps/activities.d.ts +18725 -0
  72. package/dist/apps/activities.d.ts.map +1 -0
  73. package/dist/apps/activities.js +3138 -0
  74. package/dist/apps/activities.js.map +1 -0
  75. package/dist/apps/addresses.d.ts +3662 -0
  76. package/dist/apps/addresses.d.ts.map +1 -0
  77. package/dist/apps/addresses.js +22 -0
  78. package/dist/apps/addresses.js.map +1 -0
  79. package/dist/apps/balances.d.ts +342 -0
  80. package/dist/apps/balances.d.ts.map +1 -0
  81. package/dist/apps/balances.js +393 -0
  82. package/dist/apps/balances.js.map +1 -0
  83. package/dist/apps/blocks.d.ts +931 -0
  84. package/dist/apps/blocks.d.ts.map +1 -0
  85. package/dist/apps/blocks.js +689 -0
  86. package/dist/apps/blocks.js.map +1 -0
  87. package/dist/apps/coingecko.d.ts +1053 -0
  88. package/dist/apps/coingecko.d.ts.map +1 -0
  89. package/dist/apps/coingecko.js +1015 -0
  90. package/dist/apps/coingecko.js.map +1 -0
  91. package/dist/apps/exchanges.d.ts +3000 -0
  92. package/dist/apps/exchanges.d.ts.map +1 -0
  93. package/dist/apps/exchanges.js +3570 -0
  94. package/dist/apps/exchanges.js.map +1 -0
  95. package/dist/apps/fee-amm.d.ts +640 -0
  96. package/dist/apps/fee-amm.d.ts.map +1 -0
  97. package/dist/apps/fee-amm.js +815 -0
  98. package/dist/apps/fee-amm.js.map +1 -0
  99. package/dist/apps/indexer.d.ts +116 -0
  100. package/dist/apps/indexer.d.ts.map +1 -0
  101. package/dist/apps/indexer.js +270 -0
  102. package/dist/apps/indexer.js.map +1 -0
  103. package/dist/apps/receipts.d.ts +1438 -0
  104. package/dist/apps/receipts.d.ts.map +1 -0
  105. package/dist/apps/receipts.js +874 -0
  106. package/dist/apps/receipts.js.map +1 -0
  107. package/dist/apps/rpc.d.ts +173 -0
  108. package/dist/apps/rpc.d.ts.map +1 -0
  109. package/dist/apps/rpc.js +191 -0
  110. package/dist/apps/rpc.js.map +1 -0
  111. package/dist/apps/tokenlist.d.ts +192 -0
  112. package/dist/apps/tokenlist.d.ts.map +1 -0
  113. package/dist/apps/tokenlist.js +153 -0
  114. package/dist/apps/tokenlist.js.map +1 -0
  115. package/dist/apps/tokens.d.ts +2246 -0
  116. package/dist/apps/tokens.d.ts.map +1 -0
  117. package/dist/apps/tokens.js +1789 -0
  118. package/dist/apps/tokens.js.map +1 -0
  119. package/dist/apps/transactions.d.ts +2327 -0
  120. package/dist/apps/transactions.d.ts.map +1 -0
  121. package/dist/apps/transactions.js +975 -0
  122. package/dist/apps/transactions.js.map +1 -0
  123. package/dist/apps/transfers.d.ts +589 -0
  124. package/dist/apps/transfers.d.ts.map +1 -0
  125. package/dist/apps/transfers.js +769 -0
  126. package/dist/apps/transfers.js.map +1 -0
  127. package/dist/apps/verified-tokens.d.ts +544 -0
  128. package/dist/apps/verified-tokens.d.ts.map +1 -0
  129. package/dist/apps/verified-tokens.js +234 -0
  130. package/dist/apps/verified-tokens.js.map +1 -0
  131. package/dist/apps/webhooks.d.ts +7684 -0
  132. package/dist/apps/webhooks.d.ts.map +1 -0
  133. package/dist/apps/webhooks.js +2112 -0
  134. package/dist/apps/webhooks.js.map +1 -0
  135. package/dist/cloudflare.d.ts +32 -0
  136. package/dist/cloudflare.d.ts.map +1 -0
  137. package/dist/cloudflare.js +45 -0
  138. package/dist/cloudflare.js.map +1 -0
  139. package/dist/index.d.ts +16 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +16 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/internal/Auth.d.ts +298 -0
  144. package/dist/internal/Auth.d.ts.map +1 -0
  145. package/dist/internal/Auth.js +618 -0
  146. package/dist/internal/Auth.js.map +1 -0
  147. package/dist/internal/Cache.d.ts +74 -0
  148. package/dist/internal/Cache.d.ts.map +1 -0
  149. package/dist/internal/Cache.js +215 -0
  150. package/dist/internal/Cache.js.map +1 -0
  151. package/dist/internal/Cursor.d.ts +79 -0
  152. package/dist/internal/Cursor.d.ts.map +1 -0
  153. package/dist/internal/Cursor.js +116 -0
  154. package/dist/internal/Cursor.js.map +1 -0
  155. package/dist/internal/EdgeCache.d.ts +59 -0
  156. package/dist/internal/EdgeCache.d.ts.map +1 -0
  157. package/dist/internal/EdgeCache.js +174 -0
  158. package/dist/internal/EdgeCache.js.map +1 -0
  159. package/dist/internal/Log.d.ts +104 -0
  160. package/dist/internal/Log.d.ts.map +1 -0
  161. package/dist/internal/Log.js +118 -0
  162. package/dist/internal/Log.js.map +1 -0
  163. package/dist/internal/MetricSink.d.ts +65 -0
  164. package/dist/internal/MetricSink.d.ts.map +1 -0
  165. package/dist/internal/MetricSink.js +146 -0
  166. package/dist/internal/MetricSink.js.map +1 -0
  167. package/dist/internal/Mpp.d.ts +71 -0
  168. package/dist/internal/Mpp.d.ts.map +1 -0
  169. package/dist/internal/Mpp.js +105 -0
  170. package/dist/internal/Mpp.js.map +1 -0
  171. package/dist/internal/OpenApi.d.ts +313 -0
  172. package/dist/internal/OpenApi.d.ts.map +1 -0
  173. package/dist/internal/OpenApi.fonts.d.ts +2 -0
  174. package/dist/internal/OpenApi.fonts.d.ts.map +1 -0
  175. package/dist/internal/OpenApi.fonts.js +39 -0
  176. package/dist/internal/OpenApi.fonts.js.map +1 -0
  177. package/dist/internal/OpenApi.js +335 -0
  178. package/dist/internal/OpenApi.js.map +1 -0
  179. package/dist/internal/OpenApi.logo.d.ts +6 -0
  180. package/dist/internal/OpenApi.logo.d.ts.map +1 -0
  181. package/dist/internal/OpenApi.logo.js +19 -0
  182. package/dist/internal/OpenApi.logo.js.map +1 -0
  183. package/dist/internal/Path.d.ts +5 -0
  184. package/dist/internal/Path.d.ts.map +1 -0
  185. package/dist/internal/Path.js +16 -0
  186. package/dist/internal/Path.js.map +1 -0
  187. package/dist/internal/RateLimit.d.ts +60 -0
  188. package/dist/internal/RateLimit.d.ts.map +1 -0
  189. package/dist/internal/RateLimit.js +48 -0
  190. package/dist/internal/RateLimit.js.map +1 -0
  191. package/dist/internal/Response.d.ts +132 -0
  192. package/dist/internal/Response.d.ts.map +1 -0
  193. package/dist/internal/Response.js +72 -0
  194. package/dist/internal/Response.js.map +1 -0
  195. package/dist/internal/Schema.d.ts +257 -0
  196. package/dist/internal/Schema.d.ts.map +1 -0
  197. package/dist/internal/Schema.js +360 -0
  198. package/dist/internal/Schema.js.map +1 -0
  199. package/dist/internal/Store.d.ts +204 -0
  200. package/dist/internal/Store.d.ts.map +1 -0
  201. package/dist/internal/Store.js +291 -0
  202. package/dist/internal/Store.js.map +1 -0
  203. package/dist/internal/Tidx.d.ts +120 -0
  204. package/dist/internal/Tidx.d.ts.map +1 -0
  205. package/dist/internal/Tidx.js +156 -0
  206. package/dist/internal/Tidx.js.map +1 -0
  207. package/dist/internal/Timing.d.ts +22 -0
  208. package/dist/internal/Timing.d.ts.map +1 -0
  209. package/dist/internal/Timing.js +32 -0
  210. package/dist/internal/Timing.js.map +1 -0
  211. package/dist/internal/Ttl.d.ts +25 -0
  212. package/dist/internal/Ttl.d.ts.map +1 -0
  213. package/dist/internal/Ttl.js +49 -0
  214. package/dist/internal/Ttl.js.map +1 -0
  215. package/dist/internal/Value.d.ts +47 -0
  216. package/dist/internal/Value.d.ts.map +1 -0
  217. package/dist/internal/Value.js +122 -0
  218. package/dist/internal/Value.js.map +1 -0
  219. package/dist/internal/VerifiedTokens.d.ts +228 -0
  220. package/dist/internal/VerifiedTokens.d.ts.map +1 -0
  221. package/dist/internal/VerifiedTokens.js +450 -0
  222. package/dist/internal/VerifiedTokens.js.map +1 -0
  223. package/dist/internal/Viem.d.ts +2082 -0
  224. package/dist/internal/Viem.d.ts.map +1 -0
  225. package/dist/internal/Viem.js +63 -0
  226. package/dist/internal/Viem.js.map +1 -0
  227. package/dist/internal/WebhookDestination.d.ts +198 -0
  228. package/dist/internal/WebhookDestination.d.ts.map +1 -0
  229. package/dist/internal/WebhookDestination.js +170 -0
  230. package/dist/internal/WebhookDestination.js.map +1 -0
  231. package/dist/internal/Webhooks.d.ts +433 -0
  232. package/dist/internal/Webhooks.d.ts.map +1 -0
  233. package/dist/internal/Webhooks.js +489 -0
  234. package/dist/internal/Webhooks.js.map +1 -0
  235. package/dist/internal/webhookDestinations/betterStack.d.ts +26 -0
  236. package/dist/internal/webhookDestinations/betterStack.d.ts.map +1 -0
  237. package/dist/internal/webhookDestinations/betterStack.js +76 -0
  238. package/dist/internal/webhookDestinations/betterStack.js.map +1 -0
  239. package/dist/internal/webhookDestinations/slack.d.ts +59 -0
  240. package/dist/internal/webhookDestinations/slack.d.ts.map +1 -0
  241. package/dist/internal/webhookDestinations/slack.js +422 -0
  242. package/dist/internal/webhookDestinations/slack.js.map +1 -0
  243. package/dist/internal/webhookDestinations/url.d.ts +17 -0
  244. package/dist/internal/webhookDestinations/url.d.ts.map +1 -0
  245. package/dist/internal/webhookDestinations/url.js +130 -0
  246. package/dist/internal/webhookDestinations/url.js.map +1 -0
  247. package/dist/openrpc.json +5302 -0
  248. package/package.json +46 -4
  249. package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +1 -0
  250. package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
  251. package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
  252. package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
  253. package/seeds/31318/verified-tokens.json +30 -0
  254. package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
  255. package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +1 -0
  256. package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +1 -0
  257. package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +4 -0
  258. package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +30 -0
  259. package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +1 -0
  260. package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +1 -0
  261. package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +1 -0
  262. package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +11 -0
  263. package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +1 -0
  264. package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +1 -0
  265. package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
  266. package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +1 -0
  267. package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
  268. package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +1 -0
  269. package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +5 -0
  270. package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +1 -0
  271. package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +1 -0
  272. package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +1 -0
  273. package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +1 -0
  274. package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +1 -0
  275. package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +1 -0
  276. package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +1 -0
  277. package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +1 -0
  278. package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
  279. package/seeds/4217/verified-tokens.json +177 -0
  280. package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
  281. package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
  282. package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
  283. package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
  284. package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +1 -0
  285. package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +1 -0
  286. package/seeds/42431/verified-tokens.json +44 -0
  287. package/seeds/openrpc/README.md +27 -0
  288. package/seeds/openrpc/execution-apis.json +8989 -0
  289. package/src/ApiKey.test.ts +91 -0
  290. package/src/ApiKey.ts +122 -0
  291. package/src/ApiKeySource.test-d.ts +11 -0
  292. package/src/ApiKeySource.test.ts +295 -0
  293. package/src/ApiKeySource.ts +303 -0
  294. package/src/App.test-d.ts +38 -0
  295. package/src/App.test.ts +65927 -0
  296. package/src/App.ts +855 -0
  297. package/src/Assets.ts +58 -0
  298. package/src/Auth.ts +1 -0
  299. package/src/Cli.test.ts +81 -0
  300. package/src/Cli.ts +38 -0
  301. package/src/Client.test-d.ts +1438 -0
  302. package/src/Client.test.ts +134 -0
  303. package/src/Client.ts +45 -0
  304. package/src/Metrics.ts +154 -0
  305. package/src/Scope.ts +50 -0
  306. package/src/Webhooks.test.ts +49 -0
  307. package/src/Webhooks.ts +172 -0
  308. package/src/admin/Access.test.ts +130 -0
  309. package/src/admin/Access.ts +87 -0
  310. package/src/admin/App.test.ts +225 -0
  311. package/src/admin/App.ts +216 -0
  312. package/src/admin/apps/api-keys.test.ts +156 -0
  313. package/src/admin/apps/api-keys.ts +157 -0
  314. package/src/admin/apps/scopes.test.ts +52 -0
  315. package/src/admin/apps/scopes.ts +47 -0
  316. package/src/admin/apps/verified-tokens.test.ts +415 -0
  317. package/src/admin/apps/verified-tokens.ts +566 -0
  318. package/src/admin/index.ts +2 -0
  319. package/src/admin/ui/plugin.ts +135 -0
  320. package/src/admin/ui/src/components/Checkbox.tsx +22 -0
  321. package/src/admin/ui/src/components/Dialog.tsx +32 -0
  322. package/src/admin/ui/src/components/MobileProfile.tsx +31 -0
  323. package/src/admin/ui/src/components/Page.tsx +53 -0
  324. package/src/admin/ui/src/components/TempoLogo.tsx +37 -0
  325. package/src/admin/ui/src/fonts/Pilat-Demi.woff2 +0 -0
  326. package/src/admin/ui/src/fonts/Pilat-Regular.woff2 +0 -0
  327. package/src/admin/ui/src/lib/api-keys.ts +63 -0
  328. package/src/admin/ui/src/lib/client.ts +15 -0
  329. package/src/admin/ui/src/lib/config.ts +57 -0
  330. package/src/admin/ui/src/lib/query-client.ts +26 -0
  331. package/src/admin/ui/src/lib/scopes.ts +25 -0
  332. package/src/admin/ui/src/lib/verified-tokens.ts +89 -0
  333. package/src/admin/ui/src/lib/wagmi.ts +18 -0
  334. package/src/admin/ui/src/routeTree.gen.ts +104 -0
  335. package/src/admin/ui/src/router.tsx +25 -0
  336. package/src/admin/ui/src/routes/__root.tsx +219 -0
  337. package/src/admin/ui/src/routes/api-keys.tsx +329 -0
  338. package/src/admin/ui/src/routes/index.tsx +7 -0
  339. package/src/admin/ui/src/routes/verified-tokens.tsx +331 -0
  340. package/src/admin/ui/src/styles.css +20 -0
  341. package/src/admin/ui/tsconfig.json +16 -0
  342. package/src/admin/ui/vite.config.ts +29 -0
  343. package/src/admin/ui.generated.ts +60 -0
  344. package/src/apps/activities.test.ts +1020 -0
  345. package/src/apps/activities.ts +3934 -0
  346. package/src/apps/addresses.ts +24 -0
  347. package/src/apps/balances.test.ts +274 -0
  348. package/src/apps/balances.ts +533 -0
  349. package/src/apps/blocks.test.ts +385 -0
  350. package/src/apps/blocks.ts +896 -0
  351. package/src/apps/coingecko.test.ts +218 -0
  352. package/src/apps/coingecko.ts +1383 -0
  353. package/src/apps/exchanges.test.ts +958 -0
  354. package/src/apps/exchanges.ts +4773 -0
  355. package/src/apps/fee-amm.test.ts +321 -0
  356. package/src/apps/fee-amm.ts +1121 -0
  357. package/src/apps/indexer.test.ts +153 -0
  358. package/src/apps/indexer.ts +330 -0
  359. package/src/apps/receipts.test.ts +285 -0
  360. package/src/apps/receipts.ts +1193 -0
  361. package/src/apps/rpc.test.ts +302 -0
  362. package/src/apps/rpc.ts +222 -0
  363. package/src/apps/tokenlist.test.ts +80 -0
  364. package/src/apps/tokenlist.ts +207 -0
  365. package/src/apps/tokens.test.ts +1062 -0
  366. package/src/apps/tokens.ts +2292 -0
  367. package/src/apps/transactions.test.ts +408 -0
  368. package/src/apps/transactions.ts +1363 -0
  369. package/src/apps/transfers.test.ts +371 -0
  370. package/src/apps/transfers.ts +1116 -0
  371. package/src/apps/verified-tokens.test.ts +114 -0
  372. package/src/apps/verified-tokens.ts +295 -0
  373. package/src/apps/webhooks.test.ts +1937 -0
  374. package/src/apps/webhooks.ts +2926 -0
  375. package/src/cloudflare.ts +55 -0
  376. package/src/index.ts +15 -0
  377. package/src/internal/Auth.test.ts +980 -0
  378. package/src/internal/Auth.ts +1012 -0
  379. package/src/internal/Cache.test.ts +240 -0
  380. package/src/internal/Cache.ts +262 -0
  381. package/src/internal/Cursor.test.ts +100 -0
  382. package/src/internal/Cursor.ts +149 -0
  383. package/src/internal/EdgeCache.test.ts +234 -0
  384. package/src/internal/EdgeCache.ts +224 -0
  385. package/src/internal/Errors.ts +14 -0
  386. package/src/internal/Log.test.ts +244 -0
  387. package/src/internal/Log.ts +216 -0
  388. package/src/internal/MetricSink.ts +220 -0
  389. package/src/internal/Mpp.test.ts +64 -0
  390. package/src/internal/Mpp.ts +141 -0
  391. package/src/internal/OpenApi.fonts.ts +38 -0
  392. package/src/internal/OpenApi.logo.ts +18 -0
  393. package/src/internal/OpenApi.ts +488 -0
  394. package/src/internal/Path.test.ts +14 -0
  395. package/src/internal/Path.ts +15 -0
  396. package/src/internal/RateLimit.test.ts +93 -0
  397. package/src/internal/RateLimit.ts +93 -0
  398. package/src/internal/Response.ts +131 -0
  399. package/src/internal/Schema.test.ts +34 -0
  400. package/src/internal/Schema.ts +523 -0
  401. package/src/internal/Store.test.ts +545 -0
  402. package/src/internal/Store.ts +526 -0
  403. package/src/internal/Tidx.local.test.ts +33 -0
  404. package/src/internal/Tidx.test.ts +294 -0
  405. package/src/internal/Tidx.ts +238 -0
  406. package/src/internal/Timing.test.ts +22 -0
  407. package/src/internal/Timing.ts +62 -0
  408. package/src/internal/Ttl.test.ts +18 -0
  409. package/src/internal/Ttl.ts +59 -0
  410. package/src/internal/Value.ts +114 -0
  411. package/src/internal/VerifiedTokens.test.ts +333 -0
  412. package/src/internal/VerifiedTokens.ts +645 -0
  413. package/src/internal/Viem.test.ts +115 -0
  414. package/src/internal/Viem.ts +165 -0
  415. package/src/internal/WebhookDestination.test.ts +648 -0
  416. package/src/internal/WebhookDestination.ts +331 -0
  417. package/src/internal/Webhooks.test.ts +668 -0
  418. package/src/internal/Webhooks.ts +940 -0
  419. package/src/internal/webhookDestinations/betterStack.ts +91 -0
  420. package/src/internal/webhookDestinations/slack.ts +496 -0
  421. package/src/internal/webhookDestinations/url.ts +128 -0
  422. package/src/openrpc.json +5302 -0
@@ -0,0 +1,91 @@
1
+ import * as ApiKeySource from './ApiKeySource.js'
2
+ import * as ApiKey from './ApiKey.js'
3
+ import * as Store from './internal/Store.js'
4
+
5
+ describe('schema.ApiKey', () => {
6
+ test('environment defaults to production when omitted', () => {
7
+ const parsed = ApiKey.schema.ApiKey.parse({
8
+ id: 'key_test',
9
+ orgId: 'org_test',
10
+ scopes: ['data:read'],
11
+ })
12
+ expect(parsed.environment).toMatchInlineSnapshot(`"production"`)
13
+ })
14
+
15
+ test('accepts an explicit sandbox environment', () => {
16
+ const parsed = ApiKey.schema.ApiKey.parse({
17
+ environment: 'sandbox',
18
+ id: 'key_test',
19
+ orgId: 'org_test',
20
+ scopes: ['data:read'],
21
+ })
22
+ expect(parsed.environment).toMatchInlineSnapshot(`"sandbox"`)
23
+ })
24
+
25
+ test('rejects an unknown environment', () => {
26
+ expect(
27
+ ApiKey.schema.ApiKey.safeParse({
28
+ environment: 'staging',
29
+ id: 'key_test',
30
+ orgId: 'org_test',
31
+ scopes: ['data:read'],
32
+ }).success,
33
+ ).toBe(false)
34
+ })
35
+ })
36
+
37
+ describe('redact', () => {
38
+ test('masks tokens anywhere in a string', () => {
39
+ const token = `tempo:sk:${'a'.repeat(48)}`
40
+ expect(ApiKey.redact(`auth failed for ${token} on /tokens`)).toMatchInlineSnapshot(
41
+ `"auth failed for tempo:sk:… on /tokens"`,
42
+ )
43
+ })
44
+
45
+ test('masks sandbox tokens, preserving their prefix', () => {
46
+ const token = `tempo_sandbox:sk:${'a'.repeat(48)}`
47
+ expect(ApiKey.redact(`auth failed for ${token} on /tokens`)).toMatchInlineSnapshot(
48
+ `"auth failed for tempo_sandbox:sk:… on /tokens"`,
49
+ )
50
+ })
51
+
52
+ test('masks deprecated v1 tokens', () => {
53
+ const token = `tempo_${'a'.repeat(40)}`
54
+ expect(ApiKey.redact(`auth failed for ${token} on /tokens`)).toMatchInlineSnapshot(
55
+ `"auth failed for tempo_… on /tokens"`,
56
+ )
57
+ })
58
+
59
+ test('leaves non-token text untouched', () => {
60
+ expect(ApiKey.redact('nothing secret here')).toMatchInlineSnapshot(`"nothing secret here"`)
61
+ })
62
+ })
63
+
64
+ // The wire layout (record prefix + token hash) is the contract every persisted
65
+ // key is stored under; the resolver and every source's `mint` must agree on it.
66
+ // These assertions pin it so an accidental change fails loudly.
67
+ describe('keyFor', () => {
68
+ test('pins the record prefix and token hash (sha256 of UTF-8 bytes, hex)', () => {
69
+ expect(ApiKey.recordPrefix).toMatchInlineSnapshot(`"apikey:"`)
70
+ expect(ApiKey.keyFor('tempo:sk:test')).toMatchInlineSnapshot(
71
+ `"apikey:9e11781fc2ea4581de193fc7fde09dda7c01151785cdcf2f5fbef52125b225b8"`,
72
+ )
73
+ })
74
+
75
+ test('reader resolves a record written with the documented wire layout', async () => {
76
+ const token = `tempo:sk:${'a'.repeat(48)}`
77
+ const record = {
78
+ createdAt: '2026-01-01T00:00:00.000Z',
79
+ id: 'key_smoke',
80
+ orgId: 'org_test',
81
+ scopes: ['data:read'],
82
+ tokenLast4: token.slice(-4),
83
+ }
84
+ const store = Store.memory({ entries: [[ApiKey.keyFor(token), JSON.stringify(record)]] })
85
+ expect(await ApiKeySource.store(store).resolve(token)).toMatchObject({
86
+ id: 'key_smoke',
87
+ orgId: 'org_test',
88
+ scopes: ['data:read'],
89
+ })
90
+ })
91
+ })
package/src/ApiKey.ts ADDED
@@ -0,0 +1,122 @@
1
+ /**
2
+ * The resolved API-key resource and the reusable credential primitives every
3
+ * source backend shares.
4
+ *
5
+ * Holds the resolved {@link ApiKey} type and its {@link schema}, the token
6
+ * format/generation ({@link generateToken}/{@link generateId}), the storage-key
7
+ * derivation ({@link keyFor}/{@link recordPrefix}), and log {@link redact}ion.
8
+ * These live here — not in a single source — so every `ApiKeySource` backend
9
+ * (the built-in store, a future D1/Postgres source) issues and parses
10
+ * byte-identical credentials and cannot drift. The persisted record/mint-input
11
+ * shapes and provisioning (mint/list/revoke) belong to the
12
+ * `ApiKeySource.Source` contract, which composes these primitives with its own
13
+ * persistence.
14
+ */
15
+
16
+ import { nanoid } from 'nanoid'
17
+ import { Hash, Hex } from 'ox'
18
+ import * as z from 'zod/mini'
19
+
20
+ import * as RateLimit from './internal/RateLimit.js'
21
+ import * as Scope from './Scope.js'
22
+
23
+ /** Zod schemas owned by the API-key module. */
24
+ export namespace schema {
25
+ /**
26
+ * Canonical schema for resolved API-key metadata, and the single source of
27
+ * truth for the {@link ApiKey} type. `ApiKeySource` derives its persisted
28
+ * `Record` and `MintInput` schemas from this one, so the resolved and
29
+ * persisted shapes cannot drift.
30
+ */
31
+ export const ApiKey = z.object({
32
+ environment: z
33
+ ._default(z.enum(['production', 'sandbox']), 'production')
34
+ .check(z.describe('Key environment.')),
35
+ id: z.string().check(z.describe('Stable key id.')),
36
+ name: z.optional(z.string()).check(z.describe('Human-readable key name.')),
37
+ orgId: z.string().check(z.describe('Owning organization id.')),
38
+ rateLimits: z
39
+ .optional(z.record(z.string(), RateLimit.schema.Limit))
40
+ .check(
41
+ z.describe(
42
+ "Per-key quota overrides keyed by quota scope. The reserved '*' entry is the per-key default; any other key overrides that scope. Omit to inherit server config. The most specific match wins.",
43
+ ),
44
+ ),
45
+ scopes: z
46
+ .readonly(z.array(z.enum([...Scope.catalog.map((entry) => entry.scope), Scope.wildcard])))
47
+ .check(z.describe("Granted scopes. '*' grants all scopes.")),
48
+ })
49
+ }
50
+
51
+ /** API-key metadata resolved by an auth source. */
52
+ export type ApiKey = z.output<typeof schema.ApiKey>
53
+
54
+ /**
55
+ * Replaces every issued token in a string with a masked placeholder so secrets
56
+ * never reach logs. Apply to anything that may embed a credential — error
57
+ * stacks, request dumps, and the values of the `tempo-api-key` and
58
+ * `Authorization` headers (whose tokens match the issued-token pattern).
59
+ */
60
+ export function redact(text: string): string {
61
+ return text
62
+ .replace(tokenPattern(), (match) => `${match.split('sk:')[0]}sk:…`)
63
+ .replace(legacyTokenPattern(), 'tempo_…')
64
+ }
65
+
66
+ /**
67
+ * Token prefix per environment. The prefix encodes the environment so a leaked
68
+ * sandbox token is visibly distinct from a production one; otherwise there is a
69
+ * single token kind. Prefixes exist purely for recognizability and leak
70
+ * detection (CI secret scanning, log redaction — see {@link redact}).
71
+ */
72
+ const tokenPrefix = {
73
+ production: 'tempo:sk:',
74
+ sandbox: 'tempo_sandbox:sk:',
75
+ } as const
76
+
77
+ /**
78
+ * Greppable pattern matching an issued token (`tempo:sk:`/`tempo_sandbox:sk:` +
79
+ * 48–64 lowercase hex chars), suitable for CI secret scanning and log
80
+ * redaction. A fresh instance is returned on each call so callers never share
81
+ * `lastIndex` state.
82
+ */
83
+ function tokenPattern(): RegExp {
84
+ return /tempo(_sandbox)?:sk:[a-f0-9]{48,64}/g
85
+ }
86
+
87
+ /**
88
+ * Greppable pattern matching a deprecated v1 token (`tempo_` + 40 lowercase hex
89
+ * chars), kept so legacy credentials are redacted from logs with the same
90
+ * guarantees as current tokens. A fresh instance is returned on each call so
91
+ * callers never share `lastIndex` state.
92
+ */
93
+ function legacyTokenPattern(): RegExp {
94
+ return /tempo_[a-f0-9]{40}/g
95
+ }
96
+
97
+ /**
98
+ * Generates a new plaintext token (environment prefix + 48 lowercase hex chars
99
+ * / 192 bits). Shared by every source backend so issued tokens are
100
+ * format-identical.
101
+ */
102
+ export function generateToken(environment: ApiKey['environment'] = 'production'): string {
103
+ return `${tokenPrefix[environment]}${Hex.random(24).slice(2)}`
104
+ }
105
+
106
+ /** Generates a stable, opaque key id (`key_…`). */
107
+ export function generateId(): string {
108
+ return `key_${nanoid()}`
109
+ }
110
+
111
+ /** Storage-key prefix under which key records are persisted, keyed by token hash. */
112
+ export const recordPrefix = 'apikey:'
113
+
114
+ /** Hashes a plaintext token to its at-rest lookup hash (lowercase hex, no `0x`). */
115
+ function hash(token: string): string {
116
+ return Hash.sha256(Hex.fromString(token)).slice(2)
117
+ }
118
+
119
+ /** Storage key under which the record for a plaintext token is persisted. */
120
+ export function keyFor(token: string): string {
121
+ return `${recordPrefix}${hash(token)}`
122
+ }
@@ -0,0 +1,11 @@
1
+ import type * as ApiKeySource from './ApiKeySource.js'
2
+
3
+ describe('MintInput.scopes', () => {
4
+ // The scope union flows from the central `Scope.catalog`, so minting
5
+ // with an unissuable scope is a compile error.
6
+ test('accepts catalog scopes and the wildcard, rejects unknown ones', () => {
7
+ expectTypeOf<['data:read', 'webhooks:write']>().toExtend<ApiKeySource.MintInput['scopes']>()
8
+ expectTypeOf<['*']>().toExtend<ApiKeySource.MintInput['scopes']>()
9
+ expectTypeOf<['totally:made-up']>().not.toExtend<ApiKeySource.MintInput['scopes']>()
10
+ })
11
+ })
@@ -0,0 +1,295 @@
1
+ import * as ApiKeySource from './ApiKeySource.js'
2
+ import * as Store from './internal/Store.js'
3
+
4
+ describe('store', () => {
5
+ test('resolves an unknown token to null', async () => {
6
+ const source = ApiKeySource.store(Store.memory())
7
+ expect(await source.resolve('tempo:sk:missing')).toBeNull()
8
+ })
9
+
10
+ // Mock the system clock so timestamps are deterministic without injecting a
11
+ // clock into the source.
12
+ describe('provisioning', () => {
13
+ beforeEach(() => vi.useFakeTimers({ now: new Date('2026-01-01T00:00:00.000Z') }))
14
+ afterEach(() => vi.useRealTimers())
15
+
16
+ test('mints a key and resolves it', async () => {
17
+ const source = ApiKeySource.store(Store.memory())
18
+
19
+ const { record, token } = await source.mint({
20
+ createdBy: 'admin@tempo.xyz',
21
+ name: 'CI key',
22
+ orgId: 'org_acme',
23
+ scopes: ['data:read', 'webhooks:write'],
24
+ })
25
+
26
+ expect(token).toMatch(/^tempo:sk:[a-f0-9]{48}$/)
27
+ expect(record.tokenLast4).toBe(token.slice(-4))
28
+ expect({ ...record, id: '<id>', tokenLast4: '<last4>' }).toMatchInlineSnapshot(`
29
+ {
30
+ "createdAt": "2026-01-01T00:00:00.000Z",
31
+ "createdBy": "admin@tempo.xyz",
32
+ "environment": "production",
33
+ "id": "<id>",
34
+ "name": "CI key",
35
+ "orgId": "org_acme",
36
+ "scopes": [
37
+ "data:read",
38
+ "webhooks:write",
39
+ ],
40
+ "tokenLast4": "<last4>",
41
+ }
42
+ `)
43
+
44
+ const resolved = await source.resolve(token)
45
+ expect(resolved?.orgId).toBe('org_acme')
46
+ expect(resolved?.scopes).toEqual(['data:read', 'webhooks:write'])
47
+ })
48
+
49
+ test('lists keys newest first, filtered by org', async () => {
50
+ const source = ApiKeySource.store(Store.memory())
51
+
52
+ // Advance the clock between mints so their createdAt timestamps differ and
53
+ // "newest first" is well-defined.
54
+ await source.mint({ name: 'a', orgId: 'org_a', scopes: ['data:read'] })
55
+ vi.setSystemTime(new Date('2026-01-01T00:00:01.000Z'))
56
+ await source.mint({ name: 'b', orgId: 'org_b', scopes: ['data:read'] })
57
+
58
+ const all = await source.list()
59
+ expect(all.map((record) => record.name)).toMatchInlineSnapshot(`
60
+ [
61
+ "b",
62
+ "a",
63
+ ]
64
+ `)
65
+
66
+ const scoped = await source.list({ orgId: 'org_b' })
67
+ expect(scoped.map((record) => record.orgId)).toMatchInlineSnapshot(`
68
+ [
69
+ "org_b",
70
+ ]
71
+ `)
72
+ })
73
+
74
+ test('revokes a key by id', async () => {
75
+ const source = ApiKeySource.store(Store.memory())
76
+
77
+ const { record, token } = await source.mint({ orgId: 'org_a', scopes: ['data:read'] })
78
+
79
+ expect(await source.revoke(record.id)).toBe(true)
80
+ expect(await source.resolve(token)).toBeNull()
81
+ expect(await source.revoke(record.id)).toBe(false)
82
+ })
83
+
84
+ test('revoke is O(1): deletes the record without scanning the prefix', async () => {
85
+ const store = Store.memory()
86
+ const source = ApiKeySource.store(store)
87
+
88
+ const { record } = await source.mint({ orgId: 'org_a', scopes: ['data:read'] })
89
+
90
+ // The id index entry maps id -> record key; revoke uses it directly.
91
+ expect(await source.revoke(record.id)).toBe(true)
92
+ // Both the record and its id index entry are gone.
93
+ const { keys } = await store.list({ prefix: 'apikey' })
94
+ expect(keys).toMatchInlineSnapshot(`[]`)
95
+ })
96
+
97
+ test('excludes a key past its expiry from list', async () => {
98
+ const source = ApiKeySource.store(Store.memory())
99
+
100
+ await source.mint({
101
+ expiresAt: '2026-01-01T00:00:30.000Z',
102
+ name: 'short-lived',
103
+ orgId: 'org_a',
104
+ scopes: ['data:read'],
105
+ })
106
+
107
+ expect((await source.list()).map((record) => record.name)).toMatchInlineSnapshot(`
108
+ [
109
+ "short-lived",
110
+ ]
111
+ `)
112
+
113
+ // Advance the clock past the expiry.
114
+ vi.setSystemTime(new Date('2026-01-01T00:01:00.000Z'))
115
+ expect(await source.list()).toMatchInlineSnapshot(`[]`)
116
+ })
117
+ })
118
+
119
+ test('resolves before expiry, rejects after', async () => {
120
+ vi.useFakeTimers({ now: new Date('2026-01-01T00:00:00.000Z') })
121
+ try {
122
+ const source = ApiKeySource.store(Store.memory())
123
+ const { token } = await source.mint({
124
+ expiresAt: '2026-01-01T00:01:00.000Z',
125
+ orgId: 'org_a',
126
+ scopes: ['data:read'],
127
+ })
128
+
129
+ expect((await source.resolve(token))?.orgId).toBe('org_a')
130
+
131
+ // Advance the clock past the expiry.
132
+ vi.setSystemTime(new Date('2026-01-01T00:02:00.000Z'))
133
+ expect(await source.resolve(token)).toBeNull()
134
+ } finally {
135
+ vi.useRealTimers()
136
+ }
137
+ })
138
+
139
+ test('treats a corrupt record as absent', async () => {
140
+ const store = Store.memory()
141
+ const source = ApiKeySource.store(store)
142
+ const { token } = await source.mint({
143
+ orgId: 'org_a',
144
+ scopes: ['data:read'],
145
+ })
146
+ // Overwrite the stored record (keyed by token hash) with invalid JSON.
147
+ const { keys } = await store.list({ prefix: 'apikey:' })
148
+ await store.put(keys[0]!.name, 'not json')
149
+ expect(await source.resolve(token)).toBeNull()
150
+ })
151
+
152
+ test('rejects a record with an unknown scope', async () => {
153
+ const store = Store.memory()
154
+ const source = ApiKeySource.store(store)
155
+ const { token } = await source.mint({
156
+ orgId: 'org_a',
157
+ scopes: ['data:read'],
158
+ })
159
+ const { keys } = await store.list({ prefix: 'apikey:' })
160
+ await store.put(
161
+ keys[0]!.name,
162
+ JSON.stringify({
163
+ createdAt: '2026-01-01T00:00:00.000Z',
164
+ id: 'key_x',
165
+ orgId: 'org_a',
166
+ scopes: ['data:read', 'totally:made-up'],
167
+ tokenLast4: 'xxxx',
168
+ }),
169
+ )
170
+ expect(await source.resolve(token)).toBeNull()
171
+ })
172
+ })
173
+
174
+ describe('cached', () => {
175
+ /** Wraps a source so resolve calls to the backend can be counted. */
176
+ function counting(source: ApiKeySource.Source) {
177
+ let resolves = 0
178
+ return {
179
+ resolves: () => resolves,
180
+ source: ApiKeySource.from({
181
+ ...source,
182
+ async resolve(token) {
183
+ resolves++
184
+ return source.resolve(token)
185
+ },
186
+ }),
187
+ }
188
+ }
189
+
190
+ test('serves repeat resolves from cache until the TTL expires', async () => {
191
+ const backing = ApiKeySource.store(Store.memory())
192
+ const { token } = await backing.mint({ orgId: 'org_acme', scopes: ['data:read'] })
193
+ const { resolves, source } = counting(backing)
194
+ let time = 0
195
+ const cached = ApiKeySource.cached(source, { now: () => time })
196
+
197
+ const first = await cached.resolve(token)
198
+ time = 59_999
199
+ const second = await cached.resolve(token)
200
+
201
+ expect(resolves()).toMatchInlineSnapshot(`1`)
202
+ expect(second).toBe(first)
203
+ expect({
204
+ ...first,
205
+ createdAt: '<createdAt>',
206
+ id: '<id>',
207
+ tokenLast4: '<last4>',
208
+ }).toMatchInlineSnapshot(`
209
+ {
210
+ "createdAt": "<createdAt>",
211
+ "environment": "production",
212
+ "id": "<id>",
213
+ "orgId": "org_acme",
214
+ "scopes": [
215
+ "data:read",
216
+ ],
217
+ "tokenLast4": "<last4>",
218
+ }
219
+ `)
220
+
221
+ time = 60_000
222
+ await cached.resolve(token)
223
+ expect(resolves()).toMatchInlineSnapshot(`2`)
224
+ })
225
+
226
+ test('negative-caches unknown tokens with the shorter TTL', async () => {
227
+ const { resolves, source } = counting(ApiKeySource.store(Store.memory()))
228
+ let time = 0
229
+ const cached = ApiKeySource.cached(source, { now: () => time })
230
+
231
+ expect(await cached.resolve('tempo:sk:missing')).toBeNull()
232
+ time = 9_999
233
+ expect(await cached.resolve('tempo:sk:missing')).toBeNull()
234
+ expect(resolves()).toMatchInlineSnapshot(`1`)
235
+
236
+ time = 10_000
237
+ expect(await cached.resolve('tempo:sk:missing')).toBeNull()
238
+ expect(resolves()).toMatchInlineSnapshot(`2`)
239
+ })
240
+
241
+ test('single-flights concurrent misses for one token', async () => {
242
+ let calls = 0
243
+ const pending = deferred<null>()
244
+ const cached = ApiKeySource.cached(
245
+ ApiKeySource.from({
246
+ ...ApiKeySource.noop,
247
+ async resolve() {
248
+ calls++
249
+ return pending.promise
250
+ },
251
+ }),
252
+ )
253
+
254
+ const requests = [cached.resolve('tempo:sk:a'), cached.resolve('tempo:sk:a')]
255
+ pending.resolve(null)
256
+
257
+ expect(await Promise.all(requests)).toMatchInlineSnapshot(`
258
+ [
259
+ null,
260
+ null,
261
+ ]
262
+ `)
263
+ expect(calls).toMatchInlineSnapshot(`1`)
264
+ })
265
+
266
+ test('does not cache resolve failures', async () => {
267
+ let calls = 0
268
+ const cached = ApiKeySource.cached(
269
+ ApiKeySource.from({
270
+ ...ApiKeySource.noop,
271
+ async resolve() {
272
+ calls++
273
+ if (calls === 1) throw new Error('kv unavailable')
274
+ return null
275
+ },
276
+ }),
277
+ )
278
+
279
+ await expect(cached.resolve('tempo:sk:a')).rejects.toThrowErrorMatchingInlineSnapshot(
280
+ `[Error: kv unavailable]`,
281
+ )
282
+ expect(await cached.resolve('tempo:sk:a')).toBeNull()
283
+ expect(calls).toMatchInlineSnapshot(`2`)
284
+ })
285
+ })
286
+
287
+ function deferred<value>() {
288
+ let reject!: (cause?: unknown) => void
289
+ let resolve!: (value: PromiseLike<value> | value) => void
290
+ const promise = new Promise<value>((resolve_, reject_) => {
291
+ reject = reject_
292
+ resolve = resolve_
293
+ })
294
+ return { promise, reject, resolve }
295
+ }