mppx 0.1.0 → 0.2.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 (231) hide show
  1. package/README.md +1 -1
  2. package/dist/Challenge.d.ts +18 -18
  3. package/dist/Challenge.d.ts.map +1 -1
  4. package/dist/Challenge.js +8 -8
  5. package/dist/Challenge.js.map +1 -1
  6. package/dist/Errors.d.ts +58 -8
  7. package/dist/Errors.d.ts.map +1 -1
  8. package/dist/Errors.js +51 -9
  9. package/dist/Errors.js.map +1 -1
  10. package/dist/Method.d.ts +154 -0
  11. package/dist/Method.d.ts.map +1 -0
  12. package/dist/Method.js +81 -0
  13. package/dist/Method.js.map +1 -0
  14. package/dist/PaymentRequest.d.ts +5 -5
  15. package/dist/PaymentRequest.d.ts.map +1 -1
  16. package/dist/PaymentRequest.js +5 -5
  17. package/dist/cli.js +67 -18
  18. package/dist/cli.js.map +1 -1
  19. package/dist/client/Methods.d.ts +2 -2
  20. package/dist/client/Methods.d.ts.map +1 -1
  21. package/dist/client/Methods.js +2 -2
  22. package/dist/client/Methods.js.map +1 -1
  23. package/dist/client/Mppx.d.ts +12 -7
  24. package/dist/client/Mppx.d.ts.map +1 -1
  25. package/dist/client/Mppx.js +10 -5
  26. package/dist/client/Mppx.js.map +1 -1
  27. package/dist/client/internal/Fetch.d.ts +13 -11
  28. package/dist/client/internal/Fetch.d.ts.map +1 -1
  29. package/dist/client/internal/Fetch.js +8 -4
  30. package/dist/client/internal/Fetch.js.map +1 -1
  31. package/dist/index.d.ts +1 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +1 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/mcp-sdk/client/McpClient.d.ts +6 -6
  36. package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -1
  37. package/dist/mcp-sdk/client/McpClient.js +4 -4
  38. package/dist/mcp-sdk/client/McpClient.js.map +1 -1
  39. package/dist/middlewares/elysia.d.ts +1 -1
  40. package/dist/middlewares/express.d.ts +1 -1
  41. package/dist/middlewares/hono.d.ts +1 -1
  42. package/dist/middlewares/internal/mppx.d.ts +7 -7
  43. package/dist/middlewares/internal/mppx.d.ts.map +1 -1
  44. package/dist/middlewares/internal/mppx.js +5 -5
  45. package/dist/middlewares/internal/mppx.js.map +1 -1
  46. package/dist/middlewares/nextjs.d.ts +1 -1
  47. package/dist/proxy/Service.js +2 -2
  48. package/dist/proxy/Service.js.map +1 -1
  49. package/dist/server/Methods.d.ts +2 -2
  50. package/dist/server/Methods.d.ts.map +1 -1
  51. package/dist/server/Methods.js +2 -2
  52. package/dist/server/Methods.js.map +1 -1
  53. package/dist/server/Mppx.d.ts +17 -17
  54. package/dist/server/Mppx.d.ts.map +1 -1
  55. package/dist/server/Mppx.js +9 -9
  56. package/dist/server/Mppx.js.map +1 -1
  57. package/dist/stripe/{Intents.d.ts → Methods.d.ts} +22 -22
  58. package/dist/stripe/Methods.d.ts.map +1 -0
  59. package/dist/stripe/Methods.js +42 -0
  60. package/dist/stripe/Methods.js.map +1 -0
  61. package/dist/stripe/client/Charge.d.ts +48 -44
  62. package/dist/stripe/client/Charge.d.ts.map +1 -1
  63. package/dist/stripe/client/Charge.js +22 -17
  64. package/dist/stripe/client/Charge.js.map +1 -1
  65. package/dist/stripe/client/{MethodIntents.d.ts → Methods.d.ts} +25 -24
  66. package/dist/stripe/client/Methods.d.ts.map +1 -0
  67. package/dist/stripe/client/{MethodIntents.js → Methods.js} +4 -4
  68. package/dist/stripe/client/Methods.js.map +1 -0
  69. package/dist/stripe/client/index.d.ts +1 -1
  70. package/dist/stripe/client/index.d.ts.map +1 -1
  71. package/dist/stripe/client/index.js +1 -1
  72. package/dist/stripe/client/index.js.map +1 -1
  73. package/dist/stripe/index.d.ts +1 -1
  74. package/dist/stripe/index.d.ts.map +1 -1
  75. package/dist/stripe/index.js +1 -1
  76. package/dist/stripe/index.js.map +1 -1
  77. package/dist/stripe/internal/types.d.ts +25 -0
  78. package/dist/stripe/internal/types.d.ts.map +1 -0
  79. package/dist/stripe/internal/types.js +2 -0
  80. package/dist/stripe/internal/types.js.map +1 -0
  81. package/dist/stripe/server/Charge.d.ts +47 -28
  82. package/dist/stripe/server/Charge.d.ts.map +1 -1
  83. package/dist/stripe/server/Charge.js +90 -32
  84. package/dist/stripe/server/Charge.js.map +1 -1
  85. package/dist/stripe/server/{MethodIntents.d.ts → Methods.d.ts} +24 -23
  86. package/dist/stripe/server/Methods.d.ts.map +1 -0
  87. package/dist/stripe/server/{MethodIntents.js → Methods.js} +3 -3
  88. package/dist/stripe/server/Methods.js.map +1 -0
  89. package/dist/stripe/server/index.d.ts +1 -1
  90. package/dist/stripe/server/index.d.ts.map +1 -1
  91. package/dist/stripe/server/index.js +1 -1
  92. package/dist/stripe/server/index.js.map +1 -1
  93. package/dist/tempo/{Intents.d.ts → Methods.d.ts} +72 -69
  94. package/dist/tempo/Methods.d.ts.map +1 -0
  95. package/dist/tempo/Methods.js +118 -0
  96. package/dist/tempo/Methods.js.map +1 -0
  97. package/dist/tempo/client/ChannelOps.d.ts +1 -1
  98. package/dist/tempo/client/ChannelOps.js +1 -1
  99. package/dist/tempo/client/Charge.d.ts +25 -25
  100. package/dist/tempo/client/Charge.d.ts.map +1 -1
  101. package/dist/tempo/client/Charge.js +3 -3
  102. package/dist/tempo/client/Charge.js.map +1 -1
  103. package/dist/tempo/client/{MethodIntents.d.ts → Methods.d.ts} +74 -70
  104. package/dist/tempo/client/Methods.d.ts.map +1 -0
  105. package/dist/tempo/client/{MethodIntents.js → Methods.js} +3 -3
  106. package/dist/tempo/client/Methods.js.map +1 -0
  107. package/dist/tempo/client/Session.d.ts +49 -45
  108. package/dist/tempo/client/Session.d.ts.map +1 -1
  109. package/dist/tempo/client/Session.js +4 -4
  110. package/dist/tempo/client/Session.js.map +1 -1
  111. package/dist/tempo/client/SessionManager.d.ts +1 -1
  112. package/dist/tempo/client/SessionManager.d.ts.map +1 -1
  113. package/dist/tempo/client/SessionManager.js +10 -5
  114. package/dist/tempo/client/SessionManager.js.map +1 -1
  115. package/dist/tempo/client/index.d.ts +1 -1
  116. package/dist/tempo/client/index.d.ts.map +1 -1
  117. package/dist/tempo/client/index.js +1 -1
  118. package/dist/tempo/client/index.js.map +1 -1
  119. package/dist/tempo/index.d.ts +1 -1
  120. package/dist/tempo/index.d.ts.map +1 -1
  121. package/dist/tempo/index.js +1 -1
  122. package/dist/tempo/index.js.map +1 -1
  123. package/dist/tempo/internal/defaults.d.ts +1 -1
  124. package/dist/tempo/internal/defaults.js +1 -1
  125. package/dist/tempo/server/Charge.d.ts +27 -27
  126. package/dist/tempo/server/Charge.d.ts.map +1 -1
  127. package/dist/tempo/server/Charge.js +3 -3
  128. package/dist/tempo/server/Charge.js.map +1 -1
  129. package/dist/tempo/server/{MethodIntents.d.ts → Methods.d.ts} +73 -69
  130. package/dist/tempo/server/Methods.d.ts.map +1 -0
  131. package/dist/tempo/server/{MethodIntents.js → Methods.js} +4 -4
  132. package/dist/tempo/server/Methods.js.map +1 -0
  133. package/dist/tempo/server/Session.d.ts +51 -47
  134. package/dist/tempo/server/Session.d.ts.map +1 -1
  135. package/dist/tempo/server/Session.js +4 -4
  136. package/dist/tempo/server/Session.js.map +1 -1
  137. package/dist/tempo/server/index.d.ts +6 -0
  138. package/dist/tempo/server/index.d.ts.map +1 -0
  139. package/dist/tempo/server/index.js +6 -0
  140. package/dist/tempo/server/index.js.map +1 -0
  141. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  142. package/dist/tempo/server/internal/transport.js +2 -1
  143. package/dist/tempo/server/internal/transport.js.map +1 -1
  144. package/package.json +1 -1
  145. package/src/Challenge.test-d.ts +3 -3
  146. package/src/Challenge.test.ts +6 -6
  147. package/src/Challenge.ts +34 -34
  148. package/src/Errors.test.ts +75 -21
  149. package/src/Errors.ts +74 -9
  150. package/src/Method.test.ts +76 -0
  151. package/src/Method.ts +228 -0
  152. package/src/PaymentRequest.test.ts +4 -4
  153. package/src/PaymentRequest.ts +9 -9
  154. package/src/cli.test.ts +12 -22
  155. package/src/cli.ts +74 -21
  156. package/src/client/Methods.ts +2 -2
  157. package/src/client/Mppx.test-d.ts +6 -6
  158. package/src/client/Mppx.test.ts +26 -22
  159. package/src/client/Mppx.ts +29 -13
  160. package/src/client/Transport.test.ts +2 -2
  161. package/src/client/internal/Fetch.test.ts +35 -1
  162. package/src/client/internal/Fetch.ts +36 -27
  163. package/src/index.ts +1 -2
  164. package/src/mcp-sdk/client/McpClient.ts +11 -13
  165. package/src/middlewares/elysia.ts +1 -1
  166. package/src/middlewares/express.ts +1 -1
  167. package/src/middlewares/hono.ts +1 -1
  168. package/src/middlewares/internal/mppx.ts +10 -10
  169. package/src/middlewares/nextjs.ts +1 -1
  170. package/src/proxy/Service.ts +2 -2
  171. package/src/server/Methods.ts +2 -2
  172. package/src/server/Mppx.test-d.ts +27 -29
  173. package/src/server/Mppx.test.ts +23 -19
  174. package/src/server/Mppx.ts +43 -43
  175. package/src/server/Transport.test.ts +3 -3
  176. package/src/stripe/Charge.integration.test.ts +4 -1
  177. package/src/stripe/{Intents.test.ts → Methods.test.ts} +12 -12
  178. package/src/stripe/Methods.ts +45 -0
  179. package/src/stripe/client/Charge.test.ts +189 -0
  180. package/src/stripe/client/Charge.ts +40 -31
  181. package/src/stripe/client/{MethodIntents.ts → Methods.ts} +3 -3
  182. package/src/stripe/client/index.ts +1 -1
  183. package/src/stripe/index.ts +1 -1
  184. package/src/stripe/internal/types.ts +22 -0
  185. package/src/stripe/server/Charge.test.ts +241 -0
  186. package/src/stripe/server/Charge.ts +124 -38
  187. package/src/stripe/server/{MethodIntents.ts → Methods.ts} +2 -2
  188. package/src/stripe/server/index.ts +1 -1
  189. package/src/tempo/{Intents.test.ts → Methods.test.ts} +15 -15
  190. package/src/tempo/{Intents.ts → Methods.ts} +77 -22
  191. package/src/tempo/client/ChannelOps.ts +1 -1
  192. package/src/tempo/client/Charge.ts +3 -3
  193. package/src/tempo/client/{MethodIntents.ts → Methods.ts} +2 -2
  194. package/src/tempo/client/Session.ts +4 -4
  195. package/src/tempo/client/SessionManager.ts +11 -5
  196. package/src/tempo/client/index.ts +1 -1
  197. package/src/tempo/index.ts +1 -1
  198. package/src/tempo/internal/defaults.ts +1 -1
  199. package/src/tempo/server/Charge.ts +4 -7
  200. package/src/tempo/server/{MethodIntents.ts → Methods.ts} +3 -3
  201. package/src/tempo/server/Session.test.ts +4 -7
  202. package/src/tempo/server/Session.ts +6 -6
  203. package/src/tempo/server/index.ts +1 -1
  204. package/src/tempo/server/internal/transport.ts +3 -2
  205. package/dist/Intent.d.ts +0 -101
  206. package/dist/Intent.d.ts.map +0 -1
  207. package/dist/Intent.js +0 -83
  208. package/dist/Intent.js.map +0 -1
  209. package/dist/MethodIntent.d.ts +0 -225
  210. package/dist/MethodIntent.d.ts.map +0 -1
  211. package/dist/MethodIntent.js +0 -156
  212. package/dist/MethodIntent.js.map +0 -1
  213. package/dist/stripe/Intents.d.ts.map +0 -1
  214. package/dist/stripe/Intents.js +0 -27
  215. package/dist/stripe/Intents.js.map +0 -1
  216. package/dist/stripe/client/MethodIntents.d.ts.map +0 -1
  217. package/dist/stripe/client/MethodIntents.js.map +0 -1
  218. package/dist/stripe/server/MethodIntents.d.ts.map +0 -1
  219. package/dist/stripe/server/MethodIntents.js.map +0 -1
  220. package/dist/tempo/Intents.d.ts.map +0 -1
  221. package/dist/tempo/Intents.js +0 -81
  222. package/dist/tempo/Intents.js.map +0 -1
  223. package/dist/tempo/client/MethodIntents.d.ts.map +0 -1
  224. package/dist/tempo/client/MethodIntents.js.map +0 -1
  225. package/dist/tempo/server/MethodIntents.d.ts.map +0 -1
  226. package/dist/tempo/server/MethodIntents.js.map +0 -1
  227. package/src/Intent.test.ts +0 -180
  228. package/src/Intent.ts +0 -109
  229. package/src/MethodIntent.test.ts +0 -303
  230. package/src/MethodIntent.ts +0 -388
  231. package/src/stripe/Intents.ts +0 -27
@@ -11,6 +11,8 @@ import {
11
11
  InvalidSignatureError,
12
12
  MalformedCredentialError,
13
13
  PaymentExpiredError,
14
+ PaymentInsufficientError,
15
+ PaymentMethodUnsupportedError,
14
16
  PaymentRequiredError,
15
17
  SignerMismatchError,
16
18
  VerificationFailedError,
@@ -32,7 +34,7 @@ describe('MalformedCredentialError', () => {
32
34
  "message": "Credential is malformed.",
33
35
  "name": "MalformedCredentialError",
34
36
  "status": 402,
35
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/malformed-credential",
37
+ "type": "https://paymentauth.org/problems/malformed-credential",
36
38
  }
37
39
  `)
38
40
  })
@@ -45,7 +47,7 @@ describe('MalformedCredentialError', () => {
45
47
  "message": "Credential is malformed: invalid base64url.",
46
48
  "name": "MalformedCredentialError",
47
49
  "status": 402,
48
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/malformed-credential",
50
+ "type": "https://paymentauth.org/problems/malformed-credential",
49
51
  }
50
52
  `)
51
53
  })
@@ -58,7 +60,7 @@ describe('InvalidChallengeError', () => {
58
60
  "message": "Challenge is invalid.",
59
61
  "name": "InvalidChallengeError",
60
62
  "status": 402,
61
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge",
63
+ "type": "https://paymentauth.org/problems/invalid-challenge",
62
64
  }
63
65
  `)
64
66
  })
@@ -69,7 +71,7 @@ describe('InvalidChallengeError', () => {
69
71
  "message": "Challenge "abc123" is invalid.",
70
72
  "name": "InvalidChallengeError",
71
73
  "status": 402,
72
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge",
74
+ "type": "https://paymentauth.org/problems/invalid-challenge",
73
75
  }
74
76
  `)
75
77
  })
@@ -80,7 +82,7 @@ describe('InvalidChallengeError', () => {
80
82
  "message": "Challenge is invalid: expired.",
81
83
  "name": "InvalidChallengeError",
82
84
  "status": 402,
83
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge",
85
+ "type": "https://paymentauth.org/problems/invalid-challenge",
84
86
  }
85
87
  `)
86
88
  })
@@ -93,7 +95,7 @@ describe('InvalidChallengeError', () => {
93
95
  "message": "Challenge "abc123" is invalid: already used.",
94
96
  "name": "InvalidChallengeError",
95
97
  "status": 402,
96
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge",
98
+ "type": "https://paymentauth.org/problems/invalid-challenge",
97
99
  }
98
100
  `)
99
101
  })
@@ -106,7 +108,7 @@ describe('VerificationFailedError', () => {
106
108
  "message": "Payment verification failed.",
107
109
  "name": "VerificationFailedError",
108
110
  "status": 402,
109
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/verification-failed",
111
+ "type": "https://paymentauth.org/problems/verification-failed",
110
112
  }
111
113
  `)
112
114
  })
@@ -119,7 +121,7 @@ describe('VerificationFailedError', () => {
119
121
  "message": "Payment verification failed: invalid signature.",
120
122
  "name": "VerificationFailedError",
121
123
  "status": 402,
122
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/verification-failed",
124
+ "type": "https://paymentauth.org/problems/verification-failed",
123
125
  }
124
126
  `)
125
127
  })
@@ -132,7 +134,7 @@ describe('PaymentExpiredError', () => {
132
134
  "message": "Payment has expired.",
133
135
  "name": "PaymentExpiredError",
134
136
  "status": 402,
135
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/payment-expired",
137
+ "type": "https://paymentauth.org/problems/payment-expired",
136
138
  }
137
139
  `)
138
140
  })
@@ -145,7 +147,7 @@ describe('PaymentExpiredError', () => {
145
147
  "message": "Payment expired at 2025-01-26T12:00:00Z.",
146
148
  "name": "PaymentExpiredError",
147
149
  "status": 402,
148
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/payment-expired",
150
+ "type": "https://paymentauth.org/problems/payment-expired",
149
151
  }
150
152
  `)
151
153
  })
@@ -158,7 +160,7 @@ describe('PaymentRequiredError', () => {
158
160
  "message": "Payment is required.",
159
161
  "name": "PaymentRequiredError",
160
162
  "status": 402,
161
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/payment-required",
163
+ "type": "https://paymentauth.org/problems/payment-required",
162
164
  }
163
165
  `)
164
166
  })
@@ -171,7 +173,7 @@ describe('PaymentRequiredError', () => {
171
173
  "message": "Payment is required for "api.example.com".",
172
174
  "name": "PaymentRequiredError",
173
175
  "status": 402,
174
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/payment-required",
176
+ "type": "https://paymentauth.org/problems/payment-required",
175
177
  }
176
178
  `)
177
179
  })
@@ -186,7 +188,7 @@ describe('PaymentRequiredError', () => {
186
188
  "message": "Payment is required for "api.example.com" (API access fee).",
187
189
  "name": "PaymentRequiredError",
188
190
  "status": 402,
189
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/payment-required",
191
+ "type": "https://paymentauth.org/problems/payment-required",
190
192
  }
191
193
  `)
192
194
  })
@@ -199,7 +201,7 @@ describe('InvalidPayloadError', () => {
199
201
  "message": "Credential payload is invalid.",
200
202
  "name": "InvalidPayloadError",
201
203
  "status": 402,
202
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-payload",
204
+ "type": "https://paymentauth.org/problems/invalid-payload",
203
205
  }
204
206
  `)
205
207
  })
@@ -212,7 +214,7 @@ describe('InvalidPayloadError', () => {
212
214
  "message": "Credential payload is invalid: missing signature field.",
213
215
  "name": "InvalidPayloadError",
214
216
  "status": 402,
215
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-payload",
217
+ "type": "https://paymentauth.org/problems/invalid-payload",
216
218
  }
217
219
  `)
218
220
  })
@@ -225,7 +227,7 @@ describe('BadRequestError', () => {
225
227
  "message": "Bad request.",
226
228
  "name": "BadRequestError",
227
229
  "status": 400,
228
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/bad-request",
230
+ "type": "https://paymentauth.org/problems/bad-request",
229
231
  }
230
232
  `)
231
233
  })
@@ -238,7 +240,59 @@ describe('BadRequestError', () => {
238
240
  "message": "Bad request: cannot combine hash type with feePayer.",
239
241
  "name": "BadRequestError",
240
242
  "status": 400,
241
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/bad-request",
243
+ "type": "https://paymentauth.org/problems/bad-request",
244
+ }
245
+ `)
246
+ })
247
+ })
248
+
249
+ describe('PaymentInsufficientError', () => {
250
+ test('default', () => {
251
+ expect(errorSnapshot(new PaymentInsufficientError())).toMatchInlineSnapshot(`
252
+ {
253
+ "message": "Payment amount is insufficient.",
254
+ "name": "PaymentInsufficientError",
255
+ "status": 402,
256
+ "type": "https://paymentauth.org/problems/payment-insufficient",
257
+ }
258
+ `)
259
+ })
260
+
261
+ test('with reason', () => {
262
+ expect(
263
+ errorSnapshot(new PaymentInsufficientError({ reason: 'expected 1000, received 500' })),
264
+ ).toMatchInlineSnapshot(`
265
+ {
266
+ "message": "Payment insufficient: expected 1000, received 500.",
267
+ "name": "PaymentInsufficientError",
268
+ "status": 402,
269
+ "type": "https://paymentauth.org/problems/payment-insufficient",
270
+ }
271
+ `)
272
+ })
273
+ })
274
+
275
+ describe('PaymentMethodUnsupportedError', () => {
276
+ test('default', () => {
277
+ expect(errorSnapshot(new PaymentMethodUnsupportedError())).toMatchInlineSnapshot(`
278
+ {
279
+ "message": "Payment method is not supported.",
280
+ "name": "PaymentMethodUnsupportedError",
281
+ "status": 400,
282
+ "type": "https://paymentauth.org/problems/method-unsupported",
283
+ }
284
+ `)
285
+ })
286
+
287
+ test('with method', () => {
288
+ expect(
289
+ errorSnapshot(new PaymentMethodUnsupportedError({ method: 'bitcoin' })),
290
+ ).toMatchInlineSnapshot(`
291
+ {
292
+ "message": "Payment method "bitcoin" is not supported.",
293
+ "name": "PaymentMethodUnsupportedError",
294
+ "status": 400,
295
+ "type": "https://paymentauth.org/problems/method-unsupported",
242
296
  }
243
297
  `)
244
298
  })
@@ -381,8 +435,8 @@ describe('toProblemDetails', () => {
381
435
  {
382
436
  "detail": "Credential is malformed: invalid JSON.",
383
437
  "status": 402,
384
- "title": "MalformedCredentialError",
385
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/malformed-credential",
438
+ "title": "Malformed Credential",
439
+ "type": "https://paymentauth.org/problems/malformed-credential",
386
440
  }
387
441
  `)
388
442
  })
@@ -394,8 +448,8 @@ describe('toProblemDetails', () => {
394
448
  "challengeId": "abc123",
395
449
  "detail": "Challenge "abc123" is invalid: expired.",
396
450
  "status": 402,
397
- "title": "InvalidChallengeError",
398
- "type": "https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge",
451
+ "title": "Invalid Challenge",
452
+ "type": "https://paymentauth.org/problems/invalid-challenge",
399
453
  }
400
454
  `)
401
455
  })
package/src/Errors.ts CHANGED
@@ -5,6 +5,9 @@ export abstract class PaymentError extends Error {
5
5
  /** RFC 9457 Problem Details type URI. */
6
6
  abstract readonly type: string
7
7
 
8
+ /** Human-readable summary for RFC 9457 Problem Details. */
9
+ abstract readonly title: string
10
+
8
11
  /** HTTP status code. */
9
12
  readonly status: number = 402
10
13
 
@@ -12,7 +15,7 @@ export abstract class PaymentError extends Error {
12
15
  toProblemDetails(challengeId?: string): PaymentError.ProblemDetails {
13
16
  return {
14
17
  type: this.type,
15
- title: this.name,
18
+ title: this.title,
16
19
  status: this.status,
17
20
  detail: this.message,
18
21
  ...(challengeId && { challengeId }),
@@ -40,7 +43,9 @@ export declare namespace PaymentError {
40
43
  */
41
44
  export class MalformedCredentialError extends PaymentError {
42
45
  override readonly name = 'MalformedCredentialError'
43
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/malformed-credential'
46
+ readonly title = 'Malformed Credential'
47
+ override readonly status = 402
48
+ readonly type = 'https://paymentauth.org/problems/malformed-credential'
44
49
 
45
50
  constructor(options: MalformedCredentialError.Options = {}) {
46
51
  const { reason } = options
@@ -60,7 +65,9 @@ export declare namespace MalformedCredentialError {
60
65
  */
61
66
  export class InvalidChallengeError extends PaymentError {
62
67
  override readonly name = 'InvalidChallengeError'
63
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/invalid-challenge'
68
+ readonly title = 'Invalid Challenge'
69
+ override readonly status = 402
70
+ readonly type = 'https://paymentauth.org/problems/invalid-challenge'
64
71
 
65
72
  constructor(options: InvalidChallengeError.Options = {}) {
66
73
  const { id, reason } = options
@@ -84,7 +91,8 @@ export declare namespace InvalidChallengeError {
84
91
  */
85
92
  export class VerificationFailedError extends PaymentError {
86
93
  override readonly name = 'VerificationFailedError'
87
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/verification-failed'
94
+ readonly title = 'Verification Failed'
95
+ readonly type = 'https://paymentauth.org/problems/verification-failed'
88
96
 
89
97
  constructor(options: VerificationFailedError.Options = {}) {
90
98
  const { reason } = options
@@ -104,7 +112,8 @@ export declare namespace VerificationFailedError {
104
112
  */
105
113
  export class PaymentActionRequiredError extends PaymentError {
106
114
  override readonly name = 'PaymentActionRequiredError'
107
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/payment-action-required'
115
+ readonly title = 'Payment Action Required'
116
+ readonly type = 'https://paymentauth.org/problems/payment-action-required'
108
117
 
109
118
  constructor(options: PaymentActionRequiredError.Options = {}) {
110
119
  const { reason } = options
@@ -124,7 +133,8 @@ export declare namespace PaymentActionRequiredError {
124
133
  */
125
134
  export class PaymentExpiredError extends PaymentError {
126
135
  override readonly name = 'PaymentExpiredError'
127
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/payment-expired'
136
+ readonly title = 'Payment Expired'
137
+ readonly type = 'https://paymentauth.org/problems/payment-expired'
128
138
 
129
139
  constructor(options: PaymentExpiredError.Options = {}) {
130
140
  const { expires } = options
@@ -144,7 +154,8 @@ export declare namespace PaymentExpiredError {
144
154
  */
145
155
  export class PaymentRequiredError extends PaymentError {
146
156
  override readonly name = 'PaymentRequiredError'
147
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/payment-required'
157
+ readonly title = 'Payment Required'
158
+ readonly type = 'https://paymentauth.org/problems/payment-required'
148
159
 
149
160
  constructor(options: PaymentRequiredError.Options = {}) {
150
161
  const { description, realm } = options
@@ -169,7 +180,8 @@ export declare namespace PaymentRequiredError {
169
180
  */
170
181
  export class InvalidPayloadError extends PaymentError {
171
182
  override readonly name = 'InvalidPayloadError'
172
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/invalid-payload'
183
+ readonly title = 'Invalid Payload'
184
+ readonly type = 'https://paymentauth.org/problems/invalid-payload'
173
185
 
174
186
  constructor(options: InvalidPayloadError.Options = {}) {
175
187
  const { reason } = options
@@ -189,8 +201,9 @@ export declare namespace InvalidPayloadError {
189
201
  */
190
202
  export class BadRequestError extends PaymentError {
191
203
  override readonly name = 'BadRequestError'
204
+ readonly title = 'Bad Request'
192
205
  override readonly status = 400
193
- readonly type = 'https://tempoxyz.github.io/payment-auth-spec/problems/bad-request'
206
+ readonly type = 'https://paymentauth.org/problems/bad-request'
194
207
 
195
208
  constructor(options: BadRequestError.Options = {}) {
196
209
  const { reason } = options
@@ -205,11 +218,57 @@ export declare namespace BadRequestError {
205
218
  }
206
219
  }
207
220
 
221
+ /**
222
+ * Payment amount is insufficient (too low).
223
+ */
224
+ export class PaymentInsufficientError extends PaymentError {
225
+ override readonly name = 'PaymentInsufficientError'
226
+ readonly title = 'Payment Insufficient'
227
+ readonly type = 'https://paymentauth.org/problems/payment-insufficient'
228
+
229
+ constructor(options: PaymentInsufficientError.Options = {}) {
230
+ const { reason } = options
231
+ super(reason ? `Payment insufficient: ${reason}.` : 'Payment amount is insufficient.')
232
+ }
233
+ }
234
+
235
+ export declare namespace PaymentInsufficientError {
236
+ type Options = {
237
+ /** Reason the payment is insufficient (e.g., "expected 1000, received 500"). */
238
+ reason?: string
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Payment method is not supported by the server.
244
+ */
245
+ export class PaymentMethodUnsupportedError extends PaymentError {
246
+ override readonly name = 'PaymentMethodUnsupportedError'
247
+ readonly title = 'Method Unsupported'
248
+ override readonly status = 400
249
+ readonly type = 'https://paymentauth.org/problems/method-unsupported'
250
+
251
+ constructor(options: PaymentMethodUnsupportedError.Options = {}) {
252
+ const { method } = options
253
+ super(
254
+ method ? `Payment method "${method}" is not supported.` : 'Payment method is not supported.',
255
+ )
256
+ }
257
+ }
258
+
259
+ export declare namespace PaymentMethodUnsupportedError {
260
+ type Options = {
261
+ /** The unsupported method identifier. */
262
+ method?: string
263
+ }
264
+ }
265
+
208
266
  /**
209
267
  * Insufficient balance in the payment channel.
210
268
  */
211
269
  export class InsufficientBalanceError extends PaymentError {
212
270
  override readonly name = 'InsufficientBalanceError'
271
+ readonly title = 'Insufficient Balance'
213
272
  override readonly status = 402
214
273
  readonly type = 'https://paymentauth.org/problems/stream/insufficient-balance'
215
274
 
@@ -231,6 +290,7 @@ export declare namespace InsufficientBalanceError {
231
290
  */
232
291
  export class InvalidSignatureError extends PaymentError {
233
292
  override readonly name = 'InvalidSignatureError'
293
+ readonly title = 'Invalid Signature'
234
294
  override readonly status = 402
235
295
  readonly type = 'https://paymentauth.org/problems/stream/invalid-signature'
236
296
 
@@ -251,6 +311,7 @@ export declare namespace InvalidSignatureError {
251
311
  */
252
312
  export class SignerMismatchError extends PaymentError {
253
313
  override readonly name = 'SignerMismatchError'
314
+ readonly title = 'Signer Mismatch'
254
315
  override readonly status = 402
255
316
  readonly type = 'https://paymentauth.org/problems/stream/signer-mismatch'
256
317
 
@@ -271,6 +332,7 @@ export declare namespace SignerMismatchError {
271
332
  */
272
333
  export class AmountExceedsDepositError extends PaymentError {
273
334
  override readonly name = 'AmountExceedsDepositError'
335
+ readonly title = 'Amount Exceeds Deposit'
274
336
  override readonly status = 402
275
337
  readonly type = 'https://paymentauth.org/problems/stream/amount-exceeds-deposit'
276
338
 
@@ -291,6 +353,7 @@ export declare namespace AmountExceedsDepositError {
291
353
  */
292
354
  export class DeltaTooSmallError extends PaymentError {
293
355
  override readonly name = 'DeltaTooSmallError'
356
+ readonly title = 'Delta Too Small'
294
357
  override readonly status = 402
295
358
  readonly type = 'https://paymentauth.org/problems/stream/delta-too-small'
296
359
 
@@ -311,6 +374,7 @@ export declare namespace DeltaTooSmallError {
311
374
  */
312
375
  export class ChannelNotFoundError extends PaymentError {
313
376
  override readonly name = 'ChannelNotFoundError'
377
+ readonly title = 'Channel Not Found'
314
378
  override readonly status = 410
315
379
  readonly type = 'https://paymentauth.org/problems/stream/channel-not-found'
316
380
 
@@ -331,6 +395,7 @@ export declare namespace ChannelNotFoundError {
331
395
  */
332
396
  export class ChannelClosedError extends PaymentError {
333
397
  override readonly name = 'ChannelClosedError'
398
+ readonly title = 'Channel Closed'
334
399
  override readonly status = 410
335
400
  readonly type = 'https://paymentauth.org/problems/stream/channel-finalized'
336
401
 
@@ -0,0 +1,76 @@
1
+ import { Method, z } from 'mppx'
2
+ import { describe, expect, expectTypeOf, test } from 'vitest'
3
+
4
+ describe('from', () => {
5
+ test('behavior: creates intent', () => {
6
+ const method = Method.from({
7
+ name: 'tempo',
8
+ intent: 'charge',
9
+ schema: {
10
+ credential: {
11
+ payload: z.object({
12
+ signature: z.string(),
13
+ }),
14
+ },
15
+ request: z.object({
16
+ amount: z.string(),
17
+ currency: z.string(),
18
+ }),
19
+ },
20
+ })
21
+
22
+ expect(method.intent).toBe('charge')
23
+ expect(method.name).toBe('tempo')
24
+ expect(method.schema.request).toBeDefined()
25
+ expect(method.schema.credential.payload).toBeDefined()
26
+ })
27
+
28
+ test('types: intent literal is inferred', () => {
29
+ const method = Method.from({
30
+ name: 'tempo',
31
+ intent: 'charge',
32
+ schema: {
33
+ credential: { payload: z.object({ sig: z.string() }) },
34
+ request: z.object({ amount: z.string() }),
35
+ },
36
+ })
37
+
38
+ expectTypeOf(method.intent).toEqualTypeOf<'charge'>()
39
+ })
40
+
41
+ test('types: name literal is inferred', () => {
42
+ const method = Method.from({
43
+ name: 'tempo',
44
+ intent: 'charge',
45
+ schema: {
46
+ credential: { payload: z.object({ sig: z.string() }) },
47
+ request: z.object({ amount: z.string() }),
48
+ },
49
+ })
50
+
51
+ expectTypeOf(method.name).toEqualTypeOf<'tempo'>()
52
+ })
53
+
54
+ test('types: schema types are preserved', () => {
55
+ const requestSchema = z.object({
56
+ amount: z.string(),
57
+ currency: z.string(),
58
+ })
59
+ const payloadSchema = z.object({
60
+ signature: z.string(),
61
+ type: z.literal('transaction'),
62
+ })
63
+
64
+ const method = Method.from({
65
+ name: 'tempo',
66
+ intent: 'charge',
67
+ schema: {
68
+ credential: { payload: payloadSchema },
69
+ request: requestSchema,
70
+ },
71
+ })
72
+
73
+ expectTypeOf(method.schema.request).toEqualTypeOf(requestSchema)
74
+ expectTypeOf(method.schema.credential.payload).toEqualTypeOf(payloadSchema)
75
+ })
76
+ })