@calimero-network/registry-cli 1.10.0 → 1.12.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,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import chalk6 from 'chalk';
3
+ import chalk7 from 'chalk';
4
4
  import { createRequire } from 'module';
5
- import ora6 from 'ora';
5
+ import ora7 from 'ora';
6
6
  import { table } from 'table';
7
7
  import axios from 'axios';
8
8
  import fs9, { existsSync, writeFileSync } from 'fs';
@@ -1039,14 +1039,14 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1039
1039
  globalOpts?.url,
1040
1040
  parseInt(globalOpts?.timeout || "10000")
1041
1041
  );
1042
- const spinner2 = ora6("Fetching applications...").start();
1042
+ const spinner2 = ora7("Fetching applications...").start();
1043
1043
  try {
1044
1044
  const apps = await client.getApps({
1045
1045
  name: options.name
1046
1046
  });
1047
1047
  spinner2.succeed(`Found ${apps.length} application(s)`);
1048
1048
  if (apps.length === 0) {
1049
- console.log(chalk6.yellow("No applications found"));
1049
+ console.log(chalk7.yellow("No applications found"));
1050
1050
  return;
1051
1051
  }
1052
1052
  const tableData = [
@@ -1063,7 +1063,7 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1063
1063
  } catch (error) {
1064
1064
  spinner2.fail("Failed to fetch applications");
1065
1065
  if (error instanceof Error) {
1066
- console.error(chalk6.red(`Error: ${error.message}`));
1066
+ console.error(chalk7.red(`Error: ${error.message}`));
1067
1067
  }
1068
1068
  process.exit(1);
1069
1069
  }
@@ -1077,12 +1077,12 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1077
1077
  globalOpts?.url,
1078
1078
  parseInt(globalOpts?.timeout || "10000")
1079
1079
  );
1080
- const spinner2 = ora6(`Fetching versions for ${appId}...`).start();
1080
+ const spinner2 = ora7(`Fetching versions for ${appId}...`).start();
1081
1081
  try {
1082
1082
  const versions = await client.getAppVersions(appId);
1083
1083
  spinner2.succeed(`Found ${versions.length} version(s)`);
1084
1084
  if (versions.length === 0) {
1085
- console.log(chalk6.yellow("No versions found"));
1085
+ console.log(chalk7.yellow("No versions found"));
1086
1086
  return;
1087
1087
  }
1088
1088
  const tableData = [
@@ -1090,14 +1090,14 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1090
1090
  ...versions.map((version2) => [
1091
1091
  version2.semver,
1092
1092
  version2.cid.substring(0, 12) + "...",
1093
- version2.yanked ? chalk6.red("Yes") : chalk6.green("No")
1093
+ version2.yanked ? chalk7.red("Yes") : chalk7.green("No")
1094
1094
  ])
1095
1095
  ];
1096
1096
  console.log(table(tableData));
1097
1097
  } catch (error) {
1098
1098
  spinner2.fail("Failed to fetch versions");
1099
1099
  if (error instanceof Error) {
1100
- console.error(chalk6.red(`Error: ${error.message}`));
1100
+ console.error(chalk7.red(`Error: ${error.message}`));
1101
1101
  }
1102
1102
  process.exit(1);
1103
1103
  }
@@ -1111,18 +1111,18 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1111
1111
  globalOpts?.url,
1112
1112
  parseInt(globalOpts?.timeout || "10000")
1113
1113
  );
1114
- const spinner2 = ora6(
1114
+ const spinner2 = ora7(
1115
1115
  `Fetching manifest for ${appId}@${version2}...`
1116
1116
  ).start();
1117
1117
  try {
1118
1118
  const manifest = await client.getAppManifest(appId, version2);
1119
1119
  spinner2.succeed("Manifest fetched successfully");
1120
- console.log(chalk6.blue("\nApplication Manifest:"));
1120
+ console.log(chalk7.blue("\nApplication Manifest:"));
1121
1121
  console.log(JSON.stringify(manifest, null, 2));
1122
1122
  } catch (error) {
1123
1123
  spinner2.fail("Failed to fetch manifest");
1124
1124
  if (error instanceof Error) {
1125
- console.error(chalk6.red(`Error: ${error.message}`));
1125
+ console.error(chalk7.red(`Error: ${error.message}`));
1126
1126
  }
1127
1127
  process.exit(1);
1128
1128
  }
@@ -1136,12 +1136,12 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1136
1136
  globalOpts?.url,
1137
1137
  parseInt(globalOpts?.timeout || "10000")
1138
1138
  );
1139
- const spinner2 = ora6("Reading manifest file...").start();
1139
+ const spinner2 = ora7("Reading manifest file...").start();
1140
1140
  try {
1141
1141
  const manifestPath = path7.resolve(manifestFile);
1142
1142
  if (!fs9.existsSync(manifestPath)) {
1143
1143
  spinner2.fail("Manifest file not found");
1144
- console.error(chalk6.red(`File not found: ${manifestFile}`));
1144
+ console.error(chalk7.red(`File not found: ${manifestFile}`));
1145
1145
  process.exit(1);
1146
1146
  }
1147
1147
  const manifestContent = fs9.readFileSync(manifestPath, "utf8");
@@ -1149,20 +1149,20 @@ var appsCommand = new Command("apps").description("Manage self-sovereign applica
1149
1149
  spinner2.text = "Submitting application manifest...";
1150
1150
  const result = await client.submitAppManifest(manifest);
1151
1151
  spinner2.succeed("Application submitted successfully");
1152
- console.log(chalk6.green(`
1152
+ console.log(chalk7.green(`
1153
1153
  \u2705 ${result.message}`));
1154
1154
  if (manifest.app?.name) {
1155
- console.log(chalk6.blue(`
1155
+ console.log(chalk7.blue(`
1156
1156
  \u{1F4F1} App: ${manifest.app.name}`));
1157
1157
  console.log(
1158
- chalk6.blue(`\u{1F464} Developer: ${manifest.app.developer_pubkey}`)
1158
+ chalk7.blue(`\u{1F464} Developer: ${manifest.app.developer_pubkey}`)
1159
1159
  );
1160
- console.log(chalk6.blue(`\u{1F4E6} Version: ${manifest.version?.semver}`));
1160
+ console.log(chalk7.blue(`\u{1F4E6} Version: ${manifest.version?.semver}`));
1161
1161
  }
1162
1162
  } catch (error) {
1163
1163
  spinner2.fail("Failed to submit application");
1164
1164
  if (error instanceof Error) {
1165
- console.error(chalk6.red(`Error: ${error.message}`));
1165
+ console.error(chalk7.red(`Error: ${error.message}`));
1166
1166
  }
1167
1167
  process.exit(1);
1168
1168
  }
@@ -1175,33 +1175,33 @@ var developersCommand = new Command("developers").description("Manage developer
1175
1175
  baseURL: globalOpts?.url || "http://localhost:8082",
1176
1176
  timeout: parseInt(globalOpts?.timeout || "10000")
1177
1177
  });
1178
- const spinner2 = ora6("Fetching developer profile...").start();
1178
+ const spinner2 = ora7("Fetching developer profile...").start();
1179
1179
  try {
1180
1180
  const profile = await client.getDeveloper(pubkey);
1181
1181
  spinner2.succeed("Developer profile fetched successfully");
1182
- console.log(chalk6.blue("\nDeveloper Profile:"));
1183
- console.log(chalk6.green("Display Name:"), profile.display_name);
1182
+ console.log(chalk7.blue("\nDeveloper Profile:"));
1183
+ console.log(chalk7.green("Display Name:"), profile.display_name);
1184
1184
  if (profile.website) {
1185
- console.log(chalk6.green("Website:"), profile.website);
1185
+ console.log(chalk7.green("Website:"), profile.website);
1186
1186
  }
1187
1187
  if (profile.proofs.length > 0) {
1188
- console.log(chalk6.green("\nProofs:"));
1188
+ console.log(chalk7.green("\nProofs:"));
1189
1189
  const tableData = [
1190
1190
  ["Type", "Value", "Verified"],
1191
1191
  ...profile.proofs.map((proof) => [
1192
1192
  proof.type,
1193
1193
  proof.value.substring(0, 20) + "...",
1194
- proof.verified ? chalk6.green("Yes") : chalk6.red("No")
1194
+ proof.verified ? chalk7.green("Yes") : chalk7.red("No")
1195
1195
  ])
1196
1196
  ];
1197
1197
  console.log(table(tableData));
1198
1198
  } else {
1199
- console.log(chalk6.yellow("\nNo proofs found"));
1199
+ console.log(chalk7.yellow("\nNo proofs found"));
1200
1200
  }
1201
1201
  } catch (error) {
1202
1202
  spinner2.fail("Failed to fetch developer profile");
1203
1203
  if (error instanceof Error) {
1204
- console.error(chalk6.red(`Error: ${error.message}`));
1204
+ console.error(chalk7.red(`Error: ${error.message}`));
1205
1205
  }
1206
1206
  process.exit(1);
1207
1207
  }
@@ -1213,7 +1213,7 @@ var developersCommand = new Command("developers").description("Manage developer
1213
1213
  baseURL: globalOpts?.url || "http://localhost:8082",
1214
1214
  timeout: parseInt(globalOpts?.timeout || "10000")
1215
1215
  });
1216
- const spinner2 = ora6("Creating developer profile...").start();
1216
+ const spinner2 = ora7("Creating developer profile...").start();
1217
1217
  try {
1218
1218
  let proofs = [];
1219
1219
  if (options.proofs) {
@@ -1221,7 +1221,7 @@ var developersCommand = new Command("developers").description("Manage developer
1221
1221
  proofs = JSON.parse(options.proofs);
1222
1222
  } catch {
1223
1223
  spinner2.fail("Invalid proofs JSON format");
1224
- console.error(chalk6.red("Proofs must be a valid JSON array"));
1224
+ console.error(chalk7.red("Proofs must be a valid JSON array"));
1225
1225
  process.exit(1);
1226
1226
  }
1227
1227
  }
@@ -1233,18 +1233,18 @@ var developersCommand = new Command("developers").description("Manage developer
1233
1233
  };
1234
1234
  const result = await client.submitDeveloperProfile(pubkey, profile);
1235
1235
  spinner2.succeed("Developer profile created successfully");
1236
- console.log(chalk6.green(`
1236
+ console.log(chalk7.green(`
1237
1237
  \u2705 ${result.message}`));
1238
- console.log(chalk6.blue(`
1238
+ console.log(chalk7.blue(`
1239
1239
  \u{1F464} Developer: ${displayName}`));
1240
- console.log(chalk6.blue(`\u{1F511} Public Key: ${pubkey}`));
1240
+ console.log(chalk7.blue(`\u{1F511} Public Key: ${pubkey}`));
1241
1241
  if (options.website) {
1242
- console.log(chalk6.blue(`\u{1F310} Website: ${options.website}`));
1242
+ console.log(chalk7.blue(`\u{1F310} Website: ${options.website}`));
1243
1243
  }
1244
1244
  } catch (error) {
1245
1245
  spinner2.fail("Failed to create developer profile");
1246
1246
  if (error instanceof Error) {
1247
- console.error(chalk6.red(`Error: ${error.message}`));
1247
+ console.error(chalk7.red(`Error: ${error.message}`));
1248
1248
  }
1249
1249
  process.exit(1);
1250
1250
  }
@@ -1257,7 +1257,7 @@ var attestationsCommand = new Command("attestations").description("Manage applic
1257
1257
  baseURL: globalOpts?.url || "http://localhost:8082",
1258
1258
  timeout: parseInt(globalOpts?.timeout || "10000")
1259
1259
  });
1260
- const spinner2 = ora6(
1260
+ const spinner2 = ora7(
1261
1261
  `Fetching attestation for ${name}@${version2}...`
1262
1262
  ).start();
1263
1263
  try {
@@ -1267,16 +1267,16 @@ var attestationsCommand = new Command("attestations").description("Manage applic
1267
1267
  version2
1268
1268
  );
1269
1269
  spinner2.succeed("Attestation fetched successfully");
1270
- console.log(chalk6.blue("\nAttestation:"));
1271
- console.log(chalk6.green("Status:"), attestation.status);
1272
- console.log(chalk6.green("Timestamp:"), attestation.timestamp);
1270
+ console.log(chalk7.blue("\nAttestation:"));
1271
+ console.log(chalk7.green("Status:"), attestation.status);
1272
+ console.log(chalk7.green("Timestamp:"), attestation.timestamp);
1273
1273
  if (attestation.comment) {
1274
- console.log(chalk6.green("Comment:"), attestation.comment);
1274
+ console.log(chalk7.green("Comment:"), attestation.comment);
1275
1275
  }
1276
1276
  } catch (error) {
1277
1277
  spinner2.fail("Failed to fetch attestation");
1278
1278
  if (error instanceof Error) {
1279
- console.error(chalk6.red(`Error: ${error.message}`));
1279
+ console.error(chalk7.red(`Error: ${error.message}`));
1280
1280
  }
1281
1281
  process.exit(1);
1282
1282
  }
@@ -1290,15 +1290,15 @@ var healthCommand = new Command("health").description("Check the health of the C
1290
1290
  globalOpts?.url,
1291
1291
  parseInt(globalOpts?.timeout || "10000")
1292
1292
  );
1293
- const spinner2 = ora6("Checking API health...").start();
1293
+ const spinner2 = ora7("Checking API health...").start();
1294
1294
  try {
1295
1295
  const health = await client.healthCheck();
1296
1296
  spinner2.succeed("API is healthy");
1297
- console.log(chalk6.green(`Status: ${health.status}`));
1297
+ console.log(chalk7.green(`Status: ${health.status}`));
1298
1298
  } catch (error) {
1299
1299
  spinner2.fail("API health check failed");
1300
1300
  if (error instanceof Error) {
1301
- console.error(chalk6.red(`Error: ${error.message}`));
1301
+ console.error(chalk7.red(`Error: ${error.message}`));
1302
1302
  }
1303
1303
  process.exit(1);
1304
1304
  }
@@ -1333,7 +1333,7 @@ This is a demo file that would normally contain the actual application data.`;
1333
1333
  );
1334
1334
  }
1335
1335
  }
1336
- var spinner = (text) => ora6(text);
1336
+ var spinner = (text) => ora7(text);
1337
1337
 
1338
1338
  // src/commands/ipfs.ts
1339
1339
  var ipfsCommand = new Command("ipfs").description("IPFS operations").addCommand(
@@ -1585,7 +1585,7 @@ localCommand.addCommand(
1585
1585
  "Public host exposed in manifest artifact URLs",
1586
1586
  "host.docker.internal"
1587
1587
  ).action(async (options) => {
1588
- const spinner2 = ora6("Starting local registry...").start();
1588
+ const spinner2 = ora7("Starting local registry...").start();
1589
1589
  try {
1590
1590
  const config = new LocalConfig();
1591
1591
  config.setHost(options.host);
@@ -1596,37 +1596,37 @@ localCommand.addCommand(
1596
1596
  spinner2.succeed(
1597
1597
  `Local registry started on http://${config.getHost()}:${config.getPort()}`
1598
1598
  );
1599
- console.log(chalk6.blue("\n\u{1F4F1} Local Registry Status:"));
1599
+ console.log(chalk7.blue("\n\u{1F4F1} Local Registry Status:"));
1600
1600
  console.log(
1601
- chalk6.green(
1601
+ chalk7.green(
1602
1602
  `\u2705 Server: http://${config.getHost()}:${config.getPort()}`
1603
1603
  )
1604
1604
  );
1605
1605
  console.log(
1606
- chalk6.green(
1606
+ chalk7.green(
1607
1607
  `\u{1F310} Public URL: http://${config.getPublicHost()}:${config.getPort()}`
1608
1608
  )
1609
1609
  );
1610
- console.log(chalk6.green(`\u{1F4C1} Data: ${config.getDataDir()}`));
1610
+ console.log(chalk7.green(`\u{1F4C1} Data: ${config.getDataDir()}`));
1611
1611
  console.log(
1612
- chalk6.green(
1612
+ chalk7.green(
1613
1613
  `\u{1F4CB} Health: http://${config.getHost()}:${config.getPort()}/healthz`
1614
1614
  )
1615
1615
  );
1616
1616
  console.log(
1617
- chalk6.green(
1617
+ chalk7.green(
1618
1618
  `\u{1F4CA} Stats: http://${config.getHost()}:${config.getPort()}/stats`
1619
1619
  )
1620
1620
  );
1621
1621
  console.log(
1622
- chalk6.blue(
1622
+ chalk7.blue(
1623
1623
  "\n\u{1F4A1} Use --local flag with other commands to use local registry"
1624
1624
  )
1625
1625
  );
1626
1626
  } catch (error) {
1627
1627
  spinner2.fail("Failed to start local registry");
1628
1628
  if (error instanceof Error) {
1629
- console.error(chalk6.red(`Error: ${error.message}`));
1629
+ console.error(chalk7.red(`Error: ${error.message}`));
1630
1630
  }
1631
1631
  process.exit(1);
1632
1632
  }
@@ -1634,7 +1634,7 @@ localCommand.addCommand(
1634
1634
  );
1635
1635
  localCommand.addCommand(
1636
1636
  new Command("stop").description("Stop local registry server").action(async () => {
1637
- const spinner2 = ora6("Stopping local registry...").start();
1637
+ const spinner2 = ora7("Stopping local registry...").start();
1638
1638
  try {
1639
1639
  const config = new LocalConfig();
1640
1640
  const server = new LocalRegistryServer(config);
@@ -1643,7 +1643,7 @@ localCommand.addCommand(
1643
1643
  } catch (error) {
1644
1644
  spinner2.fail("Failed to stop local registry");
1645
1645
  if (error instanceof Error) {
1646
- console.error(chalk6.red(`Error: ${error.message}`));
1646
+ console.error(chalk7.red(`Error: ${error.message}`));
1647
1647
  }
1648
1648
  process.exit(1);
1649
1649
  }
@@ -1651,23 +1651,23 @@ localCommand.addCommand(
1651
1651
  );
1652
1652
  localCommand.addCommand(
1653
1653
  new Command("status").description("Check local registry status").action(async () => {
1654
- const spinner2 = ora6("Checking local registry status...").start();
1654
+ const spinner2 = ora7("Checking local registry status...").start();
1655
1655
  try {
1656
1656
  const config = new LocalConfig();
1657
1657
  const server = new LocalRegistryServer(config);
1658
1658
  const status = await server.getStatus();
1659
1659
  if (status.running) {
1660
1660
  spinner2.succeed("Local registry is running");
1661
- console.log(chalk6.green(`\u2705 Server: ${status.url}`));
1662
- console.log(chalk6.green(`\u{1F4C1} Data: ${status.dataDir}`));
1663
- console.log(chalk6.green(`\u{1F4CA} Apps: ${status.appsCount} applications`));
1661
+ console.log(chalk7.green(`\u2705 Server: ${status.url}`));
1662
+ console.log(chalk7.green(`\u{1F4C1} Data: ${status.dataDir}`));
1663
+ console.log(chalk7.green(`\u{1F4CA} Apps: ${status.appsCount} applications`));
1664
1664
  console.log(
1665
- chalk6.green(`\u{1F4E6} Artifacts: ${status.artifactsCount} artifacts`)
1665
+ chalk7.green(`\u{1F4E6} Artifacts: ${status.artifactsCount} artifacts`)
1666
1666
  );
1667
1667
  } else {
1668
1668
  spinner2.warn("Local registry is not running");
1669
1669
  console.log(
1670
- chalk6.yellow(
1670
+ chalk7.yellow(
1671
1671
  '\u{1F4A1} Run "calimero-registry local start" to start the local registry'
1672
1672
  )
1673
1673
  );
@@ -1675,7 +1675,7 @@ localCommand.addCommand(
1675
1675
  } catch (error) {
1676
1676
  spinner2.fail("Failed to check local registry status");
1677
1677
  if (error instanceof Error) {
1678
- console.error(chalk6.red(`Error: ${error.message}`));
1678
+ console.error(chalk7.red(`Error: ${error.message}`));
1679
1679
  }
1680
1680
  process.exit(1);
1681
1681
  }
@@ -1685,22 +1685,22 @@ localCommand.addCommand(
1685
1685
  new Command("reset").description("Reset local registry data").option("-f, --force", "Force reset without confirmation").action(async (options) => {
1686
1686
  if (!options.force) {
1687
1687
  console.log(
1688
- chalk6.yellow("\u26A0\uFE0F This will delete all local registry data!")
1688
+ chalk7.yellow("\u26A0\uFE0F This will delete all local registry data!")
1689
1689
  );
1690
- console.log(chalk6.yellow(" Use --force flag to confirm"));
1690
+ console.log(chalk7.yellow(" Use --force flag to confirm"));
1691
1691
  return;
1692
1692
  }
1693
- const spinner2 = ora6("Resetting local registry data...").start();
1693
+ const spinner2 = ora7("Resetting local registry data...").start();
1694
1694
  try {
1695
1695
  const config = new LocalConfig();
1696
1696
  const server = new LocalRegistryServer(config);
1697
1697
  await server.reset();
1698
1698
  spinner2.succeed("Local registry data reset");
1699
- console.log(chalk6.green("\u2705 All local data has been cleared"));
1699
+ console.log(chalk7.green("\u2705 All local data has been cleared"));
1700
1700
  } catch (error) {
1701
1701
  spinner2.fail("Failed to reset local registry data");
1702
1702
  if (error instanceof Error) {
1703
- console.error(chalk6.red(`Error: ${error.message}`));
1703
+ console.error(chalk7.red(`Error: ${error.message}`));
1704
1704
  }
1705
1705
  process.exit(1);
1706
1706
  }
@@ -1708,17 +1708,17 @@ localCommand.addCommand(
1708
1708
  );
1709
1709
  localCommand.addCommand(
1710
1710
  new Command("backup").description("Backup local registry data").option("-o, --output <file>", "Output file path").action(async (options) => {
1711
- const spinner2 = ora6("Creating backup...").start();
1711
+ const spinner2 = ora7("Creating backup...").start();
1712
1712
  try {
1713
1713
  const config = new LocalConfig();
1714
1714
  const server = new LocalRegistryServer(config);
1715
1715
  const backupPath = await server.backup(options.output);
1716
1716
  spinner2.succeed("Backup created successfully");
1717
- console.log(chalk6.green(`\u{1F4E6} Backup saved to: ${backupPath}`));
1717
+ console.log(chalk7.green(`\u{1F4E6} Backup saved to: ${backupPath}`));
1718
1718
  } catch (error) {
1719
1719
  spinner2.fail("Failed to create backup");
1720
1720
  if (error instanceof Error) {
1721
- console.error(chalk6.red(`Error: ${error.message}`));
1721
+ console.error(chalk7.red(`Error: ${error.message}`));
1722
1722
  }
1723
1723
  process.exit(1);
1724
1724
  }
@@ -1726,22 +1726,22 @@ localCommand.addCommand(
1726
1726
  );
1727
1727
  localCommand.addCommand(
1728
1728
  new Command("restore").description("Restore local registry data from backup").argument("<backup-file>", "Path to backup file").action(async (backupFile) => {
1729
- const spinner2 = ora6("Restoring from backup...").start();
1729
+ const spinner2 = ora7("Restoring from backup...").start();
1730
1730
  try {
1731
1731
  if (!fs9.existsSync(backupFile)) {
1732
1732
  spinner2.fail("Backup file not found");
1733
- console.error(chalk6.red(`File not found: ${backupFile}`));
1733
+ console.error(chalk7.red(`File not found: ${backupFile}`));
1734
1734
  process.exit(1);
1735
1735
  }
1736
1736
  const config = new LocalConfig();
1737
1737
  const server = new LocalRegistryServer(config);
1738
1738
  await server.restore(backupFile);
1739
1739
  spinner2.succeed("Data restored successfully");
1740
- console.log(chalk6.green(`\u2705 Restored from: ${backupFile}`));
1740
+ console.log(chalk7.green(`\u2705 Restored from: ${backupFile}`));
1741
1741
  } catch (error) {
1742
1742
  spinner2.fail("Failed to restore from backup");
1743
1743
  if (error instanceof Error) {
1744
- console.error(chalk6.red(`Error: ${error.message}`));
1744
+ console.error(chalk7.red(`Error: ${error.message}`));
1745
1745
  }
1746
1746
  process.exit(1);
1747
1747
  }
@@ -1749,24 +1749,24 @@ localCommand.addCommand(
1749
1749
  );
1750
1750
  localCommand.addCommand(
1751
1751
  new Command("seed").description("Seed local registry with sample data").action(async () => {
1752
- const spinner2 = ora6("Seeding local registry with sample data...").start();
1752
+ const spinner2 = ora7("Seeding local registry with sample data...").start();
1753
1753
  try {
1754
1754
  const config = new LocalConfig();
1755
1755
  const server = new LocalRegistryServer(config);
1756
1756
  await server.seed();
1757
1757
  spinner2.succeed("Sample data seeded successfully");
1758
1758
  console.log(
1759
- chalk6.green("\u2705 Local registry populated with sample applications")
1759
+ chalk7.green("\u2705 Local registry populated with sample applications")
1760
1760
  );
1761
1761
  console.log(
1762
- chalk6.blue(
1762
+ chalk7.blue(
1763
1763
  '\u{1F4A1} Run "calimero-registry apps list --local" to see the sample apps'
1764
1764
  )
1765
1765
  );
1766
1766
  } catch (error) {
1767
1767
  spinner2.fail("Failed to seed sample data");
1768
1768
  if (error instanceof Error) {
1769
- console.error(chalk6.red(`Error: ${error.message}`));
1769
+ console.error(chalk7.red(`Error: ${error.message}`));
1770
1770
  }
1771
1771
  process.exit(1);
1772
1772
  }
@@ -2101,65 +2101,33 @@ Note:
2101
2101
  links: Object.keys(links).length > 0 ? links : void 0,
2102
2102
  signature: void 0
2103
2103
  };
2104
- let outputPath = finalOutput;
2105
- if (!outputPath) {
2106
- const outputDir = path7.join(
2107
- process.cwd(),
2108
- finalPackage,
2109
- finalVersion
2110
- );
2111
- if (!fs9.existsSync(outputDir)) {
2112
- fs9.mkdirSync(outputDir, { recursive: true });
2113
- }
2114
- outputPath = path7.join(
2115
- outputDir,
2116
- `${finalPackage}-${finalVersion}.mpk`
2117
- );
2118
- } else {
2119
- outputPath = path7.resolve(outputPath);
2120
- const outputDir = path7.dirname(outputPath);
2121
- if (!fs9.existsSync(outputDir)) {
2122
- fs9.mkdirSync(outputDir, { recursive: true });
2123
- }
2104
+ let outputDir = finalOutput ? path7.resolve(finalOutput) : path7.join(process.cwd(), finalPackage, finalVersion);
2105
+ if (!fs9.existsSync(outputDir)) {
2106
+ fs9.mkdirSync(outputDir, { recursive: true });
2124
2107
  }
2125
- const tempDir = path7.join(
2126
- path7.dirname(outputPath),
2127
- `.temp-bundle-${Date.now()}`
2108
+ fs9.writeFileSync(
2109
+ path7.join(outputDir, "manifest.json"),
2110
+ JSON.stringify(manifest, null, 2)
2128
2111
  );
2129
- fs9.mkdirSync(tempDir, { recursive: true });
2130
- try {
2131
- fs9.writeFileSync(
2132
- path7.join(tempDir, "manifest.json"),
2133
- JSON.stringify(manifest, null, 2)
2134
- );
2135
- fs9.writeFileSync(path7.join(tempDir, "app.wasm"), wasmContent);
2136
- const archiveFiles = ["manifest.json", "app.wasm"];
2137
- if (abiContent) {
2138
- fs9.writeFileSync(path7.join(tempDir, "abi.json"), abiContent);
2139
- archiveFiles.push("abi.json");
2140
- }
2141
- await tar.create(
2142
- {
2143
- gzip: true,
2144
- file: outputPath,
2145
- cwd: tempDir
2146
- },
2147
- archiveFiles
2148
- );
2149
- const outputSize = fs9.statSync(outputPath).size;
2150
- console.log(`\u2705 Created MPK bundle: ${outputPath}`);
2151
- console.log(` Package: ${finalPackage}`);
2152
- console.log(` Version: ${finalVersion}`);
2153
- console.log(` Size: ${outputSize} bytes`);
2154
- console.log(` WASM Hash: ${wasmHash}`);
2155
- if (abiArtifact) {
2156
- console.log(` ABI Hash: ${abiArtifact.hash}`);
2157
- }
2158
- } finally {
2159
- if (fs9.existsSync(tempDir)) {
2160
- fs9.rmSync(tempDir, { recursive: true, force: true });
2161
- }
2112
+ fs9.writeFileSync(path7.join(outputDir, "app.wasm"), wasmContent);
2113
+ if (abiContent) {
2114
+ fs9.writeFileSync(path7.join(outputDir, "abi.json"), abiContent);
2115
+ }
2116
+ console.log(`\u2705 Bundle files written to: ${outputDir}`);
2117
+ console.log(` Package: ${finalPackage}`);
2118
+ console.log(` Version: ${finalVersion}`);
2119
+ console.log(` WASM Hash: ${wasmHash}`);
2120
+ if (abiArtifact) {
2121
+ console.log(` ABI Hash: ${abiArtifact.hash}`);
2162
2122
  }
2123
+ console.log("");
2124
+ console.log("Next steps:");
2125
+ console.log(
2126
+ ` 1. Sign the manifest: mero-sign sign ${path7.join(outputDir, "manifest.json")} --key key.json`
2127
+ );
2128
+ console.log(
2129
+ ` 2. Push the bundle: calimero-registry bundle push ${outputDir} --remote`
2130
+ );
2163
2131
  } catch (error) {
2164
2132
  const message = error instanceof Error ? error.message : "Unknown error";
2165
2133
  console.error("\u274C Failed to create bundle:", message);
@@ -2201,6 +2169,8 @@ Note:
2201
2169
  - Priority: flag > environment variable > config file > default
2202
2170
  `
2203
2171
  ).action(async (bundleFile, options) => {
2172
+ let mpkPath = "";
2173
+ let tempMpk = null;
2204
2174
  try {
2205
2175
  if (!options.remote && (options.url || options.apiKey)) {
2206
2176
  console.warn(
@@ -2227,8 +2197,34 @@ Note:
2227
2197
  console.error(`\u274C File not found: ${bundleFile}`);
2228
2198
  process.exit(1);
2229
2199
  }
2230
- console.log(`\u{1F4E6} Processing bundle: ${path7.basename(fullPath)}`);
2231
- const manifest = await extractManifest(fullPath);
2200
+ mpkPath = fullPath;
2201
+ if (fs9.statSync(fullPath).isDirectory()) {
2202
+ const manifestInDir = path7.join(fullPath, "manifest.json");
2203
+ const wasmInDir = path7.join(fullPath, "app.wasm");
2204
+ if (!fs9.existsSync(manifestInDir)) {
2205
+ console.error(
2206
+ `\u274C manifest.json not found in directory: ${fullPath}`
2207
+ );
2208
+ process.exit(1);
2209
+ }
2210
+ if (!fs9.existsSync(wasmInDir)) {
2211
+ console.error(`\u274C app.wasm not found in directory: ${fullPath}`);
2212
+ process.exit(1);
2213
+ }
2214
+ tempMpk = path7.join(fullPath, `.temp-push-${Date.now()}.mpk`);
2215
+ const archiveFiles = ["manifest.json", "app.wasm"];
2216
+ if (fs9.existsSync(path7.join(fullPath, "abi.json"))) {
2217
+ archiveFiles.push("abi.json");
2218
+ }
2219
+ await tar.create(
2220
+ { gzip: true, file: tempMpk, cwd: fullPath },
2221
+ archiveFiles
2222
+ );
2223
+ mpkPath = tempMpk;
2224
+ console.log(`\u{1F4E6} Packed directory into temporary bundle`);
2225
+ }
2226
+ console.log(`\u{1F4E6} Processing bundle: ${path7.basename(mpkPath)}`);
2227
+ const manifest = await extractManifest(mpkPath);
2232
2228
  if (!manifest) {
2233
2229
  console.error("\u274C manifest.json not found in bundle");
2234
2230
  process.exit(1);
@@ -2248,7 +2244,7 @@ Note:
2248
2244
  const artifactServer = new LocalArtifactServer(config, store);
2249
2245
  const bundleFilename = `${manifest.package}-${manifest.appVersion}.mpk`;
2250
2246
  const targetPath = await artifactServer.copyArtifactToLocal(
2251
- fullPath,
2247
+ mpkPath,
2252
2248
  manifest.package,
2253
2249
  manifest.appVersion,
2254
2250
  bundleFilename
@@ -2267,12 +2263,16 @@ Note:
2267
2263
  const remoteConfig = new RemoteConfig();
2268
2264
  const registryUrl = options.url || process.env.CALIMERO_REGISTRY_URL || remoteConfig.getRegistryUrl();
2269
2265
  const apiKey = options.apiKey || process.env.CALIMERO_API_KEY || remoteConfig.getApiKey();
2270
- await pushToRemote(fullPath, manifest, registryUrl, apiKey);
2266
+ await pushToRemote(mpkPath, manifest, registryUrl, apiKey);
2271
2267
  }
2272
2268
  } catch (error) {
2273
2269
  const message = error instanceof Error ? error.message : String(error);
2274
2270
  console.error("\u274C Failed to push bundle:", message);
2275
2271
  process.exit(1);
2272
+ } finally {
2273
+ if (tempMpk && fs9.existsSync(tempMpk)) {
2274
+ fs9.rmSync(tempMpk);
2275
+ }
2276
2276
  }
2277
2277
  });
2278
2278
  }
@@ -2377,9 +2377,8 @@ Examples:
2377
2377
  console.log(` Package: ${body.package || pkg}`);
2378
2378
  console.log(` Version: ${body.version || version2}`);
2379
2379
  } else {
2380
- console.error(
2381
- `\u274C PATCH failed (${res2.status}): ${body.error ?? body.message ?? text}`
2382
- );
2380
+ const errMsg = body.message && String(body.message).trim() || body.error || text;
2381
+ console.error(`\u274C PATCH failed (${res2.status}): ${errMsg}`);
2383
2382
  process.exit(1);
2384
2383
  }
2385
2384
  return;
@@ -2672,29 +2671,29 @@ function createConfigSetCommand() {
2672
2671
  case "url":
2673
2672
  config.setRegistryUrl(value);
2674
2673
  console.log(
2675
- chalk6.green(`\u2705 Registry URL set to: ${chalk6.bold(value)}`)
2674
+ chalk7.green(`\u2705 Registry URL set to: ${chalk7.bold(value)}`)
2676
2675
  );
2677
2676
  break;
2678
2677
  case "api-key":
2679
2678
  case "apiKey":
2680
2679
  config.setApiKey(value);
2681
- console.log(chalk6.green("\u2705 API key set successfully"));
2680
+ console.log(chalk7.green("\u2705 API key set successfully"));
2682
2681
  console.log(
2683
- chalk6.yellow(
2682
+ chalk7.yellow(
2684
2683
  "\u{1F4A1} Note: API key is stored in plain text. Consider using CALIMERO_API_KEY environment variable for better security."
2685
2684
  )
2686
2685
  );
2687
2686
  break;
2688
2687
  default:
2689
- console.error(chalk6.red(`\u274C Unknown configuration key: ${key}`));
2690
- console.log(chalk6.blue("\nAvailable keys:"));
2688
+ console.error(chalk7.red(`\u274C Unknown configuration key: ${key}`));
2689
+ console.log(chalk7.blue("\nAvailable keys:"));
2691
2690
  console.log(" registry-url - Default registry URL");
2692
2691
  console.log(" api-key - API key for authentication");
2693
2692
  process.exit(1);
2694
2693
  }
2695
2694
  } catch (error) {
2696
2695
  const message = error instanceof Error ? error.message : String(error);
2697
- console.error(chalk6.red("\u274C Failed to set configuration:"), message);
2696
+ console.error(chalk7.red("\u274C Failed to set configuration:"), message);
2698
2697
  process.exit(1);
2699
2698
  }
2700
2699
  });
@@ -2716,7 +2715,7 @@ function createConfigGetCommand() {
2716
2715
  const masked = apiKey.length > 8 ? `${apiKey.substring(0, 4)}...${apiKey.substring(apiKey.length - 4)}` : "***";
2717
2716
  console.log(masked);
2718
2717
  console.log(
2719
- chalk6.yellow(
2718
+ chalk7.yellow(
2720
2719
  '\u{1F4A1} Note: API key is masked. Use "config list" to see source.'
2721
2720
  )
2722
2721
  );
@@ -2726,15 +2725,15 @@ function createConfigGetCommand() {
2726
2725
  break;
2727
2726
  }
2728
2727
  default:
2729
- console.error(chalk6.red(`\u274C Unknown configuration key: ${key}`));
2730
- console.log(chalk6.blue("\nAvailable keys:"));
2728
+ console.error(chalk7.red(`\u274C Unknown configuration key: ${key}`));
2729
+ console.log(chalk7.blue("\nAvailable keys:"));
2731
2730
  console.log(" registry-url - Default registry URL");
2732
2731
  console.log(" api-key - API key for authentication");
2733
2732
  process.exit(1);
2734
2733
  }
2735
2734
  } catch (error) {
2736
2735
  const message = error instanceof Error ? error.message : String(error);
2737
- console.error(chalk6.red("\u274C Failed to get configuration:"), message);
2736
+ console.error(chalk7.red("\u274C Failed to get configuration:"), message);
2738
2737
  process.exit(1);
2739
2738
  }
2740
2739
  });
@@ -2743,43 +2742,43 @@ function createConfigListCommand() {
2743
2742
  return new Command("list").description("List all configuration values").alias("ls").action(() => {
2744
2743
  try {
2745
2744
  const config = new RemoteConfig();
2746
- console.log(chalk6.blue("\n\u{1F4CB} Remote Registry Configuration\n"));
2745
+ console.log(chalk7.blue("\n\u{1F4CB} Remote Registry Configuration\n"));
2747
2746
  const configPath = config.getConfigPath();
2748
2747
  const configFileExists = fs9.existsSync(configPath);
2749
2748
  const url = config.getRegistryUrl();
2750
2749
  let urlSource;
2751
2750
  if (process.env.CALIMERO_REGISTRY_URL) {
2752
- urlSource = chalk6.yellow("(from CALIMERO_REGISTRY_URL env var)");
2751
+ urlSource = chalk7.yellow("(from CALIMERO_REGISTRY_URL env var)");
2753
2752
  } else if (configFileExists) {
2754
- urlSource = chalk6.gray("(from config file)");
2753
+ urlSource = chalk7.gray("(from config file)");
2755
2754
  } else {
2756
- urlSource = chalk6.gray("(default)");
2755
+ urlSource = chalk7.gray("(default)");
2757
2756
  }
2758
- console.log(` ${chalk6.bold("Registry URL:")} ${url} ${urlSource}`);
2757
+ console.log(` ${chalk7.bold("Registry URL:")} ${url} ${urlSource}`);
2759
2758
  const apiKey = config.getApiKey();
2760
2759
  if (apiKey) {
2761
2760
  let apiKeySource;
2762
2761
  if (process.env.CALIMERO_API_KEY) {
2763
- apiKeySource = chalk6.yellow("(from CALIMERO_API_KEY env var)");
2762
+ apiKeySource = chalk7.yellow("(from CALIMERO_API_KEY env var)");
2764
2763
  } else if (configFileExists) {
2765
- apiKeySource = chalk6.gray("(from config file)");
2764
+ apiKeySource = chalk7.gray("(from config file)");
2766
2765
  } else {
2767
- apiKeySource = chalk6.gray("(default)");
2766
+ apiKeySource = chalk7.gray("(default)");
2768
2767
  }
2769
2768
  const masked = apiKey.length > 8 ? `${apiKey.substring(0, 4)}...${apiKey.substring(apiKey.length - 4)}` : "***";
2770
- console.log(` ${chalk6.bold("API Key:")} ${masked} ${apiKeySource}`);
2769
+ console.log(` ${chalk7.bold("API Key:")} ${masked} ${apiKeySource}`);
2771
2770
  } else {
2772
- console.log(` ${chalk6.bold("API Key:")} ${chalk6.gray("(not set)")}`);
2771
+ console.log(` ${chalk7.bold("API Key:")} ${chalk7.gray("(not set)")}`);
2773
2772
  }
2774
- console.log(chalk6.blue(`
2773
+ console.log(chalk7.blue(`
2775
2774
  \u{1F4C1} Config file: ${configPath}`));
2776
2775
  if (!configFileExists) {
2777
- console.log(chalk6.gray(" (file does not exist, using defaults)"));
2776
+ console.log(chalk7.gray(" (file does not exist, using defaults)"));
2778
2777
  }
2779
2778
  console.log();
2780
2779
  } catch (error) {
2781
2780
  const message = error instanceof Error ? error.message : String(error);
2782
- console.error(chalk6.red("\u274C Failed to list configuration:"), message);
2781
+ console.error(chalk7.red("\u274C Failed to list configuration:"), message);
2783
2782
  process.exit(1);
2784
2783
  }
2785
2784
  });
@@ -2789,10 +2788,10 @@ function createConfigResetCommand() {
2789
2788
  try {
2790
2789
  if (!options.force) {
2791
2790
  console.error(
2792
- chalk6.red("\u274C Configuration reset requires --force flag")
2791
+ chalk7.red("\u274C Configuration reset requires --force flag")
2793
2792
  );
2794
2793
  console.log(
2795
- chalk6.yellow(
2794
+ chalk7.yellow(
2796
2795
  "\u26A0\uFE0F This will reset all configuration to defaults. Use --force to confirm."
2797
2796
  )
2798
2797
  );
@@ -2800,17 +2799,484 @@ function createConfigResetCommand() {
2800
2799
  }
2801
2800
  const config = new RemoteConfig();
2802
2801
  config.reset();
2803
- console.log(chalk6.green("\u2705 Configuration reset to defaults"));
2804
- console.log(chalk6.blue("\nDefault values:"));
2802
+ console.log(chalk7.green("\u2705 Configuration reset to defaults"));
2803
+ console.log(chalk7.blue("\nDefault values:"));
2805
2804
  console.log(" Registry URL: https://apps.calimero.network");
2806
2805
  console.log(" API Key: (not set)");
2807
2806
  } catch (error) {
2808
2807
  const message = error instanceof Error ? error.message : String(error);
2809
- console.error(chalk6.red("\u274C Failed to reset configuration:"), message);
2808
+ console.error(chalk7.red("\u274C Failed to reset configuration:"), message);
2810
2809
  process.exit(1);
2811
2810
  }
2812
2811
  });
2813
2812
  }
2813
+ var DEFAULT_TIMEOUT = 1e4;
2814
+ function getGlobalOpts(command) {
2815
+ const opts = command.parent?.parent?.opts() ?? {};
2816
+ const remoteConfig = new RemoteConfig();
2817
+ const url = opts.url || process.env.CALIMERO_REGISTRY_URL || remoteConfig.getRegistryUrl();
2818
+ return {
2819
+ url,
2820
+ timeout: parseInt(String(opts.timeout ?? DEFAULT_TIMEOUT), 10) || DEFAULT_TIMEOUT
2821
+ };
2822
+ }
2823
+ function getAuthHeaders() {
2824
+ const remoteConfig = new RemoteConfig();
2825
+ const apiKey = remoteConfig.getApiKey();
2826
+ if (!apiKey) {
2827
+ throw new Error(
2828
+ "API token required for org write operations.\nGet a token from the Organizations page in the web UI, then run:\n calimero-registry config set api-key <token>"
2829
+ );
2830
+ }
2831
+ return { Authorization: `Bearer ${apiKey}` };
2832
+ }
2833
+ async function fetchJson(url, options = {}) {
2834
+ const { timeout = DEFAULT_TIMEOUT, ...init } = options;
2835
+ const controller = new AbortController();
2836
+ const id = setTimeout(() => controller.abort(), timeout);
2837
+ const res = await fetch(url, {
2838
+ ...init,
2839
+ signal: controller.signal,
2840
+ headers: {
2841
+ "Content-Type": "application/json",
2842
+ ...init.headers
2843
+ }
2844
+ });
2845
+ clearTimeout(id);
2846
+ const text = await res.text();
2847
+ const data = text ? JSON.parse(text) : void 0;
2848
+ return { data, status: res.status };
2849
+ }
2850
+ var orgCommand = new Command("org").description("Manage organizations (create, list, members, packages)").addCommand(
2851
+ new Command("list").description(
2852
+ "List organizations you belong to (uses API token to resolve identity)"
2853
+ ).action(async (_options, command) => {
2854
+ const { url, timeout } = getGlobalOpts(command);
2855
+ const spinner2 = ora7("Resolving identity...").start();
2856
+ let authHeaders;
2857
+ try {
2858
+ authHeaders = getAuthHeaders();
2859
+ } catch (e) {
2860
+ spinner2.fail("API token required");
2861
+ console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2862
+ process.exit(1);
2863
+ }
2864
+ const base = url.replace(/\/$/, "");
2865
+ let myEmail;
2866
+ try {
2867
+ const { data, status } = await fetchJson(`${base}/api/auth/me`, {
2868
+ method: "GET",
2869
+ headers: authHeaders,
2870
+ timeout
2871
+ });
2872
+ if (status !== 200 || !data?.user?.email) {
2873
+ spinner2.fail("Could not resolve identity from API token");
2874
+ console.error(
2875
+ chalk7.red(
2876
+ "Ensure your API token is valid. Get a new one from the web UI."
2877
+ )
2878
+ );
2879
+ process.exit(1);
2880
+ }
2881
+ myEmail = data.user.email;
2882
+ spinner2.text = `Fetching organizations for ${myEmail}...`;
2883
+ } catch (e) {
2884
+ spinner2.fail("Request failed");
2885
+ console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2886
+ process.exit(1);
2887
+ }
2888
+ const apiUrl = `${base}/api/v2/orgs?member=${encodeURIComponent(myEmail)}`;
2889
+ try {
2890
+ const { data, status } = await fetchJson(apiUrl, {
2891
+ method: "GET",
2892
+ headers: authHeaders,
2893
+ timeout
2894
+ });
2895
+ if (status !== 200) {
2896
+ spinner2.fail("Failed to list organizations");
2897
+ console.error(chalk7.red(JSON.stringify(data)));
2898
+ process.exit(1);
2899
+ }
2900
+ const orgs = Array.isArray(data) ? data : [];
2901
+ spinner2.succeed(`Found ${orgs.length} organization(s)`);
2902
+ if (orgs.length === 0) {
2903
+ console.log(chalk7.yellow("No organizations found"));
2904
+ return;
2905
+ }
2906
+ const memberResults = await Promise.all(
2907
+ orgs.map(
2908
+ (o) => fetchJson(
2909
+ `${base}/api/v2/orgs/${encodeURIComponent(o.id)}/members`,
2910
+ { method: "GET", headers: authHeaders, timeout }
2911
+ ).catch(() => ({ data: { members: [] }, status: 0 }))
2912
+ )
2913
+ );
2914
+ const lines = orgs.map((o, i) => {
2915
+ const members = memberResults[i].data?.members ?? [];
2916
+ const myMember = members.find((m) => m.email === myEmail);
2917
+ const role = myMember?.role ?? "?";
2918
+ const count = members.length;
2919
+ const roleLabel = role === "admin" ? chalk7.yellow("admin") : chalk7.gray(role);
2920
+ return `${chalk7.white(o.slug)} ${chalk7.gray(o.name)} ${chalk7.gray(`${count} member${count !== 1 ? "s" : ""}`)} ${roleLabel}`;
2921
+ });
2922
+ console.log(lines.join("\n"));
2923
+ } catch (e) {
2924
+ spinner2.fail("Request failed");
2925
+ console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2926
+ process.exit(1);
2927
+ }
2928
+ })
2929
+ ).addCommand(
2930
+ 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(
2931
+ async (options, command) => {
2932
+ const { url, timeout } = getGlobalOpts(command);
2933
+ const spinner2 = ora7("Creating organization...").start();
2934
+ try {
2935
+ const authHeaders = getAuthHeaders();
2936
+ const pathname = "/api/v2/orgs";
2937
+ const body = {
2938
+ name: options.name.trim(),
2939
+ slug: options.slug.trim().toLowerCase()
2940
+ };
2941
+ const base = url.replace(/\/$/, "");
2942
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
2943
+ method: "POST",
2944
+ body: JSON.stringify(body),
2945
+ timeout,
2946
+ headers: authHeaders
2947
+ });
2948
+ if (status >= 400) {
2949
+ const err = data;
2950
+ spinner2.fail(err?.message || `HTTP ${status}`);
2951
+ console.error(chalk7.red(JSON.stringify(data)));
2952
+ process.exit(1);
2953
+ }
2954
+ spinner2.succeed("Organization created");
2955
+ console.log(chalk7.green(JSON.stringify(data, null, 2)));
2956
+ } catch (e) {
2957
+ spinner2.fail("Failed");
2958
+ console.error(
2959
+ chalk7.red(e instanceof Error ? e.message : String(e))
2960
+ );
2961
+ process.exit(1);
2962
+ }
2963
+ }
2964
+ )
2965
+ ).addCommand(
2966
+ new Command("get").description("Get organization by id/slug").argument("<orgId>", "Organization id or slug").action(async (orgId, _options, command) => {
2967
+ const { url, timeout } = getGlobalOpts(command);
2968
+ const base = url.replace(/\/$/, "");
2969
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}`;
2970
+ const spinner2 = ora7("Fetching organization...").start();
2971
+ try {
2972
+ const { data, status } = await fetchJson(`${base}${pathname}`, { method: "GET", timeout });
2973
+ if (status === 404) {
2974
+ spinner2.fail("Organization not found");
2975
+ process.exit(1);
2976
+ }
2977
+ if (status !== 200) {
2978
+ spinner2.fail("Request failed");
2979
+ console.error(chalk7.red(JSON.stringify(data)));
2980
+ process.exit(1);
2981
+ }
2982
+ spinner2.succeed("OK");
2983
+ console.log(JSON.stringify(data, null, 2));
2984
+ } catch (e) {
2985
+ spinner2.fail("Request failed");
2986
+ console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
2987
+ process.exit(1);
2988
+ }
2989
+ })
2990
+ ).addCommand(
2991
+ 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(
2992
+ async (orgId, options, command) => {
2993
+ const { url, timeout } = getGlobalOpts(command);
2994
+ const spinner2 = ora7("Updating organization...").start();
2995
+ try {
2996
+ const authHeaders = getAuthHeaders();
2997
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}`;
2998
+ const body = {};
2999
+ if (options.name !== void 0) body.name = options.name;
3000
+ if (options.metadata !== void 0) {
3001
+ try {
3002
+ body.metadata = JSON.parse(options.metadata);
3003
+ } catch {
3004
+ spinner2.fail("--metadata must be valid JSON");
3005
+ process.exit(1);
3006
+ }
3007
+ }
3008
+ const base = url.replace(/\/$/, "");
3009
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3010
+ method: "PATCH",
3011
+ body: Object.keys(body).length > 0 ? JSON.stringify(body) : void 0,
3012
+ timeout,
3013
+ headers: authHeaders
3014
+ });
3015
+ if (status >= 400) {
3016
+ spinner2.fail(
3017
+ data?.message || `HTTP ${status}`
3018
+ );
3019
+ console.error(chalk7.red(JSON.stringify(data)));
3020
+ process.exit(1);
3021
+ }
3022
+ spinner2.succeed("Updated");
3023
+ console.log(JSON.stringify(data, null, 2));
3024
+ } catch (e) {
3025
+ spinner2.fail("Failed");
3026
+ console.error(
3027
+ chalk7.red(e instanceof Error ? e.message : String(e))
3028
+ );
3029
+ process.exit(1);
3030
+ }
3031
+ }
3032
+ )
3033
+ ).addCommand(
3034
+ new Command("delete").description("Delete an organization and all its data (irreversible)").argument("<orgId>", "Organization id or slug").option("-y, --yes", "Skip confirmation prompt").action(
3035
+ async (orgId, options, command) => {
3036
+ const { url, timeout } = getGlobalOpts(command);
3037
+ if (!options.yes) {
3038
+ const { createInterface } = await import('readline');
3039
+ const rl = createInterface({
3040
+ input: process.stdin,
3041
+ output: process.stdout
3042
+ });
3043
+ const confirmed = await new Promise((resolve) => {
3044
+ rl.question(
3045
+ chalk7.yellow(
3046
+ `Delete organization "${orgId}" and all its members/packages? This cannot be undone. Type "yes" to confirm: `
3047
+ ),
3048
+ (answer) => {
3049
+ rl.close();
3050
+ resolve(answer.trim().toLowerCase() === "yes");
3051
+ }
3052
+ );
3053
+ });
3054
+ if (!confirmed) {
3055
+ console.log(chalk7.gray("Aborted."));
3056
+ return;
3057
+ }
3058
+ }
3059
+ const spinner2 = ora7("Deleting organization...").start();
3060
+ try {
3061
+ const authHeaders = getAuthHeaders();
3062
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}`;
3063
+ const base = url.replace(/\/$/, "");
3064
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3065
+ method: "DELETE",
3066
+ timeout,
3067
+ headers: authHeaders
3068
+ });
3069
+ if (status >= 400) {
3070
+ spinner2.fail(
3071
+ data?.message || `HTTP ${status}`
3072
+ );
3073
+ console.error(chalk7.red(JSON.stringify(data)));
3074
+ process.exit(1);
3075
+ }
3076
+ spinner2.succeed("Organization deleted");
3077
+ } catch (e) {
3078
+ spinner2.fail("Failed");
3079
+ console.error(
3080
+ chalk7.red(e instanceof Error ? e.message : String(e))
3081
+ );
3082
+ process.exit(1);
3083
+ }
3084
+ }
3085
+ )
3086
+ ).addCommand(
3087
+ new Command("members").description("List, add, or remove organization members").addCommand(
3088
+ new Command("list").description("List members of an org").argument("<orgId>", "Organization id or slug").action(async (orgId, _options, command) => {
3089
+ const { url, timeout } = getGlobalOpts(command);
3090
+ const base = url.replace(/\/$/, "");
3091
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members`;
3092
+ const spinner2 = ora7("Fetching members...").start();
3093
+ try {
3094
+ const { data, status } = await fetchJson(`${base}${pathname}`, { method: "GET", timeout });
3095
+ if (status !== 200) {
3096
+ spinner2.fail("Failed");
3097
+ console.error(chalk7.red(JSON.stringify(data)));
3098
+ process.exit(1);
3099
+ }
3100
+ spinner2.succeed("OK");
3101
+ const members = data?.members ?? [];
3102
+ console.log(JSON.stringify(members, null, 2));
3103
+ } catch (e) {
3104
+ spinner2.fail("Request failed");
3105
+ console.error(
3106
+ chalk7.red(e instanceof Error ? e.message : String(e))
3107
+ );
3108
+ process.exit(1);
3109
+ }
3110
+ })
3111
+ ).addCommand(
3112
+ 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(
3113
+ async (orgId, email, options, command) => {
3114
+ const { url, timeout } = getGlobalOpts(command);
3115
+ const spinner2 = ora7("Adding member...").start();
3116
+ try {
3117
+ const authHeaders = getAuthHeaders();
3118
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members`;
3119
+ const body = {
3120
+ email: email.trim(),
3121
+ role: options.role === "admin" ? "admin" : "member"
3122
+ };
3123
+ const base = url.replace(/\/$/, "");
3124
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3125
+ method: "POST",
3126
+ body: JSON.stringify(body),
3127
+ timeout,
3128
+ headers: authHeaders
3129
+ });
3130
+ if (status >= 400) {
3131
+ spinner2.fail(
3132
+ data?.message || `HTTP ${status}`
3133
+ );
3134
+ console.error(chalk7.red(JSON.stringify(data)));
3135
+ process.exit(1);
3136
+ }
3137
+ spinner2.succeed("Member added");
3138
+ } catch (e) {
3139
+ spinner2.fail("Failed");
3140
+ console.error(
3141
+ chalk7.red(e instanceof Error ? e.message : String(e))
3142
+ );
3143
+ process.exit(1);
3144
+ }
3145
+ }
3146
+ )
3147
+ ).addCommand(
3148
+ new Command("update").description("Update a member role (admin or member)").argument("<orgId>", "Organization id or slug").argument("<email>", "Member email address").requiredOption("-r, --role <role>", "New role: admin or member").action(
3149
+ async (orgId, email, options, command) => {
3150
+ const { url, timeout } = getGlobalOpts(command);
3151
+ const role = options.role === "admin" ? "admin" : "member";
3152
+ const spinner2 = ora7("Updating member role...").start();
3153
+ try {
3154
+ const authHeaders = getAuthHeaders();
3155
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(email.trim())}`;
3156
+ const body = { role };
3157
+ const base = url.replace(/\/$/, "");
3158
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3159
+ method: "PATCH",
3160
+ body: JSON.stringify(body),
3161
+ timeout,
3162
+ headers: authHeaders
3163
+ });
3164
+ if (status >= 400) {
3165
+ spinner2.fail(
3166
+ data?.message || `HTTP ${status}`
3167
+ );
3168
+ console.error(chalk7.red(JSON.stringify(data)));
3169
+ process.exit(1);
3170
+ }
3171
+ spinner2.succeed(`Role updated to "${role}"`);
3172
+ } catch (e) {
3173
+ spinner2.fail("Failed");
3174
+ console.error(
3175
+ chalk7.red(e instanceof Error ? e.message : String(e))
3176
+ );
3177
+ process.exit(1);
3178
+ }
3179
+ }
3180
+ )
3181
+ ).addCommand(
3182
+ new Command("remove").description("Remove a member by email").argument("<orgId>", "Organization id or slug").argument("<email>", "Member email address").action(
3183
+ async (orgId, email, _options, command) => {
3184
+ const { url, timeout } = getGlobalOpts(command);
3185
+ const spinner2 = ora7("Removing member...").start();
3186
+ try {
3187
+ const authHeaders = getAuthHeaders();
3188
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(email.trim())}`;
3189
+ const base = url.replace(/\/$/, "");
3190
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3191
+ method: "DELETE",
3192
+ timeout,
3193
+ headers: authHeaders
3194
+ });
3195
+ if (status >= 400) {
3196
+ spinner2.fail(
3197
+ data?.message || `HTTP ${status}`
3198
+ );
3199
+ console.error(chalk7.red(JSON.stringify(data)));
3200
+ process.exit(1);
3201
+ }
3202
+ spinner2.succeed("Member removed");
3203
+ } catch (e) {
3204
+ spinner2.fail("Failed");
3205
+ console.error(
3206
+ chalk7.red(e instanceof Error ? e.message : String(e))
3207
+ );
3208
+ process.exit(1);
3209
+ }
3210
+ }
3211
+ )
3212
+ )
3213
+ ).addCommand(
3214
+ new Command("packages").description("Link or unlink packages to the organization").addCommand(
3215
+ new Command("link").description("Link a package to the organization").argument("<orgId>", "Organization id or slug").argument("<package>", "Package name").action(
3216
+ async (orgId, pkg, _options, command) => {
3217
+ const { url, timeout } = getGlobalOpts(command);
3218
+ const spinner2 = ora7("Linking package...").start();
3219
+ try {
3220
+ const authHeaders = getAuthHeaders();
3221
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/packages`;
3222
+ const body = { package: pkg.trim() };
3223
+ const base = url.replace(/\/$/, "");
3224
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3225
+ method: "POST",
3226
+ body: JSON.stringify(body),
3227
+ timeout,
3228
+ headers: authHeaders
3229
+ });
3230
+ if (status >= 400) {
3231
+ spinner2.fail(
3232
+ data?.message || `HTTP ${status}`
3233
+ );
3234
+ console.error(chalk7.red(JSON.stringify(data)));
3235
+ process.exit(1);
3236
+ }
3237
+ spinner2.succeed("Package linked");
3238
+ } catch (e) {
3239
+ spinner2.fail("Failed");
3240
+ console.error(
3241
+ chalk7.red(e instanceof Error ? e.message : String(e))
3242
+ );
3243
+ process.exit(1);
3244
+ }
3245
+ }
3246
+ )
3247
+ ).addCommand(
3248
+ new Command("unlink").description("Unlink a package from the organization").argument("<orgId>", "Organization id or slug").argument("<package>", "Package name").action(
3249
+ async (orgId, pkg, _options, command) => {
3250
+ const { url, timeout } = getGlobalOpts(command);
3251
+ const spinner2 = ora7("Unlinking package...").start();
3252
+ try {
3253
+ const authHeaders = getAuthHeaders();
3254
+ const pathname = `/api/v2/orgs/${encodeURIComponent(orgId)}/packages/${encodeURIComponent(pkg.trim())}`;
3255
+ const base = url.replace(/\/$/, "");
3256
+ const { data, status } = await fetchJson(`${base}${pathname}`, {
3257
+ method: "DELETE",
3258
+ timeout,
3259
+ headers: authHeaders
3260
+ });
3261
+ if (status >= 400) {
3262
+ spinner2.fail(
3263
+ data?.message || `HTTP ${status}`
3264
+ );
3265
+ console.error(chalk7.red(JSON.stringify(data)));
3266
+ process.exit(1);
3267
+ }
3268
+ spinner2.succeed("Package unlinked");
3269
+ } catch (e) {
3270
+ spinner2.fail("Failed");
3271
+ console.error(
3272
+ chalk7.red(e instanceof Error ? e.message : String(e))
3273
+ );
3274
+ process.exit(1);
3275
+ }
3276
+ }
3277
+ )
3278
+ )
3279
+ );
2814
3280
 
2815
3281
  // src/index.ts
2816
3282
  var require2 = createRequire(import.meta.url);
@@ -2831,7 +3297,7 @@ Examples:
2831
3297
  For more information, visit: https://github.com/calimero-network/app-registry
2832
3298
  `
2833
3299
  );
2834
- program.option("-u, --url <url>", "Registry API URL", "http://localhost:8082");
3300
+ program.option("-u, --url <url>", "Registry API URL (overrides saved config)");
2835
3301
  program.option(
2836
3302
  "-t, --timeout <timeout>",
2837
3303
  "Request timeout in milliseconds",
@@ -2846,14 +3312,18 @@ program.addCommand(ipfsCommand);
2846
3312
  program.addCommand(localCommand);
2847
3313
  program.addCommand(bundleCommand);
2848
3314
  program.addCommand(configCommand);
3315
+ program.addCommand(orgCommand);
2849
3316
  program.exitOverride();
2850
3317
  try {
2851
3318
  program.parse();
2852
3319
  } catch (err) {
3320
+ if (err && typeof err === "object" && "exitCode" in err) {
3321
+ process.exit(err.exitCode ?? 0);
3322
+ }
2853
3323
  if (err instanceof Error) {
2854
- console.error(chalk6.red("Error:"), err.message);
3324
+ console.error(chalk7.red("Error:"), err.message);
2855
3325
  } else {
2856
- console.error(chalk6.red("Unknown error occurred"));
3326
+ console.error(chalk7.red("Unknown error occurred"));
2857
3327
  }
2858
3328
  process.exit(1);
2859
3329
  }