mppx 0.4.8 → 0.4.10
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.
- package/CHANGELOG.md +26 -3
- package/README.md +13 -13
- package/dist/BodyDigest.d.ts.map +1 -1
- package/dist/BodyDigest.js.map +1 -1
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js.map +1 -1
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Credential.js.map +1 -1
- package/dist/Errors.js +64 -67
- package/dist/Errors.js.map +1 -1
- package/dist/PaymentRequest.d.ts.map +1 -1
- package/dist/PaymentRequest.js.map +1 -1
- package/dist/Receipt.d.ts.map +1 -1
- package/dist/Receipt.js.map +1 -1
- package/dist/Store.d.ts +9 -0
- package/dist/Store.d.ts.map +1 -1
- package/dist/Store.js +17 -0
- package/dist/Store.js.map +1 -1
- package/dist/cli/account.d.ts.map +1 -1
- package/dist/cli/account.js +40 -5
- package/dist/cli/account.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +157 -1
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/internal.d.ts.map +1 -1
- package/dist/cli/internal.js.map +1 -1
- package/dist/cli/plugins/stripe.d.ts.map +1 -1
- package/dist/cli/plugins/stripe.js.map +1 -1
- package/dist/cli/plugins/tempo.d.ts.map +1 -1
- package/dist/cli/plugins/tempo.js +2 -1
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts +2 -0
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +1 -1
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/discovery/Discovery.d.ts +146 -0
- package/dist/discovery/Discovery.d.ts.map +1 -0
- package/dist/discovery/Discovery.js +60 -0
- package/dist/discovery/Discovery.js.map +1 -0
- package/dist/discovery/OpenApi.d.ts +61 -0
- package/dist/discovery/OpenApi.d.ts.map +1 -0
- package/dist/discovery/OpenApi.js +139 -0
- package/dist/discovery/OpenApi.js.map +1 -0
- package/dist/discovery/Validate.d.ts +10 -0
- package/dist/discovery/Validate.d.ts.map +1 -0
- package/dist/discovery/Validate.js +63 -0
- package/dist/discovery/Validate.js.map +1 -0
- package/dist/discovery/index.d.ts +4 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +4 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -1
- package/dist/mcp-sdk/client/McpClient.js +1 -1
- package/dist/mcp-sdk/client/McpClient.js.map +1 -1
- package/dist/mcp-sdk/server/Transport.d.ts.map +1 -1
- package/dist/mcp-sdk/server/Transport.js.map +1 -1
- package/dist/middlewares/elysia.d.ts +52 -1
- package/dist/middlewares/elysia.d.ts.map +1 -1
- package/dist/middlewares/elysia.js +17 -0
- package/dist/middlewares/elysia.js.map +1 -1
- package/dist/middlewares/express.d.ts +13 -1
- package/dist/middlewares/express.d.ts.map +1 -1
- package/dist/middlewares/express.js +23 -2
- package/dist/middlewares/express.js.map +1 -1
- package/dist/middlewares/hono.d.ts +19 -1
- package/dist/middlewares/hono.d.ts.map +1 -1
- package/dist/middlewares/hono.js +51 -0
- package/dist/middlewares/hono.js.map +1 -1
- package/dist/middlewares/internal/mppx.d.ts +4 -2
- package/dist/middlewares/internal/mppx.d.ts.map +1 -1
- package/dist/middlewares/internal/mppx.js +10 -3
- package/dist/middlewares/internal/mppx.js.map +1 -1
- package/dist/middlewares/nextjs.d.ts +11 -0
- package/dist/middlewares/nextjs.d.ts.map +1 -1
- package/dist/middlewares/nextjs.js +15 -0
- package/dist/middlewares/nextjs.js.map +1 -1
- package/dist/proxy/Proxy.d.ts +6 -0
- package/dist/proxy/Proxy.d.ts.map +1 -1
- package/dist/proxy/Proxy.js +56 -80
- package/dist/proxy/Proxy.js.map +1 -1
- package/dist/proxy/Service.d.ts +16 -23
- package/dist/proxy/Service.d.ts.map +1 -1
- package/dist/proxy/Service.js +20 -84
- package/dist/proxy/Service.js.map +1 -1
- package/dist/proxy/internal/Route.js +1 -1
- package/dist/proxy/internal/Route.js.map +1 -1
- package/dist/proxy/services/anthropic.d.ts.map +1 -1
- package/dist/proxy/services/anthropic.js +5 -0
- package/dist/proxy/services/anthropic.js.map +1 -1
- package/dist/proxy/services/openai.d.ts.map +1 -1
- package/dist/proxy/services/openai.js +6 -3
- package/dist/proxy/services/openai.js.map +1 -1
- package/dist/proxy/services/stripe.d.ts.map +1 -1
- package/dist/proxy/services/stripe.js +6 -3
- package/dist/proxy/services/stripe.js.map +1 -1
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +35 -17
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/Request.d.ts.map +1 -1
- package/dist/server/Request.js.map +1 -1
- package/dist/stripe/Methods.d.ts.map +1 -1
- package/dist/stripe/Methods.js.map +1 -1
- package/dist/tempo/Methods.d.ts.map +1 -1
- package/dist/tempo/Methods.js.map +1 -1
- package/dist/tempo/client/ChannelOps.d.ts.map +1 -1
- package/dist/tempo/client/ChannelOps.js.map +1 -1
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Session.d.ts.map +1 -1
- package/dist/tempo/client/Session.js.map +1 -1
- package/dist/tempo/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/client/SessionManager.js +1 -1
- package/dist/tempo/client/SessionManager.js.map +1 -1
- package/dist/tempo/internal/auto-swap.d.ts.map +1 -1
- package/dist/tempo/internal/auto-swap.js +1 -1
- package/dist/tempo/internal/auto-swap.js.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +1 -1
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +1 -1
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Session.d.ts.map +1 -1
- package/dist/tempo/server/Session.js +18 -5
- package/dist/tempo/server/Session.js.map +1 -1
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +8 -0
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/dist/tempo/session/Chain.d.ts.map +1 -1
- package/dist/tempo/session/Chain.js +1 -1
- package/dist/tempo/session/Chain.js.map +1 -1
- package/dist/tempo/session/ChannelStore.d.ts.map +1 -1
- package/dist/tempo/session/ChannelStore.js.map +1 -1
- package/dist/tempo/session/Receipt.d.ts.map +1 -1
- package/dist/tempo/session/Receipt.js.map +1 -1
- package/dist/tempo/session/Sse.d.ts.map +1 -1
- package/dist/tempo/session/Sse.js.map +1 -1
- package/dist/tempo/session/Voucher.d.ts.map +1 -1
- package/dist/tempo/session/Voucher.js.map +1 -1
- package/dist/viem/Client.d.ts.map +1 -1
- package/dist/viem/Client.js.map +1 -1
- package/package.json +6 -1
- package/src/BodyDigest.test.ts +1 -1
- package/src/BodyDigest.ts +1 -0
- package/src/Challenge.fuzz.test.ts +121 -0
- package/src/Challenge.test-d.ts +2 -1
- package/src/Challenge.test.ts +1 -1
- package/src/Challenge.ts +1 -0
- package/src/Credential.fuzz.test.ts +62 -0
- package/src/Credential.test.ts +1 -1
- package/src/Credential.ts +1 -0
- package/src/Errors.test.ts +28 -40
- package/src/Expires.test.ts +2 -1
- package/src/Method.test.ts +1 -1
- package/src/PaymentRequest.test.ts +1 -1
- package/src/PaymentRequest.ts +1 -0
- package/src/Receipt.test.ts +1 -1
- package/src/Receipt.ts +1 -0
- package/src/Store.test-d.ts +2 -1
- package/src/Store.test.ts +57 -7
- package/src/Store.ts +25 -0
- package/src/cli/account.ts +65 -30
- package/src/cli/cli.test.ts +215 -2
- package/src/cli/cli.ts +166 -1
- package/src/cli/config.test.ts +1 -0
- package/src/cli/internal.ts +1 -0
- package/src/cli/plugins/stripe.ts +1 -0
- package/src/cli/plugins/tempo.ts +4 -1
- package/src/cli/utils.ts +1 -0
- package/src/client/Mppx.test-d.ts +2 -1
- package/src/client/Mppx.test.ts +1 -1
- package/src/client/Transport.test.ts +1 -1
- package/src/client/internal/Fetch.browser.test.ts +2 -1
- package/src/client/internal/Fetch.test-d.ts +2 -1
- package/src/client/internal/Fetch.test.ts +3 -1
- package/src/client/internal/Fetch.ts +1 -1
- package/src/discovery/Discovery.test.ts +152 -0
- package/src/discovery/Discovery.ts +72 -0
- package/src/discovery/OpenApi.test.ts +425 -0
- package/src/discovery/OpenApi.ts +224 -0
- package/src/discovery/Validate.test.ts +188 -0
- package/src/discovery/Validate.ts +76 -0
- package/src/discovery/index.ts +3 -0
- package/src/internal/constantTimeEqual.test.ts +2 -1
- package/src/internal/types.ts +1 -3
- package/src/mcp-sdk/client/McpClient.test-d.ts +2 -1
- package/src/mcp-sdk/client/McpClient.test.ts +2 -1
- package/src/mcp-sdk/client/McpClient.ts +2 -0
- package/src/mcp-sdk/server/Transport.test.ts +2 -1
- package/src/mcp-sdk/server/Transport.ts +1 -0
- package/src/middlewares/elysia.test.ts +28 -2
- package/src/middlewares/elysia.ts +36 -1
- package/src/middlewares/express.test.ts +95 -7
- package/src/middlewares/express.ts +40 -2
- package/src/middlewares/hono.test.ts +28 -6
- package/src/middlewares/hono.ts +74 -1
- package/src/middlewares/internal/mppx.test.ts +2 -1
- package/src/middlewares/internal/mppx.ts +14 -6
- package/src/middlewares/nextjs.test.ts +32 -6
- package/src/middlewares/nextjs.ts +28 -0
- package/src/proxy/Proxy.test.ts +55 -270
- package/src/proxy/Proxy.ts +73 -93
- package/src/proxy/Service.test.ts +24 -1
- package/src/proxy/Service.ts +48 -88
- package/src/proxy/internal/Headers.test.ts +2 -1
- package/src/proxy/internal/Route.test.ts +9 -1
- package/src/proxy/internal/Route.ts +1 -1
- package/src/proxy/services/anthropic.test.ts +132 -0
- package/src/proxy/services/anthropic.ts +5 -0
- package/src/proxy/services/openai.test.ts +2 -1
- package/src/proxy/services/openai.ts +6 -4
- package/src/proxy/services/stripe.test.ts +132 -0
- package/src/proxy/services/stripe.ts +6 -4
- package/src/server/Mppx.test-d.ts +1 -1
- package/src/server/Mppx.test.ts +194 -1
- package/src/server/Mppx.ts +38 -19
- package/src/server/NodeListener.test.ts +1 -1
- package/src/server/Request.test.ts +2 -1
- package/src/server/Request.ts +1 -0
- package/src/server/Response.test.ts +2 -1
- package/src/server/Transport.test.ts +2 -1
- package/src/stripe/Charge.integration.test.ts +1 -1
- package/src/stripe/Methods.test.ts +1 -1
- package/src/stripe/Methods.ts +1 -0
- package/src/stripe/client/Charge.test.ts +2 -1
- package/src/stripe/server/Charge.test.ts +2 -1
- package/src/tempo/Attribution.test.ts +2 -1
- package/src/tempo/Methods.test.ts +1 -1
- package/src/tempo/Methods.ts +1 -0
- package/src/tempo/client/ChannelOps.test.ts +7 -3
- package/src/tempo/client/ChannelOps.ts +1 -0
- package/src/tempo/client/Charge.ts +1 -0
- package/src/tempo/client/Session.test.ts +6 -2
- package/src/tempo/client/Session.ts +1 -0
- package/src/tempo/client/SessionManager.test.ts +29 -1
- package/src/tempo/client/SessionManager.ts +2 -1
- package/src/tempo/internal/auto-swap.test.ts +2 -1
- package/src/tempo/internal/auto-swap.ts +1 -0
- package/src/tempo/internal/defaults.test.ts +2 -1
- package/src/tempo/internal/fee-payer.test.ts +2 -1
- package/src/tempo/internal/fee-payer.ts +1 -0
- package/src/tempo/server/Charge.test.ts +2 -1
- package/src/tempo/server/Charge.ts +1 -0
- package/src/tempo/server/Session.test.ts +88 -37
- package/src/tempo/server/Session.ts +26 -8
- package/src/tempo/server/Sse.test.ts +2 -1
- package/src/tempo/server/internal/transport.test.ts +25 -1
- package/src/tempo/server/internal/transport.ts +11 -0
- package/src/tempo/session/Chain.test.ts +6 -2
- package/src/tempo/session/Chain.ts +2 -1
- package/src/tempo/session/Channel.test.ts +2 -1
- package/src/tempo/session/ChannelStore.test.ts +2 -1
- package/src/tempo/session/ChannelStore.ts +1 -0
- package/src/tempo/session/Receipt.test.ts +2 -1
- package/src/tempo/session/Receipt.ts +1 -0
- package/src/tempo/session/Sse.fuzz.test.ts +138 -0
- package/src/tempo/session/Sse.test.ts +2 -1
- package/src/tempo/session/Sse.ts +1 -0
- package/src/tempo/session/Voucher.test.ts +2 -1
- package/src/tempo/session/Voucher.ts +1 -0
- package/src/viem/Account.test.ts +2 -1
- package/src/viem/Client.test.ts +2 -1
- package/src/viem/Client.ts +1 -0
- package/src/zod.test.ts +147 -0
package/src/Store.test.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { describe, expect, test } from '
|
|
1
|
+
import { describe, expect, test } from 'vp/test'
|
|
2
|
+
|
|
2
3
|
import * as Store from './Store.js'
|
|
3
4
|
|
|
4
5
|
const nested = {
|
|
@@ -7,16 +8,16 @@ const nested = {
|
|
|
7
8
|
meta: { active: true, tags: ['a', 'b'] },
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
function fakeKv()
|
|
11
|
+
function fakeKv() {
|
|
11
12
|
const map = new Map<string, string>()
|
|
12
13
|
return {
|
|
13
|
-
async get(key) {
|
|
14
|
+
async get(key: string) {
|
|
14
15
|
return map.get(key) ?? null
|
|
15
16
|
},
|
|
16
|
-
async put(key, value) {
|
|
17
|
+
async put(key: string, value: string) {
|
|
17
18
|
map.set(key, value)
|
|
18
19
|
},
|
|
19
|
-
async delete(key) {
|
|
20
|
+
async delete(key: string) {
|
|
20
21
|
map.delete(key)
|
|
21
22
|
},
|
|
22
23
|
}
|
|
@@ -25,6 +26,17 @@ function fakeKv(): Store.cloudflare.Parameters {
|
|
|
25
26
|
describe.each([
|
|
26
27
|
{ label: 'memory', create: () => Store.memory() },
|
|
27
28
|
{ label: 'cloudflare', create: () => Store.cloudflare(fakeKv()) },
|
|
29
|
+
{
|
|
30
|
+
label: 'redis',
|
|
31
|
+
create: () => {
|
|
32
|
+
const kv = fakeKv()
|
|
33
|
+
return Store.redis({
|
|
34
|
+
get: kv.get,
|
|
35
|
+
set: kv.put,
|
|
36
|
+
del: (key) => kv.delete(key),
|
|
37
|
+
})
|
|
38
|
+
},
|
|
39
|
+
},
|
|
28
40
|
{
|
|
29
41
|
label: 'upstash',
|
|
30
42
|
create: () => {
|
|
@@ -64,6 +76,20 @@ describe.each([
|
|
|
64
76
|
})
|
|
65
77
|
|
|
66
78
|
describe('json roundtrip behavior', () => {
|
|
79
|
+
test('cloudflare json-roundtrips nested objects', async () => {
|
|
80
|
+
const store = Store.cloudflare(fakeKv())
|
|
81
|
+
const value = { a: [1, { b: 'c' }], d: null }
|
|
82
|
+
await store.put('k', value)
|
|
83
|
+
expect(await store.get('k')).toEqual(value)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('cloudflare roundtrips BigInt values', async () => {
|
|
87
|
+
const store = Store.cloudflare(fakeKv())
|
|
88
|
+
const value = { amount: 1000000000000000000n, nested: { big: 42n } }
|
|
89
|
+
await store.put('k', value)
|
|
90
|
+
expect(await store.get('k')).toEqual(value)
|
|
91
|
+
})
|
|
92
|
+
|
|
67
93
|
test('memory json-roundtrips nested objects', async () => {
|
|
68
94
|
const store = Store.memory()
|
|
69
95
|
const value = { a: [1, { b: 'c' }], d: null }
|
|
@@ -71,13 +97,37 @@ describe('json roundtrip behavior', () => {
|
|
|
71
97
|
expect(await store.get('k')).toEqual(value)
|
|
72
98
|
})
|
|
73
99
|
|
|
74
|
-
test('
|
|
75
|
-
const store = Store.
|
|
100
|
+
test('memory roundtrips BigInt values', async () => {
|
|
101
|
+
const store = Store.memory()
|
|
102
|
+
const value = { amount: 1000000000000000000n, nested: { big: 42n } }
|
|
103
|
+
await store.put('k', value)
|
|
104
|
+
expect(await store.get('k')).toEqual(value)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('redis json-roundtrips nested objects', async () => {
|
|
108
|
+
const kv = fakeKv()
|
|
109
|
+
const store = Store.redis({
|
|
110
|
+
get: kv.get,
|
|
111
|
+
set: kv.put,
|
|
112
|
+
del: (key) => kv.delete(key),
|
|
113
|
+
})
|
|
76
114
|
const value = { a: [1, { b: 'c' }], d: null }
|
|
77
115
|
await store.put('k', value)
|
|
78
116
|
expect(await store.get('k')).toEqual(value)
|
|
79
117
|
})
|
|
80
118
|
|
|
119
|
+
test('redis roundtrips BigInt values', async () => {
|
|
120
|
+
const kv = fakeKv()
|
|
121
|
+
const store = Store.redis({
|
|
122
|
+
get: kv.get,
|
|
123
|
+
set: kv.put,
|
|
124
|
+
del: (key) => kv.delete(key),
|
|
125
|
+
})
|
|
126
|
+
const value = { amount: 1000000000000000000n, nested: { big: 42n } }
|
|
127
|
+
await store.put('k', value)
|
|
128
|
+
expect(await store.get('k')).toEqual(value)
|
|
129
|
+
})
|
|
130
|
+
|
|
81
131
|
test('upstash passes values through without json serialization', async () => {
|
|
82
132
|
const kv = fakeKv()
|
|
83
133
|
const store = Store.upstash({
|
package/src/Store.ts
CHANGED
|
@@ -62,6 +62,31 @@ export function memory(): Store {
|
|
|
62
62
|
})
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/** Wraps a standard Redis client (ioredis, node-redis, Valkey). */
|
|
66
|
+
export function redis(client: redis.Parameters): Store {
|
|
67
|
+
return from({
|
|
68
|
+
async get(key) {
|
|
69
|
+
const raw = await client.get(key)
|
|
70
|
+
if (raw == null) return null as any
|
|
71
|
+
return Json.parse(raw)
|
|
72
|
+
},
|
|
73
|
+
async put(key, value) {
|
|
74
|
+
await client.set(key, Json.stringify(value))
|
|
75
|
+
},
|
|
76
|
+
async delete(key) {
|
|
77
|
+
await client.del(key)
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export declare namespace redis {
|
|
83
|
+
export type Parameters = {
|
|
84
|
+
get: (key: string) => Promise<string | null>
|
|
85
|
+
set: (key: string, value: string) => Promise<unknown>
|
|
86
|
+
del: (key: string) => Promise<unknown>
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
65
90
|
/** Wraps an Upstash Redis instance (e.g. Vercel KV). */
|
|
66
91
|
export function upstash(redis: upstash.Parameters): Store {
|
|
67
92
|
return from({
|
package/src/cli/account.ts
CHANGED
|
@@ -55,50 +55,85 @@ export function createKeychain(account = 'main') {
|
|
|
55
55
|
async list(): Promise<string[]> {
|
|
56
56
|
const platform = os.platform()
|
|
57
57
|
if (platform === 'darwin') {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
const { stdout, error } = await execCommand('security', ['dump-keychain'])
|
|
59
|
+
if (error) return []
|
|
60
|
+
const accounts: string[] = []
|
|
61
|
+
const blocks = stdout.split('keychain:')
|
|
62
|
+
for (const block of blocks) {
|
|
63
|
+
const serviceMatch = block.match(/"svce"<blob>="([^"]*)"/)
|
|
64
|
+
const accountMatch = block.match(/"acct"<blob>="([^"]*)"/)
|
|
65
|
+
if (serviceMatch?.[1] === service && accountMatch?.[1]) accounts.push(accountMatch[1])
|
|
66
|
+
}
|
|
67
|
+
return accounts
|
|
68
68
|
}
|
|
69
69
|
if (platform === 'linux') {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
const { stdout, stderr, error } = await execCommand('secret-tool', [
|
|
71
|
+
'search',
|
|
72
|
+
'--all',
|
|
73
|
+
'--unlock',
|
|
74
|
+
'service',
|
|
75
|
+
service,
|
|
76
|
+
])
|
|
77
|
+
if (error) return []
|
|
78
|
+
const combined = `${stdout}\n${stderr}`
|
|
79
|
+
const accounts: string[] = []
|
|
80
|
+
const matches = combined.matchAll(/\baccount = (.+)/g)
|
|
81
|
+
for (const match of matches) if (match[1]) accounts.push(match[1])
|
|
82
|
+
return accounts
|
|
77
83
|
}
|
|
78
84
|
throw new Error(`Unsupported platform: ${platform}`)
|
|
79
85
|
},
|
|
80
86
|
async get(): Promise<string | undefined> {
|
|
81
87
|
const platform = os.platform()
|
|
82
88
|
if (platform === 'darwin') {
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
const { stdout, error } = await execCommand('security', [
|
|
90
|
+
'find-generic-password',
|
|
91
|
+
'-s',
|
|
92
|
+
service,
|
|
93
|
+
'-a',
|
|
94
|
+
account,
|
|
95
|
+
'-w',
|
|
96
|
+
])
|
|
97
|
+
return error ? undefined : stdout
|
|
85
98
|
}
|
|
86
99
|
if (platform === 'linux') {
|
|
87
|
-
|
|
88
|
-
|
|
100
|
+
const { stdout, error } = await execCommand('secret-tool', [
|
|
101
|
+
'lookup',
|
|
102
|
+
'service',
|
|
103
|
+
service,
|
|
104
|
+
'account',
|
|
105
|
+
account,
|
|
106
|
+
])
|
|
107
|
+
return error ? undefined : stdout || undefined
|
|
89
108
|
}
|
|
90
109
|
throw new Error(`Unsupported platform: ${platform}`)
|
|
91
110
|
},
|
|
92
111
|
async set(value: string): Promise<void> {
|
|
93
112
|
const platform = os.platform()
|
|
94
113
|
if (platform === 'darwin') {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
114
|
+
await execCommand('security', ['delete-generic-password', '-s', service, '-a', account])
|
|
115
|
+
const { error } = await execCommand('security', [
|
|
116
|
+
'add-generic-password',
|
|
117
|
+
'-s',
|
|
118
|
+
service,
|
|
119
|
+
'-a',
|
|
120
|
+
account,
|
|
121
|
+
'-w',
|
|
122
|
+
value,
|
|
123
|
+
])
|
|
124
|
+
if (error) throw error
|
|
125
|
+
return
|
|
99
126
|
}
|
|
100
127
|
if (platform === 'linux') {
|
|
101
|
-
const proc = child.execFile('secret-tool', [
|
|
128
|
+
const proc = child.execFile('secret-tool', [
|
|
129
|
+
'store',
|
|
130
|
+
'--label',
|
|
131
|
+
`${service} ${account}`,
|
|
132
|
+
'service',
|
|
133
|
+
service,
|
|
134
|
+
'account',
|
|
135
|
+
account,
|
|
136
|
+
])
|
|
102
137
|
proc.stdin?.write(value)
|
|
103
138
|
proc.stdin?.end()
|
|
104
139
|
return new Promise((resolve, reject) => {
|
|
@@ -114,12 +149,12 @@ export function createKeychain(account = 'main') {
|
|
|
114
149
|
async delete(): Promise<void> {
|
|
115
150
|
const platform = os.platform()
|
|
116
151
|
if (platform === 'darwin') {
|
|
117
|
-
|
|
118
|
-
|
|
152
|
+
await execCommand('security', ['delete-generic-password', '-s', service, '-a', account])
|
|
153
|
+
return
|
|
119
154
|
}
|
|
120
155
|
if (platform === 'linux') {
|
|
121
|
-
|
|
122
|
-
|
|
156
|
+
await execCommand('secret-tool', ['clear', 'service', service, 'account', account])
|
|
157
|
+
return
|
|
123
158
|
}
|
|
124
159
|
throw new Error(`Unsupported platform: ${platform}`)
|
|
125
160
|
},
|
package/src/cli/cli.test.ts
CHANGED
|
@@ -2,18 +2,20 @@ import { spawnSync } from 'node:child_process'
|
|
|
2
2
|
import * as fs from 'node:fs'
|
|
3
3
|
import * as os from 'node:os'
|
|
4
4
|
import * as path from 'node:path'
|
|
5
|
+
|
|
5
6
|
import { parseUnits } from 'viem'
|
|
6
7
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
7
8
|
import { Addresses } from 'viem/tempo'
|
|
8
|
-
import { afterAll, describe, expect, test } from '
|
|
9
|
+
import { afterAll, describe, expect, test } from 'vp/test'
|
|
9
10
|
import * as Http from '~test/Http.js'
|
|
10
11
|
import { rpcUrl } from '~test/tempo/prool.js'
|
|
11
12
|
import { deployEscrow } from '~test/tempo/session.js'
|
|
12
13
|
import { accounts, asset, client, fundAccount } from '~test/tempo/viem.js'
|
|
14
|
+
|
|
13
15
|
import * as Credential from '../Credential.js'
|
|
14
|
-
import * as Store from '../Store.js'
|
|
15
16
|
import * as Mppx_server from '../server/Mppx.js'
|
|
16
17
|
import { toNodeListener } from '../server/Mppx.js'
|
|
18
|
+
import * as Store from '../Store.js'
|
|
17
19
|
import { stripe as stripe_server } from '../stripe/server/Methods.js'
|
|
18
20
|
import { tempo } from '../tempo/server/Methods.js'
|
|
19
21
|
import type { SessionCredentialPayload } from '../tempo/session/Types.js'
|
|
@@ -74,6 +76,217 @@ async function serve(argv: string[], options?: { env?: Record<string, string | u
|
|
|
74
76
|
return { output, stderr, exitCode }
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
describe('discover validate', () => {
|
|
80
|
+
test('validates a local discovery document', async () => {
|
|
81
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mppx-discovery-'))
|
|
82
|
+
const file = path.join(dir, 'openapi.json')
|
|
83
|
+
fs.writeFileSync(
|
|
84
|
+
file,
|
|
85
|
+
JSON.stringify({
|
|
86
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
87
|
+
openapi: '3.1.0',
|
|
88
|
+
paths: {
|
|
89
|
+
'/search': {
|
|
90
|
+
post: {
|
|
91
|
+
'x-payment-info': {
|
|
92
|
+
amount: '100',
|
|
93
|
+
intent: 'charge',
|
|
94
|
+
method: 'tempo',
|
|
95
|
+
},
|
|
96
|
+
requestBody: {
|
|
97
|
+
content: { 'application/json': { schema: { type: 'object' } } },
|
|
98
|
+
},
|
|
99
|
+
responses: {
|
|
100
|
+
'200': { description: 'OK' },
|
|
101
|
+
'402': { description: 'Payment Required' },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
const { output, exitCode } = await serve(['discover', 'validate', file])
|
|
110
|
+
expect(exitCode).toBeUndefined()
|
|
111
|
+
expect(output).toContain('Discovery document is valid.')
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('returns non-zero for invalid discovery documents', async () => {
|
|
115
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mppx-discovery-'))
|
|
116
|
+
const file = path.join(dir, 'openapi.json')
|
|
117
|
+
fs.writeFileSync(
|
|
118
|
+
file,
|
|
119
|
+
JSON.stringify({
|
|
120
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
121
|
+
openapi: '3.1.0',
|
|
122
|
+
paths: {
|
|
123
|
+
'/search': {
|
|
124
|
+
post: {
|
|
125
|
+
'x-payment-info': {
|
|
126
|
+
amount: '100',
|
|
127
|
+
intent: 'charge',
|
|
128
|
+
method: 'tempo',
|
|
129
|
+
},
|
|
130
|
+
responses: {
|
|
131
|
+
'200': { description: 'OK' },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
}),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
const { output, exitCode } = await serve(['discover', 'validate', file])
|
|
140
|
+
expect(exitCode).toBe(1)
|
|
141
|
+
expect(output).toContain('[error]')
|
|
142
|
+
expect(output).toContain('402')
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test(
|
|
146
|
+
'validates remote discovery documents and reports warnings',
|
|
147
|
+
{ timeout: 20_000 },
|
|
148
|
+
async () => {
|
|
149
|
+
const body = JSON.stringify({
|
|
150
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
151
|
+
openapi: '3.1.0',
|
|
152
|
+
paths: {
|
|
153
|
+
'/search': {
|
|
154
|
+
post: {
|
|
155
|
+
'x-payment-info': {
|
|
156
|
+
amount: '100',
|
|
157
|
+
intent: 'charge',
|
|
158
|
+
method: 'tempo',
|
|
159
|
+
},
|
|
160
|
+
responses: {
|
|
161
|
+
'200': { description: 'OK' },
|
|
162
|
+
'402': { description: 'Payment Required' },
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
const server = await Http.createServer((_req, res) => {
|
|
169
|
+
res.setHeader('Content-Type', 'application/json')
|
|
170
|
+
res.end(body)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const { output, exitCode } = await serve(['discover', 'validate', server.url])
|
|
175
|
+
expect(exitCode).toBeUndefined()
|
|
176
|
+
expect(output).toContain('[warning]')
|
|
177
|
+
expect(output).toContain('requestBody')
|
|
178
|
+
expect(output).toContain('valid with 1 warning')
|
|
179
|
+
} finally {
|
|
180
|
+
server.close()
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
test(
|
|
186
|
+
'rejects oversized discovery documents via content-length',
|
|
187
|
+
{ timeout: 20_000 },
|
|
188
|
+
async () => {
|
|
189
|
+
const server = await Http.createServer((_req, res) => {
|
|
190
|
+
res.setHeader('Content-Type', 'application/json')
|
|
191
|
+
res.setHeader('Content-Length', String(11 * 1024 * 1024))
|
|
192
|
+
res.end('{}')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const { exitCode, output } = await serve(['discover', 'validate', server.url])
|
|
197
|
+
expect(exitCode).toBe(1)
|
|
198
|
+
expect(output).toContain('10 MB')
|
|
199
|
+
} finally {
|
|
200
|
+
server.close()
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
)
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
describe('discover generate', () => {
|
|
207
|
+
test('generates from a pre-built OpenAPI document module', async () => {
|
|
208
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mppx-generate-'))
|
|
209
|
+
const mod = path.join(dir, 'doc.mjs')
|
|
210
|
+
fs.writeFileSync(
|
|
211
|
+
mod,
|
|
212
|
+
`export default ${JSON.stringify({
|
|
213
|
+
openapi: '3.1.0',
|
|
214
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
215
|
+
paths: {
|
|
216
|
+
'/pay': {
|
|
217
|
+
post: {
|
|
218
|
+
'x-payment-info': { amount: '100', intent: 'charge', method: 'tempo' },
|
|
219
|
+
responses: {
|
|
220
|
+
'200': { description: 'OK' },
|
|
221
|
+
'402': { description: 'Payment Required' },
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
})}`,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
const { output, exitCode } = await serve(['discover', 'generate', mod])
|
|
230
|
+
expect(exitCode).toBeUndefined()
|
|
231
|
+
const doc = JSON.parse(output)
|
|
232
|
+
expect(doc.openapi).toBe('3.1.0')
|
|
233
|
+
expect(doc.paths['/pay'].post['x-payment-info'].amount).toBe('100')
|
|
234
|
+
|
|
235
|
+
fs.rmSync(dir, { recursive: true, force: true })
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
test('writes to file with --output', async () => {
|
|
239
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mppx-generate-'))
|
|
240
|
+
const mod = path.join(dir, 'doc.mjs')
|
|
241
|
+
const outFile = path.join(dir, 'openapi.json')
|
|
242
|
+
fs.writeFileSync(
|
|
243
|
+
mod,
|
|
244
|
+
`export default ${JSON.stringify({
|
|
245
|
+
openapi: '3.1.0',
|
|
246
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
247
|
+
paths: {},
|
|
248
|
+
})}`,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
const { output, stderr, exitCode } = await serve([
|
|
252
|
+
'discover',
|
|
253
|
+
'generate',
|
|
254
|
+
mod,
|
|
255
|
+
'--output',
|
|
256
|
+
outFile,
|
|
257
|
+
])
|
|
258
|
+
expect(exitCode).toBeUndefined()
|
|
259
|
+
expect(output).toBe('')
|
|
260
|
+
expect(stderr).toContain(outFile)
|
|
261
|
+
const written = JSON.parse(fs.readFileSync(outFile, 'utf-8'))
|
|
262
|
+
expect(written.openapi).toBe('3.1.0')
|
|
263
|
+
|
|
264
|
+
fs.rmSync(dir, { recursive: true, force: true })
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
test('errors when module not found', async () => {
|
|
268
|
+
const { output, exitCode } = await serve([
|
|
269
|
+
'discover',
|
|
270
|
+
'generate',
|
|
271
|
+
'/tmp/nonexistent-mppx-module.mjs',
|
|
272
|
+
])
|
|
273
|
+
expect(exitCode).toBe(1)
|
|
274
|
+
expect(output).toContain('MODULE_NOT_FOUND')
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
test('errors when module has no mppx or openapi export', async () => {
|
|
278
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mppx-generate-'))
|
|
279
|
+
const mod = path.join(dir, 'bad.mjs')
|
|
280
|
+
fs.writeFileSync(mod, 'export default { foo: "bar" }')
|
|
281
|
+
|
|
282
|
+
const { output, exitCode } = await serve(['discover', 'generate', mod])
|
|
283
|
+
expect(exitCode).toBe(1)
|
|
284
|
+
expect(output).toContain('INVALID_MODULE')
|
|
285
|
+
|
|
286
|
+
fs.rmSync(dir, { recursive: true, force: true })
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
77
290
|
describe('basic charge (examples/basic)', () => {
|
|
78
291
|
test('happy path: makes payment and receives response', { timeout: 120_000 }, async () => {
|
|
79
292
|
const { Actions } = await import('viem/tempo')
|