mppx 0.0.1 → 0.1.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 (446) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/BodyDigest.d.ts +42 -0
  4. package/dist/BodyDigest.d.ts.map +1 -0
  5. package/dist/BodyDigest.js +40 -0
  6. package/dist/BodyDigest.js.map +1 -0
  7. package/dist/Challenge.d.ts +271 -0
  8. package/dist/Challenge.d.ts.map +1 -0
  9. package/dist/Challenge.js +291 -0
  10. package/dist/Challenge.js.map +1 -0
  11. package/dist/Credential.d.ts +91 -0
  12. package/dist/Credential.d.ts.map +1 -0
  13. package/dist/Credential.js +122 -0
  14. package/dist/Credential.js.map +1 -0
  15. package/dist/Errors.d.ts +243 -0
  16. package/dist/Errors.d.ts.map +1 -0
  17. package/dist/Errors.js +201 -0
  18. package/dist/Errors.js.map +1 -0
  19. package/dist/Expires.d.ts +15 -0
  20. package/dist/Expires.d.ts.map +1 -0
  21. package/dist/Expires.js +29 -0
  22. package/dist/Expires.js.map +1 -0
  23. package/dist/Intent.d.ts +101 -0
  24. package/dist/Intent.d.ts.map +1 -0
  25. package/dist/Intent.js +83 -0
  26. package/dist/Intent.js.map +1 -0
  27. package/dist/Mcp.d.ts +74 -0
  28. package/dist/Mcp.d.ts.map +1 -0
  29. package/dist/Mcp.js +9 -0
  30. package/dist/Mcp.js.map +1 -0
  31. package/dist/MethodIntent.d.ts +225 -0
  32. package/dist/MethodIntent.d.ts.map +1 -0
  33. package/dist/MethodIntent.js +156 -0
  34. package/dist/MethodIntent.js.map +1 -0
  35. package/dist/PaymentRequest.d.ts +88 -0
  36. package/dist/PaymentRequest.d.ts.map +1 -0
  37. package/dist/PaymentRequest.js +81 -0
  38. package/dist/PaymentRequest.js.map +1 -0
  39. package/dist/Receipt.d.ts +110 -0
  40. package/dist/Receipt.d.ts.map +1 -0
  41. package/dist/Receipt.js +105 -0
  42. package/dist/Receipt.js.map +1 -0
  43. package/dist/Store.d.ts +28 -0
  44. package/dist/Store.d.ts.map +1 -0
  45. package/dist/Store.js +61 -0
  46. package/dist/Store.js.map +1 -0
  47. package/dist/cli.d.ts +3 -0
  48. package/dist/cli.d.ts.map +1 -0
  49. package/dist/cli.js +1219 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/client/Methods.d.ts +4 -0
  52. package/dist/client/Methods.d.ts.map +1 -0
  53. package/dist/client/Methods.js +4 -0
  54. package/dist/client/Methods.js.map +1 -0
  55. package/dist/client/Mppx.d.ts +84 -0
  56. package/dist/client/Mppx.d.ts.map +1 -0
  57. package/dist/client/Mppx.js +64 -0
  58. package/dist/client/Mppx.js.map +1 -0
  59. package/dist/client/Transport.d.ts +56 -0
  60. package/dist/client/Transport.d.ts.map +1 -0
  61. package/dist/client/Transport.js +81 -0
  62. package/dist/client/Transport.js.map +1 -0
  63. package/dist/client/index.d.ts +5 -0
  64. package/dist/client/index.d.ts.map +1 -0
  65. package/dist/client/index.js +5 -0
  66. package/dist/client/index.js.map +1 -0
  67. package/dist/client/internal/Fetch.d.ts +85 -0
  68. package/dist/client/internal/Fetch.d.ts.map +1 -0
  69. package/dist/client/internal/Fetch.js +95 -0
  70. package/dist/client/internal/Fetch.js.map +1 -0
  71. package/dist/index.d.ts +13 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +13 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/internal/types.d.ts +302 -0
  76. package/dist/internal/types.d.ts.map +1 -0
  77. package/dist/internal/types.js +2 -0
  78. package/dist/internal/types.js.map +1 -0
  79. package/dist/mcp-sdk/client/McpClient.d.ts +78 -0
  80. package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -0
  81. package/dist/mcp-sdk/client/McpClient.js +98 -0
  82. package/dist/mcp-sdk/client/McpClient.js.map +1 -0
  83. package/dist/mcp-sdk/client/index.d.ts +3 -0
  84. package/dist/mcp-sdk/client/index.d.ts.map +1 -0
  85. package/dist/mcp-sdk/client/index.js +3 -0
  86. package/dist/mcp-sdk/client/index.js.map +1 -0
  87. package/dist/mcp-sdk/server/Transport.d.ts +43 -0
  88. package/dist/mcp-sdk/server/Transport.d.ts.map +1 -0
  89. package/dist/mcp-sdk/server/Transport.js +71 -0
  90. package/dist/mcp-sdk/server/Transport.js.map +1 -0
  91. package/dist/mcp-sdk/server/index.d.ts +2 -0
  92. package/dist/mcp-sdk/server/index.d.ts.map +1 -0
  93. package/dist/mcp-sdk/server/index.js +2 -0
  94. package/dist/mcp-sdk/server/index.js.map +1 -0
  95. package/dist/middlewares/elysia.d.ts +51 -0
  96. package/dist/middlewares/elysia.d.ts.map +1 -0
  97. package/dist/middlewares/elysia.js +59 -0
  98. package/dist/middlewares/elysia.js.map +1 -0
  99. package/dist/middlewares/express.d.ts +46 -0
  100. package/dist/middlewares/express.d.ts.map +1 -0
  101. package/dist/middlewares/express.js +69 -0
  102. package/dist/middlewares/express.js.map +1 -0
  103. package/dist/middlewares/hono.d.ts +46 -0
  104. package/dist/middlewares/hono.d.ts.map +1 -0
  105. package/dist/middlewares/hono.js +57 -0
  106. package/dist/middlewares/hono.js.map +1 -0
  107. package/dist/middlewares/internal/mppx.d.ts +16 -0
  108. package/dist/middlewares/internal/mppx.d.ts.map +1 -0
  109. package/dist/middlewares/internal/mppx.js +16 -0
  110. package/dist/middlewares/internal/mppx.js.map +1 -0
  111. package/dist/middlewares/nextjs.d.ts +45 -0
  112. package/dist/middlewares/nextjs.d.ts.map +1 -0
  113. package/dist/middlewares/nextjs.js +57 -0
  114. package/dist/middlewares/nextjs.js.map +1 -0
  115. package/dist/proxy/Proxy.d.ts +47 -0
  116. package/dist/proxy/Proxy.d.ts.map +1 -0
  117. package/dist/proxy/Proxy.js +126 -0
  118. package/dist/proxy/Proxy.js.map +1 -0
  119. package/dist/proxy/Service.d.ts +100 -0
  120. package/dist/proxy/Service.d.ts.map +1 -0
  121. package/dist/proxy/Service.js +147 -0
  122. package/dist/proxy/Service.js.map +1 -0
  123. package/dist/proxy/index.d.ts +7 -0
  124. package/dist/proxy/index.d.ts.map +1 -0
  125. package/dist/proxy/index.js +7 -0
  126. package/dist/proxy/index.js.map +1 -0
  127. package/dist/proxy/internal/Headers.d.ts +3 -0
  128. package/dist/proxy/internal/Headers.d.ts.map +1 -0
  129. package/dist/proxy/internal/Headers.js +41 -0
  130. package/dist/proxy/internal/Headers.js.map +1 -0
  131. package/dist/proxy/internal/Route.d.ts +14 -0
  132. package/dist/proxy/internal/Route.d.ts.map +1 -0
  133. package/dist/proxy/internal/Route.js +47 -0
  134. package/dist/proxy/internal/Route.js.map +1 -0
  135. package/dist/proxy/services/anthropic.d.ts +29 -0
  136. package/dist/proxy/services/anthropic.d.ts.map +1 -0
  137. package/dist/proxy/services/anthropic.js +30 -0
  138. package/dist/proxy/services/anthropic.js.map +1 -0
  139. package/dist/proxy/services/openai.d.ts +29 -0
  140. package/dist/proxy/services/openai.d.ts.map +1 -0
  141. package/dist/proxy/services/openai.js +30 -0
  142. package/dist/proxy/services/openai.js.map +1 -0
  143. package/dist/proxy/services/stripe.d.ts +29 -0
  144. package/dist/proxy/services/stripe.d.ts.map +1 -0
  145. package/dist/proxy/services/stripe.js +30 -0
  146. package/dist/proxy/services/stripe.js.map +1 -0
  147. package/dist/server/Methods.d.ts +3 -0
  148. package/dist/server/Methods.d.ts.map +1 -0
  149. package/dist/server/Methods.js +3 -0
  150. package/dist/server/Methods.js.map +1 -0
  151. package/dist/server/Mppx.d.ts +116 -0
  152. package/dist/server/Mppx.d.ts.map +1 -0
  153. package/dist/server/Mppx.js +207 -0
  154. package/dist/server/Mppx.js.map +1 -0
  155. package/dist/server/NodeListener.d.ts +3 -0
  156. package/dist/server/NodeListener.d.ts.map +1 -0
  157. package/dist/server/NodeListener.js +3 -0
  158. package/dist/server/NodeListener.js.map +1 -0
  159. package/dist/server/Request.d.ts +24 -0
  160. package/dist/server/Request.d.ts.map +1 -0
  161. package/dist/server/Request.js +26 -0
  162. package/dist/server/Request.js.map +1 -0
  163. package/dist/server/Response.d.ts +10 -0
  164. package/dist/server/Response.d.ts.map +1 -0
  165. package/dist/server/Response.js +15 -0
  166. package/dist/server/Response.js.map +1 -0
  167. package/dist/server/Transport.d.ts +93 -0
  168. package/dist/server/Transport.d.ts.map +1 -0
  169. package/dist/server/Transport.js +132 -0
  170. package/dist/server/Transport.js.map +1 -0
  171. package/dist/server/index.d.ts +9 -0
  172. package/dist/server/index.d.ts.map +1 -0
  173. package/dist/server/index.js +9 -0
  174. package/dist/server/index.js.map +1 -0
  175. package/dist/stripe/Intents.d.ts +54 -0
  176. package/dist/stripe/Intents.d.ts.map +1 -0
  177. package/dist/stripe/Intents.js +27 -0
  178. package/dist/stripe/Intents.js.map +1 -0
  179. package/dist/stripe/client/Charge.d.ts +114 -0
  180. package/dist/stripe/client/Charge.d.ts.map +1 -0
  181. package/dist/stripe/client/Charge.js +77 -0
  182. package/dist/stripe/client/Charge.js.map +1 -0
  183. package/dist/stripe/client/MethodIntents.d.ts +80 -0
  184. package/dist/stripe/client/MethodIntents.d.ts.map +1 -0
  185. package/dist/stripe/client/MethodIntents.js +34 -0
  186. package/dist/stripe/client/MethodIntents.js.map +1 -0
  187. package/dist/stripe/client/index.d.ts +3 -0
  188. package/dist/stripe/client/index.d.ts.map +1 -0
  189. package/dist/stripe/client/index.js +3 -0
  190. package/dist/stripe/client/index.js.map +1 -0
  191. package/dist/stripe/index.d.ts +2 -0
  192. package/dist/stripe/index.d.ts.map +1 -0
  193. package/dist/stripe/index.js +2 -0
  194. package/dist/stripe/index.js.map +1 -0
  195. package/dist/stripe/server/Charge.d.ts +74 -0
  196. package/dist/stripe/server/Charge.d.ts.map +1 -0
  197. package/dist/stripe/server/Charge.js +79 -0
  198. package/dist/stripe/server/Charge.js.map +1 -0
  199. package/dist/stripe/server/MethodIntents.d.ts +65 -0
  200. package/dist/stripe/server/MethodIntents.d.ts.map +1 -0
  201. package/dist/stripe/server/MethodIntents.js +21 -0
  202. package/dist/stripe/server/MethodIntents.js.map +1 -0
  203. package/dist/stripe/server/index.d.ts +3 -0
  204. package/dist/stripe/server/index.d.ts.map +1 -0
  205. package/dist/stripe/server/index.js +3 -0
  206. package/dist/stripe/server/index.js.map +1 -0
  207. package/dist/tempo/Attribution.d.ts +101 -0
  208. package/dist/tempo/Attribution.d.ts.map +1 -0
  209. package/dist/tempo/Attribution.js +124 -0
  210. package/dist/tempo/Attribution.js.map +1 -0
  211. package/dist/tempo/Intents.d.ts +132 -0
  212. package/dist/tempo/Intents.d.ts.map +1 -0
  213. package/dist/tempo/Intents.js +81 -0
  214. package/dist/tempo/Intents.js.map +1 -0
  215. package/dist/tempo/client/ChannelOps.d.ts +54 -0
  216. package/dist/tempo/client/ChannelOps.d.ts.map +1 -0
  217. package/dist/tempo/client/ChannelOps.js +138 -0
  218. package/dist/tempo/client/ChannelOps.js.map +1 -0
  219. package/dist/tempo/client/Charge.d.ts +76 -0
  220. package/dist/tempo/client/Charge.d.ts.map +1 -0
  221. package/dist/tempo/client/Charge.js +69 -0
  222. package/dist/tempo/client/Charge.js.map +1 -0
  223. package/dist/tempo/client/MethodIntents.d.ts +157 -0
  224. package/dist/tempo/client/MethodIntents.d.ts.map +1 -0
  225. package/dist/tempo/client/MethodIntents.js +25 -0
  226. package/dist/tempo/client/MethodIntents.js.map +1 -0
  227. package/dist/tempo/client/Session.d.ts +159 -0
  228. package/dist/tempo/client/Session.d.ts.map +1 -0
  229. package/dist/tempo/client/Session.js +263 -0
  230. package/dist/tempo/client/Session.js.map +1 -0
  231. package/dist/tempo/client/SessionManager.d.ts +62 -0
  232. package/dist/tempo/client/SessionManager.d.ts.map +1 -0
  233. package/dist/tempo/client/SessionManager.js +196 -0
  234. package/dist/tempo/client/SessionManager.js.map +1 -0
  235. package/dist/tempo/client/index.d.ts +6 -0
  236. package/dist/tempo/client/index.d.ts.map +1 -0
  237. package/dist/tempo/client/index.js +5 -0
  238. package/dist/tempo/client/index.js.map +1 -0
  239. package/dist/tempo/index.d.ts +3 -0
  240. package/dist/tempo/index.d.ts.map +1 -0
  241. package/dist/tempo/index.js +3 -0
  242. package/dist/tempo/index.js.map +1 -0
  243. package/dist/tempo/internal/account.d.ts +32 -0
  244. package/dist/tempo/internal/account.d.ts.map +1 -0
  245. package/dist/tempo/internal/account.js +33 -0
  246. package/dist/tempo/internal/account.js.map +1 -0
  247. package/dist/tempo/internal/defaults.d.ts +18 -0
  248. package/dist/tempo/internal/defaults.d.ts.map +1 -0
  249. package/dist/tempo/internal/defaults.js +18 -0
  250. package/dist/tempo/internal/defaults.js.map +1 -0
  251. package/dist/tempo/internal/types.d.ts +11 -0
  252. package/dist/tempo/internal/types.d.ts.map +1 -0
  253. package/dist/tempo/internal/types.js +2 -0
  254. package/dist/tempo/internal/types.js.map +1 -0
  255. package/dist/tempo/server/Charge.d.ts +77 -0
  256. package/dist/tempo/server/Charge.d.ts.map +1 -0
  257. package/dist/tempo/server/Charge.js +228 -0
  258. package/dist/tempo/server/Charge.js.map +1 -0
  259. package/dist/tempo/server/MethodIntents.d.ts +140 -0
  260. package/dist/tempo/server/MethodIntents.d.ts.map +1 -0
  261. package/dist/tempo/server/MethodIntents.js +26 -0
  262. package/dist/tempo/server/MethodIntents.js.map +1 -0
  263. package/dist/tempo/server/Session.d.ts +148 -0
  264. package/dist/tempo/server/Session.d.ts.map +1 -0
  265. package/dist/tempo/server/Session.js +529 -0
  266. package/dist/tempo/server/Session.js.map +1 -0
  267. package/dist/tempo/server/internal/transport.d.ts +47 -0
  268. package/dist/tempo/server/internal/transport.d.ts.map +1 -0
  269. package/dist/tempo/server/internal/transport.js +118 -0
  270. package/dist/tempo/server/internal/transport.js.map +1 -0
  271. package/dist/tempo/stream/Chain.d.ts +52 -0
  272. package/dist/tempo/stream/Chain.d.ts.map +1 -0
  273. package/dist/tempo/stream/Chain.js +215 -0
  274. package/dist/tempo/stream/Chain.js.map +1 -0
  275. package/dist/tempo/stream/Channel.d.ts +26 -0
  276. package/dist/tempo/stream/Channel.d.ts.map +1 -0
  277. package/dist/tempo/stream/Channel.js +27 -0
  278. package/dist/tempo/stream/Channel.js.map +1 -0
  279. package/dist/tempo/stream/ChannelStore.d.ts +103 -0
  280. package/dist/tempo/stream/ChannelStore.d.ts.map +1 -0
  281. package/dist/tempo/stream/ChannelStore.js +100 -0
  282. package/dist/tempo/stream/ChannelStore.js.map +1 -0
  283. package/dist/tempo/stream/Receipt.d.ts +22 -0
  284. package/dist/tempo/stream/Receipt.d.ts.map +1 -0
  285. package/dist/tempo/stream/Receipt.js +34 -0
  286. package/dist/tempo/stream/Receipt.js.map +1 -0
  287. package/dist/tempo/stream/Sse.d.ts +134 -0
  288. package/dist/tempo/stream/Sse.d.ts.map +1 -0
  289. package/dist/tempo/stream/Sse.js +288 -0
  290. package/dist/tempo/stream/Sse.js.map +1 -0
  291. package/dist/tempo/stream/Types.d.ts +78 -0
  292. package/dist/tempo/stream/Types.d.ts.map +1 -0
  293. package/dist/tempo/stream/Types.js +2 -0
  294. package/dist/tempo/stream/Types.js.map +1 -0
  295. package/dist/tempo/stream/Voucher.d.ts +20 -0
  296. package/dist/tempo/stream/Voucher.d.ts.map +1 -0
  297. package/dist/tempo/stream/Voucher.js +98 -0
  298. package/dist/tempo/stream/Voucher.js.map +1 -0
  299. package/dist/tempo/stream/escrow.abi.d.ts +598 -0
  300. package/dist/tempo/stream/escrow.abi.d.ts.map +1 -0
  301. package/dist/tempo/stream/escrow.abi.js +760 -0
  302. package/dist/tempo/stream/escrow.abi.js.map +1 -0
  303. package/dist/tempo/stream/index.d.ts +8 -0
  304. package/dist/tempo/stream/index.d.ts.map +1 -0
  305. package/dist/tempo/stream/index.js +8 -0
  306. package/dist/tempo/stream/index.js.map +1 -0
  307. package/dist/viem/Account.d.ts +12 -0
  308. package/dist/viem/Account.d.ts.map +1 -0
  309. package/dist/viem/Account.js +14 -0
  310. package/dist/viem/Account.js.map +1 -0
  311. package/dist/viem/Client.d.ts +21 -0
  312. package/dist/viem/Client.d.ts.map +1 -0
  313. package/dist/viem/Client.js +19 -0
  314. package/dist/viem/Client.js.map +1 -0
  315. package/dist/zod.d.ts +17 -0
  316. package/dist/zod.d.ts.map +1 -0
  317. package/dist/zod.js +35 -0
  318. package/dist/zod.js.map +1 -0
  319. package/package.json +117 -4
  320. package/src/BodyDigest.test.ts +43 -0
  321. package/src/BodyDigest.ts +53 -0
  322. package/src/Challenge.test-d.ts +81 -0
  323. package/src/Challenge.test.ts +414 -0
  324. package/src/Challenge.ts +429 -0
  325. package/src/Credential.test.ts +227 -0
  326. package/src/Credential.ts +154 -0
  327. package/src/Errors.test.ts +402 -0
  328. package/src/Errors.ts +348 -0
  329. package/src/Expires.ts +34 -0
  330. package/src/Intent.test.ts +180 -0
  331. package/src/Intent.ts +109 -0
  332. package/src/Mcp.ts +81 -0
  333. package/src/MethodIntent.test.ts +303 -0
  334. package/src/MethodIntent.ts +388 -0
  335. package/src/PaymentRequest.test.ts +152 -0
  336. package/src/PaymentRequest.ts +107 -0
  337. package/src/Receipt.test.ts +98 -0
  338. package/src/Receipt.ts +129 -0
  339. package/src/Store.ts +84 -0
  340. package/src/cli.test.ts +542 -0
  341. package/src/cli.ts +1319 -0
  342. package/src/client/Methods.ts +3 -0
  343. package/src/client/Mppx.test-d.ts +90 -0
  344. package/src/client/Mppx.test.ts +468 -0
  345. package/src/client/Mppx.ts +149 -0
  346. package/src/client/Transport.test.ts +283 -0
  347. package/src/client/Transport.ts +115 -0
  348. package/src/client/index.ts +4 -0
  349. package/src/client/internal/Fetch.test-d.ts +57 -0
  350. package/src/client/internal/Fetch.test.ts +281 -0
  351. package/src/client/internal/Fetch.ts +157 -0
  352. package/src/env.d.ts +11 -0
  353. package/src/index.ts +12 -0
  354. package/src/internal/types.ts +403 -0
  355. package/src/mcp-sdk/client/McpClient.test-d.ts +109 -0
  356. package/src/mcp-sdk/client/McpClient.test.ts +219 -0
  357. package/src/mcp-sdk/client/McpClient.ts +187 -0
  358. package/src/mcp-sdk/client/index.ts +2 -0
  359. package/src/mcp-sdk/server/Transport.ts +94 -0
  360. package/src/mcp-sdk/server/index.ts +1 -0
  361. package/src/middlewares/elysia.ts +66 -0
  362. package/src/middlewares/express.test.ts +155 -0
  363. package/src/middlewares/express.ts +82 -0
  364. package/src/middlewares/hono.test.ts +148 -0
  365. package/src/middlewares/hono.ts +62 -0
  366. package/src/middlewares/internal/mppx.ts +30 -0
  367. package/src/middlewares/nextjs.test.ts +164 -0
  368. package/src/middlewares/nextjs.ts +66 -0
  369. package/src/proxy/Proxy.test.ts +472 -0
  370. package/src/proxy/Proxy.ts +175 -0
  371. package/src/proxy/Service.test.ts +125 -0
  372. package/src/proxy/Service.ts +227 -0
  373. package/src/proxy/index.ts +6 -0
  374. package/src/proxy/internal/Headers.test.ts +100 -0
  375. package/src/proxy/internal/Headers.ts +40 -0
  376. package/src/proxy/internal/Route.test.ts +143 -0
  377. package/src/proxy/internal/Route.ts +54 -0
  378. package/src/proxy/services/anthropic.ts +45 -0
  379. package/src/proxy/services/openai.test.ts +97 -0
  380. package/src/proxy/services/openai.ts +48 -0
  381. package/src/proxy/services/stripe.ts +49 -0
  382. package/src/server/Methods.ts +2 -0
  383. package/src/server/Mppx.test-d.ts +343 -0
  384. package/src/server/Mppx.test.ts +342 -0
  385. package/src/server/Mppx.ts +378 -0
  386. package/src/server/NodeListener.test.ts +188 -0
  387. package/src/server/NodeListener.ts +3 -0
  388. package/src/server/Request.test.ts +102 -0
  389. package/src/server/Request.ts +33 -0
  390. package/src/server/Response.test.ts +31 -0
  391. package/src/server/Response.ts +27 -0
  392. package/src/server/Transport.test.ts +294 -0
  393. package/src/server/Transport.ts +222 -0
  394. package/src/server/index.ts +8 -0
  395. package/src/stripe/Charge.integration.test.ts +326 -0
  396. package/src/stripe/Intents.test.ts +52 -0
  397. package/src/stripe/Intents.ts +27 -0
  398. package/src/stripe/client/Charge.ts +119 -0
  399. package/src/stripe/client/MethodIntents.ts +37 -0
  400. package/src/stripe/client/index.ts +2 -0
  401. package/src/stripe/index.ts +1 -0
  402. package/src/stripe/server/Charge.ts +121 -0
  403. package/src/stripe/server/MethodIntents.ts +24 -0
  404. package/src/stripe/server/index.ts +2 -0
  405. package/src/tempo/Attribution.test.ts +187 -0
  406. package/src/tempo/Attribution.ts +156 -0
  407. package/src/tempo/Intents.test.ts +84 -0
  408. package/src/tempo/Intents.ts +93 -0
  409. package/src/tempo/client/ChannelOps.ts +233 -0
  410. package/src/tempo/client/Charge.ts +84 -0
  411. package/src/tempo/client/MethodIntents.ts +28 -0
  412. package/src/tempo/client/Session.ts +369 -0
  413. package/src/tempo/client/SessionManager.test.ts +223 -0
  414. package/src/tempo/client/SessionManager.ts +270 -0
  415. package/src/tempo/client/index.ts +5 -0
  416. package/src/tempo/index.ts +2 -0
  417. package/src/tempo/internal/account.ts +47 -0
  418. package/src/tempo/internal/defaults.ts +20 -0
  419. package/src/tempo/internal/types.ts +8 -0
  420. package/src/tempo/server/Charge.test.ts +847 -0
  421. package/src/tempo/server/Charge.ts +309 -0
  422. package/src/tempo/server/MethodIntents.ts +29 -0
  423. package/src/tempo/server/Session.test.ts +1349 -0
  424. package/src/tempo/server/Session.ts +773 -0
  425. package/src/tempo/server/Sse.test.ts +289 -0
  426. package/src/tempo/server/index.ts +5 -0
  427. package/src/tempo/server/internal/transport.ts +153 -0
  428. package/src/tempo/stream/Chain.ts +333 -0
  429. package/src/tempo/stream/Channel.ts +50 -0
  430. package/src/tempo/stream/ChannelStore.test.ts +473 -0
  431. package/src/tempo/stream/ChannelStore.ts +202 -0
  432. package/src/tempo/stream/Receipt.test.ts +84 -0
  433. package/src/tempo/stream/Receipt.ts +45 -0
  434. package/src/tempo/stream/Sse.test.ts +401 -0
  435. package/src/tempo/stream/Sse.ts +375 -0
  436. package/src/tempo/stream/Types.ts +86 -0
  437. package/src/tempo/stream/Voucher.test.ts +134 -0
  438. package/src/tempo/stream/Voucher.ts +123 -0
  439. package/src/tempo/stream/escrow.abi.ts +759 -0
  440. package/src/tempo/stream/index.ts +7 -0
  441. package/src/tsconfig.json +10 -0
  442. package/src/viem/Account.test.ts +71 -0
  443. package/src/viem/Account.ts +30 -0
  444. package/src/viem/Client.test.ts +58 -0
  445. package/src/viem/Client.ts +33 -0
  446. package/src/zod.ts +47 -0
@@ -0,0 +1,175 @@
1
+ import type * as http from 'node:http'
2
+ import { createFetchProxy } from '@remix-run/fetch-proxy'
3
+ import * as Request from '../server/Request.js'
4
+ import * as Headers from './internal/Headers.js'
5
+ import * as Route from './internal/Route.js'
6
+ import * as Service from './Service.js'
7
+
8
+ /** A paid API proxy that gates upstream services behind the mppx 402 protocol. */
9
+ export type Proxy = {
10
+ /** Fetch API handler. Works with Bun, Deno, Next.js, Hono, Elysia, SvelteKit, etc. */
11
+ fetch: (request: Request) => Promise<Response>
12
+ /** Node.js request listener. Works with Express, Fastify, `http.createServer`, etc. */
13
+ listener: (req: http.IncomingMessage, res: http.ServerResponse) => void
14
+ }
15
+
16
+ /**
17
+ * Creates a paid API proxy.
18
+ *
19
+ * Routes incoming requests to upstream services, injects credentials,
20
+ * and requires payment via the mppx 402 protocol for non-free endpoints.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { Proxy, openai } from 'mppx/proxy'
25
+ * import { Mppx, tempo } from 'mppx/server'
26
+ *
27
+ * const mppx = Mppx.create({ methods: [tempo()] })
28
+ *
29
+ * const proxy = Proxy.create({
30
+ * services: [
31
+ * openai({
32
+ * apiKey: 'sk-...',
33
+ * routes: {
34
+ * 'POST /v1/chat/completions': mppx.charge({ amount: '0.05' }),
35
+ * 'GET /v1/models': true,
36
+ * },
37
+ * }),
38
+ * ],
39
+ * })
40
+ * ```
41
+ */
42
+ export function create(config: create.Config): Proxy {
43
+ const fetchImpl = config.fetch ?? globalThis.fetch
44
+
45
+ const services = new Map(
46
+ config.services.map((s) => {
47
+ const proxy = createFetchProxy(s.baseUrl, {
48
+ fetch: fetchImpl,
49
+ rewriteCookieDomain: false,
50
+ rewriteCookiePath: false,
51
+ })
52
+ return [s.id, { service: s, proxy }] as const
53
+ }),
54
+ )
55
+
56
+ async function handle(request: globalThis.Request): Promise<Response> {
57
+ const url = new URL(request.url)
58
+
59
+ const pathname = Route.pathname(url, config.basePath)
60
+
61
+ if (!pathname) return new Response('Not Found', { status: 404 })
62
+
63
+ if (request.method === 'GET' && pathname === '/llms.txt')
64
+ return new Response(Service.toLlmsTxt(config.services), {
65
+ headers: { 'Content-Type': 'text/plain; charset=utf-8' },
66
+ })
67
+
68
+ if (request.method === 'GET' && (pathname === '/services' || pathname === '/services/'))
69
+ return Response.json(config.services.map(Service.serialize))
70
+
71
+ {
72
+ const match = pathname.match(/^\/services\/([^/]+)\/?$/)
73
+ if (request.method === 'GET' && match) {
74
+ const service = config.services.find((s) => s.id === match[1])
75
+ if (!service) return new Response('Not Found', { status: 404 })
76
+ return Response.json(Service.serialize(service))
77
+ }
78
+ }
79
+
80
+ const parsed = Route.parse(pathname)
81
+ if (!parsed) return new Response('Not Found', { status: 404 })
82
+
83
+ const { serviceId, upstreamPath } = parsed
84
+ const entry = services.get(serviceId)
85
+ if (!entry) return new Response('Not Found', { status: 404 })
86
+
87
+ const { service, proxy } = entry
88
+
89
+ const matched =
90
+ Route.match(service.routes, request.method, upstreamPath) ??
91
+ // Management POSTs (e.g. session close) may target a path whose route
92
+ // is registered for a different HTTP method (e.g. GET). Fall back to
93
+ // path-only matching so the payment handler can process the action.
94
+ (request.method === 'POST' && request.headers.has('authorization')
95
+ ? Route.matchPath(service.routes, upstreamPath)
96
+ : null)
97
+ if (!matched) return new Response('Not Found', { status: 404 })
98
+
99
+ const endpoint = matched.value as Service.Endpoint
100
+ const ctx: Service.Context = { request, service, upstreamPath }
101
+
102
+ if (endpoint === true) return proxyUpstream({ request, service, ctx, proxy })
103
+
104
+ const handler = typeof endpoint === 'function' ? endpoint : endpoint.pay
105
+ const result = await handler(request)
106
+ if (result.status === 402) return result.challenge
107
+
108
+ const options = Service.getOptions(endpoint)
109
+ const upstreamRes = await proxyUpstream({
110
+ request,
111
+ service,
112
+ ctx: { ...ctx, ...options },
113
+ proxy,
114
+ })
115
+ return result.withReceipt(upstreamRes)
116
+ }
117
+
118
+ return {
119
+ fetch: handle,
120
+ listener: Request.toNodeListener(handle),
121
+ }
122
+ }
123
+
124
+ export declare namespace create {
125
+ export type Config = {
126
+ /** Base path prefix to strip before routing (e.g. `'/api/proxy'`). */
127
+ basePath?: string | undefined
128
+ /** Custom `fetch` implementation. Defaults to `globalThis.fetch`. */
129
+ fetch?: typeof globalThis.fetch | undefined
130
+ /** Services to proxy. Each service is mounted at `/{serviceId}/`. */
131
+ services: Service.Service[]
132
+ }
133
+ }
134
+
135
+ declare namespace proxyUpstream {
136
+ type Options = {
137
+ ctx: Service.Context
138
+ proxy: (input: URL | RequestInfo, init?: RequestInit) => Promise<Response>
139
+ request: globalThis.Request
140
+ service: Service.Service
141
+ }
142
+ }
143
+
144
+ /** @internal */
145
+ async function proxyUpstream(options: proxyUpstream.Options): Promise<Response> {
146
+ const { request, service, ctx, proxy } = options
147
+ const url = ctx.upstreamPath + new URL(request.url).search
148
+ const headers = Headers.scrub(request.headers)
149
+
150
+ const method = request.method.toUpperCase()
151
+ const hasBody = method !== 'GET' && method !== 'HEAD'
152
+
153
+ const init: RequestInit & { duplex?: 'half' } = {
154
+ method: request.method,
155
+ headers,
156
+ signal: request.signal,
157
+ }
158
+
159
+ if (hasBody && request.body) {
160
+ init.body = request.body
161
+ init.duplex = 'half'
162
+ }
163
+
164
+ let upstreamReq = new globalThis.Request(new URL(url, new URL(service.baseUrl).origin), init)
165
+
166
+ if (service.rewriteRequest) upstreamReq = await service.rewriteRequest(upstreamReq, ctx)
167
+
168
+ let upstreamRes = await proxy(upstreamReq)
169
+
170
+ upstreamRes = Headers.scrubResponse(upstreamRes)
171
+
172
+ if (service.rewriteResponse) upstreamRes = await service.rewriteResponse(upstreamRes, ctx)
173
+
174
+ return upstreamRes
175
+ }
@@ -0,0 +1,125 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import * as Service from './Service.js'
3
+
4
+ describe('from', () => {
5
+ test('behavior: creates service with id and baseUrl', () => {
6
+ const service = Service.from('api', {
7
+ baseUrl: 'https://api.example.com',
8
+ routes: { 'GET /v1/status': true },
9
+ })
10
+ expect(service.id).toBe('api')
11
+ expect(service.baseUrl).toBe('https://api.example.com')
12
+ })
13
+
14
+ test('behavior: bearer sets Authorization header', async () => {
15
+ const service = Service.from('api', {
16
+ baseUrl: 'https://api.example.com',
17
+ bearer: 'sk-123',
18
+ routes: { 'GET /v1/data': true },
19
+ })
20
+ const req = new Request('https://example.com')
21
+ const ctx = { request: req, service, upstreamPath: '/v1/data' }
22
+ const result = await service.rewriteRequest!(req, ctx)
23
+ expect(result.headers.get('authorization')).toBe('Bearer sk-123')
24
+ })
25
+
26
+ test('behavior: headers sets custom headers', async () => {
27
+ const service = Service.from('api', {
28
+ baseUrl: 'https://api.example.com',
29
+ headers: { 'X-Api-Key': 'secret' },
30
+ routes: { 'GET /v1/data': true },
31
+ })
32
+ const req = new Request('https://example.com')
33
+ const ctx = { request: req, service, upstreamPath: '/v1/data' }
34
+ const result = await service.rewriteRequest!(req, ctx)
35
+ expect(result.headers.get('x-api-key')).toBe('secret')
36
+ })
37
+
38
+ test('behavior: multiple headers sets all headers', async () => {
39
+ const service = Service.from('api', {
40
+ baseUrl: 'https://api.example.com',
41
+ headers: { 'X-Key': 'a', 'X-Secret': 'b' },
42
+ routes: { 'GET /v1/data': true },
43
+ })
44
+ const req = new Request('https://example.com')
45
+ const ctx = { request: req, service, upstreamPath: '/v1/data' }
46
+ const result = await service.rewriteRequest!(req, ctx)
47
+ expect(result.headers.get('x-key')).toBe('a')
48
+ expect(result.headers.get('x-secret')).toBe('b')
49
+ })
50
+
51
+ test('behavior: mutate calls mutate function', async () => {
52
+ const service = Service.from('api', {
53
+ baseUrl: 'https://api.example.com',
54
+ mutate: (req) => {
55
+ req.headers.set('X-Mutated', 'yes')
56
+ return req
57
+ },
58
+ routes: { 'GET /v1/data': true },
59
+ })
60
+ const req = new Request('https://example.com')
61
+ const ctx = { request: req, service, upstreamPath: '/v1/data' }
62
+ const result = await service.rewriteRequest!(req, ctx)
63
+ expect(result.headers.get('x-mutated')).toBe('yes')
64
+ })
65
+
66
+ test('behavior: no auth config means no rewriteRequest', () => {
67
+ const service = Service.from('api', {
68
+ baseUrl: 'https://api.example.com',
69
+ routes: { 'GET /v1/data': true },
70
+ })
71
+ expect(service.rewriteRequest).toBeUndefined()
72
+ })
73
+
74
+ test('behavior: per-endpoint options override service bearer', async () => {
75
+ const handler: Service.IntentHandler = async () => ({
76
+ status: 200 as const,
77
+ withReceipt: <T>(r: T) => r,
78
+ })
79
+ const service = Service.from('api', {
80
+ baseUrl: 'https://api.example.com',
81
+ bearer: 'sk-default',
82
+ routes: {
83
+ 'GET /v1/data': {
84
+ pay: handler,
85
+ options: { bearer: 'sk-override' },
86
+ },
87
+ },
88
+ })
89
+ const endpoint = service.routes['GET /v1/data']!
90
+ const options = Service.getOptions(endpoint)
91
+ const req = new Request('https://example.com')
92
+ const ctx = { request: req, service, upstreamPath: '/v1/data', ...options }
93
+ const result = await service.rewriteRequest!(req, ctx)
94
+ expect(result.headers.get('authorization')).toBe('Bearer sk-override')
95
+ })
96
+ })
97
+
98
+ describe('custom', () => {
99
+ test('behavior: alias for from', () => {
100
+ expect(Service.custom).toBe(Service.from)
101
+ })
102
+ })
103
+
104
+ describe('getOptions', () => {
105
+ test('behavior: returns options from endpoint object', () => {
106
+ const handler: Service.IntentHandler = async () => ({
107
+ status: 200 as const,
108
+ withReceipt: <T>(r: T) => r,
109
+ })
110
+ const endpoint: Service.Endpoint = { pay: handler, options: { apiKey: 'sk-123' } }
111
+ expect(Service.getOptions(endpoint)).toEqual({ apiKey: 'sk-123' })
112
+ })
113
+
114
+ test('behavior: returns undefined for function endpoint', () => {
115
+ const handler: Service.IntentHandler = async () => ({
116
+ status: 200 as const,
117
+ withReceipt: <T>(r: T) => r,
118
+ })
119
+ expect(Service.getOptions(handler)).toBeUndefined()
120
+ })
121
+
122
+ test('behavior: returns undefined for true endpoint', () => {
123
+ expect(Service.getOptions(true)).toBeUndefined()
124
+ })
125
+ })
@@ -0,0 +1,227 @@
1
+ import { Value } from 'ox'
2
+
3
+ /** A proxied upstream service with route definitions and optional request/response hooks. */
4
+ export type Service = {
5
+ /** Unique identifier used as the URL prefix (e.g. `'openai'` → `/{id}/...`). */
6
+ id: string
7
+ /** Base URL of the upstream service (e.g. `'https://api.openai.com'`). */
8
+ baseUrl: string
9
+ /** Map of route patterns to endpoint handlers. */
10
+ routes: EndpointMap
11
+ /** Hook to modify the upstream request before sending (e.g. inject auth headers). */
12
+ rewriteRequest?: ((req: Request, ctx: Context) => Request | Promise<Request>) | undefined
13
+ /** Hook to modify the upstream response before returning to the client. */
14
+ rewriteResponse?: ((res: Response, ctx: Context) => Response | Promise<Response>) | undefined
15
+ }
16
+
17
+ /**
18
+ * An endpoint definition.
19
+ *
20
+ * - `IntentHandler` — payment required, calls the handler to issue a 402 challenge or verify payment.
21
+ * - `{ pay, options }` — payment required with per-endpoint config overrides.
22
+ * - `true` — free passthrough, no payment required, rewriteRequest is applied.
23
+ */
24
+ export type Endpoint = IntentHandler | { pay: IntentHandler; options: EndpointOptions } | true
25
+
26
+ /** Map of `"METHOD /pattern"` keys to endpoint definitions. */
27
+ export type EndpointMap<routes extends string = string> = Partial<Record<routes, Endpoint>> &
28
+ Record<string & {}, Endpoint>
29
+
30
+ /** Per-endpoint configuration overrides (e.g. `{ apiKey: 'sk-...' }`). */
31
+ export type EndpointOptions = {
32
+ [key: string]: unknown
33
+ }
34
+
35
+ /** A function that handles the mppx payment flow for a request. */
36
+ export type IntentHandler = (input: Request) => Promise<IntentResult>
37
+
38
+ /** Result of an intent handler — either a 402 challenge or a 200 with receipt attachment. */
39
+ export type IntentResult =
40
+ | { challenge: Response; status: 402 }
41
+ | { status: 200; withReceipt: <response>(response: response) => response }
42
+
43
+ /** Context passed to `rewriteRequest`/`rewriteResponse` hooks, including any per-endpoint options. */
44
+ export type Context = {
45
+ request: Request
46
+ service: Service
47
+ upstreamPath: string
48
+ } & EndpointOptions
49
+
50
+ export type From<
51
+ options extends {
52
+ routes: string
53
+ },
54
+ > = {
55
+ routes: EndpointMap<options['routes']>
56
+ } & Omit<options, 'routes'>
57
+
58
+ /**
59
+ * Creates a service definition.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * Service.from('my-api', {
64
+ * baseUrl: 'https://api.example.com',
65
+ * bearer: 'sk-...',
66
+ * routes: {
67
+ * 'POST /v1/generate': mppx.charge({ amount: '0.01' }),
68
+ * 'GET /v1/status': true,
69
+ * },
70
+ * })
71
+ * ```
72
+ */
73
+ export function from<options = unknown>(id: string, config: from.Config<options>): Service {
74
+ const rewriteFromConfig = resolveRewriteRequest(config)
75
+ return {
76
+ id,
77
+ baseUrl: config.baseUrl,
78
+ routes: config.routes,
79
+ rewriteRequest: config.rewriteRequest
80
+ ? rewriteFromConfig
81
+ ? async (req, ctx) => {
82
+ req = await rewriteFromConfig(req, ctx)
83
+ return (config.rewriteRequest as Service['rewriteRequest'])!(req, ctx)
84
+ }
85
+ : (config.rewriteRequest as Service['rewriteRequest'])
86
+ : rewriteFromConfig,
87
+ }
88
+ }
89
+
90
+ export declare namespace from {
91
+ export type Config<options = unknown> = {
92
+ /** Base URL of the upstream service. */
93
+ baseUrl: string
94
+ /** Shorthand: inject `Authorization: Bearer {token}` header. */
95
+ bearer?: string | undefined
96
+ /** Shorthand: inject custom headers. */
97
+ headers?: Record<string, string> | undefined
98
+ /** Shorthand: full request mutation function. Takes priority over `bearer`/`headers`. */
99
+ mutate?: ((req: Request) => Request | Promise<Request>) | undefined
100
+ /** Hook to modify the upstream request. Receives typed per-endpoint options via `ctx`. */
101
+ rewriteRequest?:
102
+ | ((req: Request, ctx: Context & Partial<options & {}>) => Request | Promise<Request>)
103
+ | undefined
104
+ /** Map of route patterns to endpoint definitions. */
105
+ routes: EndpointMap
106
+ }
107
+ }
108
+
109
+ export { from as custom }
110
+
111
+ function resolveRewriteRequest(
112
+ config: from.Config,
113
+ ): ((req: Request, ctx: Context) => Request | Promise<Request>) | undefined {
114
+ if (config.mutate) {
115
+ const mutate = config.mutate
116
+ return (req, ctx) => {
117
+ const options = ctx as Partial<from.Config>
118
+ const m = options.mutate ?? mutate
119
+ return m(req)
120
+ }
121
+ }
122
+ if (config.bearer) {
123
+ const bearer = config.bearer
124
+ return (req, ctx) => {
125
+ const options = ctx as Partial<from.Config>
126
+ req.headers.set('Authorization', `Bearer ${options.bearer ?? bearer}`)
127
+ return req
128
+ }
129
+ }
130
+ if (config.headers) {
131
+ const headers = config.headers
132
+ return (req, ctx) => {
133
+ const options = ctx as Partial<from.Config>
134
+ const h = options.headers ?? headers
135
+ for (const [name, value] of Object.entries(h)) req.headers.set(name, value)
136
+ return req
137
+ }
138
+ }
139
+ return undefined
140
+ }
141
+
142
+ /** Serializes a service for discovery responses. */
143
+ export function serialize(s: Service) {
144
+ return {
145
+ id: s.id,
146
+ baseUrl: s.baseUrl,
147
+ routes: Object.entries(s.routes).map(([pattern, endpoint]) => {
148
+ const tokens = pattern.trim().split(/\s+/)
149
+ const hasMethod = tokens.length >= 2
150
+ return {
151
+ method: hasMethod ? tokens[0] : undefined,
152
+ path: hasMethod ? tokens.slice(1).join(' ') : tokens[0],
153
+ pattern,
154
+ payment: endpoint ? resolvePayment(endpoint) : null,
155
+ }
156
+ }),
157
+ }
158
+ }
159
+
160
+ /** Renders an llms.txt markdown string for a list of services. */
161
+ export function toLlmsTxt(services: Service[]): string {
162
+ const lines: string[] = [
163
+ '# API Proxy',
164
+ '',
165
+ '> Paid API proxy powered by [Machine Payments Protocol](https://mpp.tempo.xyz).',
166
+ '',
167
+ 'For machine-readable service data, use `GET /services` (JSON).',
168
+ '',
169
+ ]
170
+
171
+ if (services.length === 0) return lines.join('\n')
172
+
173
+ lines.push('## Services', '')
174
+ for (const s of services) {
175
+ const serialized = serialize(s)
176
+ const free = serialized.routes.filter((r) => r.payment === null).length
177
+ const paid = serialized.routes.length - free
178
+ const parts = [paid && `${paid} paid`, free && `${free} free`].filter(Boolean).join(', ')
179
+ lines.push(`- [${s.id}](${s.baseUrl}): ${parts}`)
180
+ }
181
+
182
+ for (const s of services) {
183
+ const serialized = serialize(s)
184
+ lines.push('', `## ${s.id}`, '')
185
+ for (const route of serialized.routes) {
186
+ if (!route.payment) {
187
+ lines.push(`- \`${route.pattern}\`: Free`)
188
+ continue
189
+ }
190
+ const p = route.payment as Record<string, unknown>
191
+ const parts = [`${p.intent}`]
192
+ if (p.amount) {
193
+ const unit = `${p.amount} units`
194
+ parts.push(p.unitType ? `${unit} per ${p.unitType}` : unit)
195
+ }
196
+ if (p.description) parts.push(`"${p.description}"`)
197
+ const meta = [
198
+ p.currency && `currency: ${p.currency}`,
199
+ p.decimals !== undefined && `decimals: ${p.decimals}`,
200
+ ].filter(Boolean)
201
+ if (meta.length) parts.push(`(${meta.join(', ')})`)
202
+ lines.push(`- \`${route.pattern}\`: ${parts.join(' — ')}`)
203
+ }
204
+ }
205
+
206
+ return lines.join('\n')
207
+ }
208
+
209
+ /** Extracts per-endpoint options from an endpoint definition. */
210
+ export function getOptions(endpoint: Endpoint): EndpointOptions | undefined {
211
+ if (typeof endpoint === 'object' && endpoint !== null && 'options' in endpoint)
212
+ return endpoint.options
213
+ return undefined
214
+ }
215
+
216
+ function resolvePayment(endpoint: Endpoint): Record<string, unknown> | null {
217
+ if (endpoint === true) return null
218
+ const handler = typeof endpoint === 'function' ? endpoint : endpoint.pay
219
+ if (!('_internal' in handler)) return {}
220
+ const { name, method, defaults, schema, ...rest } = handler._internal as Record<string, unknown>
221
+ const amount = (() => {
222
+ if (typeof rest.amount === 'string' && typeof rest.decimals === 'number')
223
+ return String(Value.from(rest.amount, rest.decimals))
224
+ return rest.amount
225
+ })()
226
+ return { intent: name, method, ...rest, ...(amount !== undefined && { amount }) }
227
+ }
@@ -0,0 +1,6 @@
1
+ export * as Proxy from './Proxy.js'
2
+ export * as Service from './Service.js'
3
+ export { from as custom } from './Service.js'
4
+ export { anthropic } from './services/anthropic.js'
5
+ export { openai } from './services/openai.js'
6
+ export { stripe } from './services/stripe.js'
@@ -0,0 +1,100 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import * as Headers from './Headers.js'
3
+
4
+ describe('scrub', () => {
5
+ test('behavior: strips authorization header', () => {
6
+ const headers = new globalThis.Headers({
7
+ Authorization: 'Bearer secret',
8
+ 'Content-Type': 'application/json',
9
+ })
10
+ const result = Headers.scrub(headers)
11
+ expect(result.has('authorization')).toBe(false)
12
+ expect(result.get('content-type')).toBe('application/json')
13
+ })
14
+
15
+ test('behavior: strips cookie header', () => {
16
+ const headers = new globalThis.Headers({
17
+ Cookie: 'session=abc123',
18
+ Accept: 'text/html',
19
+ })
20
+ const result = Headers.scrub(headers)
21
+ expect(result.has('cookie')).toBe(false)
22
+ expect(result.get('accept')).toBe('text/html')
23
+ })
24
+
25
+ test('behavior: strips hop-by-hop headers', () => {
26
+ const headers = new globalThis.Headers({
27
+ Connection: 'keep-alive',
28
+ 'Keep-Alive': 'timeout=5',
29
+ 'Transfer-Encoding': 'chunked',
30
+ Upgrade: 'websocket',
31
+ 'Proxy-Authenticate': 'Basic',
32
+ 'Proxy-Authorization': 'Basic abc',
33
+ TE: 'trailers',
34
+ Trailer: 'Expires',
35
+ 'Content-Type': 'application/json',
36
+ })
37
+ const result = Headers.scrub(headers)
38
+ expect(result.has('connection')).toBe(false)
39
+ expect(result.has('keep-alive')).toBe(false)
40
+ expect(result.has('transfer-encoding')).toBe(false)
41
+ expect(result.has('upgrade')).toBe(false)
42
+ expect(result.has('proxy-authenticate')).toBe(false)
43
+ expect(result.has('proxy-authorization')).toBe(false)
44
+ expect(result.has('te')).toBe(false)
45
+ expect(result.has('trailer')).toBe(false)
46
+ expect(result.get('content-type')).toBe('application/json')
47
+ })
48
+
49
+ test('behavior: strips x-forwarded-* headers', () => {
50
+ const headers = new globalThis.Headers({
51
+ 'X-Forwarded-For': '127.0.0.1',
52
+ 'X-Forwarded-Proto': 'https',
53
+ 'X-Forwarded-Host': 'example.com',
54
+ Accept: '*/*',
55
+ })
56
+ const result = Headers.scrub(headers)
57
+ expect(result.has('x-forwarded-for')).toBe(false)
58
+ expect(result.has('x-forwarded-proto')).toBe(false)
59
+ expect(result.has('x-forwarded-host')).toBe(false)
60
+ expect(result.get('accept')).toBe('*/*')
61
+ })
62
+
63
+ test('behavior: preserves safe headers', () => {
64
+ const headers = new globalThis.Headers({
65
+ 'Content-Type': 'application/json',
66
+ Accept: 'text/html',
67
+ 'User-Agent': 'test-agent/1.0',
68
+ 'X-Custom-Header': 'value',
69
+ })
70
+ const result = Headers.scrub(headers)
71
+ expect(result.get('content-type')).toBe('application/json')
72
+ expect(result.get('accept')).toBe('text/html')
73
+ expect(result.get('user-agent')).toBe('test-agent/1.0')
74
+ expect(result.get('x-custom-header')).toBe('value')
75
+ })
76
+ })
77
+
78
+ describe('scrubResponse', () => {
79
+ test('behavior: strips content-encoding and content-length', () => {
80
+ const response = new Response('body', {
81
+ headers: {
82
+ 'Content-Encoding': 'gzip',
83
+ 'Content-Length': '42',
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ })
87
+ const result = Headers.scrubResponse(response)
88
+ expect(result.headers.has('content-encoding')).toBe(false)
89
+ expect(result.headers.has('content-length')).toBe(false)
90
+ expect(result.headers.get('content-type')).toBe('application/json')
91
+ })
92
+
93
+ test('behavior: preserves status and body', async () => {
94
+ const response = new Response('hello', { status: 201, statusText: 'Created' })
95
+ const result = Headers.scrubResponse(response)
96
+ expect(result.status).toBe(201)
97
+ expect(result.statusText).toBe('Created')
98
+ expect(await result.text()).toBe('hello')
99
+ })
100
+ })
@@ -0,0 +1,40 @@
1
+ const hopByHopHeaders = new Set([
2
+ 'connection',
3
+ 'keep-alive',
4
+ 'transfer-encoding',
5
+ 'upgrade',
6
+ 'proxy-authenticate',
7
+ 'proxy-authorization',
8
+ 'te',
9
+ 'trailer',
10
+ ])
11
+
12
+ export function scrub(headers: Headers): Headers {
13
+ const scrubbed = new Headers()
14
+
15
+ for (const [name, value] of headers) {
16
+ const lower = name.toLowerCase()
17
+
18
+ if (lower === 'authorization') continue
19
+ if (lower === 'accept-encoding') continue
20
+ if (lower === 'content-length') continue
21
+ if (lower === 'cookie') continue
22
+ if (hopByHopHeaders.has(lower)) continue
23
+ if (lower.startsWith('x-forwarded-')) continue
24
+
25
+ scrubbed.append(name, value)
26
+ }
27
+
28
+ return scrubbed
29
+ }
30
+
31
+ export function scrubResponse(response: Response): Response {
32
+ const headers = new Headers(response.headers)
33
+ headers.delete('content-encoding')
34
+ headers.delete('content-length')
35
+ return new Response(response.body, {
36
+ status: response.status,
37
+ statusText: response.statusText,
38
+ headers,
39
+ })
40
+ }