mppx 0.1.1 → 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 (219) hide show
  1. package/dist/Challenge.d.ts +16 -16
  2. package/dist/Challenge.d.ts.map +1 -1
  3. package/dist/Challenge.js +7 -7
  4. package/dist/Challenge.js.map +1 -1
  5. package/dist/Errors.d.ts +58 -8
  6. package/dist/Errors.d.ts.map +1 -1
  7. package/dist/Errors.js +51 -9
  8. package/dist/Errors.js.map +1 -1
  9. package/dist/Method.d.ts +154 -0
  10. package/dist/Method.d.ts.map +1 -0
  11. package/dist/Method.js +81 -0
  12. package/dist/Method.js.map +1 -0
  13. package/dist/PaymentRequest.d.ts +5 -5
  14. package/dist/PaymentRequest.d.ts.map +1 -1
  15. package/dist/PaymentRequest.js +5 -5
  16. package/dist/cli.js +67 -18
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client/Methods.d.ts +2 -2
  19. package/dist/client/Methods.d.ts.map +1 -1
  20. package/dist/client/Methods.js +2 -2
  21. package/dist/client/Methods.js.map +1 -1
  22. package/dist/client/Mppx.d.ts +7 -7
  23. package/dist/client/Mppx.d.ts.map +1 -1
  24. package/dist/client/Mppx.js +3 -3
  25. package/dist/client/Mppx.js.map +1 -1
  26. package/dist/client/internal/Fetch.d.ts +10 -10
  27. package/dist/client/internal/Fetch.d.ts.map +1 -1
  28. package/dist/client/internal/Fetch.js +2 -2
  29. package/dist/client/internal/Fetch.js.map +1 -1
  30. package/dist/index.d.ts +1 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/mcp-sdk/client/McpClient.d.ts +6 -6
  35. package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -1
  36. package/dist/mcp-sdk/client/McpClient.js +4 -4
  37. package/dist/mcp-sdk/client/McpClient.js.map +1 -1
  38. package/dist/middlewares/elysia.d.ts +1 -1
  39. package/dist/middlewares/express.d.ts +1 -1
  40. package/dist/middlewares/hono.d.ts +1 -1
  41. package/dist/middlewares/internal/mppx.d.ts +7 -7
  42. package/dist/middlewares/internal/mppx.d.ts.map +1 -1
  43. package/dist/middlewares/internal/mppx.js +5 -5
  44. package/dist/middlewares/internal/mppx.js.map +1 -1
  45. package/dist/middlewares/nextjs.d.ts +1 -1
  46. package/dist/proxy/Service.js +2 -2
  47. package/dist/proxy/Service.js.map +1 -1
  48. package/dist/server/Methods.d.ts +2 -2
  49. package/dist/server/Methods.d.ts.map +1 -1
  50. package/dist/server/Methods.js +2 -2
  51. package/dist/server/Methods.js.map +1 -1
  52. package/dist/server/Mppx.d.ts +17 -17
  53. package/dist/server/Mppx.d.ts.map +1 -1
  54. package/dist/server/Mppx.js +9 -9
  55. package/dist/server/Mppx.js.map +1 -1
  56. package/dist/stripe/{Intents.d.ts → Methods.d.ts} +22 -22
  57. package/dist/stripe/Methods.d.ts.map +1 -0
  58. package/dist/stripe/Methods.js +42 -0
  59. package/dist/stripe/Methods.js.map +1 -0
  60. package/dist/stripe/client/Charge.d.ts +40 -27
  61. package/dist/stripe/client/Charge.d.ts.map +1 -1
  62. package/dist/stripe/client/Charge.js +15 -7
  63. package/dist/stripe/client/Charge.js.map +1 -1
  64. package/dist/stripe/client/{MethodIntents.d.ts → Methods.d.ts} +24 -23
  65. package/dist/stripe/client/Methods.d.ts.map +1 -0
  66. package/dist/stripe/client/{MethodIntents.js → Methods.js} +3 -3
  67. package/dist/stripe/client/Methods.js.map +1 -0
  68. package/dist/stripe/client/index.d.ts +1 -1
  69. package/dist/stripe/client/index.d.ts.map +1 -1
  70. package/dist/stripe/client/index.js +1 -1
  71. package/dist/stripe/client/index.js.map +1 -1
  72. package/dist/stripe/index.d.ts +1 -1
  73. package/dist/stripe/index.d.ts.map +1 -1
  74. package/dist/stripe/index.js +1 -1
  75. package/dist/stripe/index.js.map +1 -1
  76. package/dist/stripe/internal/types.d.ts +25 -0
  77. package/dist/stripe/internal/types.d.ts.map +1 -0
  78. package/dist/stripe/internal/types.js +2 -0
  79. package/dist/stripe/internal/types.js.map +1 -0
  80. package/dist/stripe/server/Charge.d.ts +47 -28
  81. package/dist/stripe/server/Charge.d.ts.map +1 -1
  82. package/dist/stripe/server/Charge.js +90 -32
  83. package/dist/stripe/server/Charge.js.map +1 -1
  84. package/dist/stripe/server/{MethodIntents.d.ts → Methods.d.ts} +24 -23
  85. package/dist/stripe/server/Methods.d.ts.map +1 -0
  86. package/dist/stripe/server/{MethodIntents.js → Methods.js} +3 -3
  87. package/dist/stripe/server/Methods.js.map +1 -0
  88. package/dist/stripe/server/index.d.ts +1 -1
  89. package/dist/stripe/server/index.d.ts.map +1 -1
  90. package/dist/stripe/server/index.js +1 -1
  91. package/dist/stripe/server/index.js.map +1 -1
  92. package/dist/tempo/{Intents.d.ts → Methods.d.ts} +72 -69
  93. package/dist/tempo/Methods.d.ts.map +1 -0
  94. package/dist/tempo/Methods.js +118 -0
  95. package/dist/tempo/Methods.js.map +1 -0
  96. package/dist/tempo/client/ChannelOps.d.ts +1 -1
  97. package/dist/tempo/client/ChannelOps.js +1 -1
  98. package/dist/tempo/client/Charge.d.ts +25 -25
  99. package/dist/tempo/client/Charge.d.ts.map +1 -1
  100. package/dist/tempo/client/Charge.js +3 -3
  101. package/dist/tempo/client/Charge.js.map +1 -1
  102. package/dist/tempo/client/{MethodIntents.d.ts → Methods.d.ts} +74 -70
  103. package/dist/tempo/client/Methods.d.ts.map +1 -0
  104. package/dist/tempo/client/{MethodIntents.js → Methods.js} +3 -3
  105. package/dist/tempo/client/Methods.js.map +1 -0
  106. package/dist/tempo/client/Session.d.ts +49 -45
  107. package/dist/tempo/client/Session.d.ts.map +1 -1
  108. package/dist/tempo/client/Session.js +4 -4
  109. package/dist/tempo/client/Session.js.map +1 -1
  110. package/dist/tempo/client/SessionManager.d.ts +1 -1
  111. package/dist/tempo/client/SessionManager.js +1 -1
  112. package/dist/tempo/client/index.d.ts +1 -1
  113. package/dist/tempo/client/index.d.ts.map +1 -1
  114. package/dist/tempo/client/index.js +1 -1
  115. package/dist/tempo/client/index.js.map +1 -1
  116. package/dist/tempo/index.d.ts +1 -1
  117. package/dist/tempo/index.d.ts.map +1 -1
  118. package/dist/tempo/index.js +1 -1
  119. package/dist/tempo/index.js.map +1 -1
  120. package/dist/tempo/server/Charge.d.ts +27 -27
  121. package/dist/tempo/server/Charge.d.ts.map +1 -1
  122. package/dist/tempo/server/Charge.js +3 -3
  123. package/dist/tempo/server/Charge.js.map +1 -1
  124. package/dist/tempo/server/{MethodIntents.d.ts → Methods.d.ts} +73 -69
  125. package/dist/tempo/server/Methods.d.ts.map +1 -0
  126. package/dist/tempo/server/{MethodIntents.js → Methods.js} +4 -4
  127. package/dist/tempo/server/Methods.js.map +1 -0
  128. package/dist/tempo/server/Session.d.ts +51 -47
  129. package/dist/tempo/server/Session.d.ts.map +1 -1
  130. package/dist/tempo/server/Session.js +4 -4
  131. package/dist/tempo/server/Session.js.map +1 -1
  132. package/dist/tempo/server/index.d.ts +6 -0
  133. package/dist/tempo/server/index.d.ts.map +1 -0
  134. package/dist/tempo/server/index.js +6 -0
  135. package/dist/tempo/server/index.js.map +1 -0
  136. package/package.json +1 -1
  137. package/src/Challenge.test-d.ts +3 -3
  138. package/src/Challenge.test.ts +6 -6
  139. package/src/Challenge.ts +32 -32
  140. package/src/Errors.test.ts +75 -21
  141. package/src/Errors.ts +74 -9
  142. package/src/Method.test.ts +76 -0
  143. package/src/Method.ts +228 -0
  144. package/src/PaymentRequest.test.ts +4 -4
  145. package/src/PaymentRequest.ts +9 -9
  146. package/src/cli.test.ts +12 -22
  147. package/src/cli.ts +74 -21
  148. package/src/client/Methods.ts +2 -2
  149. package/src/client/Mppx.test-d.ts +6 -6
  150. package/src/client/Mppx.test.ts +26 -22
  151. package/src/client/Mppx.ts +10 -10
  152. package/src/client/Transport.test.ts +2 -2
  153. package/src/client/internal/Fetch.ts +21 -24
  154. package/src/index.ts +1 -2
  155. package/src/mcp-sdk/client/McpClient.ts +11 -13
  156. package/src/middlewares/elysia.ts +1 -1
  157. package/src/middlewares/express.ts +1 -1
  158. package/src/middlewares/hono.ts +1 -1
  159. package/src/middlewares/internal/mppx.ts +10 -10
  160. package/src/middlewares/nextjs.ts +1 -1
  161. package/src/proxy/Service.ts +2 -2
  162. package/src/server/Methods.ts +2 -2
  163. package/src/server/Mppx.test-d.ts +27 -29
  164. package/src/server/Mppx.test.ts +23 -19
  165. package/src/server/Mppx.ts +43 -43
  166. package/src/server/Transport.test.ts +3 -3
  167. package/src/stripe/{Intents.test.ts → Methods.test.ts} +12 -12
  168. package/src/stripe/Methods.ts +45 -0
  169. package/src/stripe/client/Charge.test.ts +189 -0
  170. package/src/stripe/client/Charge.ts +29 -16
  171. package/src/stripe/client/{MethodIntents.ts → Methods.ts} +2 -2
  172. package/src/stripe/client/index.ts +1 -1
  173. package/src/stripe/index.ts +1 -1
  174. package/src/stripe/internal/types.ts +22 -0
  175. package/src/stripe/server/Charge.test.ts +241 -0
  176. package/src/stripe/server/Charge.ts +124 -38
  177. package/src/stripe/server/{MethodIntents.ts → Methods.ts} +2 -2
  178. package/src/stripe/server/index.ts +1 -1
  179. package/src/tempo/{Intents.test.ts → Methods.test.ts} +15 -15
  180. package/src/tempo/{Intents.ts → Methods.ts} +77 -22
  181. package/src/tempo/client/ChannelOps.ts +1 -1
  182. package/src/tempo/client/Charge.ts +3 -3
  183. package/src/tempo/client/{MethodIntents.ts → Methods.ts} +2 -2
  184. package/src/tempo/client/Session.ts +4 -4
  185. package/src/tempo/client/SessionManager.ts +1 -1
  186. package/src/tempo/client/index.ts +1 -1
  187. package/src/tempo/index.ts +1 -1
  188. package/src/tempo/server/Charge.ts +4 -7
  189. package/src/tempo/server/{MethodIntents.ts → Methods.ts} +3 -3
  190. package/src/tempo/server/Session.test.ts +4 -7
  191. package/src/tempo/server/Session.ts +6 -6
  192. package/src/tempo/server/index.ts +1 -1
  193. package/dist/Intent.d.ts +0 -101
  194. package/dist/Intent.d.ts.map +0 -1
  195. package/dist/Intent.js +0 -83
  196. package/dist/Intent.js.map +0 -1
  197. package/dist/MethodIntent.d.ts +0 -225
  198. package/dist/MethodIntent.d.ts.map +0 -1
  199. package/dist/MethodIntent.js +0 -156
  200. package/dist/MethodIntent.js.map +0 -1
  201. package/dist/stripe/Intents.d.ts.map +0 -1
  202. package/dist/stripe/Intents.js +0 -27
  203. package/dist/stripe/Intents.js.map +0 -1
  204. package/dist/stripe/client/MethodIntents.d.ts.map +0 -1
  205. package/dist/stripe/client/MethodIntents.js.map +0 -1
  206. package/dist/stripe/server/MethodIntents.d.ts.map +0 -1
  207. package/dist/stripe/server/MethodIntents.js.map +0 -1
  208. package/dist/tempo/Intents.d.ts.map +0 -1
  209. package/dist/tempo/Intents.js +0 -81
  210. package/dist/tempo/Intents.js.map +0 -1
  211. package/dist/tempo/client/MethodIntents.d.ts.map +0 -1
  212. package/dist/tempo/client/MethodIntents.js.map +0 -1
  213. package/dist/tempo/server/MethodIntents.d.ts.map +0 -1
  214. package/dist/tempo/server/MethodIntents.js.map +0 -1
  215. package/src/Intent.test.ts +0 -180
  216. package/src/Intent.ts +0 -109
  217. package/src/MethodIntent.test.ts +0 -303
  218. package/src/MethodIntent.ts +0 -388
  219. package/src/stripe/Intents.ts +0 -27
@@ -0,0 +1,154 @@
1
+ import type * as Challenge from './Challenge.js';
2
+ import type * as Credential from './Credential.js';
3
+ import type { ExactPartial, LooseOmit, MaybePromise } from './internal/types.js';
4
+ import type * as Receipt from './Receipt.js';
5
+ import type * as Transport from './server/Transport.js';
6
+ import type * as z from './zod.js';
7
+ /**
8
+ * A payment method.
9
+ */
10
+ export type Method = {
11
+ name: string;
12
+ intent: string;
13
+ schema: {
14
+ credential: {
15
+ payload: z.ZodMiniType;
16
+ };
17
+ request: z.ZodMiniType<Record<string, unknown>>;
18
+ };
19
+ };
20
+ /**
21
+ * Creates a payment method.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { z } from 'zod/mini'
26
+ * import { Method } from 'mppx'
27
+ *
28
+ * const tempoCharge = Method.from({
29
+ * name: 'tempo',
30
+ * intent: 'charge',
31
+ * schema: {
32
+ * credential: {
33
+ * payload: z.object({
34
+ * signature: z.string(),
35
+ * type: z.literal('transaction'),
36
+ * }),
37
+ * },
38
+ * request: z.object({
39
+ * amount: z.string(),
40
+ * currency: z.string(),
41
+ * recipient: z.string(),
42
+ * }),
43
+ * },
44
+ * })
45
+ * ```
46
+ */
47
+ export declare function from<const method extends Method>(method: method): method;
48
+ /**
49
+ * A client-side configured method with credential creation logic.
50
+ */
51
+ export type Client<method extends Method = Method, context extends z.ZodMiniType | undefined = z.ZodMiniType | undefined> = method & {
52
+ context?: context;
53
+ createCredential: CreateCredentialFn<method, context extends z.ZodMiniType ? z.output<context> : Record<never, never>>;
54
+ };
55
+ export type AnyClient = Client<any, any>;
56
+ /**
57
+ * A server-side configured method with verification logic.
58
+ */
59
+ export type Server<method extends Method = Method, defaults extends ExactPartial<z.input<method['schema']['request']>> = {}, transportOverride = undefined> = method & {
60
+ defaults?: defaults | undefined;
61
+ request?: RequestFn<method> | undefined;
62
+ respond?: RespondFn<method> | undefined;
63
+ transport?: transportOverride | undefined;
64
+ verify: VerifyFn<method>;
65
+ };
66
+ export type AnyServer = Server<any, any, any>;
67
+ /** Credential creation function for a single method. */
68
+ export type CreateCredentialFn<method extends Method, context = unknown> = (parameters: {
69
+ challenge: Challenge.Challenge<z.output<method['schema']['request']>, method['intent'], method['name']>;
70
+ } & ([keyof context] extends [never] ? unknown : {
71
+ context: context;
72
+ })) => Promise<string>;
73
+ /** Request transform function for a single method. */
74
+ export type RequestFn<method extends Method> = (options: {
75
+ credential?: Credential.Credential | null | undefined;
76
+ request: z.input<method['schema']['request']>;
77
+ }) => MaybePromise<z.input<method['schema']['request']>>;
78
+ /** Verification function for a single method. */
79
+ export type VerifyFn<method extends Method> = (parameters: {
80
+ credential: Credential.Credential<z.output<method['schema']['credential']['payload']>, Challenge.Challenge<z.output<method['schema']['request']>, method['intent'], method['name']>>;
81
+ request: z.input<method['schema']['request']>;
82
+ }) => Promise<Receipt.Receipt>;
83
+ /**
84
+ * Optional respond function for a server-side method.
85
+ *
86
+ * Called after `verify` succeeds. If it returns a `Response`, the library
87
+ * treats the request as fully handled (e.g. channel open/close) and
88
+ * `withReceipt()` will short-circuit — returning the management response
89
+ * with the receipt header attached without invoking any user-supplied
90
+ * response or generator. If it returns `undefined`, the server handler
91
+ * is expected to serve content via `withReceipt(response)`.
92
+ *
93
+ * **HTTP-only.** The `input` parameter is a `Request` object; MCP transports
94
+ * do not invoke this hook.
95
+ */
96
+ export type RespondFn<method extends Method> = (parameters: {
97
+ credential: Credential.Credential<z.output<method['schema']['credential']['payload']>, Challenge.Challenge<z.output<method['schema']['request']>, method['intent'], method['name']>>;
98
+ input: globalThis.Request;
99
+ receipt: Receipt.Receipt;
100
+ request: z.input<method['schema']['request']>;
101
+ }) => MaybePromise<globalThis.Response | undefined>;
102
+ /** Partial request type for defaults. */
103
+ export type RequestDefaults<method extends Method> = ExactPartial<z.input<method['schema']['request']>>;
104
+ /** Makes fields optional if they exist in defaults. */
105
+ export type WithDefaults<request, defaults> = [keyof defaults] extends [never] ? request : LooseOmit<request, keyof defaults & string> & ExactPartial<Pick<request, keyof defaults & keyof request>>;
106
+ /**
107
+ * Extends a method with client-side credential creation logic.
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * import { Method } from 'mppx'
112
+ * import { Methods } from 'mppx/tempo'
113
+ *
114
+ * const tempoCharge = Method.toClient(Methods.charge, {
115
+ * async createCredential({ challenge }) {
116
+ * return Credential.serialize({ challenge, payload: { ... } })
117
+ * },
118
+ * })
119
+ * ```
120
+ */
121
+ export declare function toClient<const method extends Method, const context extends z.ZodMiniType | undefined = undefined>(method: method, options: toClient.Options<method, context>): Client<method, context>;
122
+ export declare namespace toClient {
123
+ type Options<method extends Method, context extends z.ZodMiniType | undefined = undefined> = {
124
+ context?: context;
125
+ createCredential: CreateCredentialFn<method, context extends z.ZodMiniType ? z.output<context> : Record<never, never>>;
126
+ };
127
+ }
128
+ /**
129
+ * Extends a method with server-side verification logic.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * import { Method } from 'mppx'
134
+ * import { Methods } from 'mppx/tempo'
135
+ *
136
+ * const tempoCharge = Method.toServer(Methods.charge, {
137
+ * async verify({ credential }) {
138
+ * // verification logic
139
+ * return { status: 'success', ... }
140
+ * },
141
+ * })
142
+ * ```
143
+ */
144
+ export declare function toServer<const method extends Method, const defaults extends RequestDefaults<method> = {}, const transportOverride extends Transport.AnyTransport | undefined = undefined>(method: method, options: toServer.Options<method, defaults, transportOverride>): Server<method, defaults, transportOverride>;
145
+ export declare namespace toServer {
146
+ type Options<method extends Method, defaults extends RequestDefaults<method> = {}, transportOverride extends Transport.AnyTransport | undefined = undefined> = {
147
+ defaults?: defaults | undefined;
148
+ request?: RequestFn<method> | undefined;
149
+ respond?: RespondFn<method> | undefined;
150
+ transport?: transportOverride | undefined;
151
+ verify: VerifyFn<method>;
152
+ };
153
+ }
154
+ //# sourceMappingURL=Method.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Method.d.ts","sourceRoot":"","sources":["../src/Method.ts"],"names":[],"mappings":"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"}
package/dist/Method.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Creates a payment method.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { z } from 'zod/mini'
7
+ * import { Method } from 'mppx'
8
+ *
9
+ * const tempoCharge = Method.from({
10
+ * name: 'tempo',
11
+ * intent: 'charge',
12
+ * schema: {
13
+ * credential: {
14
+ * payload: z.object({
15
+ * signature: z.string(),
16
+ * type: z.literal('transaction'),
17
+ * }),
18
+ * },
19
+ * request: z.object({
20
+ * amount: z.string(),
21
+ * currency: z.string(),
22
+ * recipient: z.string(),
23
+ * }),
24
+ * },
25
+ * })
26
+ * ```
27
+ */
28
+ export function from(method) {
29
+ return method;
30
+ }
31
+ /**
32
+ * Extends a method with client-side credential creation logic.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { Method } from 'mppx'
37
+ * import { Methods } from 'mppx/tempo'
38
+ *
39
+ * const tempoCharge = Method.toClient(Methods.charge, {
40
+ * async createCredential({ challenge }) {
41
+ * return Credential.serialize({ challenge, payload: { ... } })
42
+ * },
43
+ * })
44
+ * ```
45
+ */
46
+ export function toClient(method, options) {
47
+ const { context, createCredential } = options;
48
+ return {
49
+ ...method,
50
+ context,
51
+ createCredential,
52
+ };
53
+ }
54
+ /**
55
+ * Extends a method with server-side verification logic.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * import { Method } from 'mppx'
60
+ * import { Methods } from 'mppx/tempo'
61
+ *
62
+ * const tempoCharge = Method.toServer(Methods.charge, {
63
+ * async verify({ credential }) {
64
+ * // verification logic
65
+ * return { status: 'success', ... }
66
+ * },
67
+ * })
68
+ * ```
69
+ */
70
+ export function toServer(method, options) {
71
+ const { defaults, request, respond, transport, verify } = options;
72
+ return {
73
+ ...method,
74
+ defaults,
75
+ request,
76
+ respond,
77
+ transport,
78
+ verify,
79
+ };
80
+ }
81
+ //# sourceMappingURL=Method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Method.js","sourceRoot":"","sources":["../src/Method.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,IAAI,CAA8B,MAAc;IAC9D,OAAO,MAAM,CAAA;AACf,CAAC;AA6FD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CAGtB,MAAc,EAAE,OAA0C;IAC1D,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAA;IAC7C,OAAO;QACL,GAAG,MAAM;QACT,OAAO;QACP,gBAAgB;KACU,CAAA;AAC9B,CAAC;AAYD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,QAAQ,CAKtB,MAAc,EACd,OAA8D;IAE9D,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IACjE,OAAO;QACL,GAAG,MAAM;QACT,QAAQ;QACR,OAAO;QACP,OAAO;QACP,SAAS;QACT,MAAM;KACwC,CAAA;AAClD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { Compute } from './internal/types.js';
2
- import type * as MethodIntent from './MethodIntent.js';
2
+ import type * as Method from './Method.js';
3
3
  import type * as z from './zod.js';
4
4
  /**
5
5
  * Intent-specific payment parameters.
@@ -51,16 +51,16 @@ export declare function from<const request extends Request>(request: request): r
51
51
  /**
52
52
  * Creates a validated request from a method intent.
53
53
  *
54
- * @param intent - The method intent to validate against.
54
+ * @param method - The method to validate against.
55
55
  * @param request - Request parameters.
56
56
  * @returns A validated request.
57
57
  *
58
58
  * @example
59
59
  * ```ts
60
60
  * import { Request } from 'mppx'
61
- * import { Intents } from 'mppx/tempo'
61
+ * import { Methods } from 'mppx/tempo'
62
62
  *
63
- * const request = Request.fromIntent(Intents.charge, {
63
+ * const request = Request.fromIntent(Methods.charge, {
64
64
  * amount: '1000000',
65
65
  * currency: '0x20c0000000000000000000000000000000000001',
66
66
  * recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
@@ -69,7 +69,7 @@ export declare function from<const request extends Request>(request: request): r
69
69
  * })
70
70
  * ```
71
71
  */
72
- export declare function fromIntent<const intent extends MethodIntent.MethodIntent>(intent: intent, request: z.input<intent['schema']['request']>): Request<z.output<intent['schema']['request']>>;
72
+ export declare function fromIntent<const method extends Method.Method>(method: method, request: z.input<method['schema']['request']>): Request<z.output<method['schema']['request']>>;
73
73
  /**
74
74
  * Serializes a request to a base64url string.
75
75
  *
@@ -1 +1 @@
1
- {"version":3,"file":"PaymentRequest.d.ts","sourceRoot":"","sources":["../src/PaymentRequest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,KAAK,YAAY,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU,CAAA;AAElC;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACnF,OAAO,CAAC,OAAO,CAAC,CAAA;AAElB;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAE7E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,YAAY,EACvE,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,GAC5C,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAEhD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGlD"}
1
+ {"version":3,"file":"PaymentRequest.d.ts","sourceRoot":"","sources":["../src/PaymentRequest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU,CAAA;AAElC;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACnF,OAAO,CAAC,OAAO,CAAC,CAAA;AAElB;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAE7E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAC3D,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,GAC5C,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAEhD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGlD"}
@@ -39,16 +39,16 @@ export function from(request) {
39
39
  /**
40
40
  * Creates a validated request from a method intent.
41
41
  *
42
- * @param intent - The method intent to validate against.
42
+ * @param method - The method to validate against.
43
43
  * @param request - Request parameters.
44
44
  * @returns A validated request.
45
45
  *
46
46
  * @example
47
47
  * ```ts
48
48
  * import { Request } from 'mppx'
49
- * import { Intents } from 'mppx/tempo'
49
+ * import { Methods } from 'mppx/tempo'
50
50
  *
51
- * const request = Request.fromIntent(Intents.charge, {
51
+ * const request = Request.fromIntent(Methods.charge, {
52
52
  * amount: '1000000',
53
53
  * currency: '0x20c0000000000000000000000000000000000001',
54
54
  * recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
@@ -57,8 +57,8 @@ export function from(request) {
57
57
  * })
58
58
  * ```
59
59
  */
60
- export function fromIntent(intent, request) {
61
- return intent.schema.request.parse(request);
60
+ export function fromIntent(method, request) {
61
+ return method.schema.request.parse(request);
62
62
  }
63
63
  /**
64
64
  * Serializes a request to a base64url string.
package/dist/cli.js CHANGED
@@ -34,15 +34,16 @@ cli
34
34
  .option('-L, --location', 'Follow redirects')
35
35
  .option('-X, --method <method>', 'HTTP method')
36
36
  .option('--channel <id>', 'Reuse existing stream channel ID')
37
+ .option('--confirm', 'Show confirmation prompts')
37
38
  .option('--deposit <amount>', 'Deposit amount for stream payments (human-readable units)')
38
39
  .option('--json <json>', 'Send JSON body (sets Content-Type and Accept, implies POST)')
39
- .option('--yes', 'Skip confirmation prompts')
40
40
  .example(`${name} example.com/content`)
41
41
  .example(`${name} example.com/api --json '{"key":"value"}'`)
42
42
  .action(async (rawUrl, rawOptions) => {
43
43
  const options = parseOptions(z.object({
44
44
  account: z.optional(z.string()),
45
45
  channel: z.optional(z.coerce.string()),
46
+ confirm: z.optional(z.boolean()),
46
47
  data: z.optional(z.string()),
47
48
  deposit: z.optional(z.union([z.string(), z.number()])),
48
49
  fail: z.optional(z.boolean()),
@@ -56,7 +57,6 @@ cli
56
57
  silent: z.optional(z.boolean()),
57
58
  userAgent: z.optional(z.string()),
58
59
  verbose: z.optional(z.boolean()),
59
- yes: z.optional(z.boolean()),
60
60
  }), rawOptions);
61
61
  if (!rawUrl) {
62
62
  cli.outputHelp();
@@ -65,7 +65,7 @@ cli
65
65
  const silent = options.silent ?? false;
66
66
  const info = silent ? (_msg) => { } : (msg) => process.stderr.write(msg);
67
67
  if (silent)
68
- options.yes = true;
68
+ options.confirm = false;
69
69
  const accountName = resolveAccountName(options.account);
70
70
  const privateKey = process.env.MPPX_PRIVATE_KEY ?? (await createKeychain(accountName).get());
71
71
  if (!privateKey) {
@@ -257,9 +257,9 @@ cli
257
257
  info(`${indent}${line}\n`);
258
258
  }
259
259
  }
260
- info('\n');
261
- if (!options.yes) {
262
- const ok = await confirm(`Proceed with ${challenge.intent}?`);
260
+ if (options.confirm) {
261
+ info('\n');
262
+ const ok = await confirm(`Proceed with ${challenge.intent}?`, true);
263
263
  if (!ok) {
264
264
  info('Aborted.\n');
265
265
  process.exit(0);
@@ -314,7 +314,7 @@ cli
314
314
  const depositDisplay = depositRaw
315
315
  ? ` ${pc.dim(`(deposit ${depositRaw} ${tokenSymbol})`)}`
316
316
  : '';
317
- info(`${pc.dim(`Channel opened ${parsed.payload.channelId}`)}${depositDisplay}\n`);
317
+ info(`\n${pc.dim(`Channel opened ${parsed.payload.channelId}`)}${depositDisplay}\n`);
318
318
  }
319
319
  }
320
320
  const credentialFetchInit = {
@@ -361,11 +361,26 @@ cli
361
361
  }
362
362
  info(`\n${pc.bold(pc.green('Payment Receipt'))}\n`);
363
363
  const rows = [];
364
+ const channelId = receiptJson.channelId;
365
+ const reference = receiptJson.reference;
366
+ const skipReference = channelId && reference && channelId === reference;
367
+ const receiptBalanceKeys = new Set(['acceptedCumulative', 'spent']);
364
368
  for (const [key, value] of Object.entries(receiptJson)) {
365
369
  if (value === undefined || shownKeys.has(key))
366
370
  continue;
367
- if (key === 'reference' && typeof value === 'string' && explorerUrl)
371
+ if (key === 'reference' && skipReference)
372
+ continue;
373
+ if (receiptBalanceKeys.has(key) && typeof value === 'string') {
374
+ rows.push([
375
+ key,
376
+ `${value} ${pc.dim(`(${fmtBalance(BigInt(value), tokenSymbol, tokenDecimals)})`)}`,
377
+ ]);
378
+ }
379
+ else if ((key === 'reference' || key === 'txHash') &&
380
+ typeof value === 'string' &&
381
+ explorerUrl) {
368
382
  rows.push([key, pc.link(`${explorerUrl}/tx/${value}`, value)]);
383
+ }
369
384
  else
370
385
  rows.push([key, String(value)]);
371
386
  }
@@ -400,7 +415,7 @@ cli
400
415
  ? BigInt(streamCred.payload.cumulativeAmount)
401
416
  : 0n;
402
417
  let _voucherSeq = 0;
403
- const termBg = await detectTerminalBg();
418
+ const termBg = verbose ? await detectTerminalBg() : undefined;
404
419
  const chunkBgs = (() => {
405
420
  if (!termBg || !pc.isColorSupported)
406
421
  return undefined;
@@ -476,10 +491,13 @@ cli
476
491
  const receipt = JSON.parse(data);
477
492
  info(`\n\n${pc.bold(pc.green('Payment Receipt'))}\n`);
478
493
  const rows = [];
494
+ const skipRef = receipt.channelId &&
495
+ receipt.reference &&
496
+ receipt.channelId === receipt.reference;
479
497
  for (const [key, value] of Object.entries(receipt)) {
480
498
  if (value === undefined || shownKeys.has(key))
481
499
  continue;
482
- if (key === 'channelId' && value === receipt.reference)
500
+ if (key === 'reference' && skipRef)
483
501
  continue;
484
502
  const receiptBalanceKeys = ['acceptedCumulative', 'spent'];
485
503
  if (receiptBalanceKeys.includes(key) && typeof value === 'string') {
@@ -488,8 +506,11 @@ cli
488
506
  `${value} ${pc.dim(`(${fmtBalance(BigInt(value), tokenSymbol, tokenDecimals)})`)}`,
489
507
  ]);
490
508
  }
491
- else if (key === 'reference' && typeof value === 'string' && explorerUrl)
509
+ else if ((key === 'reference' || key === 'txHash') &&
510
+ typeof value === 'string' &&
511
+ explorerUrl) {
492
512
  rows.push([key, pc.link(`${explorerUrl}/tx/${value}`, value)]);
513
+ }
493
514
  else
494
515
  rows.push([key, String(value)]);
495
516
  }
@@ -546,7 +567,20 @@ cli
546
567
  headers: { Authorization: closeCred },
547
568
  });
548
569
  if (closeRes.ok) {
549
- info(`\n${pc.dim('Channel closed.')} ${pc.dim(`Spent ${fmtBalance(cumulativeAmount, tokenSymbol, tokenDecimals)}.`)}\n`);
570
+ const closeReceiptHeader = closeRes.headers.get('Payment-Receipt');
571
+ let closeTxHash;
572
+ if (closeReceiptHeader) {
573
+ try {
574
+ const r = JSON.parse(Base64.toString(closeReceiptHeader));
575
+ if (typeof r.txHash === 'string')
576
+ closeTxHash = r.txHash;
577
+ }
578
+ catch { }
579
+ }
580
+ const txInfo = closeTxHash && explorerUrl
581
+ ? ` ${pc.dim(pc.link(`${explorerUrl}/tx/${closeTxHash}`, closeTxHash))}`
582
+ : '';
583
+ info(`\n${pc.dim('Channel closed.')} ${pc.dim(`Spent ${fmtBalance(cumulativeAmount, tokenSymbol, tokenDecimals)}.`)}${txInfo}\n`);
550
584
  }
551
585
  else {
552
586
  info(`\n${pc.dim(pc.yellow('Channel close failed'))} ${pc.dim(`(${closeRes.status})`)}\n`);
@@ -561,10 +595,10 @@ cli
561
595
  streamChannelId &&
562
596
  streamEscrowContract &&
563
597
  streamChainId;
564
- if (shouldClose && !options.yes) {
598
+ if (shouldClose && options.confirm) {
565
599
  info('\n');
566
600
  }
567
- if (shouldClose && !(options.yes || (await confirm('Close channel?')))) {
601
+ if (shouldClose && options.confirm && !(await confirm('Close channel?', true))) {
568
602
  info(`${pc.dim('Kept channel open.')}\n`);
569
603
  }
570
604
  else if (shouldClose) {
@@ -589,7 +623,20 @@ cli
589
623
  });
590
624
  if (closeRes.ok) {
591
625
  deleteChannelState(streamChannelId);
592
- info(`${pc.dim('Channel closed.')} ${pc.dim(`Spent ${fmtBalance(streamCumulativeAmount, tokenSymbol, tokenDecimals)}.`)}\n`);
626
+ const closeReceiptHeader = closeRes.headers.get('Payment-Receipt');
627
+ let closeTxHash;
628
+ if (closeReceiptHeader) {
629
+ try {
630
+ const r = JSON.parse(Base64.toString(closeReceiptHeader));
631
+ if (typeof r.txHash === 'string')
632
+ closeTxHash = r.txHash;
633
+ }
634
+ catch { }
635
+ }
636
+ const txInfo = closeTxHash && explorerUrl
637
+ ? ` ${pc.dim(pc.link(`${explorerUrl}/tx/${closeTxHash}`, closeTxHash))}`
638
+ : '';
639
+ info(`\n${pc.dim('Channel closed.')} ${pc.dim(`Spent ${fmtBalance(streamCumulativeAmount, tokenSymbol, tokenDecimals)}.`)}${txInfo}\n`);
593
640
  }
594
641
  else {
595
642
  const closeBody = await closeRes.text().catch(() => '');
@@ -1024,12 +1071,14 @@ function prompt(message) {
1024
1071
  });
1025
1072
  });
1026
1073
  }
1027
- function confirm(prompt) {
1074
+ function confirm(prompt, defaultYes = false) {
1028
1075
  const reader = readline.createInterface({ input: process.stdin, output: process.stderr });
1029
1076
  return new Promise((resolve) => {
1030
- reader.question(`${pc.bold(`▸ ${prompt}`)} ${pc.dim('(y/N)')} `, (answer) => {
1077
+ const hint = defaultYes ? '(Y/n)' : '(y/N)';
1078
+ reader.question(`${pc.bold(`▸ ${prompt}`)} ${pc.dim(hint)} `, (answer) => {
1031
1079
  reader.close();
1032
- resolve(answer.trim().toLowerCase() === 'y');
1080
+ const trimmed = answer.trim().toLowerCase();
1081
+ resolve(trimmed === '' ? defaultYes : trimmed === 'y');
1033
1082
  });
1034
1083
  });
1035
1084
  }