@calimero-network/registry-cli 1.16.0 → 1.17.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.
package/dist/index.js CHANGED
@@ -1,456 +1,185 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import chalk7 from 'chalk';
3
+ import chalk4 from 'chalk';
4
4
  import { createRequire } from 'module';
5
- import ora7 from 'ora';
6
- import { table } from 'table';
5
+ import ora4 from 'ora';
7
6
  import axios from 'axios';
8
- import fs9, { existsSync, writeFileSync } from 'fs';
9
- import path7 from 'path';
10
- import os from 'os';
11
- import crypto2 from 'crypto';
7
+ import fs7, { existsSync, writeFileSync } from 'fs';
8
+ import path5 from 'path';
9
+ import os2 from 'os';
12
10
  import fastify from 'fastify';
13
11
  import cors from '@fastify/cors';
12
+ import crypto2 from 'crypto';
14
13
  import * as tar from 'tar';
15
14
 
16
- var CalimeroRegistryClient = class {
17
- api;
18
- /**
19
- * Creates a new Calimero Registry client instance.
20
- *
21
- * @param config - Configuration options for the client
22
- * @param config.baseURL - Base URL for the API (default: 'http://localhost:8082')
23
- * @param config.timeout - Request timeout in milliseconds (default: 10000)
24
- * @param config.headers - Additional headers to include in requests
25
- *
26
- * @example
27
- * ```typescript
28
- * // Basic configuration
29
- * const client = new CalimeroRegistryClient();
30
- *
31
- * // Custom configuration
32
- * const client = new CalimeroRegistryClient({
33
- * baseURL: 'https://api.calimero.network',
34
- * timeout: 30000,
35
- * headers: {
36
- * 'Authorization': 'Bearer token',
37
- * },
38
- * });
39
- * ```
40
- */
41
- constructor(config = {}) {
42
- this.api = axios.create({
43
- baseURL: config.baseURL || "http://localhost:8082",
44
- timeout: config.timeout || 1e4,
45
- headers: {
46
- "Content-Type": "application/json",
47
- ...config.headers
48
- }
49
- });
50
- this.api.interceptors.response.use(
51
- (response) => response,
52
- (error) => {
53
- const apiError = {
54
- message: error.response?.data?.message || error.message,
55
- code: error.response?.data?.code,
56
- details: error.response?.data?.details
15
+ var DEFAULT_REGISTRY_URL = "https://apps.calimero.network";
16
+ function defaultConfig() {
17
+ return { registry: { url: DEFAULT_REGISTRY_URL } };
18
+ }
19
+ var RemoteConfig = class {
20
+ configPath;
21
+ config;
22
+ constructor() {
23
+ this.configPath = path5.join(
24
+ os2.homedir(),
25
+ ".calimero-registry",
26
+ "remote-config.json"
27
+ );
28
+ this.config = this.loadConfig();
29
+ }
30
+ loadConfig() {
31
+ const defaults = defaultConfig();
32
+ if (fs7.existsSync(this.configPath)) {
33
+ try {
34
+ const existingConfig = JSON.parse(
35
+ fs7.readFileSync(this.configPath, "utf8")
36
+ );
37
+ return {
38
+ registry: {
39
+ ...defaults.registry,
40
+ ...existingConfig.registry || {}
41
+ }
57
42
  };
58
- return Promise.reject(apiError);
43
+ } catch {
44
+ console.warn("Failed to load existing config, using defaults");
59
45
  }
60
- );
46
+ }
47
+ return defaults;
61
48
  }
62
- /**
63
- * Retrieves a list of all applications with optional filtering.
64
- *
65
- * @param params - Optional filtering parameters
66
- * @param params.dev - Filter by developer public key
67
- * @param params.name - Filter by application name (partial match)
68
- * @returns Promise resolving to an array of application summaries
69
- *
70
- * @example
71
- * ```typescript
72
- * // Get all applications
73
- * const allApps = await client.getApps();
74
- *
75
- * // Filter by developer
76
- * const devApps = await client.getApps({ dev: 'ed25519:abc123...' });
77
- *
78
- * // Filter by name
79
- * const walletApps = await client.getApps({ name: 'wallet' });
80
- *
81
- * // Filter by both
82
- * const filteredApps = await client.getApps({
83
- * dev: 'ed25519:abc123...',
84
- * name: 'wallet'
85
- * });
86
- * ```
87
- *
88
- * @throws {ApiError} When the API request fails
89
- */
90
- async getApps(params) {
91
- const response = await this.api.get("/apps", { params });
92
- return response.data;
49
+ saveConfig() {
50
+ const configDir = path5.dirname(this.configPath);
51
+ if (!fs7.existsSync(configDir)) {
52
+ fs7.mkdirSync(configDir, { recursive: true });
53
+ }
54
+ const configToSave = {
55
+ registry: {
56
+ url: this.config.registry.url,
57
+ // Save API key if it exists in config (regardless of env var)
58
+ ...this.config.registry.apiKey ? { apiKey: this.config.registry.apiKey } : {}
59
+ }
60
+ };
61
+ fs7.writeFileSync(this.configPath, JSON.stringify(configToSave, null, 2));
93
62
  }
94
63
  /**
95
- * Retrieves all versions of a specific application.
96
- *
97
- * @param pubkey - Developer's public key (Ed25519 format)
98
- * @param appName - Name of the application
99
- * @returns Promise resolving to an array of version information
100
- *
101
- * @example
102
- * ```typescript
103
- * const versions = await client.getAppVersions(
104
- * 'ed25519:abc123...',
105
- * 'my-wallet-app'
106
- * );
107
- *
108
- * versions.forEach(version => {
109
- * console.log(`Version ${version.semver}: ${version.cid}`);
110
- * if (version.yanked) {
111
- * console.log(' ⚠️ This version has been yanked');
112
- * }
113
- * });
114
- * ```
115
- *
116
- * @throws {ApiError} When the application is not found or request fails
64
+ * Get registry URL with priority:
65
+ * 1. Environment variable CALIMERO_REGISTRY_URL
66
+ * 2. Config file value
67
+ * 3. Default value
117
68
  */
118
- async getAppVersions(appId) {
119
- const response = await this.api.get(`/apps/${appId}`);
120
- return response.data;
69
+ getRegistryUrl() {
70
+ return process.env.CALIMERO_REGISTRY_URL || this.config.registry.url || DEFAULT_REGISTRY_URL;
121
71
  }
122
72
  /**
123
- * Retrieves the complete manifest for a specific application version.
124
- *
125
- * @param appId - Unique application identifier
126
- * @param semver - Semantic version (e.g., '1.0.0', '2.1.3')
127
- * @returns Promise resolving to the application manifest
128
- *
129
- * @example
130
- * ```typescript
131
- * const manifest = await client.getAppManifest('my-wallet-app', '1.2.0');
132
- *
133
- * console.log(`App: ${manifest.app.name}`);
134
- * console.log(`Version: ${manifest.version.semver}`);
135
- * console.log(`Supported chains: ${manifest.supported_chains.join(', ')}`);
136
- *
137
- * // Check permissions
138
- * manifest.permissions.forEach(perm => {
139
- * console.log(`Permission: ${perm.cap} (${perm.bytes} bytes)`);
140
- * });
141
- *
142
- * // List artifacts
143
- * manifest.artifacts.forEach(artifact => {
144
- * console.log(`Artifact: ${artifact.type} -> ${artifact.cid}`);
145
- * });
146
- * ```
147
- *
148
- * @throws {ApiError} When the manifest is not found or request fails
73
+ * Set registry URL
149
74
  */
150
- async getAppManifest(appId, semver) {
151
- const response = await this.api.get(`/apps/${appId}/${semver}`);
152
- return response.data;
75
+ setRegistryUrl(url) {
76
+ this.config.registry.url = url;
77
+ this.saveConfig();
153
78
  }
154
79
  /**
155
- * Retrieves developer profile information.
156
- *
157
- * @param pubkey - Developer's public key (Ed25519 format)
158
- * @returns Promise resolving to the developer profile
159
- *
160
- * @example
161
- * ```typescript
162
- * const profile = await client.getDeveloper('ed25519:abc123...');
163
- *
164
- * console.log(`Developer: ${profile.display_name}`);
165
- * if (profile.website) {
166
- * console.log(`Website: ${profile.website}`);
167
- * }
168
- *
169
- * // Check verification proofs
170
- * profile.proofs.forEach(proof => {
171
- * const status = proof.verified ? '✅' : '❌';
172
- * console.log(`${status} ${proof.type}: ${proof.value}`);
173
- * });
174
- * ```
175
- *
176
- * @throws {ApiError} When the developer is not found or request fails
80
+ * Get API key with priority:
81
+ * 1. Environment variable CALIMERO_API_KEY
82
+ * 2. Config file value
83
+ * 3. undefined
177
84
  */
178
- async getDeveloper(pubkey) {
179
- const response = await this.api.get(`/developers/${pubkey}`);
180
- return response.data;
85
+ getApiKey() {
86
+ return process.env.CALIMERO_API_KEY || this.config.registry.apiKey;
181
87
  }
182
88
  /**
183
- * Retrieves attestation information for a specific application version.
184
- *
185
- * @param pubkey - Developer's public key (Ed25519 format)
186
- * @param appName - Name of the application
187
- * @param semver - Semantic version (e.g., '1.0.0', '2.1.3')
188
- * @returns Promise resolving to the attestation information
189
- *
190
- * @example
191
- * ```typescript
192
- * const attestation = await client.getAttestation(
193
- * 'ed25519:abc123...',
194
- * 'my-wallet-app',
195
- * '1.2.0'
196
- * );
197
- *
198
- * console.log(`Status: ${attestation.status}`);
199
- * console.log(`Timestamp: ${attestation.timestamp}`);
200
- * if (attestation.comment) {
201
- * console.log(`Comment: ${attestation.comment}`);
202
- * }
203
- *
204
- * // Check status
205
- * switch (attestation.status) {
206
- * case 'ok':
207
- * console.log('✅ Application is verified and safe');
208
- * break;
209
- * case 'yanked':
210
- * console.log('⚠️ Application has been yanked');
211
- * break;
212
- * case 'tested':
213
- * console.log('🧪 Application is in testing phase');
214
- * break;
215
- * }
216
- * ```
217
- *
218
- * @throws {ApiError} When the attestation is not found or request fails
89
+ * Set API key (stored in config file)
219
90
  */
220
- async getAttestation(pubkey, appName, semver) {
221
- const response = await this.api.get(
222
- `/attestations/${pubkey}/${appName}/${semver}`
223
- );
224
- return response.data;
91
+ setApiKey(apiKey) {
92
+ this.config.registry.apiKey = apiKey;
93
+ this.saveConfig();
225
94
  }
226
95
  /**
227
- * Submits a new application manifest to the registry.
228
- *
229
- * @param manifest - Complete application manifest with signature
230
- * @returns Promise resolving to submission result
231
- *
232
- * @example
233
- * ```typescript
234
- * const manifest: AppManifest = {
235
- * manifest_version: '1.0.0',
236
- * app: {
237
- * name: 'my-wallet-app',
238
- * developer_pubkey: 'ed25519:abc123...',
239
- * id: 'unique-app-id',
240
- * alias: 'My Wallet',
241
- * },
242
- * version: {
243
- * semver: '1.0.0',
244
- * },
245
- * supported_chains: ['mainnet', 'testnet'],
246
- * permissions: [
247
- * { cap: 'wallet', bytes: 1024 },
248
- * { cap: 'network', bytes: 512 },
249
- * ],
250
- * artifacts: [
251
- * {
252
- * type: 'wasm',
253
- * target: 'browser',
254
- * cid: 'QmHash...',
255
- * size: 1024000,
256
- * },
257
- * ],
258
- * metadata: {
259
- * description: 'A secure wallet application',
260
- * author: 'John Doe',
261
- * },
262
- * distribution: 'ipfs',
263
- * signature: {
264
- * alg: 'ed25519',
265
- * sig: 'signature...',
266
- * signed_at: '2024-01-01T00:00:00Z',
267
- * },
268
- * };
269
- *
270
- * const result = await client.submitAppManifest(manifest);
271
- *
272
- * if (result.success) {
273
- * console.log('✅ Manifest submitted successfully');
274
- * console.log(result.message);
275
- * } else {
276
- * console.log('❌ Submission failed');
277
- * console.log(result.message);
278
- * }
279
- * ```
280
- *
281
- * @throws {ApiError} When the submission fails (validation errors, etc.)
96
+ * Remove API key from config
282
97
  */
283
- async submitAppManifest(manifest) {
284
- const response = await this.api.post("/apps", manifest);
285
- return response.data;
98
+ removeApiKey() {
99
+ delete this.config.registry.apiKey;
100
+ this.saveConfig();
286
101
  }
287
102
  /**
288
- * Submits or updates developer profile information.
289
- *
290
- * @param pubkey - Developer's public key (Ed25519 format)
291
- * @param profile - Developer profile information
292
- * @returns Promise resolving to submission result
293
- *
294
- * @example
295
- * ```typescript
296
- * const profile: DeveloperProfile = {
297
- * display_name: 'John Doe',
298
- * website: 'https://johndoe.dev',
299
- * proofs: [
300
- * {
301
- * type: 'github',
302
- * value: 'johndoe',
303
- * verified: true,
304
- * },
305
- * {
306
- * type: 'twitter',
307
- * value: '@johndoe',
308
- * verified: false,
309
- * },
310
- * ],
311
- * };
312
- *
313
- * const result = await client.submitDeveloperProfile(
314
- * 'ed25519:abc123...',
315
- * profile
316
- * );
317
- *
318
- * if (result.success) {
319
- * console.log('✅ Profile submitted successfully');
320
- * } else {
321
- * console.log('❌ Submission failed:', result.message);
322
- * }
323
- * ```
324
- *
325
- * @throws {ApiError} When the submission fails (validation errors, etc.)
103
+ * Get full configuration
326
104
  */
327
- async submitDeveloperProfile(pubkey, profile) {
328
- const response = await this.api.post("/developers", {
329
- pubkey,
330
- ...profile
331
- });
332
- return response.data;
105
+ getConfig() {
106
+ return {
107
+ registry: {
108
+ url: this.getRegistryUrl(),
109
+ // Don't expose API key in getConfig (security)
110
+ apiKey: this.getApiKey() ? "***" : void 0
111
+ }
112
+ };
333
113
  }
334
114
  /**
335
- * Submits an attestation for a specific application version.
336
- *
337
- * @param pubkey - Developer's public key (Ed25519 format)
338
- * @param appName - Name of the application
339
- * @param semver - Semantic version (e.g., '1.0.0', '2.1.3')
340
- * @param attestation - Attestation information
341
- * @returns Promise resolving to submission result
342
- *
343
- * @example
344
- * ```typescript
345
- * const attestation: Attestation = {
346
- * status: 'ok',
347
- * comment: 'Passed security audit and functionality testing',
348
- * timestamp: new Date().toISOString(),
349
- * };
350
- *
351
- * const result = await client.submitAttestation(
352
- * 'ed25519:abc123...',
353
- * 'my-wallet-app',
354
- * '1.2.0',
355
- * attestation
356
- * );
357
- *
358
- * if (result.success) {
359
- * console.log('✅ Attestation submitted successfully');
360
- * } else {
361
- * console.log('❌ Submission failed:', result.message);
362
- * }
363
- * ```
364
- *
365
- * @throws {ApiError} When the submission fails (validation errors, etc.)
115
+ * Get config file path
366
116
  */
367
- async submitAttestation(pubkey, appName, semver, attestation) {
368
- const response = await this.api.post(
369
- `/attestations/${pubkey}/${appName}/${semver}`,
370
- attestation
371
- );
372
- return response.data;
117
+ getConfigPath() {
118
+ return this.configPath;
373
119
  }
374
120
  /**
375
- * Checks if the API is healthy and responding.
376
- *
377
- * @returns Promise resolving to health status
378
- *
379
- * @example
380
- * ```typescript
381
- * try {
382
- * const health = await client.healthCheck();
383
- * console.log(`API Status: ${health.status}`);
384
- *
385
- * if (health.status === 'ok') {
386
- * console.log('✅ API is healthy');
387
- * } else {
388
- * console.log('⚠️ API has issues');
389
- * }
390
- * } catch (error) {
391
- * console.log('❌ API is not responding');
392
- * }
393
- * ```
394
- *
395
- * @throws {ApiError} When the API is not responding
121
+ * Reset to defaults
396
122
  */
397
- async healthCheck() {
398
- const response = await this.api.get("/healthz");
399
- return response.data;
123
+ reset() {
124
+ this.config = defaultConfig();
125
+ this.saveConfig();
400
126
  }
401
127
  };
128
+ function defaultConfig2() {
129
+ return {
130
+ server: {
131
+ // Reset used to say localhost here, but never reached the listener:
132
+ // `local start` sets the host on every run and defaults to 0.0.0.0,
133
+ // which is also what publicHost assumes, since a container reaching
134
+ // host.docker.internal cannot be served from loopback.
135
+ host: "0.0.0.0",
136
+ port: 8082,
137
+ publicHost: "host.docker.internal"
138
+ },
139
+ data: {
140
+ dir: path5.join(os2.homedir(), ".calimero-registry", "data"),
141
+ artifactsDir: path5.join(os2.homedir(), ".calimero-registry", "artifacts")
142
+ },
143
+ artifacts: {
144
+ storageDir: path5.join(os2.homedir(), ".calimero-registry", "artifacts"),
145
+ serveLocal: true,
146
+ copyArtifacts: true,
147
+ maxFileSize: "100MB",
148
+ allowedTypes: ["wasm", "js", "html"]
149
+ }
150
+ };
151
+ }
402
152
  var LocalConfig = class {
403
153
  configPath;
404
154
  dataDir;
405
155
  config;
406
156
  constructor() {
407
- this.configPath = path7.join(
408
- os.homedir(),
157
+ this.configPath = path5.join(
158
+ os2.homedir(),
409
159
  ".calimero-registry",
410
160
  "config.json"
411
161
  );
412
- this.dataDir = path7.join(os.homedir(), ".calimero-registry");
162
+ this.dataDir = path5.join(os2.homedir(), ".calimero-registry");
413
163
  this.config = this.loadConfig();
414
164
  }
415
165
  loadConfig() {
416
- const defaultConfig = {
417
- server: {
418
- port: 8082,
419
- host: "0.0.0.0",
420
- publicHost: "host.docker.internal"
421
- },
422
- data: {
423
- dir: path7.join(os.homedir(), ".calimero-registry", "data"),
424
- artifactsDir: path7.join(
425
- os.homedir(),
426
- ".calimero-registry",
427
- "artifacts"
428
- )
429
- },
430
- artifacts: {
431
- storageDir: path7.join(os.homedir(), ".calimero-registry", "artifacts"),
432
- serveLocal: true,
433
- copyArtifacts: true,
434
- maxFileSize: "100MB",
435
- allowedTypes: ["wasm", "js", "html"]
436
- }
437
- };
438
- if (fs9.existsSync(this.configPath)) {
166
+ const defaults = defaultConfig2();
167
+ if (fs7.existsSync(this.configPath)) {
439
168
  try {
440
169
  const existingConfig = JSON.parse(
441
- fs9.readFileSync(this.configPath, "utf8")
170
+ fs7.readFileSync(this.configPath, "utf8")
442
171
  );
443
172
  return {
444
173
  server: {
445
- ...defaultConfig.server,
174
+ ...defaults.server,
446
175
  ...existingConfig.server || {}
447
176
  },
448
177
  data: {
449
- ...defaultConfig.data,
178
+ ...defaults.data,
450
179
  ...existingConfig.data || {}
451
180
  },
452
181
  artifacts: {
453
- ...defaultConfig.artifacts,
182
+ ...defaults.artifacts,
454
183
  ...existingConfig.artifacts || {}
455
184
  }
456
185
  };
@@ -458,14 +187,14 @@ var LocalConfig = class {
458
187
  console.warn("Failed to load existing config, using defaults");
459
188
  }
460
189
  }
461
- return defaultConfig;
190
+ return defaults;
462
191
  }
463
192
  saveConfig() {
464
- const configDir = path7.dirname(this.configPath);
465
- if (!fs9.existsSync(configDir)) {
466
- fs9.mkdirSync(configDir, { recursive: true });
193
+ const configDir = path5.dirname(this.configPath);
194
+ if (!fs7.existsSync(configDir)) {
195
+ fs7.mkdirSync(configDir, { recursive: true });
467
196
  }
468
- fs9.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
197
+ fs7.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
469
198
  }
470
199
  // Server configuration
471
200
  getPort() {
@@ -495,7 +224,8 @@ var LocalConfig = class {
495
224
  }
496
225
  setDataDir(dir) {
497
226
  this.config.data.dir = dir;
498
- this.config.artifacts.storageDir = path7.join(dir, "artifacts");
227
+ this.config.data.artifactsDir = path5.join(dir, "artifacts");
228
+ this.config.artifacts.storageDir = path5.join(dir, "artifacts");
499
229
  this.saveConfig();
500
230
  }
501
231
  getArtifactsDir() {
@@ -519,12 +249,12 @@ var LocalConfig = class {
519
249
  const dirs = [
520
250
  this.getDataDir(),
521
251
  this.getArtifactsDir(),
522
- path7.join(this.getDataDir(), "backups"),
523
- path7.join(this.getDataDir(), "logs")
252
+ path5.join(this.getDataDir(), "backups"),
253
+ path5.join(this.getDataDir(), "logs")
524
254
  ];
525
255
  dirs.forEach((dir) => {
526
- if (!fs9.existsSync(dir)) {
527
- fs9.mkdirSync(dir, { recursive: true });
256
+ if (!fs7.existsSync(dir)) {
257
+ fs7.mkdirSync(dir, { recursive: true });
528
258
  }
529
259
  });
530
260
  }
@@ -537,30 +267,121 @@ var LocalConfig = class {
537
267
  }
538
268
  // Reset to defaults
539
269
  reset() {
540
- this.config = {
541
- server: {
542
- port: 8082,
543
- host: "localhost"
544
- },
545
- data: {
546
- dir: path7.join(os.homedir(), ".calimero-registry", "data"),
547
- artifactsDir: path7.join(
548
- os.homedir(),
549
- ".calimero-registry",
550
- "artifacts"
551
- )
552
- },
553
- artifacts: {
554
- storageDir: path7.join(os.homedir(), ".calimero-registry", "artifacts"),
555
- serveLocal: true,
556
- copyArtifacts: true,
557
- maxFileSize: "100MB",
558
- allowedTypes: ["wasm", "js", "html"]
559
- }
560
- };
270
+ this.config = defaultConfig2();
561
271
  this.saveConfig();
562
272
  }
563
273
  };
274
+
275
+ // src/commands/health.ts
276
+ var healthCommand = new Command("health").description("Check the health of the Calimero Registry API").action(async (options, command) => {
277
+ const globalOpts = command.parent?.opts();
278
+ let url;
279
+ if (globalOpts?.local) {
280
+ const local = new LocalConfig();
281
+ url = `http://${local.getHost()}:${local.getPort()}/healthz`;
282
+ } else {
283
+ const base = (globalOpts?.url || new RemoteConfig().getRegistryUrl()).trim().replace(/\/$/, "");
284
+ url = `${base}/api/healthz`;
285
+ }
286
+ const spinner2 = ora4("Checking API health...").start();
287
+ try {
288
+ const { data } = await axios.get(url, {
289
+ timeout: parseInt(globalOpts?.timeout || "10000"),
290
+ headers: { Accept: "application/json" }
291
+ });
292
+ if (data?.status !== "ok") {
293
+ throw new Error(
294
+ `unexpected response from ${url}: ${JSON.stringify(data)}`
295
+ );
296
+ }
297
+ spinner2.succeed("API is healthy");
298
+ console.log(chalk4.green(`Status: ${data.status}`));
299
+ if (data.timestamp) {
300
+ console.log(chalk4.gray(`Checked: ${data.timestamp}`));
301
+ }
302
+ } catch (error) {
303
+ spinner2.fail("API health check failed");
304
+ const reason = error instanceof Error && error.message || axios.isAxiosError(error) && error.code || "no response";
305
+ console.error(chalk4.red(`Error: ${reason}`));
306
+ console.error(chalk4.gray(`Tried: ${url}`));
307
+ if (globalOpts?.local) {
308
+ console.error(
309
+ chalk4.gray('Is it running? "calimero-registry local start"')
310
+ );
311
+ }
312
+ process.exit(1);
313
+ }
314
+ });
315
+ async function uploadToIPFS(filePath) {
316
+ try {
317
+ if (!existsSync(filePath)) {
318
+ throw new Error(`File not found: ${filePath}`);
319
+ }
320
+ const simulatedCid = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
321
+ console.log("\u26A0\uFE0F Using simulated IPFS upload for demo purposes");
322
+ console.log(" In production, use a service like Pinata or Infura");
323
+ return simulatedCid;
324
+ } catch (error) {
325
+ throw new Error(
326
+ `Failed to upload to IPFS: ${error instanceof Error ? error.message : "Unknown error"}`,
327
+ { cause: error }
328
+ );
329
+ }
330
+ }
331
+ async function downloadFromIPFS(cid, outputPath) {
332
+ try {
333
+ console.log("\u26A0\uFE0F Using simulated IPFS download for demo purposes");
334
+ console.log(" In production, use a service like Pinata or Infura");
335
+ const simulatedContent = `Simulated IPFS file content for CID: ${cid}
336
+ This is a demo file that would normally contain the actual application data.`;
337
+ const finalOutputPath = outputPath || `${cid}.wasm`;
338
+ writeFileSync(finalOutputPath, simulatedContent);
339
+ return finalOutputPath;
340
+ } catch (error) {
341
+ throw new Error(
342
+ `Failed to download from IPFS: ${error instanceof Error ? error.message : "Unknown error"}`,
343
+ { cause: error }
344
+ );
345
+ }
346
+ }
347
+ var spinner = (text) => ora4(text);
348
+
349
+ // src/commands/ipfs.ts
350
+ var ipfsCommand = new Command("ipfs").description("IPFS operations").addCommand(
351
+ new Command("upload").description("Upload a file to IPFS").argument("<file>", "Path to the file to upload").action(async (file) => {
352
+ const s = spinner("Uploading to IPFS...").start();
353
+ try {
354
+ const cid = await uploadToIPFS(file);
355
+ s.succeed(`File uploaded successfully!`);
356
+ console.log(`CID: ${cid}`);
357
+ console.log(`Gateway URL: https://ipfs.io/ipfs/${cid}`);
358
+ } catch (error) {
359
+ s.fail("Upload failed");
360
+ console.error(
361
+ "Error:",
362
+ error instanceof Error ? error.message : "Unknown error"
363
+ );
364
+ process.exit(1);
365
+ }
366
+ })
367
+ ).addCommand(
368
+ new Command("download").description("Download a file from IPFS").argument("<cid>", "IPFS CID to download").argument("[output]", "Output file path (optional)").action(async (cid, output) => {
369
+ const s = spinner("Downloading from IPFS...").start();
370
+ try {
371
+ const outputPath = await downloadFromIPFS(cid, output);
372
+ s.succeed(`File downloaded successfully!`);
373
+ console.log(`Saved to: ${outputPath}`);
374
+ console.log(`Gateway URL: https://ipfs.io/ipfs/${cid}`);
375
+ } catch (error) {
376
+ s.fail("Download failed");
377
+ console.error(
378
+ "Error:",
379
+ error instanceof Error ? error.message : "Unknown error"
380
+ );
381
+ process.exit(1);
382
+ }
383
+ })
384
+ );
564
385
  var LocalDataStore = class {
565
386
  config;
566
387
  data;
@@ -569,12 +390,12 @@ var LocalDataStore = class {
569
390
  artifactsFile;
570
391
  constructor(config) {
571
392
  this.config = config;
572
- this.appsFile = path7.join(config.getDataDir(), "apps.json");
573
- this.bundleManifestsFile = path7.join(
393
+ this.appsFile = path5.join(config.getDataDir(), "apps.json");
394
+ this.bundleManifestsFile = path5.join(
574
395
  config.getDataDir(),
575
396
  "bundle_manifests.json"
576
397
  );
577
- this.artifactsFile = path7.join(config.getDataDir(), "artifacts.json");
398
+ this.artifactsFile = path5.join(config.getDataDir(), "artifacts.json");
578
399
  this.data = {
579
400
  apps: /* @__PURE__ */ new Map(),
580
401
  bundleManifests: /* @__PURE__ */ new Map(),
@@ -584,21 +405,21 @@ var LocalDataStore = class {
584
405
  }
585
406
  loadData() {
586
407
  try {
587
- if (fs9.existsSync(this.appsFile)) {
588
- const appsData = JSON.parse(fs9.readFileSync(this.appsFile, "utf8"));
408
+ if (fs7.existsSync(this.appsFile)) {
409
+ const appsData = JSON.parse(fs7.readFileSync(this.appsFile, "utf8"));
589
410
  this.data.apps = new Map(Object.entries(appsData));
590
411
  }
591
- if (fs9.existsSync(this.bundleManifestsFile)) {
412
+ if (fs7.existsSync(this.bundleManifestsFile)) {
592
413
  const bundleManifestsData = JSON.parse(
593
- fs9.readFileSync(this.bundleManifestsFile, "utf8")
414
+ fs7.readFileSync(this.bundleManifestsFile, "utf8")
594
415
  );
595
416
  this.data.bundleManifests = new Map(
596
417
  Object.entries(bundleManifestsData)
597
418
  );
598
419
  }
599
- if (fs9.existsSync(this.artifactsFile)) {
420
+ if (fs7.existsSync(this.artifactsFile)) {
600
421
  const artifactsData = JSON.parse(
601
- fs9.readFileSync(this.artifactsFile, "utf8")
422
+ fs7.readFileSync(this.artifactsFile, "utf8")
602
423
  );
603
424
  this.data.artifacts = new Map(Object.entries(artifactsData));
604
425
  }
@@ -610,14 +431,14 @@ var LocalDataStore = class {
610
431
  try {
611
432
  this.config.ensureDirectories();
612
433
  const appsObj = Object.fromEntries(this.data.apps);
613
- fs9.writeFileSync(this.appsFile, JSON.stringify(appsObj, null, 2));
434
+ fs7.writeFileSync(this.appsFile, JSON.stringify(appsObj, null, 2));
614
435
  const bundleManifestsObj = Object.fromEntries(this.data.bundleManifests);
615
- fs9.writeFileSync(
436
+ fs7.writeFileSync(
616
437
  this.bundleManifestsFile,
617
438
  JSON.stringify(bundleManifestsObj, null, 2)
618
439
  );
619
440
  const artifactsObj = Object.fromEntries(this.data.artifacts);
620
- fs9.writeFileSync(
441
+ fs7.writeFileSync(
621
442
  this.artifactsFile,
622
443
  JSON.stringify(artifactsObj, null, 2)
623
444
  );
@@ -695,14 +516,14 @@ var LocalDataStore = class {
695
516
  // Backup and restore
696
517
  async backup(outputPath) {
697
518
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
698
- const backupPath = outputPath || path7.join(
519
+ const backupPath = outputPath || path5.join(
699
520
  this.config.getDataDir(),
700
521
  "backups",
701
522
  `backup-${timestamp}.json`
702
523
  );
703
- const backupDir = path7.dirname(backupPath);
704
- if (!fs9.existsSync(backupDir)) {
705
- fs9.mkdirSync(backupDir, { recursive: true });
524
+ const backupDir = path5.dirname(backupPath);
525
+ if (!fs7.existsSync(backupDir)) {
526
+ fs7.mkdirSync(backupDir, { recursive: true });
706
527
  }
707
528
  const backupData = {
708
529
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -710,14 +531,14 @@ var LocalDataStore = class {
710
531
  bundleManifests: Object.fromEntries(this.data.bundleManifests),
711
532
  artifacts: Object.fromEntries(this.data.artifacts)
712
533
  };
713
- fs9.writeFileSync(backupPath, JSON.stringify(backupData, null, 2));
534
+ fs7.writeFileSync(backupPath, JSON.stringify(backupData, null, 2));
714
535
  return backupPath;
715
536
  }
716
537
  async restore(backupPath) {
717
- if (!fs9.existsSync(backupPath)) {
538
+ if (!fs7.existsSync(backupPath)) {
718
539
  throw new Error(`Backup file not found: ${backupPath}`);
719
540
  }
720
- const backupData = JSON.parse(fs9.readFileSync(backupPath, "utf8"));
541
+ const backupData = JSON.parse(fs7.readFileSync(backupPath, "utf8"));
721
542
  this.data.apps = new Map(Object.entries(backupData.apps || {}));
722
543
  this.data.bundleManifests = new Map(
723
544
  Object.entries(backupData.bundleManifests || {})
@@ -788,48 +609,48 @@ var LocalArtifactServer = class {
788
609
  this.ensureArtifactsDir();
789
610
  }
790
611
  ensureArtifactsDir() {
791
- if (!fs9.existsSync(this.artifactsDir)) {
792
- fs9.mkdirSync(this.artifactsDir, { recursive: true });
612
+ if (!fs7.existsSync(this.artifactsDir)) {
613
+ fs7.mkdirSync(this.artifactsDir, { recursive: true });
793
614
  }
794
615
  }
795
616
  // Copy artifact to local storage
796
617
  async copyArtifactToLocal(sourcePath, appId, version2, filename) {
797
- if (!fs9.existsSync(sourcePath)) {
618
+ if (!fs7.existsSync(sourcePath)) {
798
619
  throw new Error(`Source file not found: ${sourcePath}`);
799
620
  }
800
- const appVersionDir = path7.join(this.artifactsDir, appId, version2);
801
- if (!fs9.existsSync(appVersionDir)) {
802
- fs9.mkdirSync(appVersionDir, { recursive: true });
621
+ const appVersionDir = path5.join(this.artifactsDir, appId, version2);
622
+ if (!fs7.existsSync(appVersionDir)) {
623
+ fs7.mkdirSync(appVersionDir, { recursive: true });
803
624
  }
804
- const targetPath = path7.join(appVersionDir, filename);
805
- fs9.copyFileSync(sourcePath, targetPath);
625
+ const targetPath = path5.join(appVersionDir, filename);
626
+ fs7.copyFileSync(sourcePath, targetPath);
806
627
  const fileHash = await this.calculateFileHash(targetPath);
807
628
  this.dataStore.setArtifactPath(fileHash, targetPath);
808
629
  return targetPath;
809
630
  }
810
631
  // Serve artifact by app ID, version, and filename
811
632
  async serveArtifact(appId, version2, filename) {
812
- const artifactPath = path7.join(this.artifactsDir, appId, version2, filename);
813
- if (!fs9.existsSync(artifactPath)) {
633
+ const artifactPath = path5.join(this.artifactsDir, appId, version2, filename);
634
+ if (!fs7.existsSync(artifactPath)) {
814
635
  throw new Error(`Artifact not found: ${artifactPath}`);
815
636
  }
816
- return fs9.readFileSync(artifactPath);
637
+ return fs7.readFileSync(artifactPath);
817
638
  }
818
639
  // Serve artifact by hash
819
640
  async serveByHash(hash) {
820
641
  const artifactPath = this.dataStore.getArtifactPath(hash);
821
- if (!artifactPath || !fs9.existsSync(artifactPath)) {
642
+ if (!artifactPath || !fs7.existsSync(artifactPath)) {
822
643
  throw new Error(`Artifact not found for hash: ${hash}`);
823
644
  }
824
- return fs9.readFileSync(artifactPath);
645
+ return fs7.readFileSync(artifactPath);
825
646
  }
826
647
  // Validate artifact file
827
648
  async validateArtifact(filePath) {
828
- if (!fs9.existsSync(filePath)) {
649
+ if (!fs7.existsSync(filePath)) {
829
650
  throw new Error(`File not found: ${filePath}`);
830
651
  }
831
- const stats = fs9.statSync(filePath);
832
- const fileBuffer = fs9.readFileSync(filePath);
652
+ const stats = fs7.statSync(filePath);
653
+ const fileBuffer = fs7.readFileSync(filePath);
833
654
  const sha256 = crypto2.createHash("sha256").update(fileBuffer).digest("hex");
834
655
  return {
835
656
  size: stats.size,
@@ -838,7 +659,7 @@ var LocalArtifactServer = class {
838
659
  }
839
660
  // Calculate file hash
840
661
  async calculateFileHash(filePath) {
841
- const fileBuffer = fs9.readFileSync(filePath);
662
+ const fileBuffer = fs7.readFileSync(filePath);
842
663
  return crypto2.createHash("sha256").update(fileBuffer).digest("hex");
843
664
  }
844
665
  // Get artifact URL for local serving
@@ -851,37 +672,15 @@ var LocalArtifactServer = class {
851
672
  const baseUrl = `http://${this.config.getPublicHost()}:${this.config.getPort()}`;
852
673
  return `${baseUrl}/artifacts/${hash}`;
853
674
  }
854
- // Update manifest artifact to use local URLs (and preserve HTTP access)
855
- updateManifestArtifact(manifest) {
856
- const updatedManifest = { ...manifest };
857
- if (!manifest.artifact?.uri) {
858
- return updatedManifest;
859
- }
860
- const uri = manifest.artifact.uri;
861
- if (uri.startsWith("/")) {
862
- updatedManifest.artifact = {
863
- ...manifest.artifact,
864
- uri: `${this.getArtifactUrl(manifest.id, manifest.version, path7.basename(manifest.artifact.uri))}`
865
- };
866
- } else if (uri.startsWith("file://")) {
867
- const filePath = uri.replace("file://", "");
868
- const filename = path7.basename(filePath);
869
- updatedManifest.artifact = {
870
- ...manifest.artifact,
871
- uri: this.getArtifactUrl(manifest.id, manifest.version, filename)
872
- };
873
- }
874
- return updatedManifest;
875
- }
876
675
  // Clean up old artifacts
877
676
  async cleanupOldArtifacts(maxAge = 30 * 24 * 60 * 60 * 1e3) {
878
677
  const now = Date.now();
879
678
  const getAllFiles = (dir) => {
880
679
  let files = [];
881
- const items = fs9.readdirSync(dir);
680
+ const items = fs7.readdirSync(dir);
882
681
  for (const item of items) {
883
- const fullPath = path7.join(dir, item);
884
- const stat = fs9.statSync(fullPath);
682
+ const fullPath = path5.join(dir, item);
683
+ const stat = fs7.statSync(fullPath);
885
684
  if (stat.isDirectory()) {
886
685
  files = files.concat(getAllFiles(fullPath));
887
686
  } else {
@@ -892,10 +691,10 @@ var LocalArtifactServer = class {
892
691
  };
893
692
  const allFiles = getAllFiles(this.artifactsDir);
894
693
  for (const file of allFiles) {
895
- const stats = fs9.statSync(file);
694
+ const stats = fs7.statSync(file);
896
695
  const age = now - stats.mtime.getTime();
897
696
  if (age > maxAge) {
898
- fs9.unlinkSync(file);
697
+ fs7.unlinkSync(file);
899
698
  console.log(`Cleaned up old artifact: ${file}`);
900
699
  }
901
700
  }
@@ -907,10 +706,10 @@ var LocalArtifactServer = class {
907
706
  let oldestFile = null;
908
707
  const getAllFiles = (dir) => {
909
708
  let files = [];
910
- const items = fs9.readdirSync(dir);
709
+ const items = fs7.readdirSync(dir);
911
710
  for (const item of items) {
912
- const fullPath = path7.join(dir, item);
913
- const stat = fs9.statSync(fullPath);
711
+ const fullPath = path5.join(dir, item);
712
+ const stat = fs7.statSync(fullPath);
914
713
  if (stat.isDirectory()) {
915
714
  files = files.concat(getAllFiles(fullPath));
916
715
  } else {
@@ -919,10 +718,10 @@ var LocalArtifactServer = class {
919
718
  }
920
719
  return files;
921
720
  };
922
- if (fs9.existsSync(this.artifactsDir)) {
721
+ if (fs7.existsSync(this.artifactsDir)) {
923
722
  const allFiles = getAllFiles(this.artifactsDir);
924
723
  for (const file of allFiles) {
925
- const stats = fs9.statSync(file);
724
+ const stats = fs7.statSync(file);
926
725
  totalFiles++;
927
726
  totalSize += stats.size;
928
727
  if (!oldestFile || stats.mtime < oldestFile) {
@@ -937,459 +736,6 @@ var LocalArtifactServer = class {
937
736
  };
938
737
  }
939
738
  };
940
- var RemoteRegistryClient = class {
941
- client;
942
- constructor(baseURL, timeout) {
943
- this.client = new CalimeroRegistryClient({
944
- baseURL,
945
- timeout
946
- });
947
- }
948
- async getApps(filters) {
949
- return await this.client.getApps(filters);
950
- }
951
- async getAppVersions(appId) {
952
- return await this.client.getAppVersions(appId);
953
- }
954
- async getAppManifest(appId, semver) {
955
- return await this.client.getAppManifest(appId, semver);
956
- }
957
- async submitAppManifest(manifest) {
958
- return await this.client.submitAppManifest(manifest);
959
- }
960
- async healthCheck() {
961
- return await this.client.healthCheck();
962
- }
963
- };
964
- var LocalRegistryClient = class {
965
- config;
966
- dataStore;
967
- artifactServer;
968
- constructor() {
969
- this.config = new LocalConfig();
970
- this.dataStore = new LocalDataStore(this.config);
971
- this.artifactServer = new LocalArtifactServer(this.config, this.dataStore);
972
- }
973
- async getApps(filters) {
974
- return this.dataStore.getApps(filters);
975
- }
976
- async getAppVersions(appId) {
977
- return this.dataStore.getAppVersions(appId);
978
- }
979
- async getAppManifest(appId, semver) {
980
- const manifest = this.dataStore.getManifest(appId, semver);
981
- if (!manifest) {
982
- throw new Error("Manifest not found");
983
- }
984
- return this.artifactServer.updateManifestArtifact(manifest);
985
- }
986
- async submitAppManifest(manifest) {
987
- if (!this.validateManifest(manifest)) {
988
- throw new Error("Invalid manifest structure");
989
- }
990
- const processedManifest = await this.processManifestArtifacts(manifest);
991
- const manifestKey = `${processedManifest.id}/${processedManifest.version}`;
992
- this.dataStore.setManifest(manifestKey, processedManifest);
993
- const appSummary = {
994
- id: processedManifest.id,
995
- name: processedManifest.name,
996
- latest_version: processedManifest.version,
997
- latest_digest: processedManifest.artifact.digest
998
- };
999
- this.dataStore.setApp(processedManifest.id, appSummary);
1000
- return {
1001
- success: true,
1002
- message: "App version registered successfully"
1003
- };
1004
- }
1005
- async healthCheck() {
1006
- return { status: "ok" };
1007
- }
1008
- validateManifest(manifest) {
1009
- return !!(manifest.manifest_version && manifest.id && manifest.name && manifest.version && manifest.artifact && manifest.artifact.type && manifest.artifact.target && manifest.artifact.digest && manifest.artifact.uri);
1010
- }
1011
- async processManifestArtifacts(manifest) {
1012
- const processedManifest = { ...manifest };
1013
- if (manifest.artifact?.uri?.startsWith("file://")) {
1014
- const filePath = manifest.artifact.uri.replace("file://", "");
1015
- if (fs9.existsSync(filePath)) {
1016
- const filename = path7.basename(filePath);
1017
- try {
1018
- await this.artifactServer.copyArtifactToLocal(
1019
- filePath,
1020
- manifest.id,
1021
- manifest.version,
1022
- filename
1023
- );
1024
- processedManifest.artifact = {
1025
- ...manifest.artifact,
1026
- uri: this.artifactServer.getArtifactUrl(
1027
- manifest.id,
1028
- manifest.version,
1029
- filename
1030
- )
1031
- };
1032
- } catch (error) {
1033
- console.warn(`Failed to copy artifact ${filePath}:`, error);
1034
- }
1035
- }
1036
- }
1037
- return processedManifest;
1038
- }
1039
- };
1040
- function createRegistryClient(useLocal, baseURL, timeout) {
1041
- if (useLocal) {
1042
- return new LocalRegistryClient();
1043
- } else {
1044
- return new RemoteRegistryClient(
1045
- baseURL || "http://localhost:8082",
1046
- timeout || 1e4
1047
- );
1048
- }
1049
- }
1050
- var appsCommand = new Command("apps").description("Manage self-sovereign applications").addCommand(
1051
- new Command("list").description("List all applications").option("-n, --name <name>", "Filter by application name").action(async (options, command) => {
1052
- const globalOpts = command.parent?.parent?.opts();
1053
- const useLocal = globalOpts?.local || false;
1054
- const client = createRegistryClient(
1055
- useLocal,
1056
- globalOpts?.url,
1057
- parseInt(globalOpts?.timeout || "10000")
1058
- );
1059
- const spinner2 = ora7("Fetching applications...").start();
1060
- try {
1061
- const apps = await client.getApps({
1062
- name: options.name
1063
- });
1064
- spinner2.succeed(`Found ${apps.length} application(s)`);
1065
- if (apps.length === 0) {
1066
- console.log(chalk7.yellow("No applications found"));
1067
- return;
1068
- }
1069
- const tableData = [
1070
- ["ID", "Name", "Latest Version", "Digest"],
1071
- ...apps.map((app) => [
1072
- app.id,
1073
- app.name,
1074
- app.latest_version,
1075
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1076
- (app.latest_digest || app.latest_cid || "N/A").toString().substring(0, 12) + "..."
1077
- ])
1078
- ];
1079
- console.log(table(tableData));
1080
- } catch (error) {
1081
- spinner2.fail("Failed to fetch applications");
1082
- if (error instanceof Error) {
1083
- console.error(chalk7.red(`Error: ${error.message}`));
1084
- }
1085
- process.exit(1);
1086
- }
1087
- })
1088
- ).addCommand(
1089
- new Command("versions").description("List versions of a specific application").argument("<appId>", "Application ID").action(async (appId, options, command) => {
1090
- const globalOpts = command.parent?.parent?.opts();
1091
- const useLocal = globalOpts?.local || false;
1092
- const client = createRegistryClient(
1093
- useLocal,
1094
- globalOpts?.url,
1095
- parseInt(globalOpts?.timeout || "10000")
1096
- );
1097
- const spinner2 = ora7(`Fetching versions for ${appId}...`).start();
1098
- try {
1099
- const versions = await client.getAppVersions(appId);
1100
- spinner2.succeed(`Found ${versions.length} version(s)`);
1101
- if (versions.length === 0) {
1102
- console.log(chalk7.yellow("No versions found"));
1103
- return;
1104
- }
1105
- const tableData = [
1106
- ["Version", "CID", "Yanked"],
1107
- ...versions.map((version2) => [
1108
- version2.semver,
1109
- version2.cid.substring(0, 12) + "...",
1110
- version2.yanked ? chalk7.red("Yes") : chalk7.green("No")
1111
- ])
1112
- ];
1113
- console.log(table(tableData));
1114
- } catch (error) {
1115
- spinner2.fail("Failed to fetch versions");
1116
- if (error instanceof Error) {
1117
- console.error(chalk7.red(`Error: ${error.message}`));
1118
- }
1119
- process.exit(1);
1120
- }
1121
- })
1122
- ).addCommand(
1123
- new Command("manifest").description("Get manifest for a specific application version").argument("<appId>", "Application ID").argument("<version>", "Application version").action(async (appId, version2, options, command) => {
1124
- const globalOpts = command.parent?.parent?.opts();
1125
- const useLocal = globalOpts?.local || false;
1126
- const client = createRegistryClient(
1127
- useLocal,
1128
- globalOpts?.url,
1129
- parseInt(globalOpts?.timeout || "10000")
1130
- );
1131
- const spinner2 = ora7(
1132
- `Fetching manifest for ${appId}@${version2}...`
1133
- ).start();
1134
- try {
1135
- const manifest = await client.getAppManifest(appId, version2);
1136
- spinner2.succeed("Manifest fetched successfully");
1137
- console.log(chalk7.blue("\nApplication Manifest:"));
1138
- console.log(JSON.stringify(manifest, null, 2));
1139
- } catch (error) {
1140
- spinner2.fail("Failed to fetch manifest");
1141
- if (error instanceof Error) {
1142
- console.error(chalk7.red(`Error: ${error.message}`));
1143
- }
1144
- process.exit(1);
1145
- }
1146
- })
1147
- ).addCommand(
1148
- new Command("submit").description("Submit a new application manifest").argument("<manifest-file>", "Path to the manifest JSON file").action(async (manifestFile, options, command) => {
1149
- const globalOpts = command.parent?.parent?.opts();
1150
- const useLocal = globalOpts?.local || false;
1151
- const client = createRegistryClient(
1152
- useLocal,
1153
- globalOpts?.url,
1154
- parseInt(globalOpts?.timeout || "10000")
1155
- );
1156
- const spinner2 = ora7("Reading manifest file...").start();
1157
- try {
1158
- const manifestPath = path7.resolve(manifestFile);
1159
- if (!fs9.existsSync(manifestPath)) {
1160
- spinner2.fail("Manifest file not found");
1161
- console.error(chalk7.red(`File not found: ${manifestFile}`));
1162
- process.exit(1);
1163
- }
1164
- const manifestContent = fs9.readFileSync(manifestPath, "utf8");
1165
- const manifest = JSON.parse(manifestContent);
1166
- spinner2.text = "Submitting application manifest...";
1167
- const result = await client.submitAppManifest(manifest);
1168
- spinner2.succeed("Application submitted successfully");
1169
- console.log(chalk7.green(`
1170
- \u2705 ${result.message}`));
1171
- if (manifest.app?.name) {
1172
- console.log(chalk7.blue(`
1173
- \u{1F4F1} App: ${manifest.app.name}`));
1174
- console.log(
1175
- chalk7.blue(`\u{1F464} Developer: ${manifest.app.developer_pubkey}`)
1176
- );
1177
- console.log(chalk7.blue(`\u{1F4E6} Version: ${manifest.version?.semver}`));
1178
- }
1179
- } catch (error) {
1180
- spinner2.fail("Failed to submit application");
1181
- if (error instanceof Error) {
1182
- console.error(chalk7.red(`Error: ${error.message}`));
1183
- }
1184
- process.exit(1);
1185
- }
1186
- })
1187
- );
1188
- var developersCommand = new Command("developers").description("Manage developer profiles").addCommand(
1189
- new Command("get").description("Get developer profile information").argument("<pubkey>", "Developer public key").action(async (pubkey, options, command) => {
1190
- const globalOpts = command.parent?.parent?.opts();
1191
- const client = new CalimeroRegistryClient({
1192
- baseURL: globalOpts?.url || "http://localhost:8082",
1193
- timeout: parseInt(globalOpts?.timeout || "10000")
1194
- });
1195
- const spinner2 = ora7("Fetching developer profile...").start();
1196
- try {
1197
- const profile = await client.getDeveloper(pubkey);
1198
- spinner2.succeed("Developer profile fetched successfully");
1199
- console.log(chalk7.blue("\nDeveloper Profile:"));
1200
- console.log(chalk7.green("Display Name:"), profile.display_name);
1201
- if (profile.website) {
1202
- console.log(chalk7.green("Website:"), profile.website);
1203
- }
1204
- if (profile.proofs.length > 0) {
1205
- console.log(chalk7.green("\nProofs:"));
1206
- const tableData = [
1207
- ["Type", "Value", "Verified"],
1208
- ...profile.proofs.map((proof) => [
1209
- proof.type,
1210
- proof.value.substring(0, 20) + "...",
1211
- proof.verified ? chalk7.green("Yes") : chalk7.red("No")
1212
- ])
1213
- ];
1214
- console.log(table(tableData));
1215
- } else {
1216
- console.log(chalk7.yellow("\nNo proofs found"));
1217
- }
1218
- } catch (error) {
1219
- spinner2.fail("Failed to fetch developer profile");
1220
- if (error instanceof Error) {
1221
- console.error(chalk7.red(`Error: ${error.message}`));
1222
- }
1223
- process.exit(1);
1224
- }
1225
- })
1226
- ).addCommand(
1227
- new Command("create").description("Create a new developer profile").argument("<pubkey>", "Developer public key").argument("<display-name>", "Display name for the developer").option("-w, --website <url>", "Developer website URL").option("-p, --proofs <proofs>", "JSON string of proofs array").action(async (pubkey, displayName, options, command) => {
1228
- const globalOpts = command.parent?.parent?.opts();
1229
- const client = new CalimeroRegistryClient({
1230
- baseURL: globalOpts?.url || "http://localhost:8082",
1231
- timeout: parseInt(globalOpts?.timeout || "10000")
1232
- });
1233
- const spinner2 = ora7("Creating developer profile...").start();
1234
- try {
1235
- let proofs = [];
1236
- if (options.proofs) {
1237
- try {
1238
- proofs = JSON.parse(options.proofs);
1239
- } catch {
1240
- spinner2.fail("Invalid proofs JSON format");
1241
- console.error(chalk7.red("Proofs must be a valid JSON array"));
1242
- process.exit(1);
1243
- }
1244
- }
1245
- const profile = {
1246
- pubkey,
1247
- display_name: displayName,
1248
- website: options.website,
1249
- proofs
1250
- };
1251
- const result = await client.submitDeveloperProfile(pubkey, profile);
1252
- spinner2.succeed("Developer profile created successfully");
1253
- console.log(chalk7.green(`
1254
- \u2705 ${result.message}`));
1255
- console.log(chalk7.blue(`
1256
- \u{1F464} Developer: ${displayName}`));
1257
- console.log(chalk7.blue(`\u{1F511} Public Key: ${pubkey}`));
1258
- if (options.website) {
1259
- console.log(chalk7.blue(`\u{1F310} Website: ${options.website}`));
1260
- }
1261
- } catch (error) {
1262
- spinner2.fail("Failed to create developer profile");
1263
- if (error instanceof Error) {
1264
- console.error(chalk7.red(`Error: ${error.message}`));
1265
- }
1266
- process.exit(1);
1267
- }
1268
- })
1269
- );
1270
- var attestationsCommand = new Command("attestations").description("Manage application attestations").addCommand(
1271
- new Command("get").description("Get attestation for a specific application version").argument("<pubkey>", "Developer public key").argument("<name>", "Application name").argument("<version>", "Application version").action(async (pubkey, name, version2, options, command) => {
1272
- const globalOpts = command.parent?.parent?.opts();
1273
- const client = new CalimeroRegistryClient({
1274
- baseURL: globalOpts?.url || "http://localhost:8082",
1275
- timeout: parseInt(globalOpts?.timeout || "10000")
1276
- });
1277
- const spinner2 = ora7(
1278
- `Fetching attestation for ${name}@${version2}...`
1279
- ).start();
1280
- try {
1281
- const attestation = await client.getAttestation(
1282
- pubkey,
1283
- name,
1284
- version2
1285
- );
1286
- spinner2.succeed("Attestation fetched successfully");
1287
- console.log(chalk7.blue("\nAttestation:"));
1288
- console.log(chalk7.green("Status:"), attestation.status);
1289
- console.log(chalk7.green("Timestamp:"), attestation.timestamp);
1290
- if (attestation.comment) {
1291
- console.log(chalk7.green("Comment:"), attestation.comment);
1292
- }
1293
- } catch (error) {
1294
- spinner2.fail("Failed to fetch attestation");
1295
- if (error instanceof Error) {
1296
- console.error(chalk7.red(`Error: ${error.message}`));
1297
- }
1298
- process.exit(1);
1299
- }
1300
- })
1301
- );
1302
- var healthCommand = new Command("health").description("Check the health of the Calimero Registry API").action(async (options, command) => {
1303
- const globalOpts = command.parent?.opts();
1304
- const useLocal = globalOpts?.local || false;
1305
- const client = createRegistryClient(
1306
- useLocal,
1307
- globalOpts?.url,
1308
- parseInt(globalOpts?.timeout || "10000")
1309
- );
1310
- const spinner2 = ora7("Checking API health...").start();
1311
- try {
1312
- const health = await client.healthCheck();
1313
- spinner2.succeed("API is healthy");
1314
- console.log(chalk7.green(`Status: ${health.status}`));
1315
- } catch (error) {
1316
- spinner2.fail("API health check failed");
1317
- if (error instanceof Error) {
1318
- console.error(chalk7.red(`Error: ${error.message}`));
1319
- }
1320
- process.exit(1);
1321
- }
1322
- });
1323
- async function uploadToIPFS(filePath) {
1324
- try {
1325
- if (!existsSync(filePath)) {
1326
- throw new Error(`File not found: ${filePath}`);
1327
- }
1328
- const simulatedCid = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
1329
- console.log("\u26A0\uFE0F Using simulated IPFS upload for demo purposes");
1330
- console.log(" In production, use a service like Pinata or Infura");
1331
- return simulatedCid;
1332
- } catch (error) {
1333
- throw new Error(
1334
- `Failed to upload to IPFS: ${error instanceof Error ? error.message : "Unknown error"}`,
1335
- { cause: error }
1336
- );
1337
- }
1338
- }
1339
- async function downloadFromIPFS(cid, outputPath) {
1340
- try {
1341
- console.log("\u26A0\uFE0F Using simulated IPFS download for demo purposes");
1342
- console.log(" In production, use a service like Pinata or Infura");
1343
- const simulatedContent = `Simulated IPFS file content for CID: ${cid}
1344
- This is a demo file that would normally contain the actual application data.`;
1345
- const finalOutputPath = outputPath || `${cid}.wasm`;
1346
- writeFileSync(finalOutputPath, simulatedContent);
1347
- return finalOutputPath;
1348
- } catch (error) {
1349
- throw new Error(
1350
- `Failed to download from IPFS: ${error instanceof Error ? error.message : "Unknown error"}`,
1351
- { cause: error }
1352
- );
1353
- }
1354
- }
1355
- var spinner = (text) => ora7(text);
1356
-
1357
- // src/commands/ipfs.ts
1358
- var ipfsCommand = new Command("ipfs").description("IPFS operations").addCommand(
1359
- new Command("upload").description("Upload a file to IPFS").argument("<file>", "Path to the file to upload").action(async (file) => {
1360
- const s = spinner("Uploading to IPFS...").start();
1361
- try {
1362
- const cid = await uploadToIPFS(file);
1363
- s.succeed(`File uploaded successfully!`);
1364
- console.log(`CID: ${cid}`);
1365
- console.log(`Gateway URL: https://ipfs.io/ipfs/${cid}`);
1366
- } catch (error) {
1367
- s.fail("Upload failed");
1368
- console.error(
1369
- "Error:",
1370
- error instanceof Error ? error.message : "Unknown error"
1371
- );
1372
- process.exit(1);
1373
- }
1374
- })
1375
- ).addCommand(
1376
- new Command("download").description("Download a file from IPFS").argument("<cid>", "IPFS CID to download").argument("[output]", "Output file path (optional)").action(async (cid, output) => {
1377
- const s = spinner("Downloading from IPFS...").start();
1378
- try {
1379
- const outputPath = await downloadFromIPFS(cid, output);
1380
- s.succeed(`File downloaded successfully!`);
1381
- console.log(`Saved to: ${outputPath}`);
1382
- console.log(`Gateway URL: https://ipfs.io/ipfs/${cid}`);
1383
- } catch (error) {
1384
- s.fail("Download failed");
1385
- console.error(
1386
- "Error:",
1387
- error instanceof Error ? error.message : "Unknown error"
1388
- );
1389
- process.exit(1);
1390
- }
1391
- })
1392
- );
1393
739
  var LocalRegistryServer = class {
1394
740
  config;
1395
741
  dataStore;
@@ -1446,8 +792,8 @@ var LocalRegistryServer = class {
1446
792
  async reset() {
1447
793
  this.dataStore.reset();
1448
794
  const artifactsDir = this.config.getArtifactsDir();
1449
- if (fs9.existsSync(artifactsDir)) {
1450
- fs9.rmSync(artifactsDir, { recursive: true, force: true });
795
+ if (fs7.existsSync(artifactsDir)) {
796
+ fs7.rmSync(artifactsDir, { recursive: true, force: true });
1451
797
  }
1452
798
  }
1453
799
  async backup(outputPath) {
@@ -1607,7 +953,7 @@ localCommand.addCommand(
1607
953
  "Public host exposed in manifest artifact URLs",
1608
954
  "host.docker.internal"
1609
955
  ).action(async (options) => {
1610
- const spinner2 = ora7("Starting local registry...").start();
956
+ const spinner2 = ora4("Starting local registry...").start();
1611
957
  try {
1612
958
  const config = new LocalConfig();
1613
959
  config.setHost(options.host);
@@ -1618,37 +964,37 @@ localCommand.addCommand(
1618
964
  spinner2.succeed(
1619
965
  `Local registry started on http://${config.getHost()}:${config.getPort()}`
1620
966
  );
1621
- console.log(chalk7.blue("\n\u{1F4F1} Local Registry Status:"));
967
+ console.log(chalk4.blue("\n\u{1F4F1} Local Registry Status:"));
1622
968
  console.log(
1623
- chalk7.green(
969
+ chalk4.green(
1624
970
  `\u2705 Server: http://${config.getHost()}:${config.getPort()}`
1625
971
  )
1626
972
  );
1627
973
  console.log(
1628
- chalk7.green(
974
+ chalk4.green(
1629
975
  `\u{1F310} Public URL: http://${config.getPublicHost()}:${config.getPort()}`
1630
976
  )
1631
977
  );
1632
- console.log(chalk7.green(`\u{1F4C1} Data: ${config.getDataDir()}`));
978
+ console.log(chalk4.green(`\u{1F4C1} Data: ${config.getDataDir()}`));
1633
979
  console.log(
1634
- chalk7.green(
980
+ chalk4.green(
1635
981
  `\u{1F4CB} Health: http://${config.getHost()}:${config.getPort()}/healthz`
1636
982
  )
1637
983
  );
1638
984
  console.log(
1639
- chalk7.green(
985
+ chalk4.green(
1640
986
  `\u{1F4CA} Stats: http://${config.getHost()}:${config.getPort()}/stats`
1641
987
  )
1642
988
  );
1643
989
  console.log(
1644
- chalk7.blue(
990
+ chalk4.blue(
1645
991
  "\n\u{1F4A1} Use --local flag with other commands to use local registry"
1646
992
  )
1647
993
  );
1648
994
  } catch (error) {
1649
995
  spinner2.fail("Failed to start local registry");
1650
996
  if (error instanceof Error) {
1651
- console.error(chalk7.red(`Error: ${error.message}`));
997
+ console.error(chalk4.red(`Error: ${error.message}`));
1652
998
  }
1653
999
  process.exit(1);
1654
1000
  }
@@ -1656,7 +1002,7 @@ localCommand.addCommand(
1656
1002
  );
1657
1003
  localCommand.addCommand(
1658
1004
  new Command("stop").description("Stop local registry server").action(async () => {
1659
- const spinner2 = ora7("Stopping local registry...").start();
1005
+ const spinner2 = ora4("Stopping local registry...").start();
1660
1006
  try {
1661
1007
  const config = new LocalConfig();
1662
1008
  const server = new LocalRegistryServer(config);
@@ -1665,7 +1011,7 @@ localCommand.addCommand(
1665
1011
  } catch (error) {
1666
1012
  spinner2.fail("Failed to stop local registry");
1667
1013
  if (error instanceof Error) {
1668
- console.error(chalk7.red(`Error: ${error.message}`));
1014
+ console.error(chalk4.red(`Error: ${error.message}`));
1669
1015
  }
1670
1016
  process.exit(1);
1671
1017
  }
@@ -1673,23 +1019,23 @@ localCommand.addCommand(
1673
1019
  );
1674
1020
  localCommand.addCommand(
1675
1021
  new Command("status").description("Check local registry status").action(async () => {
1676
- const spinner2 = ora7("Checking local registry status...").start();
1022
+ const spinner2 = ora4("Checking local registry status...").start();
1677
1023
  try {
1678
1024
  const config = new LocalConfig();
1679
1025
  const server = new LocalRegistryServer(config);
1680
1026
  const status = await server.getStatus();
1681
1027
  if (status.running) {
1682
1028
  spinner2.succeed("Local registry is running");
1683
- console.log(chalk7.green(`\u2705 Server: ${status.url}`));
1684
- console.log(chalk7.green(`\u{1F4C1} Data: ${status.dataDir}`));
1685
- console.log(chalk7.green(`\u{1F4CA} Apps: ${status.appsCount} applications`));
1029
+ console.log(chalk4.green(`\u2705 Server: ${status.url}`));
1030
+ console.log(chalk4.green(`\u{1F4C1} Data: ${status.dataDir}`));
1031
+ console.log(chalk4.green(`\u{1F4CA} Apps: ${status.appsCount} applications`));
1686
1032
  console.log(
1687
- chalk7.green(`\u{1F4E6} Artifacts: ${status.artifactsCount} artifacts`)
1033
+ chalk4.green(`\u{1F4E6} Artifacts: ${status.artifactsCount} artifacts`)
1688
1034
  );
1689
1035
  } else {
1690
1036
  spinner2.warn("Local registry is not running");
1691
1037
  console.log(
1692
- chalk7.yellow(
1038
+ chalk4.yellow(
1693
1039
  '\u{1F4A1} Run "calimero-registry local start" to start the local registry'
1694
1040
  )
1695
1041
  );
@@ -1697,7 +1043,7 @@ localCommand.addCommand(
1697
1043
  } catch (error) {
1698
1044
  spinner2.fail("Failed to check local registry status");
1699
1045
  if (error instanceof Error) {
1700
- console.error(chalk7.red(`Error: ${error.message}`));
1046
+ console.error(chalk4.red(`Error: ${error.message}`));
1701
1047
  }
1702
1048
  process.exit(1);
1703
1049
  }
@@ -1707,22 +1053,22 @@ localCommand.addCommand(
1707
1053
  new Command("reset").description("Reset local registry data").option("-f, --force", "Force reset without confirmation").action(async (options) => {
1708
1054
  if (!options.force) {
1709
1055
  console.log(
1710
- chalk7.yellow("\u26A0\uFE0F This will delete all local registry data!")
1056
+ chalk4.yellow("\u26A0\uFE0F This will delete all local registry data!")
1711
1057
  );
1712
- console.log(chalk7.yellow(" Use --force flag to confirm"));
1058
+ console.log(chalk4.yellow(" Use --force flag to confirm"));
1713
1059
  return;
1714
1060
  }
1715
- const spinner2 = ora7("Resetting local registry data...").start();
1061
+ const spinner2 = ora4("Resetting local registry data...").start();
1716
1062
  try {
1717
1063
  const config = new LocalConfig();
1718
1064
  const server = new LocalRegistryServer(config);
1719
1065
  await server.reset();
1720
1066
  spinner2.succeed("Local registry data reset");
1721
- console.log(chalk7.green("\u2705 All local data has been cleared"));
1067
+ console.log(chalk4.green("\u2705 All local data has been cleared"));
1722
1068
  } catch (error) {
1723
1069
  spinner2.fail("Failed to reset local registry data");
1724
1070
  if (error instanceof Error) {
1725
- console.error(chalk7.red(`Error: ${error.message}`));
1071
+ console.error(chalk4.red(`Error: ${error.message}`));
1726
1072
  }
1727
1073
  process.exit(1);
1728
1074
  }
@@ -1730,17 +1076,17 @@ localCommand.addCommand(
1730
1076
  );
1731
1077
  localCommand.addCommand(
1732
1078
  new Command("backup").description("Backup local registry data").option("-o, --output <file>", "Output file path").action(async (options) => {
1733
- const spinner2 = ora7("Creating backup...").start();
1079
+ const spinner2 = ora4("Creating backup...").start();
1734
1080
  try {
1735
1081
  const config = new LocalConfig();
1736
1082
  const server = new LocalRegistryServer(config);
1737
1083
  const backupPath = await server.backup(options.output);
1738
1084
  spinner2.succeed("Backup created successfully");
1739
- console.log(chalk7.green(`\u{1F4E6} Backup saved to: ${backupPath}`));
1085
+ console.log(chalk4.green(`\u{1F4E6} Backup saved to: ${backupPath}`));
1740
1086
  } catch (error) {
1741
1087
  spinner2.fail("Failed to create backup");
1742
1088
  if (error instanceof Error) {
1743
- console.error(chalk7.red(`Error: ${error.message}`));
1089
+ console.error(chalk4.red(`Error: ${error.message}`));
1744
1090
  }
1745
1091
  process.exit(1);
1746
1092
  }
@@ -1748,22 +1094,22 @@ localCommand.addCommand(
1748
1094
  );
1749
1095
  localCommand.addCommand(
1750
1096
  new Command("restore").description("Restore local registry data from backup").argument("<backup-file>", "Path to backup file").action(async (backupFile) => {
1751
- const spinner2 = ora7("Restoring from backup...").start();
1097
+ const spinner2 = ora4("Restoring from backup...").start();
1752
1098
  try {
1753
- if (!fs9.existsSync(backupFile)) {
1099
+ if (!fs7.existsSync(backupFile)) {
1754
1100
  spinner2.fail("Backup file not found");
1755
- console.error(chalk7.red(`File not found: ${backupFile}`));
1101
+ console.error(chalk4.red(`File not found: ${backupFile}`));
1756
1102
  process.exit(1);
1757
1103
  }
1758
1104
  const config = new LocalConfig();
1759
1105
  const server = new LocalRegistryServer(config);
1760
1106
  await server.restore(backupFile);
1761
1107
  spinner2.succeed("Data restored successfully");
1762
- console.log(chalk7.green(`\u2705 Restored from: ${backupFile}`));
1108
+ console.log(chalk4.green(`\u2705 Restored from: ${backupFile}`));
1763
1109
  } catch (error) {
1764
1110
  spinner2.fail("Failed to restore from backup");
1765
1111
  if (error instanceof Error) {
1766
- console.error(chalk7.red(`Error: ${error.message}`));
1112
+ console.error(chalk4.red(`Error: ${error.message}`));
1767
1113
  }
1768
1114
  process.exit(1);
1769
1115
  }
@@ -1771,146 +1117,29 @@ localCommand.addCommand(
1771
1117
  );
1772
1118
  localCommand.addCommand(
1773
1119
  new Command("seed").description("Seed local registry with sample data").action(async () => {
1774
- const spinner2 = ora7("Seeding local registry with sample data...").start();
1120
+ const spinner2 = ora4("Seeding local registry with sample data...").start();
1775
1121
  try {
1776
1122
  const config = new LocalConfig();
1777
1123
  const server = new LocalRegistryServer(config);
1778
1124
  await server.seed();
1779
1125
  spinner2.succeed("Sample data seeded successfully");
1780
1126
  console.log(
1781
- chalk7.green("\u2705 Local registry populated with sample applications")
1127
+ chalk4.green("\u2705 Local registry populated with sample applications")
1782
1128
  );
1783
1129
  console.log(
1784
- chalk7.blue(
1785
- '\u{1F4A1} Run "calimero-registry apps list --local" to see the sample apps'
1130
+ chalk4.blue(
1131
+ '\u{1F4A1} Run "calimero-registry bundle get com.calimero.sample-bundle 1.0.0 --local" to see the sample bundle'
1786
1132
  )
1787
1133
  );
1788
1134
  } catch (error) {
1789
1135
  spinner2.fail("Failed to seed sample data");
1790
1136
  if (error instanceof Error) {
1791
- console.error(chalk7.red(`Error: ${error.message}`));
1137
+ console.error(chalk4.red(`Error: ${error.message}`));
1792
1138
  }
1793
1139
  process.exit(1);
1794
1140
  }
1795
1141
  })
1796
1142
  );
1797
- var RemoteConfig = class {
1798
- configPath;
1799
- config;
1800
- constructor() {
1801
- this.configPath = path7.join(
1802
- os.homedir(),
1803
- ".calimero-registry",
1804
- "remote-config.json"
1805
- );
1806
- this.config = this.loadConfig();
1807
- }
1808
- loadConfig() {
1809
- const defaultConfig = {
1810
- registry: {
1811
- url: "https://apps.calimero.network"
1812
- }
1813
- };
1814
- if (fs9.existsSync(this.configPath)) {
1815
- try {
1816
- const existingConfig = JSON.parse(
1817
- fs9.readFileSync(this.configPath, "utf8")
1818
- );
1819
- return {
1820
- registry: {
1821
- ...defaultConfig.registry,
1822
- ...existingConfig.registry || {}
1823
- }
1824
- };
1825
- } catch {
1826
- console.warn("Failed to load existing config, using defaults");
1827
- }
1828
- }
1829
- return defaultConfig;
1830
- }
1831
- saveConfig() {
1832
- const configDir = path7.dirname(this.configPath);
1833
- if (!fs9.existsSync(configDir)) {
1834
- fs9.mkdirSync(configDir, { recursive: true });
1835
- }
1836
- const configToSave = {
1837
- registry: {
1838
- url: this.config.registry.url,
1839
- // Save API key if it exists in config (regardless of env var)
1840
- ...this.config.registry.apiKey ? { apiKey: this.config.registry.apiKey } : {}
1841
- }
1842
- };
1843
- fs9.writeFileSync(this.configPath, JSON.stringify(configToSave, null, 2));
1844
- }
1845
- /**
1846
- * Get registry URL with priority:
1847
- * 1. Environment variable CALIMERO_REGISTRY_URL
1848
- * 2. Config file value
1849
- * 3. Default value
1850
- */
1851
- getRegistryUrl() {
1852
- return process.env.CALIMERO_REGISTRY_URL || this.config.registry.url || "https://apps.calimero.network";
1853
- }
1854
- /**
1855
- * Set registry URL
1856
- */
1857
- setRegistryUrl(url) {
1858
- this.config.registry.url = url;
1859
- this.saveConfig();
1860
- }
1861
- /**
1862
- * Get API key with priority:
1863
- * 1. Environment variable CALIMERO_API_KEY
1864
- * 2. Config file value
1865
- * 3. undefined
1866
- */
1867
- getApiKey() {
1868
- return process.env.CALIMERO_API_KEY || this.config.registry.apiKey;
1869
- }
1870
- /**
1871
- * Set API key (stored in config file)
1872
- */
1873
- setApiKey(apiKey) {
1874
- this.config.registry.apiKey = apiKey;
1875
- this.saveConfig();
1876
- }
1877
- /**
1878
- * Remove API key from config
1879
- */
1880
- removeApiKey() {
1881
- delete this.config.registry.apiKey;
1882
- this.saveConfig();
1883
- }
1884
- /**
1885
- * Get full configuration
1886
- */
1887
- getConfig() {
1888
- return {
1889
- registry: {
1890
- url: this.getRegistryUrl(),
1891
- // Don't expose API key in getConfig (security)
1892
- apiKey: this.getApiKey() ? "***" : void 0
1893
- }
1894
- };
1895
- }
1896
- /**
1897
- * Get config file path
1898
- */
1899
- getConfigPath() {
1900
- return this.configPath;
1901
- }
1902
- /**
1903
- * Reset to defaults
1904
- */
1905
- reset() {
1906
- this.config = {
1907
- registry: {
1908
- url: "https://apps.calimero.network"
1909
- }
1910
- };
1911
- this.saveConfig();
1912
- }
1913
- };
1914
1143
 
1915
1144
  // src/lib/services.ts
1916
1145
  var SERVICE_NAME_RE = /^[a-z0-9][a-z0-9_-]*$/;
@@ -2026,14 +1255,14 @@ function createCreateCommand() {
2026
1255
  ).option("-o, --output <path>", "Output path for the MPK file").option("--name <name>", "Application name").option("--description <description>", "Application description").option("--author <author>", "Application author").option("--frontend <url>", "Frontend URL").option("--github <url>", "GitHub URL").option("--docs <url>", "Documentation URL").option(
2027
1256
  "--export <interface>",
2028
1257
  "Export interface (can be specified multiple times)",
2029
- (value, prev) => {
2030
- return [...prev || [], value];
1258
+ (value, prev = []) => {
1259
+ return [...prev, value];
2031
1260
  }
2032
1261
  ).option(
2033
1262
  "--use <interface>",
2034
1263
  "Use interface (can be specified multiple times)",
2035
- (value, prev) => {
2036
- return [...prev || [], value];
1264
+ (value, prev = []) => {
1265
+ return [...prev, value];
2037
1266
  }
2038
1267
  ).option("--abi <path>", "Path to ABI JSON file to include in bundle").option(
2039
1268
  "--service <spec>",
@@ -2086,13 +1315,13 @@ Note:
2086
1315
  try {
2087
1316
  let manifestConfig = {};
2088
1317
  if (options.manifest) {
2089
- const manifestPath = path7.resolve(options.manifest);
2090
- if (!fs9.existsSync(manifestPath)) {
1318
+ const manifestPath = path5.resolve(options.manifest);
1319
+ if (!fs7.existsSync(manifestPath)) {
2091
1320
  console.error(`\u274C Manifest file not found: ${options.manifest}`);
2092
1321
  process.exit(1);
2093
1322
  }
2094
1323
  try {
2095
- const manifestContent = fs9.readFileSync(manifestPath, "utf8");
1324
+ const manifestContent = fs7.readFileSync(manifestPath, "utf8");
2096
1325
  const parsed = JSON.parse(manifestContent);
2097
1326
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2098
1327
  console.error(`\u274C Invalid manifest file: ${options.manifest}`);
@@ -2163,13 +1392,13 @@ Note:
2163
1392
  );
2164
1393
  process.exit(1);
2165
1394
  }
2166
- const wasmPath = path7.resolve(wasmFile);
2167
- if (!fs9.existsSync(wasmPath)) {
1395
+ const wasmPath = path5.resolve(wasmFile);
1396
+ if (!fs7.existsSync(wasmPath)) {
2168
1397
  console.error(`\u274C WASM file not found: ${wasmFile}`);
2169
1398
  process.exit(1);
2170
1399
  }
2171
- console.log(`\u{1F4E6} Creating MPK bundle from: ${path7.basename(wasmPath)}`);
2172
- const wasmContent = fs9.readFileSync(wasmPath);
1400
+ console.log(`\u{1F4E6} Creating MPK bundle from: ${path5.basename(wasmPath)}`);
1401
+ const wasmContent = fs7.readFileSync(wasmPath);
2173
1402
  const wasmSize = wasmContent.length;
2174
1403
  const wasmHash = crypto2.createHash("sha256").update(wasmContent).digest("hex");
2175
1404
  let abiArtifact = void 0;
@@ -2178,17 +1407,17 @@ Note:
2178
1407
  const abiPathFromManifest = typeof manifestConfig.abi === "string" ? manifestConfig.abi : null;
2179
1408
  const abiFilePath = abiPathFromOption || abiPathFromManifest;
2180
1409
  if (abiFilePath) {
2181
- const abiResolvedPath = abiPathFromOption ? path7.resolve(abiFilePath) : options.manifest && abiPathFromManifest ? path7.resolve(
2182
- path7.dirname(path7.resolve(options.manifest)),
1410
+ const abiResolvedPath = abiPathFromOption ? path5.resolve(abiFilePath) : options.manifest && abiPathFromManifest ? path5.resolve(
1411
+ path5.dirname(path5.resolve(options.manifest)),
2183
1412
  abiFilePath
2184
- ) : path7.resolve(abiFilePath);
2185
- if (!fs9.existsSync(abiResolvedPath)) {
1413
+ ) : path5.resolve(abiFilePath);
1414
+ if (!fs7.existsSync(abiResolvedPath)) {
2186
1415
  console.error(`\u274C ABI file not found: ${abiFilePath}`);
2187
1416
  console.error(` Resolved path: ${abiResolvedPath}`);
2188
1417
  process.exit(1);
2189
1418
  }
2190
1419
  try {
2191
- abiContent = fs9.readFileSync(abiResolvedPath);
1420
+ abiContent = fs7.readFileSync(abiResolvedPath);
2192
1421
  JSON.parse(abiContent.toString("utf8"));
2193
1422
  const abiHash = crypto2.createHash("sha256").update(abiContent).digest("hex");
2194
1423
  abiArtifact = {
@@ -2197,7 +1426,7 @@ Note:
2197
1426
  size: abiContent.length
2198
1427
  };
2199
1428
  console.log(
2200
- ` Including ABI file: ${path7.basename(abiResolvedPath)}`
1429
+ ` Including ABI file: ${path5.basename(abiResolvedPath)}`
2201
1430
  );
2202
1431
  } catch (error) {
2203
1432
  console.error(
@@ -2221,7 +1450,7 @@ Note:
2221
1450
  const manifestServices = Array.isArray(
2222
1451
  manifestConfig.services
2223
1452
  ) ? manifestConfig.services : [];
2224
- const manifestDir = options.manifest ? path7.dirname(path7.resolve(options.manifest)) : process.cwd();
1453
+ const manifestDir = options.manifest ? path5.dirname(path5.resolve(options.manifest)) : process.cwd();
2225
1454
  const allServiceSources = [
2226
1455
  ...cliServices.map((src) => ({ src, baseDir: process.cwd() })),
2227
1456
  ...manifestServices.map((src) => ({ src, baseDir: manifestDir }))
@@ -2255,15 +1484,15 @@ Note:
2255
1484
  );
2256
1485
  process.exit(1);
2257
1486
  }
2258
- const svcWasmPath = path7.resolve(baseDir, src.wasm);
2259
- if (!fs9.existsSync(svcWasmPath)) {
1487
+ const svcWasmPath = path5.resolve(baseDir, src.wasm);
1488
+ if (!fs7.existsSync(svcWasmPath)) {
2260
1489
  console.error(
2261
1490
  `\u274C Service "${src.name}" WASM not found: ${src.wasm}`
2262
1491
  );
2263
1492
  console.error(` Resolved path: ${svcWasmPath}`);
2264
1493
  process.exit(1);
2265
1494
  }
2266
- const svcWasmContent = fs9.readFileSync(svcWasmPath);
1495
+ const svcWasmContent = fs7.readFileSync(svcWasmPath);
2267
1496
  const svcWasmHash = crypto2.createHash("sha256").update(svcWasmContent).digest("hex");
2268
1497
  const wasmArchivePath = serviceWasmPath(src.name);
2269
1498
  const entry = {
@@ -2279,15 +1508,15 @@ Note:
2279
1508
  content: svcWasmContent
2280
1509
  });
2281
1510
  if (src.abi) {
2282
- const svcAbiPath = path7.resolve(baseDir, src.abi);
2283
- if (!fs9.existsSync(svcAbiPath)) {
1511
+ const svcAbiPath = path5.resolve(baseDir, src.abi);
1512
+ if (!fs7.existsSync(svcAbiPath)) {
2284
1513
  console.error(
2285
1514
  `\u274C Service "${src.name}" ABI not found: ${src.abi}`
2286
1515
  );
2287
1516
  console.error(` Resolved path: ${svcAbiPath}`);
2288
1517
  process.exit(1);
2289
1518
  }
2290
- const svcAbiContent = fs9.readFileSync(svcAbiPath);
1519
+ const svcAbiContent = fs7.readFileSync(svcAbiPath);
2291
1520
  try {
2292
1521
  JSON.parse(svcAbiContent.toString("utf8"));
2293
1522
  } catch (error) {
@@ -2313,7 +1542,7 @@ Note:
2313
1542
  }
2314
1543
  serviceArtifacts.push(entry);
2315
1544
  console.log(
2316
- ` Including service: ${src.name} (${path7.basename(svcWasmPath)})`
1545
+ ` Including service: ${src.name} (${path5.basename(svcWasmPath)})`
2317
1546
  );
2318
1547
  }
2319
1548
  const metadata = {
@@ -2346,30 +1575,30 @@ Note:
2346
1575
  links: Object.keys(links).length > 0 ? links : void 0,
2347
1576
  signature: void 0
2348
1577
  };
2349
- let outputDir = finalOutput ? path7.resolve(finalOutput) : path7.join(process.cwd(), finalPackage, finalVersion);
2350
- if (!fs9.existsSync(outputDir)) {
2351
- fs9.mkdirSync(outputDir, { recursive: true });
1578
+ let outputDir = finalOutput ? path5.resolve(finalOutput) : path5.join(process.cwd(), finalPackage, finalVersion);
1579
+ if (!fs7.existsSync(outputDir)) {
1580
+ fs7.mkdirSync(outputDir, { recursive: true });
2352
1581
  }
2353
- fs9.writeFileSync(
2354
- path7.join(outputDir, "manifest.json"),
1582
+ fs7.writeFileSync(
1583
+ path5.join(outputDir, "manifest.json"),
2355
1584
  JSON.stringify(manifest, null, 2)
2356
1585
  );
2357
- fs9.writeFileSync(path7.join(outputDir, "app.wasm"), wasmContent);
1586
+ fs7.writeFileSync(path5.join(outputDir, "app.wasm"), wasmContent);
2358
1587
  if (abiContent) {
2359
- fs9.writeFileSync(path7.join(outputDir, "abi.json"), abiContent);
1588
+ fs7.writeFileSync(path5.join(outputDir, "abi.json"), abiContent);
2360
1589
  }
2361
- const servicesDir = path7.join(outputDir, "services");
1590
+ const servicesDir = path5.join(outputDir, "services");
2362
1591
  for (const { relPath, content } of serviceFilesToWrite) {
2363
- const dest = path7.join(outputDir, relPath);
2364
- const rel = path7.relative(servicesDir, dest);
2365
- if (rel.startsWith("..") || path7.isAbsolute(rel)) {
1592
+ const dest = path5.join(outputDir, relPath);
1593
+ const rel = path5.relative(servicesDir, dest);
1594
+ if (rel.startsWith("..") || path5.isAbsolute(rel)) {
2366
1595
  console.error(
2367
1596
  `\u274C Refusing to write service file outside services/: ${relPath}`
2368
1597
  );
2369
1598
  process.exit(1);
2370
1599
  }
2371
- fs9.mkdirSync(path7.dirname(dest), { recursive: true });
2372
- fs9.writeFileSync(dest, content);
1600
+ fs7.mkdirSync(path5.dirname(dest), { recursive: true });
1601
+ fs7.writeFileSync(dest, content);
2373
1602
  }
2374
1603
  console.log(`\u2705 Bundle files written to: ${outputDir}`);
2375
1604
  console.log(` Package: ${finalPackage}`);
@@ -2386,7 +1615,7 @@ Note:
2386
1615
  console.log("");
2387
1616
  console.log("Next steps:");
2388
1617
  console.log(
2389
- ` 1. Sign the manifest: mero-sign sign ${path7.join(outputDir, "manifest.json")} --key key.json`
1618
+ ` 1. Sign the manifest: mero-sign sign ${path5.join(outputDir, "manifest.json")} --key key.json`
2390
1619
  );
2391
1620
  console.log(
2392
1621
  ` 2. Push the bundle: calimero-registry bundle push ${outputDir} --remote`
@@ -2455,30 +1684,30 @@ Note:
2455
1684
  );
2456
1685
  process.exit(1);
2457
1686
  }
2458
- const fullPath = path7.resolve(bundleFile);
2459
- if (!fs9.existsSync(fullPath)) {
1687
+ const fullPath = path5.resolve(bundleFile);
1688
+ if (!fs7.existsSync(fullPath)) {
2460
1689
  console.error(`\u274C File not found: ${bundleFile}`);
2461
1690
  process.exit(1);
2462
1691
  }
2463
1692
  mpkPath = fullPath;
2464
- if (fs9.statSync(fullPath).isDirectory()) {
2465
- const manifestInDir = path7.join(fullPath, "manifest.json");
2466
- const wasmInDir = path7.join(fullPath, "app.wasm");
2467
- if (!fs9.existsSync(manifestInDir)) {
1693
+ if (fs7.statSync(fullPath).isDirectory()) {
1694
+ const manifestInDir = path5.join(fullPath, "manifest.json");
1695
+ const wasmInDir = path5.join(fullPath, "app.wasm");
1696
+ if (!fs7.existsSync(manifestInDir)) {
2468
1697
  console.error(
2469
1698
  `\u274C manifest.json not found in directory: ${fullPath}`
2470
1699
  );
2471
1700
  process.exit(1);
2472
1701
  }
2473
- if (!fs9.existsSync(wasmInDir)) {
1702
+ if (!fs7.existsSync(wasmInDir)) {
2474
1703
  console.error(`\u274C app.wasm not found in directory: ${fullPath}`);
2475
1704
  process.exit(1);
2476
1705
  }
2477
- tempMpk = path7.join(fullPath, `.temp-push-${Date.now()}.mpk`);
1706
+ tempMpk = path5.join(fullPath, `.temp-push-${Date.now()}.mpk`);
2478
1707
  let dirManifest;
2479
1708
  try {
2480
1709
  dirManifest = JSON.parse(
2481
- fs9.readFileSync(manifestInDir, "utf8")
1710
+ fs7.readFileSync(manifestInDir, "utf8")
2482
1711
  );
2483
1712
  } catch (e) {
2484
1713
  console.error(
@@ -2511,7 +1740,7 @@ Note:
2511
1740
  process.exit(1);
2512
1741
  }
2513
1742
  for (const f of archiveFiles) {
2514
- if (!fs9.existsSync(path7.join(fullPath, f))) {
1743
+ if (!fs7.existsSync(path5.join(fullPath, f))) {
2515
1744
  console.error(
2516
1745
  `\u274C Bundle file referenced by manifest not found: ${f}`
2517
1746
  );
@@ -2527,7 +1756,7 @@ Note:
2527
1756
  `\u{1F4E6} Packed directory into temporary bundle (${archiveFiles.length} files)`
2528
1757
  );
2529
1758
  }
2530
- console.log(`\u{1F4E6} Processing bundle: ${path7.basename(mpkPath)}`);
1759
+ console.log(`\u{1F4E6} Processing bundle: ${path5.basename(mpkPath)}`);
2531
1760
  const manifest = await extractManifest(mpkPath);
2532
1761
  if (!manifest) {
2533
1762
  console.error("\u274C manifest.json not found in bundle");
@@ -2574,8 +1803,8 @@ Note:
2574
1803
  console.error("\u274C Failed to push bundle:", message);
2575
1804
  process.exit(1);
2576
1805
  } finally {
2577
- if (tempMpk && fs9.existsSync(tempMpk)) {
2578
- fs9.rmSync(tempMpk);
1806
+ if (tempMpk && fs7.existsSync(tempMpk)) {
1807
+ fs7.rmSync(tempMpk);
2579
1808
  }
2580
1809
  }
2581
1810
  });
@@ -2643,12 +1872,12 @@ Examples:
2643
1872
  };
2644
1873
  if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
2645
1874
  if (options.manifest) {
2646
- const manifestPath = path7.resolve(options.manifest);
2647
- if (!fs9.existsSync(manifestPath)) {
1875
+ const manifestPath = path5.resolve(options.manifest);
1876
+ if (!fs7.existsSync(manifestPath)) {
2648
1877
  console.error(`\u274C Manifest file not found: ${options.manifest}`);
2649
1878
  process.exit(1);
2650
1879
  }
2651
- const raw = fs9.readFileSync(manifestPath, "utf8");
1880
+ const raw = fs7.readFileSync(manifestPath, "utf8");
2652
1881
  let manifest2;
2653
1882
  try {
2654
1883
  manifest2 = JSON.parse(raw);
@@ -2735,8 +1964,8 @@ Examples:
2735
1964
  if (!manifest.links) manifest.links = {};
2736
1965
  manifest.links.docs = options.docs;
2737
1966
  }
2738
- const outputPath = path7.resolve(options.output || "manifest.json");
2739
- fs9.writeFileSync(outputPath, JSON.stringify(manifest, null, 2));
1967
+ const outputPath = path5.resolve(options.output || "manifest.json");
1968
+ fs7.writeFileSync(outputPath, JSON.stringify(manifest, null, 2));
2740
1969
  console.log(`\u2705 Wrote modified manifest to: ${outputPath}`);
2741
1970
  console.log("");
2742
1971
  console.log("Next steps:");
@@ -2756,7 +1985,7 @@ Examples:
2756
1985
  async function pushToRemote(bundlePath, manifest, registryUrl, apiKey) {
2757
1986
  try {
2758
1987
  console.log(`\u{1F4E4} Pushing to remote registry: ${registryUrl}`);
2759
- const bundleBuffer = fs9.readFileSync(bundlePath);
1988
+ const bundleBuffer = fs7.readFileSync(bundlePath);
2760
1989
  const bundleSize = bundleBuffer.length;
2761
1990
  console.log(` Bundle size: ${bundleSize} bytes`);
2762
1991
  const bundleHex = bundleBuffer.toString("hex");
@@ -2936,25 +2165,25 @@ async function extractManifest(bundlePath) {
2936
2165
  if (entry.path === "manifest.json") ;
2937
2166
  }
2938
2167
  });
2939
- const extractDir = path7.join(path7.dirname(bundlePath), `.temp-${Date.now()}`);
2940
- if (!fs9.existsSync(extractDir)) {
2941
- fs9.mkdirSync(extractDir);
2168
+ const extractDir = path5.join(path5.dirname(bundlePath), `.temp-${Date.now()}`);
2169
+ if (!fs7.existsSync(extractDir)) {
2170
+ fs7.mkdirSync(extractDir);
2942
2171
  }
2943
2172
  try {
2944
2173
  await tar.x({
2945
2174
  file: bundlePath,
2946
2175
  cwd: extractDir,
2947
- filter: (path8) => path8 === "manifest.json"
2176
+ filter: (path6) => path6 === "manifest.json"
2948
2177
  });
2949
- const manifestPath = path7.join(extractDir, "manifest.json");
2950
- if (fs9.existsSync(manifestPath)) {
2951
- const content = fs9.readFileSync(manifestPath, "utf8");
2178
+ const manifestPath = path5.join(extractDir, "manifest.json");
2179
+ if (fs7.existsSync(manifestPath)) {
2180
+ const content = fs7.readFileSync(manifestPath, "utf8");
2952
2181
  manifestContent = content;
2953
2182
  }
2954
2183
  } catch {
2955
2184
  } finally {
2956
- if (fs9.existsSync(extractDir)) {
2957
- fs9.rmSync(extractDir, { recursive: true, force: true });
2185
+ if (fs7.existsSync(extractDir)) {
2186
+ fs7.rmSync(extractDir, { recursive: true, force: true });
2958
2187
  }
2959
2188
  }
2960
2189
  if (manifestContent) {
@@ -2978,29 +2207,29 @@ function createConfigSetCommand() {
2978
2207
  case "url":
2979
2208
  config.setRegistryUrl(value);
2980
2209
  console.log(
2981
- chalk7.green(`\u2705 Registry URL set to: ${chalk7.bold(value)}`)
2210
+ chalk4.green(`\u2705 Registry URL set to: ${chalk4.bold(value)}`)
2982
2211
  );
2983
2212
  break;
2984
2213
  case "api-key":
2985
2214
  case "apiKey":
2986
2215
  config.setApiKey(value);
2987
- console.log(chalk7.green("\u2705 API key set successfully"));
2216
+ console.log(chalk4.green("\u2705 API key set successfully"));
2988
2217
  console.log(
2989
- chalk7.yellow(
2218
+ chalk4.yellow(
2990
2219
  "\u{1F4A1} Note: API key is stored in plain text. Consider using CALIMERO_API_KEY environment variable for better security."
2991
2220
  )
2992
2221
  );
2993
2222
  break;
2994
2223
  default:
2995
- console.error(chalk7.red(`\u274C Unknown configuration key: ${key}`));
2996
- console.log(chalk7.blue("\nAvailable keys:"));
2224
+ console.error(chalk4.red(`\u274C Unknown configuration key: ${key}`));
2225
+ console.log(chalk4.blue("\nAvailable keys:"));
2997
2226
  console.log(" registry-url - Default registry URL");
2998
2227
  console.log(" api-key - API key for authentication");
2999
2228
  process.exit(1);
3000
2229
  }
3001
2230
  } catch (error) {
3002
2231
  const message = error instanceof Error ? error.message : String(error);
3003
- console.error(chalk7.red("\u274C Failed to set configuration:"), message);
2232
+ console.error(chalk4.red("\u274C Failed to set configuration:"), message);
3004
2233
  process.exit(1);
3005
2234
  }
3006
2235
  });
@@ -3022,7 +2251,7 @@ function createConfigGetCommand() {
3022
2251
  const masked = apiKey.length > 8 ? `${apiKey.substring(0, 4)}...${apiKey.substring(apiKey.length - 4)}` : "***";
3023
2252
  console.log(masked);
3024
2253
  console.log(
3025
- chalk7.yellow(
2254
+ chalk4.yellow(
3026
2255
  '\u{1F4A1} Note: API key is masked. Use "config list" to see source.'
3027
2256
  )
3028
2257
  );
@@ -3032,15 +2261,15 @@ function createConfigGetCommand() {
3032
2261
  break;
3033
2262
  }
3034
2263
  default:
3035
- console.error(chalk7.red(`\u274C Unknown configuration key: ${key}`));
3036
- console.log(chalk7.blue("\nAvailable keys:"));
2264
+ console.error(chalk4.red(`\u274C Unknown configuration key: ${key}`));
2265
+ console.log(chalk4.blue("\nAvailable keys:"));
3037
2266
  console.log(" registry-url - Default registry URL");
3038
2267
  console.log(" api-key - API key for authentication");
3039
2268
  process.exit(1);
3040
2269
  }
3041
2270
  } catch (error) {
3042
2271
  const message = error instanceof Error ? error.message : String(error);
3043
- console.error(chalk7.red("\u274C Failed to get configuration:"), message);
2272
+ console.error(chalk4.red("\u274C Failed to get configuration:"), message);
3044
2273
  process.exit(1);
3045
2274
  }
3046
2275
  });
@@ -3049,43 +2278,43 @@ function createConfigListCommand() {
3049
2278
  return new Command("list").description("List all configuration values").alias("ls").action(() => {
3050
2279
  try {
3051
2280
  const config = new RemoteConfig();
3052
- console.log(chalk7.blue("\n\u{1F4CB} Remote Registry Configuration\n"));
2281
+ console.log(chalk4.blue("\n\u{1F4CB} Remote Registry Configuration\n"));
3053
2282
  const configPath = config.getConfigPath();
3054
- const configFileExists = fs9.existsSync(configPath);
2283
+ const configFileExists = fs7.existsSync(configPath);
3055
2284
  const url = config.getRegistryUrl();
3056
2285
  let urlSource;
3057
2286
  if (process.env.CALIMERO_REGISTRY_URL) {
3058
- urlSource = chalk7.yellow("(from CALIMERO_REGISTRY_URL env var)");
2287
+ urlSource = chalk4.yellow("(from CALIMERO_REGISTRY_URL env var)");
3059
2288
  } else if (configFileExists) {
3060
- urlSource = chalk7.gray("(from config file)");
2289
+ urlSource = chalk4.gray("(from config file)");
3061
2290
  } else {
3062
- urlSource = chalk7.gray("(default)");
2291
+ urlSource = chalk4.gray("(default)");
3063
2292
  }
3064
- console.log(` ${chalk7.bold("Registry URL:")} ${url} ${urlSource}`);
2293
+ console.log(` ${chalk4.bold("Registry URL:")} ${url} ${urlSource}`);
3065
2294
  const apiKey = config.getApiKey();
3066
2295
  if (apiKey) {
3067
2296
  let apiKeySource;
3068
2297
  if (process.env.CALIMERO_API_KEY) {
3069
- apiKeySource = chalk7.yellow("(from CALIMERO_API_KEY env var)");
2298
+ apiKeySource = chalk4.yellow("(from CALIMERO_API_KEY env var)");
3070
2299
  } else if (configFileExists) {
3071
- apiKeySource = chalk7.gray("(from config file)");
2300
+ apiKeySource = chalk4.gray("(from config file)");
3072
2301
  } else {
3073
- apiKeySource = chalk7.gray("(default)");
2302
+ apiKeySource = chalk4.gray("(default)");
3074
2303
  }
3075
2304
  const masked = apiKey.length > 8 ? `${apiKey.substring(0, 4)}...${apiKey.substring(apiKey.length - 4)}` : "***";
3076
- console.log(` ${chalk7.bold("API Key:")} ${masked} ${apiKeySource}`);
2305
+ console.log(` ${chalk4.bold("API Key:")} ${masked} ${apiKeySource}`);
3077
2306
  } else {
3078
- console.log(` ${chalk7.bold("API Key:")} ${chalk7.gray("(not set)")}`);
2307
+ console.log(` ${chalk4.bold("API Key:")} ${chalk4.gray("(not set)")}`);
3079
2308
  }
3080
- console.log(chalk7.blue(`
2309
+ console.log(chalk4.blue(`
3081
2310
  \u{1F4C1} Config file: ${configPath}`));
3082
2311
  if (!configFileExists) {
3083
- console.log(chalk7.gray(" (file does not exist, using defaults)"));
2312
+ console.log(chalk4.gray(" (file does not exist, using defaults)"));
3084
2313
  }
3085
2314
  console.log();
3086
2315
  } catch (error) {
3087
2316
  const message = error instanceof Error ? error.message : String(error);
3088
- console.error(chalk7.red("\u274C Failed to list configuration:"), message);
2317
+ console.error(chalk4.red("\u274C Failed to list configuration:"), message);
3089
2318
  process.exit(1);
3090
2319
  }
3091
2320
  });
@@ -3095,10 +2324,10 @@ function createConfigResetCommand() {
3095
2324
  try {
3096
2325
  if (!options.force) {
3097
2326
  console.error(
3098
- chalk7.red("\u274C Configuration reset requires --force flag")
2327
+ chalk4.red("\u274C Configuration reset requires --force flag")
3099
2328
  );
3100
2329
  console.log(
3101
- chalk7.yellow(
2330
+ chalk4.yellow(
3102
2331
  "\u26A0\uFE0F This will reset all configuration to defaults. Use --force to confirm."
3103
2332
  )
3104
2333
  );
@@ -3106,13 +2335,13 @@ function createConfigResetCommand() {
3106
2335
  }
3107
2336
  const config = new RemoteConfig();
3108
2337
  config.reset();
3109
- console.log(chalk7.green("\u2705 Configuration reset to defaults"));
3110
- console.log(chalk7.blue("\nDefault values:"));
2338
+ console.log(chalk4.green("\u2705 Configuration reset to defaults"));
2339
+ console.log(chalk4.blue("\nDefault values:"));
3111
2340
  console.log(" Registry URL: https://apps.calimero.network");
3112
2341
  console.log(" API Key: (not set)");
3113
2342
  } catch (error) {
3114
2343
  const message = error instanceof Error ? error.message : String(error);
3115
- console.error(chalk7.red("\u274C Failed to reset configuration:"), message);
2344
+ console.error(chalk4.red("\u274C Failed to reset configuration:"), message);
3116
2345
  process.exit(1);
3117
2346
  }
3118
2347
  });
@@ -3159,13 +2388,13 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3159
2388
  "List organizations you belong to (uses API token to resolve identity)"
3160
2389
  ).action(async (_options, command) => {
3161
2390
  const { url, timeout } = getGlobalOpts(command);
3162
- const spinner2 = ora7("Resolving identity...").start();
2391
+ const spinner2 = ora4("Resolving identity...").start();
3163
2392
  let authHeaders;
3164
2393
  try {
3165
2394
  authHeaders = getAuthHeaders();
3166
2395
  } catch (e) {
3167
2396
  spinner2.fail("API token required");
3168
- console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2397
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
3169
2398
  process.exit(1);
3170
2399
  }
3171
2400
  const base = url.replace(/\/$/, "");
@@ -3179,7 +2408,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3179
2408
  if (status !== 200 || !data?.user?.email) {
3180
2409
  spinner2.fail("Could not resolve identity from API token");
3181
2410
  console.error(
3182
- chalk7.red(
2411
+ chalk4.red(
3183
2412
  "Ensure your API token is valid. Get a new one from the web UI."
3184
2413
  )
3185
2414
  );
@@ -3189,7 +2418,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3189
2418
  spinner2.text = `Fetching organizations for ${myEmail}...`;
3190
2419
  } catch (e) {
3191
2420
  spinner2.fail("Request failed");
3192
- console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2421
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
3193
2422
  process.exit(1);
3194
2423
  }
3195
2424
  const apiUrl = `${base}/api/v2/orgs?member=${encodeURIComponent(myEmail)}`;
@@ -3201,13 +2430,13 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3201
2430
  });
3202
2431
  if (status !== 200) {
3203
2432
  spinner2.fail("Failed to list organizations");
3204
- console.error(chalk7.red(JSON.stringify(data)));
2433
+ console.error(chalk4.red(JSON.stringify(data)));
3205
2434
  process.exit(1);
3206
2435
  }
3207
2436
  const orgs = Array.isArray(data) ? data : [];
3208
2437
  spinner2.succeed(`Found ${orgs.length} organization(s)`);
3209
2438
  if (orgs.length === 0) {
3210
- console.log(chalk7.yellow("No organizations found"));
2439
+ console.log(chalk4.yellow("No organizations found"));
3211
2440
  return;
3212
2441
  }
3213
2442
  const memberResults = await Promise.all(
@@ -3223,13 +2452,13 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3223
2452
  const myMember = members.find((m) => m.email === myEmail);
3224
2453
  const role = myMember?.role ?? "?";
3225
2454
  const count = members.length;
3226
- const roleLabel = role === "admin" ? chalk7.yellow("admin") : chalk7.gray(role);
3227
- return `${chalk7.white(o.slug)} ${chalk7.gray(o.name)} ${chalk7.gray(`${count} member${count !== 1 ? "s" : ""}`)} ${roleLabel}`;
2455
+ const roleLabel = role === "admin" ? chalk4.yellow("admin") : chalk4.gray(role);
2456
+ return `${chalk4.white(o.slug)} ${chalk4.gray(o.name)} ${chalk4.gray(`${count} member${count !== 1 ? "s" : ""}`)} ${roleLabel}`;
3228
2457
  });
3229
2458
  console.log(lines.join("\n"));
3230
2459
  } catch (e) {
3231
2460
  spinner2.fail("Request failed");
3232
- console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2461
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
3233
2462
  process.exit(1);
3234
2463
  }
3235
2464
  })
@@ -3237,7 +2466,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3237
2466
  new Command("create").description("Create a new organization (requires API token)").requiredOption("-n, --name <name>", "Organization display name").requiredOption("-s, --slug <slug>", "Organization slug (e.g. my-org)").action(
3238
2467
  async (options, command) => {
3239
2468
  const { url, timeout } = getGlobalOpts(command);
3240
- const spinner2 = ora7("Creating organization...").start();
2469
+ const spinner2 = ora4("Creating organization...").start();
3241
2470
  try {
3242
2471
  const authHeaders = getAuthHeaders();
3243
2472
  const pathname = "/api/v2/orgs";
@@ -3255,15 +2484,15 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3255
2484
  if (status >= 400) {
3256
2485
  const err = data;
3257
2486
  spinner2.fail(err?.message || `HTTP ${status}`);
3258
- console.error(chalk7.red(JSON.stringify(data)));
2487
+ console.error(chalk4.red(JSON.stringify(data)));
3259
2488
  process.exit(1);
3260
2489
  }
3261
2490
  spinner2.succeed("Organization created");
3262
- console.log(chalk7.green(JSON.stringify(data, null, 2)));
2491
+ console.log(chalk4.green(JSON.stringify(data, null, 2)));
3263
2492
  } catch (e) {
3264
2493
  spinner2.fail("Failed");
3265
2494
  console.error(
3266
- chalk7.red(e instanceof Error ? e.message : String(e))
2495
+ chalk4.red(e instanceof Error ? e.message : String(e))
3267
2496
  );
3268
2497
  process.exit(1);
3269
2498
  }
@@ -3274,7 +2503,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3274
2503
  const { url, timeout } = getGlobalOpts(command);
3275
2504
  const base = url.replace(/\/$/, "");
3276
2505
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}`;
3277
- const spinner2 = ora7("Fetching organization...").start();
2506
+ const spinner2 = ora4("Fetching organization...").start();
3278
2507
  try {
3279
2508
  const { data, status } = await fetchJson(`${base}${pathname}`, { method: "GET", timeout });
3280
2509
  if (status === 404) {
@@ -3283,14 +2512,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3283
2512
  }
3284
2513
  if (status !== 200) {
3285
2514
  spinner2.fail("Request failed");
3286
- console.error(chalk7.red(JSON.stringify(data)));
2515
+ console.error(chalk4.red(JSON.stringify(data)));
3287
2516
  process.exit(1);
3288
2517
  }
3289
2518
  spinner2.succeed("OK");
3290
2519
  console.log(JSON.stringify(data, null, 2));
3291
2520
  } catch (e) {
3292
2521
  spinner2.fail("Request failed");
3293
- console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2522
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
3294
2523
  process.exit(1);
3295
2524
  }
3296
2525
  })
@@ -3298,7 +2527,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3298
2527
  new Command("update").description("Update organization (name, metadata)").argument("<orgId>", "Organization id or slug").option("-n, --name <name>", "New display name").option("-m, --metadata <json>", "Metadata JSON object").action(
3299
2528
  async (orgId, options, command) => {
3300
2529
  const { url, timeout } = getGlobalOpts(command);
3301
- const spinner2 = ora7("Updating organization...").start();
2530
+ const spinner2 = ora4("Updating organization...").start();
3302
2531
  try {
3303
2532
  const authHeaders = getAuthHeaders();
3304
2533
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}`;
@@ -3323,7 +2552,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3323
2552
  spinner2.fail(
3324
2553
  data?.message || `HTTP ${status}`
3325
2554
  );
3326
- console.error(chalk7.red(JSON.stringify(data)));
2555
+ console.error(chalk4.red(JSON.stringify(data)));
3327
2556
  process.exit(1);
3328
2557
  }
3329
2558
  spinner2.succeed("Updated");
@@ -3331,7 +2560,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3331
2560
  } catch (e) {
3332
2561
  spinner2.fail("Failed");
3333
2562
  console.error(
3334
- chalk7.red(e instanceof Error ? e.message : String(e))
2563
+ chalk4.red(e instanceof Error ? e.message : String(e))
3335
2564
  );
3336
2565
  process.exit(1);
3337
2566
  }
@@ -3349,7 +2578,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3349
2578
  });
3350
2579
  const confirmed = await new Promise((resolve) => {
3351
2580
  rl.question(
3352
- chalk7.yellow(
2581
+ chalk4.yellow(
3353
2582
  `Delete organization "${orgId}" and all its members/packages? This cannot be undone. Type "yes" to confirm: `
3354
2583
  ),
3355
2584
  (answer) => {
@@ -3359,11 +2588,11 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3359
2588
  );
3360
2589
  });
3361
2590
  if (!confirmed) {
3362
- console.log(chalk7.gray("Aborted."));
2591
+ console.log(chalk4.gray("Aborted."));
3363
2592
  return;
3364
2593
  }
3365
2594
  }
3366
- const spinner2 = ora7("Deleting organization...").start();
2595
+ const spinner2 = ora4("Deleting organization...").start();
3367
2596
  try {
3368
2597
  const authHeaders = getAuthHeaders();
3369
2598
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}`;
@@ -3377,14 +2606,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3377
2606
  spinner2.fail(
3378
2607
  data?.message || `HTTP ${status}`
3379
2608
  );
3380
- console.error(chalk7.red(JSON.stringify(data)));
2609
+ console.error(chalk4.red(JSON.stringify(data)));
3381
2610
  process.exit(1);
3382
2611
  }
3383
2612
  spinner2.succeed("Organization deleted");
3384
2613
  } catch (e) {
3385
2614
  spinner2.fail("Failed");
3386
2615
  console.error(
3387
- chalk7.red(e instanceof Error ? e.message : String(e))
2616
+ chalk4.red(e instanceof Error ? e.message : String(e))
3388
2617
  );
3389
2618
  process.exit(1);
3390
2619
  }
@@ -3396,12 +2625,12 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3396
2625
  const { url, timeout } = getGlobalOpts(command);
3397
2626
  const base = url.replace(/\/$/, "");
3398
2627
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members`;
3399
- const spinner2 = ora7("Fetching members...").start();
2628
+ const spinner2 = ora4("Fetching members...").start();
3400
2629
  try {
3401
2630
  const { data, status } = await fetchJson(`${base}${pathname}`, { method: "GET", timeout });
3402
2631
  if (status !== 200) {
3403
2632
  spinner2.fail("Failed");
3404
- console.error(chalk7.red(JSON.stringify(data)));
2633
+ console.error(chalk4.red(JSON.stringify(data)));
3405
2634
  process.exit(1);
3406
2635
  }
3407
2636
  spinner2.succeed("OK");
@@ -3410,7 +2639,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3410
2639
  } catch (e) {
3411
2640
  spinner2.fail("Request failed");
3412
2641
  console.error(
3413
- chalk7.red(e instanceof Error ? e.message : String(e))
2642
+ chalk4.red(e instanceof Error ? e.message : String(e))
3414
2643
  );
3415
2644
  process.exit(1);
3416
2645
  }
@@ -3419,7 +2648,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3419
2648
  new Command("add").description("Add a member by email").argument("<orgId>", "Organization id or slug").argument("<email>", "Member email address").option("-r, --role <role>", "Role: member or admin", "member").action(
3420
2649
  async (orgId, email, options, command) => {
3421
2650
  const { url, timeout } = getGlobalOpts(command);
3422
- const spinner2 = ora7("Adding member...").start();
2651
+ const spinner2 = ora4("Adding member...").start();
3423
2652
  try {
3424
2653
  const authHeaders = getAuthHeaders();
3425
2654
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members`;
@@ -3438,14 +2667,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3438
2667
  spinner2.fail(
3439
2668
  data?.message || `HTTP ${status}`
3440
2669
  );
3441
- console.error(chalk7.red(JSON.stringify(data)));
2670
+ console.error(chalk4.red(JSON.stringify(data)));
3442
2671
  process.exit(1);
3443
2672
  }
3444
2673
  spinner2.succeed("Member added");
3445
2674
  } catch (e) {
3446
2675
  spinner2.fail("Failed");
3447
2676
  console.error(
3448
- chalk7.red(e instanceof Error ? e.message : String(e))
2677
+ chalk4.red(e instanceof Error ? e.message : String(e))
3449
2678
  );
3450
2679
  process.exit(1);
3451
2680
  }
@@ -3456,7 +2685,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3456
2685
  async (orgId, email, options, command) => {
3457
2686
  const { url, timeout } = getGlobalOpts(command);
3458
2687
  const role = options.role === "admin" ? "admin" : "member";
3459
- const spinner2 = ora7("Updating member role...").start();
2688
+ const spinner2 = ora4("Updating member role...").start();
3460
2689
  try {
3461
2690
  const authHeaders = getAuthHeaders();
3462
2691
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(email.trim())}`;
@@ -3472,14 +2701,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3472
2701
  spinner2.fail(
3473
2702
  data?.message || `HTTP ${status}`
3474
2703
  );
3475
- console.error(chalk7.red(JSON.stringify(data)));
2704
+ console.error(chalk4.red(JSON.stringify(data)));
3476
2705
  process.exit(1);
3477
2706
  }
3478
2707
  spinner2.succeed(`Role updated to "${role}"`);
3479
2708
  } catch (e) {
3480
2709
  spinner2.fail("Failed");
3481
2710
  console.error(
3482
- chalk7.red(e instanceof Error ? e.message : String(e))
2711
+ chalk4.red(e instanceof Error ? e.message : String(e))
3483
2712
  );
3484
2713
  process.exit(1);
3485
2714
  }
@@ -3489,7 +2718,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3489
2718
  new Command("remove").description("Remove a member by email").argument("<orgId>", "Organization id or slug").argument("<email>", "Member email address").action(
3490
2719
  async (orgId, email, _options, command) => {
3491
2720
  const { url, timeout } = getGlobalOpts(command);
3492
- const spinner2 = ora7("Removing member...").start();
2721
+ const spinner2 = ora4("Removing member...").start();
3493
2722
  try {
3494
2723
  const authHeaders = getAuthHeaders();
3495
2724
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(email.trim())}`;
@@ -3503,14 +2732,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3503
2732
  spinner2.fail(
3504
2733
  data?.message || `HTTP ${status}`
3505
2734
  );
3506
- console.error(chalk7.red(JSON.stringify(data)));
2735
+ console.error(chalk4.red(JSON.stringify(data)));
3507
2736
  process.exit(1);
3508
2737
  }
3509
2738
  spinner2.succeed("Member removed");
3510
2739
  } catch (e) {
3511
2740
  spinner2.fail("Failed");
3512
2741
  console.error(
3513
- chalk7.red(e instanceof Error ? e.message : String(e))
2742
+ chalk4.red(e instanceof Error ? e.message : String(e))
3514
2743
  );
3515
2744
  process.exit(1);
3516
2745
  }
@@ -3522,7 +2751,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3522
2751
  new Command("link").description("Link a package to the organization").argument("<orgId>", "Organization id or slug").argument("<package>", "Package name").action(
3523
2752
  async (orgId, pkg, _options, command) => {
3524
2753
  const { url, timeout } = getGlobalOpts(command);
3525
- const spinner2 = ora7("Linking package...").start();
2754
+ const spinner2 = ora4("Linking package...").start();
3526
2755
  try {
3527
2756
  const authHeaders = getAuthHeaders();
3528
2757
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/packages`;
@@ -3538,14 +2767,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3538
2767
  spinner2.fail(
3539
2768
  data?.message || `HTTP ${status}`
3540
2769
  );
3541
- console.error(chalk7.red(JSON.stringify(data)));
2770
+ console.error(chalk4.red(JSON.stringify(data)));
3542
2771
  process.exit(1);
3543
2772
  }
3544
2773
  spinner2.succeed("Package linked");
3545
2774
  } catch (e) {
3546
2775
  spinner2.fail("Failed");
3547
2776
  console.error(
3548
- chalk7.red(e instanceof Error ? e.message : String(e))
2777
+ chalk4.red(e instanceof Error ? e.message : String(e))
3549
2778
  );
3550
2779
  process.exit(1);
3551
2780
  }
@@ -3555,7 +2784,7 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3555
2784
  new Command("unlink").description("Unlink a package from the organization").argument("<orgId>", "Organization id or slug").argument("<package>", "Package name").action(
3556
2785
  async (orgId, pkg, _options, command) => {
3557
2786
  const { url, timeout } = getGlobalOpts(command);
3558
- const spinner2 = ora7("Unlinking package...").start();
2787
+ const spinner2 = ora4("Unlinking package...").start();
3559
2788
  try {
3560
2789
  const authHeaders = getAuthHeaders();
3561
2790
  const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/packages/${encodeURIComponent(pkg.trim())}`;
@@ -3569,14 +2798,14 @@ var orgCommand = new Command("org").description("Manage organizations (create, l
3569
2798
  spinner2.fail(
3570
2799
  data?.message || `HTTP ${status}`
3571
2800
  );
3572
- console.error(chalk7.red(JSON.stringify(data)));
2801
+ console.error(chalk4.red(JSON.stringify(data)));
3573
2802
  process.exit(1);
3574
2803
  }
3575
2804
  spinner2.succeed("Package unlinked");
3576
2805
  } catch (e) {
3577
2806
  spinner2.fail("Failed");
3578
2807
  console.error(
3579
- chalk7.red(e instanceof Error ? e.message : String(e))
2808
+ chalk4.red(e instanceof Error ? e.message : String(e))
3580
2809
  );
3581
2810
  process.exit(1);
3582
2811
  }
@@ -3596,10 +2825,10 @@ program.addHelpText(
3596
2825
  "after",
3597
2826
  `
3598
2827
  Examples:
3599
- $ calimero-registry apps list
3600
- $ calimero-registry apps create --file manifest.json
2828
+ $ calimero-registry org list
2829
+ $ calimero-registry bundle get com.example.my-app 1.0.0
3601
2830
  $ calimero-registry local start
3602
- $ calimero-registry health --local
2831
+ $ calimero-registry health
3603
2832
 
3604
2833
  For more information, visit: https://github.com/calimero-network/app-registry
3605
2834
  `
@@ -3611,9 +2840,6 @@ program.option(
3611
2840
  "10000"
3612
2841
  );
3613
2842
  program.option("--local", "Use local registry instead of remote API");
3614
- program.addCommand(appsCommand);
3615
- program.addCommand(developersCommand);
3616
- program.addCommand(attestationsCommand);
3617
2843
  program.addCommand(healthCommand);
3618
2844
  program.addCommand(ipfsCommand);
3619
2845
  program.addCommand(localCommand);
@@ -3628,9 +2854,9 @@ try {
3628
2854
  process.exit(err.exitCode ?? 0);
3629
2855
  }
3630
2856
  if (err instanceof Error) {
3631
- console.error(chalk7.red("Error:"), err.message);
2857
+ console.error(chalk4.red("Error:"), err.message);
3632
2858
  } else {
3633
- console.error(chalk7.red("Unknown error occurred"));
2859
+ console.error(chalk4.red("Unknown error occurred"));
3634
2860
  }
3635
2861
  process.exit(1);
3636
2862
  }