mppx 0.6.17 → 0.6.18
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 +8 -0
- package/dist/cli/cli.d.ts +4 -0
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +230 -10
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/plugins/plugin.d.ts +5 -0
- package/dist/cli/plugins/plugin.d.ts.map +1 -1
- package/dist/cli/plugins/plugin.js.map +1 -1
- package/dist/cli/plugins/stripe.d.ts.map +1 -1
- package/dist/cli/plugins/stripe.js +7 -2
- 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 +69 -9
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/utils.d.ts +10 -2
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +11 -4
- package/dist/cli/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/cli.test.ts +120 -0
- package/src/cli/cli.ts +254 -10
- package/src/cli/mcp.test.ts +3 -0
- package/src/cli/plugins/plugin.ts +9 -1
- package/src/cli/plugins/stripe.ts +7 -0
- package/src/cli/plugins/tempo.ts +83 -12
- package/src/cli/utils.test.ts +12 -1
- package/src/cli/utils.ts +23 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# mppx
|
|
2
2
|
|
|
3
|
+
## 0.6.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d365b41: Added Tempo CLI auto-swap and payment source token options.
|
|
8
|
+
- 9f660c2: Added Tempo CLI network shortcuts and challenge chain mismatch checks.
|
|
9
|
+
- 538c7fb: Added CLI commands for browsing the MPP services registry.
|
|
10
|
+
|
|
3
11
|
## 0.6.17
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/cli/cli.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ declare const cli: Cli.Cli<{
|
|
|
10
10
|
userAgent: string;
|
|
11
11
|
verbose: number;
|
|
12
12
|
account?: string | undefined;
|
|
13
|
+
autoSwap?: boolean | undefined;
|
|
13
14
|
config?: string | undefined;
|
|
14
15
|
data?: string | undefined;
|
|
15
16
|
fail?: boolean | undefined;
|
|
@@ -20,7 +21,10 @@ declare const cli: Cli.Cli<{
|
|
|
20
21
|
location?: boolean | undefined;
|
|
21
22
|
method?: string | undefined;
|
|
22
23
|
methodOpt?: string[] | undefined;
|
|
24
|
+
network?: "mainnet" | "testnet" | undefined;
|
|
25
|
+
payWith?: string | undefined;
|
|
23
26
|
rpcUrl?: string | undefined;
|
|
27
|
+
slippage?: number | undefined;
|
|
24
28
|
};
|
|
25
29
|
};
|
|
26
30
|
}, undefined, undefined>;
|
package/dist/cli/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAa,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAa,MAAM,OAAO,CAAA;AAsLtC,QAAA,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAidP,CAAA;AA82BF,eAAe,GAAG,CAAA"}
|
package/dist/cli/cli.js
CHANGED
|
@@ -32,6 +32,21 @@ const discoveryIssueSchema = z.object({
|
|
|
32
32
|
path: z.string(),
|
|
33
33
|
severity: z.string(),
|
|
34
34
|
});
|
|
35
|
+
const serviceSummarySchema = z.object({
|
|
36
|
+
description: z.string().optional(),
|
|
37
|
+
id: z.string(),
|
|
38
|
+
name: z.string().optional(),
|
|
39
|
+
paidEndpoints: z.number(),
|
|
40
|
+
status: z.string().optional(),
|
|
41
|
+
url: z.string().optional(),
|
|
42
|
+
});
|
|
43
|
+
const serviceEndpointSchema = z.object({
|
|
44
|
+
description: z.string().optional(),
|
|
45
|
+
method: z.string(),
|
|
46
|
+
path: z.string(),
|
|
47
|
+
payment: z.unknown().optional(),
|
|
48
|
+
});
|
|
49
|
+
const servicesRegistryUrl = 'https://mpp.dev/api/services';
|
|
35
50
|
function shouldReturnStructured(c) {
|
|
36
51
|
return c.format === 'json' && c.formatExplicit;
|
|
37
52
|
}
|
|
@@ -46,6 +61,77 @@ function canReadCommandStdin() {
|
|
|
46
61
|
return false;
|
|
47
62
|
return process.stdin.listenerCount('data') === 0 && process.stdin.listenerCount('readable') === 0;
|
|
48
63
|
}
|
|
64
|
+
function getString(value) {
|
|
65
|
+
return typeof value === 'string' ? value : undefined;
|
|
66
|
+
}
|
|
67
|
+
function getEndpoints(service) {
|
|
68
|
+
return Array.isArray(service.endpoints)
|
|
69
|
+
? service.endpoints.filter((endpoint) => typeof endpoint === 'object' && endpoint !== null)
|
|
70
|
+
: [];
|
|
71
|
+
}
|
|
72
|
+
function summarizeService(service) {
|
|
73
|
+
const endpoints = getEndpoints(service);
|
|
74
|
+
return {
|
|
75
|
+
...(getString(service.description) ? { description: getString(service.description) } : {}),
|
|
76
|
+
id: getString(service.id) ?? getString(service.name) ?? 'unknown',
|
|
77
|
+
...(getString(service.name) ? { name: getString(service.name) } : {}),
|
|
78
|
+
paidEndpoints: endpoints.filter((endpoint) => endpoint.payment).length,
|
|
79
|
+
...(getString(service.status) ? { status: getString(service.status) } : {}),
|
|
80
|
+
...(getString(service.serviceUrl) || getString(service.url)
|
|
81
|
+
? { url: getString(service.serviceUrl) ?? getString(service.url) }
|
|
82
|
+
: {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function summarizeEndpoint(endpoint) {
|
|
86
|
+
return {
|
|
87
|
+
...(getString(endpoint.description) ? { description: getString(endpoint.description) } : {}),
|
|
88
|
+
method: getString(endpoint.method) ?? 'GET',
|
|
89
|
+
path: getString(endpoint.path) ?? '/',
|
|
90
|
+
...(endpoint.payment !== undefined ? { payment: endpoint.payment } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function formatPayment(payment) {
|
|
94
|
+
if (!payment)
|
|
95
|
+
return 'free';
|
|
96
|
+
if (typeof payment !== 'object')
|
|
97
|
+
return String(payment);
|
|
98
|
+
const p = payment;
|
|
99
|
+
const amount = getString(p.amount);
|
|
100
|
+
const currency = getString(p.currency);
|
|
101
|
+
const method = getString(p.method);
|
|
102
|
+
const intent = getString(p.intent);
|
|
103
|
+
return [amount, currency, method && intent ? `${method}/${intent}` : (method ?? intent)]
|
|
104
|
+
.filter(Boolean)
|
|
105
|
+
.join(' ');
|
|
106
|
+
}
|
|
107
|
+
async function fetchServicesRegistry() {
|
|
108
|
+
const url = process.env.MPPX_SERVICES_URL ?? servicesRegistryUrl;
|
|
109
|
+
const response = await globalThis.fetch(url);
|
|
110
|
+
if (!response.ok)
|
|
111
|
+
throw new Errors.IncurError({
|
|
112
|
+
code: 'SERVICES_FETCH_FAILED',
|
|
113
|
+
message: `Failed to fetch services registry: HTTP ${response.status}`,
|
|
114
|
+
exitCode: 1,
|
|
115
|
+
});
|
|
116
|
+
const json = (await response.json());
|
|
117
|
+
if (!json ||
|
|
118
|
+
typeof json !== 'object' ||
|
|
119
|
+
!Array.isArray(json.services))
|
|
120
|
+
throw new Errors.IncurError({
|
|
121
|
+
code: 'SERVICES_INVALID',
|
|
122
|
+
message: 'Services registry response did not contain a services array.',
|
|
123
|
+
exitCode: 1,
|
|
124
|
+
});
|
|
125
|
+
return json.services;
|
|
126
|
+
}
|
|
127
|
+
function findService(services, id) {
|
|
128
|
+
const needle = id.toLowerCase();
|
|
129
|
+
return services.find((service) => {
|
|
130
|
+
const serviceId = getString(service.id)?.toLowerCase();
|
|
131
|
+
const serviceName = getString(service.name)?.toLowerCase();
|
|
132
|
+
return serviceId === needle || serviceName === needle;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
49
135
|
const cli = Cli.create('mppx', {
|
|
50
136
|
version: packageJson.version,
|
|
51
137
|
description: 'Make HTTP requests with automatic payment handling',
|
|
@@ -55,6 +141,7 @@ const cli = Cli.create('mppx', {
|
|
|
55
141
|
}),
|
|
56
142
|
options: z.object({
|
|
57
143
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
144
|
+
autoSwap: z.boolean().optional().describe('Auto-swap source tokens into payment currency'),
|
|
58
145
|
config: z.string().optional().describe('Path to config file'),
|
|
59
146
|
confirm: z.boolean().optional().default(false).describe('Show confirmation prompts'),
|
|
60
147
|
data: z.string().optional().describe('Send request body (implies POST unless -X is set)'),
|
|
@@ -75,11 +162,14 @@ const cli = Cli.create('mppx', {
|
|
|
75
162
|
.array(z.string())
|
|
76
163
|
.optional()
|
|
77
164
|
.describe('Method-specific option (key=value, repeatable)'),
|
|
165
|
+
network: z.enum(['mainnet', 'testnet']).optional().describe('Tempo network'),
|
|
166
|
+
payWith: z.string().optional().describe('Source token for Tempo auto-swap'),
|
|
78
167
|
rpcUrl: z
|
|
79
168
|
.string()
|
|
80
169
|
.optional()
|
|
81
170
|
.describe('RPC endpoint, defaults to public RPC for chain (env: MPPX_RPC_URL)'),
|
|
82
171
|
silent: z.boolean().default(false).describe('Silent mode (suppress progress and info)'),
|
|
172
|
+
slippage: z.number().optional().describe('Tempo auto-swap max slippage percentage'),
|
|
83
173
|
userAgent: z
|
|
84
174
|
.string()
|
|
85
175
|
.optional()
|
|
@@ -232,7 +322,14 @@ const cli = Cli.create('mppx', {
|
|
|
232
322
|
if (plugin) {
|
|
233
323
|
pluginResult = await plugin.setup({
|
|
234
324
|
challenge,
|
|
235
|
-
options: {
|
|
325
|
+
options: {
|
|
326
|
+
account: c.options.account,
|
|
327
|
+
autoSwap: c.options.autoSwap,
|
|
328
|
+
network: c.options.network,
|
|
329
|
+
payWith: c.options.payWith,
|
|
330
|
+
rpcUrl: c.options.rpcUrl,
|
|
331
|
+
slippage: c.options.slippage,
|
|
332
|
+
},
|
|
236
333
|
methodOpts: parseMethodOpts(c.options.methodOpt),
|
|
237
334
|
});
|
|
238
335
|
tokenSymbol = pluginResult.tokenSymbol;
|
|
@@ -497,6 +594,7 @@ const account = Cli.create('account', {
|
|
|
497
594
|
description: 'Create new account',
|
|
498
595
|
options: z.object({
|
|
499
596
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
597
|
+
network: z.enum(['mainnet', 'testnet']).optional().describe('Tempo network'),
|
|
500
598
|
rpcUrl: z.string().optional().describe('RPC endpoint (env: MPPX_RPC_URL)'),
|
|
501
599
|
}),
|
|
502
600
|
output: z.object({ address: z.string(), name: z.string() }),
|
|
@@ -546,8 +644,8 @@ const account = Cli.create('account', {
|
|
|
546
644
|
const addrDisplay = explorerUrl
|
|
547
645
|
? link(`${explorerUrl}/address/${acct.address}`, acct.address)
|
|
548
646
|
: acct.address;
|
|
549
|
-
const rpcUrl = resolveRpcUrl(c.options.rpcUrl);
|
|
550
|
-
resolveChain({ rpcUrl })
|
|
647
|
+
const rpcUrl = resolveRpcUrl(c.options.rpcUrl, { network: c.options.network });
|
|
648
|
+
resolveChain({ network: c.options.network, rpcUrl })
|
|
551
649
|
.then((chain) => createClient({ chain, transport: http(rpcUrl) }))
|
|
552
650
|
.then((client) => import('viem/tempo').then(({ Actions }) => Actions.faucet.fund(client, { account: acct }).catch(() => { })));
|
|
553
651
|
return outputResult(c, { address: acct.address, name: resolvedName }, () => {
|
|
@@ -659,6 +757,7 @@ const account = Cli.create('account', {
|
|
|
659
757
|
description: 'Fund account with testnet tokens',
|
|
660
758
|
options: z.object({
|
|
661
759
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
760
|
+
network: z.enum(['mainnet', 'testnet']).optional().describe('Tempo network'),
|
|
662
761
|
rpcUrl: z.string().optional().describe('RPC endpoint (env: MPPX_RPC_URL)'),
|
|
663
762
|
}),
|
|
664
763
|
output: z.object({ account: z.string(), chain: z.string(), transactions: z.array(z.string()) }),
|
|
@@ -679,8 +778,8 @@ const account = Cli.create('account', {
|
|
|
679
778
|
return c.error({ code: 'ACCOUNT_NOT_FOUND', message: 'No account found.', exitCode: 69 });
|
|
680
779
|
}
|
|
681
780
|
const acct = privateKeyToAccount(key);
|
|
682
|
-
const rpcUrl = resolveRpcUrl(c.options.rpcUrl);
|
|
683
|
-
const chain = await resolveChain({ rpcUrl });
|
|
781
|
+
const rpcUrl = resolveRpcUrl(c.options.rpcUrl, { network: c.options.network });
|
|
782
|
+
const chain = await resolveChain({ network: c.options.network, rpcUrl });
|
|
684
783
|
const client = createClient({ chain, transport: http(rpcUrl) });
|
|
685
784
|
if (!structured)
|
|
686
785
|
console.log(`Funding "${accountName}" on ${chainName(chain)}`);
|
|
@@ -797,6 +896,7 @@ const account = Cli.create('account', {
|
|
|
797
896
|
description: 'View account address',
|
|
798
897
|
options: z.object({
|
|
799
898
|
account: z.string().optional().describe('Account name (env: MPPX_ACCOUNT)'),
|
|
899
|
+
network: z.enum(['mainnet', 'testnet']).optional().describe('Tempo network'),
|
|
800
900
|
rpcUrl: z.string().optional().describe('RPC endpoint (env: MPPX_RPC_URL)'),
|
|
801
901
|
}),
|
|
802
902
|
output: accountViewSchema,
|
|
@@ -813,8 +913,8 @@ const account = Cli.create('account', {
|
|
|
813
913
|
});
|
|
814
914
|
}
|
|
815
915
|
const address = tempoEntry.wallet_address;
|
|
816
|
-
const rpcUrl = resolveRpcUrl(c.options.rpcUrl);
|
|
817
|
-
const chain = await resolveChain({ rpcUrl });
|
|
916
|
+
const rpcUrl = resolveRpcUrl(c.options.rpcUrl, { network: c.options.network });
|
|
917
|
+
const chain = await resolveChain({ network: c.options.network, rpcUrl });
|
|
818
918
|
const explorerUrl = chain.blockExplorers?.default?.url;
|
|
819
919
|
const addrDisplay = explorerUrl
|
|
820
920
|
? link(`${explorerUrl}/address/${address}`, address)
|
|
@@ -846,8 +946,8 @@ const account = Cli.create('account', {
|
|
|
846
946
|
return c.error({ code: 'ACCOUNT_NOT_FOUND', message: 'No account found.', exitCode: 69 });
|
|
847
947
|
}
|
|
848
948
|
const acct = privateKeyToAccount(key);
|
|
849
|
-
const rpcUrl = resolveRpcUrl(c.options.rpcUrl);
|
|
850
|
-
const chain = await resolveChain({ rpcUrl });
|
|
949
|
+
const rpcUrl = resolveRpcUrl(c.options.rpcUrl, { network: c.options.network });
|
|
950
|
+
const chain = await resolveChain({ network: c.options.network, rpcUrl });
|
|
851
951
|
const explorerUrl = chain.blockExplorers?.default?.url;
|
|
852
952
|
const addrDisplay = explorerUrl
|
|
853
953
|
? link(`${explorerUrl}/address/${acct.address}`, acct.address)
|
|
@@ -872,14 +972,18 @@ const sign = Cli.create('sign', {
|
|
|
872
972
|
challenge: z.string().optional().describe('WWW-Authenticate challenge value'),
|
|
873
973
|
config: z.string().optional().describe('Path to config file'),
|
|
874
974
|
dryRun: z.boolean().optional().describe('Validate and parse the challenge without signing'),
|
|
975
|
+
autoSwap: z.boolean().optional().describe('Auto-swap source tokens into payment currency'),
|
|
875
976
|
methodOpt: z
|
|
876
977
|
.array(z.string())
|
|
877
978
|
.optional()
|
|
878
979
|
.describe('Method-specific option (key=value, repeatable)'),
|
|
980
|
+
network: z.enum(['mainnet', 'testnet']).optional().describe('Tempo network'),
|
|
981
|
+
payWith: z.string().optional().describe('Source token for Tempo auto-swap'),
|
|
879
982
|
rpcUrl: z
|
|
880
983
|
.string()
|
|
881
984
|
.optional()
|
|
882
985
|
.describe('RPC endpoint, defaults to public RPC for chain (env: MPPX_RPC_URL)'),
|
|
986
|
+
slippage: z.number().optional().describe('Tempo auto-swap max slippage percentage'),
|
|
883
987
|
}),
|
|
884
988
|
output: z.object({ authorization: z.string() }),
|
|
885
989
|
alias: {
|
|
@@ -947,7 +1051,14 @@ const sign = Cli.create('sign', {
|
|
|
947
1051
|
if (plugin) {
|
|
948
1052
|
const result = await plugin.setup({
|
|
949
1053
|
challenge,
|
|
950
|
-
options: {
|
|
1054
|
+
options: {
|
|
1055
|
+
account: c.options.account,
|
|
1056
|
+
autoSwap: c.options.autoSwap,
|
|
1057
|
+
network: c.options.network,
|
|
1058
|
+
payWith: c.options.payWith,
|
|
1059
|
+
rpcUrl: c.options.rpcUrl,
|
|
1060
|
+
slippage: c.options.slippage,
|
|
1061
|
+
},
|
|
951
1062
|
methodOpts,
|
|
952
1063
|
});
|
|
953
1064
|
if (result.createCredential) {
|
|
@@ -1017,6 +1128,114 @@ export default defineConfig({
|
|
|
1017
1128
|
});
|
|
1018
1129
|
},
|
|
1019
1130
|
});
|
|
1131
|
+
const services = Cli.create('services', {
|
|
1132
|
+
description: 'Browse the MPP services registry',
|
|
1133
|
+
})
|
|
1134
|
+
.command('list', {
|
|
1135
|
+
description: 'List registered MPP services',
|
|
1136
|
+
options: z.object({
|
|
1137
|
+
query: z.string().optional().describe('Filter by id, name, category, tag, or description'),
|
|
1138
|
+
}),
|
|
1139
|
+
output: z.object({ services: z.array(serviceSummarySchema) }),
|
|
1140
|
+
alias: { query: 'q' },
|
|
1141
|
+
async run(c) {
|
|
1142
|
+
const query = c.options.query?.toLowerCase();
|
|
1143
|
+
const registry = await fetchServicesRegistry();
|
|
1144
|
+
const filtered = query
|
|
1145
|
+
? registry.filter((service) => [
|
|
1146
|
+
service.id,
|
|
1147
|
+
service.name,
|
|
1148
|
+
service.description,
|
|
1149
|
+
...(Array.isArray(service.categories) ? service.categories : []),
|
|
1150
|
+
...(Array.isArray(service.tags) ? service.tags : []),
|
|
1151
|
+
]
|
|
1152
|
+
.filter((value) => typeof value === 'string')
|
|
1153
|
+
.some((value) => value.toLowerCase().includes(query)))
|
|
1154
|
+
: registry;
|
|
1155
|
+
const summaries = filtered.map(summarizeService).sort((a, b) => a.id.localeCompare(b.id));
|
|
1156
|
+
return outputResult(c, { services: summaries }, () => {
|
|
1157
|
+
if (summaries.length === 0) {
|
|
1158
|
+
console.log('No services found.');
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const idWidth = Math.max(...summaries.map((service) => service.id.length));
|
|
1162
|
+
const paidWidth = Math.max(...summaries.map((service) => String(service.paidEndpoints).length));
|
|
1163
|
+
for (const service of summaries) {
|
|
1164
|
+
const name = service.name && service.name !== service.id ? ` ${service.name}` : '';
|
|
1165
|
+
const url = service.url ? ` ${pc.dim(service.url)}` : '';
|
|
1166
|
+
console.log(`${service.id.padEnd(idWidth)} ${String(service.paidEndpoints).padStart(paidWidth)} paid${name}${url}`);
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
},
|
|
1170
|
+
})
|
|
1171
|
+
.command('show', {
|
|
1172
|
+
description: 'Show one registered MPP service',
|
|
1173
|
+
args: z.object({
|
|
1174
|
+
service: z.string().describe('Service id or name'),
|
|
1175
|
+
}),
|
|
1176
|
+
output: z.object({ service: z.record(z.string(), z.unknown()) }),
|
|
1177
|
+
async run(c) {
|
|
1178
|
+
const registry = await fetchServicesRegistry();
|
|
1179
|
+
const service = findService(registry, c.args.service);
|
|
1180
|
+
if (!service)
|
|
1181
|
+
return c.error({
|
|
1182
|
+
code: 'SERVICE_NOT_FOUND',
|
|
1183
|
+
message: `Service not found: ${c.args.service}`,
|
|
1184
|
+
exitCode: 1,
|
|
1185
|
+
});
|
|
1186
|
+
const summary = summarizeService(service);
|
|
1187
|
+
const endpoints = getEndpoints(service);
|
|
1188
|
+
return outputResult(c, { service }, () => {
|
|
1189
|
+
console.log(`${summary.name ?? summary.id} ${pc.dim(`(${summary.id})`)}`);
|
|
1190
|
+
if (summary.description)
|
|
1191
|
+
console.log(summary.description);
|
|
1192
|
+
if (summary.url)
|
|
1193
|
+
console.log(`${pc.dim('URL')} ${link(summary.url, summary.url)}`);
|
|
1194
|
+
if (summary.status)
|
|
1195
|
+
console.log(`${pc.dim('Status')} ${summary.status}`);
|
|
1196
|
+
console.log(`${pc.dim('Endpoints')} ${endpoints.length} (${summary.paidEndpoints} paid)`);
|
|
1197
|
+
const docs = service.docs;
|
|
1198
|
+
const homepage = docs && getString(docs.homepage);
|
|
1199
|
+
if (homepage)
|
|
1200
|
+
console.log(`${pc.dim('Docs')} ${link(homepage, homepage)}`);
|
|
1201
|
+
});
|
|
1202
|
+
},
|
|
1203
|
+
})
|
|
1204
|
+
.command('endpoints', {
|
|
1205
|
+
description: 'List endpoints for a registered MPP service',
|
|
1206
|
+
args: z.object({
|
|
1207
|
+
service: z.string().describe('Service id or name'),
|
|
1208
|
+
}),
|
|
1209
|
+
output: z.object({
|
|
1210
|
+
endpoints: z.array(serviceEndpointSchema),
|
|
1211
|
+
service: serviceSummarySchema,
|
|
1212
|
+
}),
|
|
1213
|
+
async run(c) {
|
|
1214
|
+
const registry = await fetchServicesRegistry();
|
|
1215
|
+
const service = findService(registry, c.args.service);
|
|
1216
|
+
if (!service)
|
|
1217
|
+
return c.error({
|
|
1218
|
+
code: 'SERVICE_NOT_FOUND',
|
|
1219
|
+
message: `Service not found: ${c.args.service}`,
|
|
1220
|
+
exitCode: 1,
|
|
1221
|
+
});
|
|
1222
|
+
const summary = summarizeService(service);
|
|
1223
|
+
const endpoints = getEndpoints(service).map(summarizeEndpoint);
|
|
1224
|
+
return outputResult(c, { endpoints, service: summary }, () => {
|
|
1225
|
+
if (endpoints.length === 0) {
|
|
1226
|
+
console.log(`No endpoints found for ${summary.id}.`);
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
const methodWidth = Math.max(...endpoints.map((endpoint) => endpoint.method.length));
|
|
1230
|
+
const pathWidth = Math.max(...endpoints.map((endpoint) => endpoint.path.length));
|
|
1231
|
+
for (const endpoint of endpoints) {
|
|
1232
|
+
const payment = formatPayment(endpoint.payment);
|
|
1233
|
+
const description = endpoint.description ? ` ${pc.dim(endpoint.description)}` : '';
|
|
1234
|
+
console.log(`${endpoint.method.padEnd(methodWidth)} ${endpoint.path.padEnd(pathWidth)} ${payment}${description}`);
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
},
|
|
1238
|
+
});
|
|
1020
1239
|
const discover = Cli.create('discover', {
|
|
1021
1240
|
description: 'Discovery tooling',
|
|
1022
1241
|
})
|
|
@@ -1186,6 +1405,7 @@ const discover = Cli.create('discover', {
|
|
|
1186
1405
|
cli.command(account);
|
|
1187
1406
|
cli.command(discover);
|
|
1188
1407
|
cli.command(init);
|
|
1408
|
+
cli.command(services);
|
|
1189
1409
|
cli.command(sign);
|
|
1190
1410
|
export default cli;
|
|
1191
1411
|
//# sourceMappingURL=cli.js.map
|