@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 +642 -172
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import
|
|
3
|
+
import chalk7 from 'chalk';
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
|
-
import
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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 ?
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
1152
|
+
console.log(chalk7.green(`
|
|
1153
1153
|
\u2705 ${result.message}`));
|
|
1154
1154
|
if (manifest.app?.name) {
|
|
1155
|
-
console.log(
|
|
1155
|
+
console.log(chalk7.blue(`
|
|
1156
1156
|
\u{1F4F1} App: ${manifest.app.name}`));
|
|
1157
1157
|
console.log(
|
|
1158
|
-
|
|
1158
|
+
chalk7.blue(`\u{1F464} Developer: ${manifest.app.developer_pubkey}`)
|
|
1159
1159
|
);
|
|
1160
|
-
console.log(
|
|
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(
|
|
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 =
|
|
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(
|
|
1183
|
-
console.log(
|
|
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(
|
|
1185
|
+
console.log(chalk7.green("Website:"), profile.website);
|
|
1186
1186
|
}
|
|
1187
1187
|
if (profile.proofs.length > 0) {
|
|
1188
|
-
console.log(
|
|
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 ?
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
1236
|
+
console.log(chalk7.green(`
|
|
1237
1237
|
\u2705 ${result.message}`));
|
|
1238
|
-
console.log(
|
|
1238
|
+
console.log(chalk7.blue(`
|
|
1239
1239
|
\u{1F464} Developer: ${displayName}`));
|
|
1240
|
-
console.log(
|
|
1240
|
+
console.log(chalk7.blue(`\u{1F511} Public Key: ${pubkey}`));
|
|
1241
1241
|
if (options.website) {
|
|
1242
|
-
console.log(
|
|
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(
|
|
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 =
|
|
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(
|
|
1271
|
-
console.log(
|
|
1272
|
-
console.log(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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) =>
|
|
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 =
|
|
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(
|
|
1599
|
+
console.log(chalk7.blue("\n\u{1F4F1} Local Registry Status:"));
|
|
1600
1600
|
console.log(
|
|
1601
|
-
|
|
1601
|
+
chalk7.green(
|
|
1602
1602
|
`\u2705 Server: http://${config.getHost()}:${config.getPort()}`
|
|
1603
1603
|
)
|
|
1604
1604
|
);
|
|
1605
1605
|
console.log(
|
|
1606
|
-
|
|
1606
|
+
chalk7.green(
|
|
1607
1607
|
`\u{1F310} Public URL: http://${config.getPublicHost()}:${config.getPort()}`
|
|
1608
1608
|
)
|
|
1609
1609
|
);
|
|
1610
|
-
console.log(
|
|
1610
|
+
console.log(chalk7.green(`\u{1F4C1} Data: ${config.getDataDir()}`));
|
|
1611
1611
|
console.log(
|
|
1612
|
-
|
|
1612
|
+
chalk7.green(
|
|
1613
1613
|
`\u{1F4CB} Health: http://${config.getHost()}:${config.getPort()}/healthz`
|
|
1614
1614
|
)
|
|
1615
1615
|
);
|
|
1616
1616
|
console.log(
|
|
1617
|
-
|
|
1617
|
+
chalk7.green(
|
|
1618
1618
|
`\u{1F4CA} Stats: http://${config.getHost()}:${config.getPort()}/stats`
|
|
1619
1619
|
)
|
|
1620
1620
|
);
|
|
1621
1621
|
console.log(
|
|
1622
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
1662
|
-
console.log(
|
|
1663
|
-
console.log(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
1688
|
+
chalk7.yellow("\u26A0\uFE0F This will delete all local registry data!")
|
|
1689
1689
|
);
|
|
1690
|
-
console.log(
|
|
1690
|
+
console.log(chalk7.yellow(" Use --force flag to confirm"));
|
|
1691
1691
|
return;
|
|
1692
1692
|
}
|
|
1693
|
-
const spinner2 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
1759
|
+
chalk7.green("\u2705 Local registry populated with sample applications")
|
|
1760
1760
|
);
|
|
1761
1761
|
console.log(
|
|
1762
|
-
|
|
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(
|
|
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
|
|
2105
|
-
if (!
|
|
2106
|
-
|
|
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
|
-
|
|
2126
|
-
path7.
|
|
2127
|
-
|
|
2108
|
+
fs9.writeFileSync(
|
|
2109
|
+
path7.join(outputDir, "manifest.json"),
|
|
2110
|
+
JSON.stringify(manifest, null, 2)
|
|
2128
2111
|
);
|
|
2129
|
-
fs9.
|
|
2130
|
-
|
|
2131
|
-
fs9.writeFileSync(
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
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
|
-
|
|
2231
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
2381
|
-
|
|
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
|
-
|
|
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(
|
|
2680
|
+
console.log(chalk7.green("\u2705 API key set successfully"));
|
|
2682
2681
|
console.log(
|
|
2683
|
-
|
|
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(
|
|
2690
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
2730
|
-
console.log(
|
|
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(
|
|
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(
|
|
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 =
|
|
2751
|
+
urlSource = chalk7.yellow("(from CALIMERO_REGISTRY_URL env var)");
|
|
2753
2752
|
} else if (configFileExists) {
|
|
2754
|
-
urlSource =
|
|
2753
|
+
urlSource = chalk7.gray("(from config file)");
|
|
2755
2754
|
} else {
|
|
2756
|
-
urlSource =
|
|
2755
|
+
urlSource = chalk7.gray("(default)");
|
|
2757
2756
|
}
|
|
2758
|
-
console.log(` ${
|
|
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 =
|
|
2762
|
+
apiKeySource = chalk7.yellow("(from CALIMERO_API_KEY env var)");
|
|
2764
2763
|
} else if (configFileExists) {
|
|
2765
|
-
apiKeySource =
|
|
2764
|
+
apiKeySource = chalk7.gray("(from config file)");
|
|
2766
2765
|
} else {
|
|
2767
|
-
apiKeySource =
|
|
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(` ${
|
|
2769
|
+
console.log(` ${chalk7.bold("API Key:")} ${masked} ${apiKeySource}`);
|
|
2771
2770
|
} else {
|
|
2772
|
-
console.log(` ${
|
|
2771
|
+
console.log(` ${chalk7.bold("API Key:")} ${chalk7.gray("(not set)")}`);
|
|
2773
2772
|
}
|
|
2774
|
-
console.log(
|
|
2773
|
+
console.log(chalk7.blue(`
|
|
2775
2774
|
\u{1F4C1} Config file: ${configPath}`));
|
|
2776
2775
|
if (!configFileExists) {
|
|
2777
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
2791
|
+
chalk7.red("\u274C Configuration reset requires --force flag")
|
|
2793
2792
|
);
|
|
2794
2793
|
console.log(
|
|
2795
|
-
|
|
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(
|
|
2804
|
-
console.log(
|
|
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(
|
|
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
|
|
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(
|
|
3324
|
+
console.error(chalk7.red("Error:"), err.message);
|
|
2855
3325
|
} else {
|
|
2856
|
-
console.error(
|
|
3326
|
+
console.error(chalk7.red("Unknown error occurred"));
|
|
2857
3327
|
}
|
|
2858
3328
|
process.exit(1);
|
|
2859
3329
|
}
|