@calimero-network/registry-cli 1.5.0 → 1.5.2
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/dist/index.js +386 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command } from 'commander';
|
|
|
3
3
|
import chalk6 from 'chalk';
|
|
4
4
|
import ora6 from 'ora';
|
|
5
5
|
import { table } from 'table';
|
|
6
|
-
import
|
|
6
|
+
import axios from 'axios';
|
|
7
7
|
import fs3, { existsSync, writeFileSync } from 'fs';
|
|
8
8
|
import path7 from 'path';
|
|
9
9
|
import os from 'os';
|
|
@@ -12,6 +12,391 @@ import fastify from 'fastify';
|
|
|
12
12
|
import cors from '@fastify/cors';
|
|
13
13
|
import * as tar from 'tar';
|
|
14
14
|
|
|
15
|
+
var SSAppRegistryClient = class {
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new SSApp Registry client instance.
|
|
18
|
+
*
|
|
19
|
+
* @param config - Configuration options for the client
|
|
20
|
+
* @param config.baseURL - Base URL for the API (default: 'http://localhost:8082')
|
|
21
|
+
* @param config.timeout - Request timeout in milliseconds (default: 10000)
|
|
22
|
+
* @param config.headers - Additional headers to include in requests
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Basic configuration
|
|
27
|
+
* const client = new SSAppRegistryClient();
|
|
28
|
+
*
|
|
29
|
+
* // Custom configuration
|
|
30
|
+
* const client = new SSAppRegistryClient({
|
|
31
|
+
* baseURL: 'https://api.calimero.network',
|
|
32
|
+
* timeout: 30000,
|
|
33
|
+
* headers: {
|
|
34
|
+
* 'Authorization': 'Bearer token',
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
constructor(config = {}) {
|
|
40
|
+
this.api = axios.create({
|
|
41
|
+
baseURL: config.baseURL || "http://localhost:8082",
|
|
42
|
+
timeout: config.timeout || 1e4,
|
|
43
|
+
headers: {
|
|
44
|
+
"Content-Type": "application/json",
|
|
45
|
+
...config.headers
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
this.api.interceptors.response.use(
|
|
49
|
+
(response) => response,
|
|
50
|
+
(error) => {
|
|
51
|
+
const apiError = {
|
|
52
|
+
message: error.response?.data?.message || error.message,
|
|
53
|
+
code: error.response?.data?.code,
|
|
54
|
+
details: error.response?.data?.details
|
|
55
|
+
};
|
|
56
|
+
return Promise.reject(apiError);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Retrieves a list of all applications with optional filtering.
|
|
62
|
+
*
|
|
63
|
+
* @param params - Optional filtering parameters
|
|
64
|
+
* @param params.dev - Filter by developer public key
|
|
65
|
+
* @param params.name - Filter by application name (partial match)
|
|
66
|
+
* @returns Promise resolving to an array of application summaries
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* // Get all applications
|
|
71
|
+
* const allApps = await client.getApps();
|
|
72
|
+
*
|
|
73
|
+
* // Filter by developer
|
|
74
|
+
* const devApps = await client.getApps({ dev: 'ed25519:abc123...' });
|
|
75
|
+
*
|
|
76
|
+
* // Filter by name
|
|
77
|
+
* const walletApps = await client.getApps({ name: 'wallet' });
|
|
78
|
+
*
|
|
79
|
+
* // Filter by both
|
|
80
|
+
* const filteredApps = await client.getApps({
|
|
81
|
+
* dev: 'ed25519:abc123...',
|
|
82
|
+
* name: 'wallet'
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @throws {ApiError} When the API request fails
|
|
87
|
+
*/
|
|
88
|
+
async getApps(params) {
|
|
89
|
+
const response = await this.api.get("/apps", { params });
|
|
90
|
+
return response.data;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Retrieves all versions of a specific application.
|
|
94
|
+
*
|
|
95
|
+
* @param pubkey - Developer's public key (Ed25519 format)
|
|
96
|
+
* @param appName - Name of the application
|
|
97
|
+
* @returns Promise resolving to an array of version information
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const versions = await client.getAppVersions(
|
|
102
|
+
* 'ed25519:abc123...',
|
|
103
|
+
* 'my-wallet-app'
|
|
104
|
+
* );
|
|
105
|
+
*
|
|
106
|
+
* versions.forEach(version => {
|
|
107
|
+
* console.log(`Version ${version.semver}: ${version.cid}`);
|
|
108
|
+
* if (version.yanked) {
|
|
109
|
+
* console.log(' ⚠️ This version has been yanked');
|
|
110
|
+
* }
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @throws {ApiError} When the application is not found or request fails
|
|
115
|
+
*/
|
|
116
|
+
async getAppVersions(appId) {
|
|
117
|
+
const response = await this.api.get(`/apps/${appId}`);
|
|
118
|
+
return response.data;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Retrieves the complete manifest for a specific application version.
|
|
122
|
+
*
|
|
123
|
+
* @param appId - Unique application identifier
|
|
124
|
+
* @param semver - Semantic version (e.g., '1.0.0', '2.1.3')
|
|
125
|
+
* @returns Promise resolving to the application manifest
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const manifest = await client.getAppManifest('my-wallet-app', '1.2.0');
|
|
130
|
+
*
|
|
131
|
+
* console.log(`App: ${manifest.app.name}`);
|
|
132
|
+
* console.log(`Version: ${manifest.version.semver}`);
|
|
133
|
+
* console.log(`Supported chains: ${manifest.supported_chains.join(', ')}`);
|
|
134
|
+
*
|
|
135
|
+
* // Check permissions
|
|
136
|
+
* manifest.permissions.forEach(perm => {
|
|
137
|
+
* console.log(`Permission: ${perm.cap} (${perm.bytes} bytes)`);
|
|
138
|
+
* });
|
|
139
|
+
*
|
|
140
|
+
* // List artifacts
|
|
141
|
+
* manifest.artifacts.forEach(artifact => {
|
|
142
|
+
* console.log(`Artifact: ${artifact.type} -> ${artifact.cid}`);
|
|
143
|
+
* });
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @throws {ApiError} When the manifest is not found or request fails
|
|
147
|
+
*/
|
|
148
|
+
async getAppManifest(appId, semver) {
|
|
149
|
+
const response = await this.api.get(`/apps/${appId}/${semver}`);
|
|
150
|
+
return response.data;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Retrieves developer profile information.
|
|
154
|
+
*
|
|
155
|
+
* @param pubkey - Developer's public key (Ed25519 format)
|
|
156
|
+
* @returns Promise resolving to the developer profile
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const profile = await client.getDeveloper('ed25519:abc123...');
|
|
161
|
+
*
|
|
162
|
+
* console.log(`Developer: ${profile.display_name}`);
|
|
163
|
+
* if (profile.website) {
|
|
164
|
+
* console.log(`Website: ${profile.website}`);
|
|
165
|
+
* }
|
|
166
|
+
*
|
|
167
|
+
* // Check verification proofs
|
|
168
|
+
* profile.proofs.forEach(proof => {
|
|
169
|
+
* const status = proof.verified ? '✅' : '❌';
|
|
170
|
+
* console.log(`${status} ${proof.type}: ${proof.value}`);
|
|
171
|
+
* });
|
|
172
|
+
* ```
|
|
173
|
+
*
|
|
174
|
+
* @throws {ApiError} When the developer is not found or request fails
|
|
175
|
+
*/
|
|
176
|
+
async getDeveloper(pubkey) {
|
|
177
|
+
const response = await this.api.get(`/developers/${pubkey}`);
|
|
178
|
+
return response.data;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Retrieves attestation information for a specific application version.
|
|
182
|
+
*
|
|
183
|
+
* @param pubkey - Developer's public key (Ed25519 format)
|
|
184
|
+
* @param appName - Name of the application
|
|
185
|
+
* @param semver - Semantic version (e.g., '1.0.0', '2.1.3')
|
|
186
|
+
* @returns Promise resolving to the attestation information
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const attestation = await client.getAttestation(
|
|
191
|
+
* 'ed25519:abc123...',
|
|
192
|
+
* 'my-wallet-app',
|
|
193
|
+
* '1.2.0'
|
|
194
|
+
* );
|
|
195
|
+
*
|
|
196
|
+
* console.log(`Status: ${attestation.status}`);
|
|
197
|
+
* console.log(`Timestamp: ${attestation.timestamp}`);
|
|
198
|
+
* if (attestation.comment) {
|
|
199
|
+
* console.log(`Comment: ${attestation.comment}`);
|
|
200
|
+
* }
|
|
201
|
+
*
|
|
202
|
+
* // Check status
|
|
203
|
+
* switch (attestation.status) {
|
|
204
|
+
* case 'ok':
|
|
205
|
+
* console.log('✅ Application is verified and safe');
|
|
206
|
+
* break;
|
|
207
|
+
* case 'yanked':
|
|
208
|
+
* console.log('⚠️ Application has been yanked');
|
|
209
|
+
* break;
|
|
210
|
+
* case 'tested':
|
|
211
|
+
* console.log('🧪 Application is in testing phase');
|
|
212
|
+
* break;
|
|
213
|
+
* }
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* @throws {ApiError} When the attestation is not found or request fails
|
|
217
|
+
*/
|
|
218
|
+
async getAttestation(pubkey, appName, semver) {
|
|
219
|
+
const response = await this.api.get(
|
|
220
|
+
`/attestations/${pubkey}/${appName}/${semver}`
|
|
221
|
+
);
|
|
222
|
+
return response.data;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Submits a new application manifest to the registry.
|
|
226
|
+
*
|
|
227
|
+
* @param manifest - Complete application manifest with signature
|
|
228
|
+
* @returns Promise resolving to submission result
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```typescript
|
|
232
|
+
* const manifest: AppManifest = {
|
|
233
|
+
* manifest_version: '1.0.0',
|
|
234
|
+
* app: {
|
|
235
|
+
* name: 'my-wallet-app',
|
|
236
|
+
* developer_pubkey: 'ed25519:abc123...',
|
|
237
|
+
* id: 'unique-app-id',
|
|
238
|
+
* alias: 'My Wallet',
|
|
239
|
+
* },
|
|
240
|
+
* version: {
|
|
241
|
+
* semver: '1.0.0',
|
|
242
|
+
* },
|
|
243
|
+
* supported_chains: ['mainnet', 'testnet'],
|
|
244
|
+
* permissions: [
|
|
245
|
+
* { cap: 'wallet', bytes: 1024 },
|
|
246
|
+
* { cap: 'network', bytes: 512 },
|
|
247
|
+
* ],
|
|
248
|
+
* artifacts: [
|
|
249
|
+
* {
|
|
250
|
+
* type: 'wasm',
|
|
251
|
+
* target: 'browser',
|
|
252
|
+
* cid: 'QmHash...',
|
|
253
|
+
* size: 1024000,
|
|
254
|
+
* },
|
|
255
|
+
* ],
|
|
256
|
+
* metadata: {
|
|
257
|
+
* description: 'A secure wallet application',
|
|
258
|
+
* author: 'John Doe',
|
|
259
|
+
* },
|
|
260
|
+
* distribution: 'ipfs',
|
|
261
|
+
* signature: {
|
|
262
|
+
* alg: 'ed25519',
|
|
263
|
+
* sig: 'signature...',
|
|
264
|
+
* signed_at: '2024-01-01T00:00:00Z',
|
|
265
|
+
* },
|
|
266
|
+
* };
|
|
267
|
+
*
|
|
268
|
+
* const result = await client.submitAppManifest(manifest);
|
|
269
|
+
*
|
|
270
|
+
* if (result.success) {
|
|
271
|
+
* console.log('✅ Manifest submitted successfully');
|
|
272
|
+
* console.log(result.message);
|
|
273
|
+
* } else {
|
|
274
|
+
* console.log('❌ Submission failed');
|
|
275
|
+
* console.log(result.message);
|
|
276
|
+
* }
|
|
277
|
+
* ```
|
|
278
|
+
*
|
|
279
|
+
* @throws {ApiError} When the submission fails (validation errors, etc.)
|
|
280
|
+
*/
|
|
281
|
+
async submitAppManifest(manifest) {
|
|
282
|
+
const response = await this.api.post("/apps", manifest);
|
|
283
|
+
return response.data;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Submits or updates developer profile information.
|
|
287
|
+
*
|
|
288
|
+
* @param pubkey - Developer's public key (Ed25519 format)
|
|
289
|
+
* @param profile - Developer profile information
|
|
290
|
+
* @returns Promise resolving to submission result
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* const profile: DeveloperProfile = {
|
|
295
|
+
* display_name: 'John Doe',
|
|
296
|
+
* website: 'https://johndoe.dev',
|
|
297
|
+
* proofs: [
|
|
298
|
+
* {
|
|
299
|
+
* type: 'github',
|
|
300
|
+
* value: 'johndoe',
|
|
301
|
+
* verified: true,
|
|
302
|
+
* },
|
|
303
|
+
* {
|
|
304
|
+
* type: 'twitter',
|
|
305
|
+
* value: '@johndoe',
|
|
306
|
+
* verified: false,
|
|
307
|
+
* },
|
|
308
|
+
* ],
|
|
309
|
+
* };
|
|
310
|
+
*
|
|
311
|
+
* const result = await client.submitDeveloperProfile(
|
|
312
|
+
* 'ed25519:abc123...',
|
|
313
|
+
* profile
|
|
314
|
+
* );
|
|
315
|
+
*
|
|
316
|
+
* if (result.success) {
|
|
317
|
+
* console.log('✅ Profile submitted successfully');
|
|
318
|
+
* } else {
|
|
319
|
+
* console.log('❌ Submission failed:', result.message);
|
|
320
|
+
* }
|
|
321
|
+
* ```
|
|
322
|
+
*
|
|
323
|
+
* @throws {ApiError} When the submission fails (validation errors, etc.)
|
|
324
|
+
*/
|
|
325
|
+
async submitDeveloperProfile(pubkey, profile) {
|
|
326
|
+
const response = await this.api.post("/developers", {
|
|
327
|
+
pubkey,
|
|
328
|
+
...profile
|
|
329
|
+
});
|
|
330
|
+
return response.data;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Submits an attestation for a specific application version.
|
|
334
|
+
*
|
|
335
|
+
* @param pubkey - Developer's public key (Ed25519 format)
|
|
336
|
+
* @param appName - Name of the application
|
|
337
|
+
* @param semver - Semantic version (e.g., '1.0.0', '2.1.3')
|
|
338
|
+
* @param attestation - Attestation information
|
|
339
|
+
* @returns Promise resolving to submission result
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* ```typescript
|
|
343
|
+
* const attestation: Attestation = {
|
|
344
|
+
* status: 'ok',
|
|
345
|
+
* comment: 'Passed security audit and functionality testing',
|
|
346
|
+
* timestamp: new Date().toISOString(),
|
|
347
|
+
* };
|
|
348
|
+
*
|
|
349
|
+
* const result = await client.submitAttestation(
|
|
350
|
+
* 'ed25519:abc123...',
|
|
351
|
+
* 'my-wallet-app',
|
|
352
|
+
* '1.2.0',
|
|
353
|
+
* attestation
|
|
354
|
+
* );
|
|
355
|
+
*
|
|
356
|
+
* if (result.success) {
|
|
357
|
+
* console.log('✅ Attestation submitted successfully');
|
|
358
|
+
* } else {
|
|
359
|
+
* console.log('❌ Submission failed:', result.message);
|
|
360
|
+
* }
|
|
361
|
+
* ```
|
|
362
|
+
*
|
|
363
|
+
* @throws {ApiError} When the submission fails (validation errors, etc.)
|
|
364
|
+
*/
|
|
365
|
+
async submitAttestation(pubkey, appName, semver, attestation) {
|
|
366
|
+
const response = await this.api.post(
|
|
367
|
+
`/attestations/${pubkey}/${appName}/${semver}`,
|
|
368
|
+
attestation
|
|
369
|
+
);
|
|
370
|
+
return response.data;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Checks if the API is healthy and responding.
|
|
374
|
+
*
|
|
375
|
+
* @returns Promise resolving to health status
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* try {
|
|
380
|
+
* const health = await client.healthCheck();
|
|
381
|
+
* console.log(`API Status: ${health.status}`);
|
|
382
|
+
*
|
|
383
|
+
* if (health.status === 'ok') {
|
|
384
|
+
* console.log('✅ API is healthy');
|
|
385
|
+
* } else {
|
|
386
|
+
* console.log('⚠️ API has issues');
|
|
387
|
+
* }
|
|
388
|
+
* } catch (error) {
|
|
389
|
+
* console.log('❌ API is not responding');
|
|
390
|
+
* }
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* @throws {ApiError} When the API is not responding
|
|
394
|
+
*/
|
|
395
|
+
async healthCheck() {
|
|
396
|
+
const response = await this.api.get("/healthz");
|
|
397
|
+
return response.data;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
15
400
|
var LocalConfig = class {
|
|
16
401
|
constructor() {
|
|
17
402
|
this.configPath = path7.join(
|