@btc-vision/cli 1.0.5 → 1.0.6

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.
Files changed (46) hide show
  1. package/package.json +4 -1
  2. package/.gitattributes +0 -2
  3. package/.github/dependabot.yml +0 -9
  4. package/.github/workflows/ci.yml +0 -48
  5. package/.prettierrc.json +0 -12
  6. package/CONTRIBUTING.md +0 -56
  7. package/NOTICE +0 -17
  8. package/SECURITY.md +0 -35
  9. package/eslint.config.js +0 -41
  10. package/gulpfile.js +0 -41
  11. package/src/commands/AcceptCommand.ts +0 -224
  12. package/src/commands/BaseCommand.ts +0 -59
  13. package/src/commands/CompileCommand.ts +0 -195
  14. package/src/commands/ConfigCommand.ts +0 -117
  15. package/src/commands/DeprecateCommand.ts +0 -193
  16. package/src/commands/InfoCommand.ts +0 -293
  17. package/src/commands/InitCommand.ts +0 -541
  18. package/src/commands/InstallCommand.ts +0 -179
  19. package/src/commands/KeygenCommand.ts +0 -157
  20. package/src/commands/ListCommand.ts +0 -169
  21. package/src/commands/LoginCommand.ts +0 -197
  22. package/src/commands/LogoutCommand.ts +0 -76
  23. package/src/commands/PublishCommand.ts +0 -340
  24. package/src/commands/ScopeRegisterCommand.ts +0 -164
  25. package/src/commands/SearchCommand.ts +0 -140
  26. package/src/commands/SignCommand.ts +0 -110
  27. package/src/commands/TransferCommand.ts +0 -363
  28. package/src/commands/UndeprecateCommand.ts +0 -167
  29. package/src/commands/UpdateCommand.ts +0 -200
  30. package/src/commands/VerifyCommand.ts +0 -228
  31. package/src/commands/WhoamiCommand.ts +0 -113
  32. package/src/index.ts +0 -88
  33. package/src/lib/PackageRegistry.abi.json +0 -765
  34. package/src/lib/PackageRegistry.abi.ts +0 -365
  35. package/src/lib/binary.ts +0 -338
  36. package/src/lib/config.ts +0 -265
  37. package/src/lib/credentials.ts +0 -176
  38. package/src/lib/ipfs.ts +0 -382
  39. package/src/lib/manifest.ts +0 -195
  40. package/src/lib/provider.ts +0 -121
  41. package/src/lib/registry.ts +0 -467
  42. package/src/lib/transaction.ts +0 -205
  43. package/src/lib/wallet.ts +0 -262
  44. package/src/types/PackageRegistry.ts +0 -344
  45. package/src/types/index.ts +0 -147
  46. package/tsconfig.json +0 -25
@@ -1,200 +0,0 @@
1
- /**
2
- * Update command - Update installed plugins
3
- *
4
- * @module commands/UpdateCommand
5
- */
6
-
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import { BaseCommand } from './BaseCommand.js';
10
- import { parseOpnetBinary, verifyChecksum } from '../lib/binary.js';
11
- import { getPackage, getVersion } from '../lib/registry.js';
12
- import { fetchFromIPFS } from '../lib/ipfs.js';
13
- import { CLIWallet } from '../lib/wallet.js';
14
- import { NetworkName } from '../types/index.js';
15
-
16
- interface UpdateOptions {
17
- dir?: string;
18
- network: string;
19
- skipVerify?: boolean;
20
- }
21
-
22
- interface UpdateInfo {
23
- file: string;
24
- name: string;
25
- currentVersion: string;
26
- latestVersion: string;
27
- cid: string;
28
- }
29
-
30
- export class UpdateCommand extends BaseCommand {
31
- constructor() {
32
- super('update', 'Update installed plugins to latest versions');
33
- }
34
-
35
- protected configure(): void {
36
- this.command
37
- .argument('[package]', 'Specific package to update (default: all)')
38
- .option('-d, --dir <path>', 'Plugins directory (default: ./plugins/)')
39
- .option('-n, --network <network>', 'Network', 'mainnet')
40
- .option('--skip-verify', 'Skip signature verification')
41
- .action((packageName?: string, options?: UpdateOptions) =>
42
- this.execute(packageName, options || { network: 'mainnet' }),
43
- );
44
- }
45
-
46
- private async execute(packageName?: string, options?: UpdateOptions): Promise<void> {
47
- try {
48
- const pluginsDir = options?.dir || path.join(process.cwd(), 'plugins');
49
-
50
- if (!fs.existsSync(pluginsDir)) {
51
- this.logger.warn('No plugins directory found.');
52
- this.logger.log(`Expected: ${pluginsDir}`);
53
- return;
54
- }
55
-
56
- // Find all .opnet files
57
- const files = fs.readdirSync(pluginsDir).filter((f) => f.endsWith('.opnet'));
58
-
59
- if (files.length === 0) {
60
- this.logger.warn('No plugins installed.');
61
- return;
62
- }
63
-
64
- const network = (options?.network || 'mainnet') as NetworkName;
65
- const updates: UpdateInfo[] = [];
66
-
67
- // Check for updates
68
- this.logger.info('\nChecking for updates...\n');
69
-
70
- for (const file of files) {
71
- const filePath = path.join(pluginsDir, file);
72
-
73
- try {
74
- const data = fs.readFileSync(filePath);
75
- const parsed = parseOpnetBinary(data);
76
- const name = parsed.metadata.name;
77
-
78
- // Filter by package name if specified
79
- if (packageName && name !== packageName) {
80
- continue;
81
- }
82
-
83
- this.logger.info(`Checking ${name}...`);
84
-
85
- const packageInfo = await getPackage(name, network);
86
- if (!packageInfo) {
87
- this.logger.info(`${name}: not found in registry`);
88
- continue;
89
- }
90
-
91
- const currentVersion = parsed.metadata.version;
92
- const latestVersion = packageInfo.latestVersion;
93
-
94
- if (currentVersion === latestVersion) {
95
- this.logger.success(`${name}@${currentVersion}: up to date`);
96
- continue;
97
- }
98
-
99
- // Get latest version info
100
- const versionInfo = await getVersion(name, latestVersion, network);
101
- if (!versionInfo) {
102
- this.logger.warn(`${name}: latest version info unavailable`);
103
- continue;
104
- }
105
-
106
- this.logger.info(`${name}: ${currentVersion} -> ${latestVersion}`);
107
- updates.push({
108
- file,
109
- name,
110
- currentVersion,
111
- latestVersion,
112
- cid: versionInfo.ipfsCid,
113
- });
114
- } catch {
115
- this.logger.warn(`${file}: failed to parse`);
116
- }
117
- }
118
-
119
- if (updates.length === 0) {
120
- this.logger.log('');
121
- this.logger.success('All plugins are up to date!');
122
- return;
123
- }
124
-
125
- // Display updates
126
- this.logger.log('');
127
- this.logger.info('Available Updates:');
128
- this.logger.log('─'.repeat(60));
129
- for (const update of updates) {
130
- this.logger.log(
131
- ` ${update.name}: ${update.currentVersion} -> ${update.latestVersion}`,
132
- );
133
- }
134
- this.logger.log('');
135
-
136
- // Perform updates
137
- for (const update of updates) {
138
- this.logger.info(`Updating ${update.name}...`);
139
-
140
- try {
141
- // Download from IPFS
142
- const result = await fetchFromIPFS(update.cid);
143
-
144
- // Verify
145
- const parsed = parseOpnetBinary(result.data);
146
-
147
- if (!verifyChecksum(parsed)) {
148
- this.logger.fail(`${update.name}: checksum failed`);
149
- continue;
150
- }
151
-
152
- if (!options?.skipVerify) {
153
- const isUnsigned = parsed.publicKey.every((b) => b === 0);
154
- if (!isUnsigned) {
155
- const mldsaLevel = ([44, 65, 87] as const)[parsed.mldsaLevel];
156
- const signatureValid = CLIWallet.verifyMLDSA(
157
- parsed.checksum,
158
- parsed.signature,
159
- parsed.publicKey,
160
- mldsaLevel,
161
- );
162
-
163
- if (!signatureValid) {
164
- this.logger.fail(`${update.name}: signature invalid`);
165
- continue;
166
- }
167
- }
168
- }
169
-
170
- // Save updated plugin
171
- const newFileName = `${update.name.replace(/^@/, '').replace(/\//g, '-')}-${update.latestVersion}.opnet`;
172
- const newFilePath = path.join(pluginsDir, newFileName);
173
-
174
- fs.writeFileSync(newFilePath, result.data);
175
-
176
- // Remove old file if different
177
- const oldFilePath = path.join(pluginsDir, update.file);
178
- if (oldFilePath !== newFilePath && fs.existsSync(oldFilePath)) {
179
- fs.unlinkSync(oldFilePath);
180
- }
181
-
182
- this.logger.success(`${update.name}: updated to ${update.latestVersion}`);
183
- } catch (error) {
184
- this.logger.fail(
185
- `${update.name}: ${error instanceof Error ? error.message : String(error)}`,
186
- );
187
- }
188
- }
189
-
190
- this.logger.log('');
191
- this.logger.success('Update complete!');
192
- this.logger.log('');
193
- } catch (error) {
194
- this.logger.fail('Update failed');
195
- this.exitWithError(this.formatError(error));
196
- }
197
- }
198
- }
199
-
200
- export const updateCommand = new UpdateCommand().getCommand();
@@ -1,228 +0,0 @@
1
- /**
2
- * Verify command - Verify .opnet binary signature
3
- *
4
- * @module commands/VerifyCommand
5
- */
6
-
7
- import * as fs from 'fs';
8
- import * as crypto from 'crypto';
9
- import { BaseCommand } from './BaseCommand.js';
10
- import { formatFileSize, parseOpnetBinary, verifyChecksum } from '../lib/binary.js';
11
- import { CLIWallet } from '../lib/wallet.js';
12
- import { CLIMldsaLevel } from '../types/index.js';
13
-
14
- interface VerifyOptions {
15
- verbose?: boolean;
16
- json?: boolean;
17
- }
18
-
19
- export class VerifyCommand extends BaseCommand {
20
- constructor() {
21
- super('verify', 'Verify a .opnet binary signature and integrity');
22
- }
23
-
24
- protected configure(): void {
25
- this.command
26
- .argument('<file>', 'Path to .opnet file')
27
- .option('-v, --verbose', 'Show detailed information')
28
- .option('--json', 'Output as JSON')
29
- .action((file: string, options: VerifyOptions) => this.execute(file, options));
30
- }
31
-
32
- private execute(file: string, options: VerifyOptions): void {
33
- try {
34
- if (!fs.existsSync(file)) {
35
- if (options.json) {
36
- this.logger.log(
37
- JSON.stringify({ valid: false, error: `File not found: ${file}` }),
38
- );
39
- process.exit(1);
40
- }
41
- this.exitWithError(`File not found: ${file}`);
42
- }
43
-
44
- const data = fs.readFileSync(file);
45
- const fileSize = data.length;
46
-
47
- // Parse binary
48
- let parsed;
49
- try {
50
- parsed = parseOpnetBinary(data);
51
- } catch (error) {
52
- if (options.json) {
53
- this.logger.log(
54
- JSON.stringify({
55
- valid: false,
56
- error: `Parse error: ${error instanceof Error ? error.message : String(error)}`,
57
- }),
58
- );
59
- process.exit(1);
60
- }
61
- this.exitWithError(
62
- `Parse error: ${error instanceof Error ? error.message : String(error)}`,
63
- );
64
- }
65
-
66
- // Get MLDSA level from binary
67
- const mldsaLevel = ([44, 65, 87] as const)[parsed.mldsaLevel] as CLIMldsaLevel;
68
-
69
- // Verify checksum
70
- const checksumValid = verifyChecksum(parsed);
71
-
72
- // Verify signature
73
- let signatureValid = false;
74
- let signatureError: string | undefined;
75
-
76
- // Check if public key is all zeros (unsigned)
77
- const isUnsigned = parsed.publicKey.every((b) => b === 0);
78
-
79
- if (isUnsigned) {
80
- signatureError = 'Binary is unsigned (public key is empty)';
81
- } else {
82
- try {
83
- signatureValid = CLIWallet.verifyMLDSA(
84
- parsed.checksum,
85
- parsed.signature,
86
- parsed.publicKey,
87
- mldsaLevel,
88
- );
89
- } catch (error) {
90
- signatureError = error instanceof Error ? error.message : String(error);
91
- }
92
- }
93
-
94
- const isValid = checksumValid && signatureValid;
95
-
96
- if (options.json) {
97
- const output = {
98
- valid: isValid,
99
- file,
100
- fileSize,
101
- formatVersion: parsed.formatVersion,
102
- mldsaLevel,
103
- checksumValid,
104
- signatureValid,
105
- signatureError,
106
- isUnsigned,
107
- metadata: parsed.metadata,
108
- publicKeyHash: crypto
109
- .createHash('sha256')
110
- .update(parsed.publicKey)
111
- .digest('hex'),
112
- bytecodeSize: parsed.bytecode.length,
113
- protoSize: parsed.proto?.length ?? 0,
114
- };
115
- this.logger.log(JSON.stringify(output, null, 2));
116
- process.exit(isValid ? 0 : 1);
117
- }
118
-
119
- // Display results
120
- this.logger.info('\nOPNet Binary Verification\n');
121
- this.logger.log('─'.repeat(60));
122
-
123
- // File info
124
- this.logger.log(`File: ${file}`);
125
- this.logger.log(`Size: ${formatFileSize(fileSize)}`);
126
- this.logger.log(`Format Version: ${parsed.formatVersion}`);
127
- this.logger.log('');
128
-
129
- // Plugin info
130
- this.logger.log('Plugin:');
131
- this.logger.log(` Name: ${parsed.metadata.name}`);
132
- this.logger.log(` Version: ${parsed.metadata.version}`);
133
- this.logger.log(` Type: ${parsed.metadata.pluginType}`);
134
- this.logger.log(` OPNet Version: ${parsed.metadata.opnetVersion}`);
135
- this.logger.log('');
136
-
137
- // Cryptographic info
138
- this.logger.log('Cryptography:');
139
- this.logger.log(` MLDSA Level: MLDSA-${mldsaLevel}`);
140
- this.logger.log(` Public Key: ${formatFileSize(parsed.publicKey.length)}`);
141
- this.logger.log(` Signature: ${formatFileSize(parsed.signature.length)}`);
142
-
143
- if (!isUnsigned) {
144
- const pkHash = crypto.createHash('sha256').update(parsed.publicKey).digest('hex');
145
- this.logger.log(` PubKey Hash: ${pkHash.substring(0, 16)}...`);
146
- }
147
- this.logger.log('');
148
-
149
- // Verification results
150
- this.logger.log('Verification:');
151
- this.logger.log(` Checksum: ${checksumValid ? 'VALID' : 'INVALID'}`);
152
-
153
- if (isUnsigned) {
154
- this.logger.log(` Signature: UNSIGNED`);
155
- } else if (signatureError) {
156
- this.logger.log(` Signature: ERROR - ${signatureError}`);
157
- } else {
158
- this.logger.log(` Signature: ${signatureValid ? 'VALID' : 'INVALID'}`);
159
- }
160
-
161
- this.logger.log('');
162
- this.logger.log('─'.repeat(60));
163
-
164
- if (isUnsigned) {
165
- this.logger.warn('WARNING: This binary is unsigned and cannot be published.');
166
- this.logger.warn('Use `opnet sign` to sign it.');
167
- } else if (isValid) {
168
- this.logger.success('VERIFIED: Binary is valid and properly signed.');
169
- } else {
170
- this.logger.fail('FAILED: Binary verification failed.');
171
- if (!checksumValid) {
172
- this.logger.error(' - Checksum mismatch (binary may be corrupted)');
173
- }
174
- if (!signatureValid && !signatureError) {
175
- this.logger.error(' - Signature invalid (binary may be tampered)');
176
- }
177
- }
178
- this.logger.log('');
179
-
180
- // Verbose output
181
- if (options.verbose) {
182
- this.logger.log('Sizes:');
183
- this.logger.log(` Metadata: ${formatFileSize(parsed.rawMetadata.length)}`);
184
- this.logger.log(` Bytecode: ${formatFileSize(parsed.bytecode.length)}`);
185
- this.logger.log(` Proto: ${formatFileSize(parsed.proto?.length ?? 0)}`);
186
- this.logger.log('');
187
-
188
- this.logger.log('Checksums:');
189
- this.logger.log(` Stored: ${parsed.checksum.toString('hex')}`);
190
- this.logger.log('');
191
-
192
- this.logger.log('Author:');
193
- this.logger.log(` Name: ${parsed.metadata.author.name}`);
194
- if (parsed.metadata.author.email) {
195
- this.logger.log(` Email: ${parsed.metadata.author.email}`);
196
- }
197
- this.logger.log('');
198
-
199
- this.logger.log('Permissions:');
200
- const perms = parsed.metadata.permissions;
201
- if (perms) {
202
- this.logger.log(` Database: ${perms.database?.enabled ? 'Yes' : 'No'}`);
203
- this.logger.log(
204
- ` Block Hooks: ${perms.blocks?.preProcess || perms.blocks?.postProcess || perms.blocks?.onChange ? 'Yes' : 'No'}`,
205
- );
206
- this.logger.log(
207
- ` Epoch Hooks: ${perms.epochs?.onChange || perms.epochs?.onFinalized ? 'Yes' : 'No'}`,
208
- );
209
- this.logger.log(` Mempool Feed: ${perms.mempool?.txFeed ? 'Yes' : 'No'}`);
210
- this.logger.log(` API Endpoints: ${perms.api?.addEndpoints ? 'Yes' : 'No'}`);
211
- this.logger.log(` Websocket: ${perms.api?.addWebsocket ? 'Yes' : 'No'}`);
212
- this.logger.log(
213
- ` Filesystem: ${perms.filesystem?.configDir || perms.filesystem?.tempDir ? 'Yes' : 'No'}`,
214
- );
215
- } else {
216
- this.logger.log(' (none configured)');
217
- }
218
- this.logger.log('');
219
- }
220
-
221
- process.exit(isValid ? 0 : 1);
222
- } catch (error) {
223
- this.exitWithError(this.formatError(error));
224
- }
225
- }
226
- }
227
-
228
- export const verifyCommand = new VerifyCommand().getCommand();
@@ -1,113 +0,0 @@
1
- /**
2
- * Whoami command - Display current identity
3
- *
4
- * @module commands/WhoamiCommand
5
- */
6
-
7
- import { BaseCommand } from './BaseCommand.js';
8
- import {
9
- getCredentialSource,
10
- hasCredentials,
11
- loadCredentials,
12
- maskSensitive,
13
- } from '../lib/credentials.js';
14
- import { CLIWallet } from '../lib/wallet.js';
15
-
16
- interface WhoamiOptions {
17
- verbose?: boolean;
18
- publicKey?: boolean;
19
- }
20
-
21
- export class WhoamiCommand extends BaseCommand {
22
- constructor() {
23
- super('whoami', 'Display current wallet identity and configuration');
24
- }
25
-
26
- protected configure(): void {
27
- this.command
28
- .option('-v, --verbose', 'Show detailed information')
29
- .option('--public-key', 'Show full MLDSA public key')
30
- .action((options: WhoamiOptions) => this.execute(options));
31
- }
32
-
33
- private execute(options: WhoamiOptions): void {
34
- try {
35
- if (!hasCredentials()) {
36
- this.logger.warn('Not logged in.');
37
- this.logger.info('Run `opnet login` to configure your wallet.');
38
- return;
39
- }
40
-
41
- const credentials = loadCredentials();
42
- if (!credentials) {
43
- this.logger.warn('No credentials found.');
44
- return;
45
- }
46
-
47
- const source = getCredentialSource();
48
-
49
- this.logger.info('\nOPNet Identity\n');
50
- this.logger.log('─'.repeat(50));
51
-
52
- this.logger.log(`Network: ${credentials.network}`);
53
- this.logger.log(`MLDSA Level: ${credentials.mldsaLevel}`);
54
- this.logger.log(`Auth Source: ${source}`);
55
-
56
- try {
57
- const wallet = CLIWallet.fromCredentials(credentials);
58
-
59
- this.logger.log('');
60
- this.logger.log(`P2TR Address: ${wallet.p2trAddress}`);
61
- this.logger.log(`MLDSA PubKey Hash: ${wallet.mldsaPublicKeyHash}`);
62
-
63
- if (options.publicKey) {
64
- this.logger.log('');
65
- this.logger.log('MLDSA Public Key:');
66
- this.logger.log(wallet.mldsaPublicKey.toString('hex'));
67
- }
68
-
69
- if (options.verbose) {
70
- this.logger.log('');
71
- this.logger.log('─'.repeat(50));
72
- this.logger.log('Details:');
73
- this.logger.log(` Security Level: MLDSA-${credentials.mldsaLevel}`);
74
- this.logger.log(` Public Key Size: ${wallet.mldsaPublicKey.length} bytes`);
75
-
76
- if (credentials.mnemonic) {
77
- this.logger.log(' Auth Method: BIP-39 Mnemonic');
78
- this.logger.log(` Mnemonic: ${maskSensitive(credentials.mnemonic, 8)}`);
79
- } else {
80
- this.logger.log(' Auth Method: WIF + MLDSA Keys');
81
- if (credentials.wif) {
82
- this.logger.log(` WIF: ${maskSensitive(credentials.wif, 4)}`);
83
- }
84
- }
85
- }
86
- } catch (error) {
87
- this.logger.log('');
88
- this.logger.warn('Could not load wallet details.');
89
- if (options.verbose) {
90
- this.logger.debug(` Error: ${this.formatError(error)}`);
91
- }
92
-
93
- this.logger.log('');
94
- if (credentials.mnemonic) {
95
- this.logger.log(`Auth Method: BIP-39 Mnemonic`);
96
- if (options.verbose) {
97
- this.logger.log(
98
- `Mnemonic: ${maskSensitive(credentials.mnemonic, 8)}`,
99
- );
100
- }
101
- } else {
102
- this.logger.log(`Auth Method: WIF + MLDSA Keys`);
103
- }
104
- }
105
-
106
- this.logger.log('');
107
- } catch (error) {
108
- this.exitWithError(this.formatError(error));
109
- }
110
- }
111
- }
112
-
113
- export const whoamiCommand = new WhoamiCommand().getCommand();
package/src/index.ts DELETED
@@ -1,88 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * OPNet CLI - Command Line Interface for OPNet Plugin Ecosystem
4
- *
5
- * @module @btc-vision/cli
6
- */
7
-
8
- import { Command } from 'commander';
9
- import { Logger } from '@btc-vision/logger';
10
-
11
- // Commands
12
- import { configCommand } from './commands/ConfigCommand.js';
13
- import { loginCommand } from './commands/LoginCommand.js';
14
- import { logoutCommand } from './commands/LogoutCommand.js';
15
- import { whoamiCommand } from './commands/WhoamiCommand.js';
16
- import { keygenCommand } from './commands/KeygenCommand.js';
17
- import { initCommand } from './commands/InitCommand.js';
18
- import { compileCommand } from './commands/CompileCommand.js';
19
- import { verifyCommand } from './commands/VerifyCommand.js';
20
- import { infoCommand } from './commands/InfoCommand.js';
21
- import { signCommand } from './commands/SignCommand.js';
22
- import { publishCommand } from './commands/PublishCommand.js';
23
- import { deprecateCommand } from './commands/DeprecateCommand.js';
24
- import { undeprecateCommand } from './commands/UndeprecateCommand.js';
25
- import { transferCommand } from './commands/TransferCommand.js';
26
- import { acceptCommand } from './commands/AcceptCommand.js';
27
- import { scopeRegisterCommand } from './commands/ScopeRegisterCommand.js';
28
- import { installCommand } from './commands/InstallCommand.js';
29
- import { updateCommand } from './commands/UpdateCommand.js';
30
- import { listCommand } from './commands/ListCommand.js';
31
- import { searchCommand } from './commands/SearchCommand.js';
32
-
33
- const logger = new Logger();
34
- const program = new Command();
35
-
36
- program
37
- .name('opnet')
38
- .description('OPNet CLI - Build, sign, and publish plugins for the OPNet ecosystem')
39
- .version('1.0.0');
40
-
41
- // Configuration commands
42
- program.addCommand(configCommand);
43
- program.addCommand(loginCommand);
44
- program.addCommand(logoutCommand);
45
- program.addCommand(whoamiCommand);
46
- program.addCommand(keygenCommand);
47
-
48
- // Plugin development commands
49
- program.addCommand(initCommand);
50
- program.addCommand(compileCommand);
51
- program.addCommand(verifyCommand);
52
- program.addCommand(infoCommand);
53
- program.addCommand(signCommand);
54
-
55
- // Registry commands
56
- program.addCommand(publishCommand);
57
- program.addCommand(deprecateCommand);
58
- program.addCommand(undeprecateCommand);
59
- program.addCommand(transferCommand);
60
- program.addCommand(acceptCommand);
61
- program.addCommand(scopeRegisterCommand);
62
- program.addCommand(installCommand);
63
- program.addCommand(updateCommand);
64
- program.addCommand(listCommand);
65
- program.addCommand(searchCommand);
66
-
67
- // Error handling
68
- program.showHelpAfterError();
69
- program.showSuggestionAfterError();
70
-
71
- // Custom error handling
72
- program.exitOverride((err) => {
73
- if (err.code === 'commander.help') {
74
- process.exit(0);
75
- }
76
- if (err.code === 'commander.version') {
77
- process.exit(0);
78
- }
79
- logger.error(`Error: ${err.message}`);
80
- process.exit(1);
81
- });
82
-
83
- // Parse command line arguments
84
- program.parseAsync(process.argv).catch((error: unknown) => {
85
- const message = error instanceof Error ? error.message : String(error);
86
- logger.error(`Error: ${message}`);
87
- process.exit(1);
88
- });