@btc-vision/cli 1.0.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.
Files changed (110) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/dependabot.yml +9 -0
  3. package/.github/workflows/ci.yml +48 -0
  4. package/.prettierrc.json +12 -0
  5. package/CONTRIBUTING.md +56 -0
  6. package/LICENSE +190 -0
  7. package/NOTICE +17 -0
  8. package/README.md +509 -0
  9. package/SECURITY.md +35 -0
  10. package/build/commands/AcceptCommand.d.ts +7 -0
  11. package/build/commands/AcceptCommand.js +110 -0
  12. package/build/commands/BaseCommand.d.ts +12 -0
  13. package/build/commands/BaseCommand.js +27 -0
  14. package/build/commands/CompileCommand.d.ts +7 -0
  15. package/build/commands/CompileCommand.js +138 -0
  16. package/build/commands/ConfigCommand.d.ts +17 -0
  17. package/build/commands/ConfigCommand.js +124 -0
  18. package/build/commands/DeprecateCommand.d.ts +7 -0
  19. package/build/commands/DeprecateCommand.js +112 -0
  20. package/build/commands/InfoCommand.d.ts +10 -0
  21. package/build/commands/InfoCommand.js +223 -0
  22. package/build/commands/InitCommand.d.ts +16 -0
  23. package/build/commands/InitCommand.js +336 -0
  24. package/build/commands/InstallCommand.d.ts +7 -0
  25. package/build/commands/InstallCommand.js +130 -0
  26. package/build/commands/KeygenCommand.d.ts +13 -0
  27. package/build/commands/KeygenCommand.js +133 -0
  28. package/build/commands/ListCommand.d.ts +7 -0
  29. package/build/commands/ListCommand.js +117 -0
  30. package/build/commands/LoginCommand.d.ts +9 -0
  31. package/build/commands/LoginCommand.js +139 -0
  32. package/build/commands/LogoutCommand.d.ts +7 -0
  33. package/build/commands/LogoutCommand.js +57 -0
  34. package/build/commands/PublishCommand.d.ts +7 -0
  35. package/build/commands/PublishCommand.js +163 -0
  36. package/build/commands/SearchCommand.d.ts +7 -0
  37. package/build/commands/SearchCommand.js +97 -0
  38. package/build/commands/SignCommand.d.ts +7 -0
  39. package/build/commands/SignCommand.js +80 -0
  40. package/build/commands/TransferCommand.d.ts +8 -0
  41. package/build/commands/TransferCommand.js +179 -0
  42. package/build/commands/UndeprecateCommand.d.ts +7 -0
  43. package/build/commands/UndeprecateCommand.js +95 -0
  44. package/build/commands/UpdateCommand.d.ts +7 -0
  45. package/build/commands/UpdateCommand.js +130 -0
  46. package/build/commands/VerifyCommand.d.ts +7 -0
  47. package/build/commands/VerifyCommand.js +167 -0
  48. package/build/commands/WhoamiCommand.d.ts +7 -0
  49. package/build/commands/WhoamiCommand.js +84 -0
  50. package/build/index.d.ts +2 -0
  51. package/build/index.js +64 -0
  52. package/build/lib/PackageRegistry.abi.d.ts +2 -0
  53. package/build/lib/PackageRegistry.abi.js +356 -0
  54. package/build/lib/binary.d.ts +16 -0
  55. package/build/lib/binary.js +165 -0
  56. package/build/lib/config.d.ts +11 -0
  57. package/build/lib/config.js +160 -0
  58. package/build/lib/credentials.d.ts +10 -0
  59. package/build/lib/credentials.js +89 -0
  60. package/build/lib/ipfs.d.ts +16 -0
  61. package/build/lib/ipfs.js +209 -0
  62. package/build/lib/manifest.d.ts +14 -0
  63. package/build/lib/manifest.js +88 -0
  64. package/build/lib/provider.d.ts +9 -0
  65. package/build/lib/provider.js +48 -0
  66. package/build/lib/registry.d.ts +58 -0
  67. package/build/lib/registry.js +197 -0
  68. package/build/lib/wallet.d.ts +32 -0
  69. package/build/lib/wallet.js +114 -0
  70. package/build/types/PackageRegistry.d.ts +177 -0
  71. package/build/types/PackageRegistry.js +1 -0
  72. package/build/types/index.d.ts +30 -0
  73. package/build/types/index.js +52 -0
  74. package/eslint.config.js +41 -0
  75. package/gulpfile.js +41 -0
  76. package/package.json +83 -0
  77. package/src/commands/AcceptCommand.ts +151 -0
  78. package/src/commands/BaseCommand.ts +59 -0
  79. package/src/commands/CompileCommand.ts +196 -0
  80. package/src/commands/ConfigCommand.ts +144 -0
  81. package/src/commands/DeprecateCommand.ts +156 -0
  82. package/src/commands/InfoCommand.ts +293 -0
  83. package/src/commands/InitCommand.ts +465 -0
  84. package/src/commands/InstallCommand.ts +179 -0
  85. package/src/commands/KeygenCommand.ts +157 -0
  86. package/src/commands/ListCommand.ts +169 -0
  87. package/src/commands/LoginCommand.ts +197 -0
  88. package/src/commands/LogoutCommand.ts +76 -0
  89. package/src/commands/PublishCommand.ts +230 -0
  90. package/src/commands/SearchCommand.ts +141 -0
  91. package/src/commands/SignCommand.ts +122 -0
  92. package/src/commands/TransferCommand.ts +235 -0
  93. package/src/commands/UndeprecateCommand.ts +134 -0
  94. package/src/commands/UpdateCommand.ts +200 -0
  95. package/src/commands/VerifyCommand.ts +228 -0
  96. package/src/commands/WhoamiCommand.ts +113 -0
  97. package/src/index.ts +86 -0
  98. package/src/lib/PackageRegistry.abi.json +765 -0
  99. package/src/lib/PackageRegistry.abi.ts +365 -0
  100. package/src/lib/binary.ts +336 -0
  101. package/src/lib/config.ts +265 -0
  102. package/src/lib/credentials.ts +176 -0
  103. package/src/lib/ipfs.ts +369 -0
  104. package/src/lib/manifest.ts +172 -0
  105. package/src/lib/provider.ts +121 -0
  106. package/src/lib/registry.ts +464 -0
  107. package/src/lib/wallet.ts +271 -0
  108. package/src/types/PackageRegistry.ts +344 -0
  109. package/src/types/index.ts +145 -0
  110. package/tsconfig.json +25 -0
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Compile command - Build plugin to .opnet binary
3
+ *
4
+ * @module commands/CompileCommand
5
+ */
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as esbuild from 'esbuild';
10
+ import bytenode from 'bytenode';
11
+ import { BaseCommand } from './BaseCommand.js';
12
+ import { getManifestPath, loadManifest } from '../lib/manifest.js';
13
+ import { buildOpnetBinary, computeChecksum, formatFileSize } from '../lib/binary.js';
14
+ import { CLIWallet } from '../lib/wallet.js';
15
+ import { canSign, loadCredentials } from '../lib/credentials.js';
16
+ import { CLIMldsaLevel } from '../types/index.js';
17
+
18
+ interface CompileOptions {
19
+ output?: string;
20
+ dir?: string;
21
+ sign: boolean;
22
+ minify: boolean;
23
+ sourcemap: boolean;
24
+ }
25
+
26
+ export class CompileCommand extends BaseCommand {
27
+ constructor() {
28
+ super('compile', 'Compile plugin to .opnet binary format');
29
+ }
30
+
31
+ protected configure(): void {
32
+ this.command
33
+ .option('-o, --output <path>', 'Output file path')
34
+ .option('-d, --dir <path>', 'Plugin directory (default: current)')
35
+ .option('--no-sign', 'Skip signing (produce unsigned binary)')
36
+ .option('--minify', 'Minify the bundled code', true)
37
+ .option('--sourcemap', 'Generate source maps', false)
38
+ .action((options: CompileOptions) => this.execute(options));
39
+ }
40
+
41
+ private async execute(options: CompileOptions): Promise<void> {
42
+ try {
43
+ const projectDir = options.dir ? path.resolve(options.dir) : process.cwd();
44
+ const manifestPath = getManifestPath(projectDir);
45
+
46
+ // Load and validate manifest
47
+ this.logger.info('Loading plugin manifest...');
48
+ const manifest = loadManifest(manifestPath);
49
+ this.logger.success(`Loaded manifest: ${manifest.name}@${manifest.version}`);
50
+
51
+ // Check for source files
52
+ const srcDir = path.join(projectDir, 'src');
53
+ const entryPoint = path.join(srcDir, 'index.ts');
54
+
55
+ if (!fs.existsSync(entryPoint)) {
56
+ this.exitWithError(`Entry point not found: ${entryPoint}`);
57
+ }
58
+
59
+ // Bundle with esbuild
60
+ this.logger.info('Bundling TypeScript...');
61
+ const bundleDir = path.join(projectDir, 'build', '.bundle');
62
+ fs.mkdirSync(bundleDir, { recursive: true });
63
+
64
+ const bundlePath = path.join(bundleDir, 'bundle.js');
65
+
66
+ await esbuild.build({
67
+ entryPoints: [entryPoint],
68
+ bundle: true,
69
+ platform: 'node',
70
+ target: 'es2022',
71
+ format: 'cjs', // bytenode requires CommonJS
72
+ outfile: bundlePath,
73
+ minify: options.minify,
74
+ sourcemap: options.sourcemap,
75
+ treeShaking: true,
76
+ external: [
77
+ '@btc-vision/plugin-sdk',
78
+ '@btc-vision/transaction',
79
+ '@btc-vision/bitcoin',
80
+ 'opnet',
81
+ ],
82
+ });
83
+ this.logger.success('TypeScript bundled');
84
+
85
+ // Compile to V8 bytecode
86
+ this.logger.info('Compiling to V8 bytecode...');
87
+ const bytecodePath = path.join(bundleDir, 'bundle.jsc');
88
+
89
+ await bytenode.compileFile({
90
+ filename: bundlePath,
91
+ output: bytecodePath,
92
+ electron: false,
93
+ });
94
+
95
+ const bytecode = fs.readFileSync(bytecodePath);
96
+ this.logger.success(`V8 bytecode generated (${formatFileSize(bytecode.length)})`);
97
+
98
+ // Check for proto file
99
+ let proto = Buffer.alloc(0);
100
+ const protoPath = path.join(projectDir, 'plugin.proto');
101
+ if (fs.existsSync(protoPath)) {
102
+ proto = fs.readFileSync(protoPath);
103
+ this.logger.info(`Found proto file (${formatFileSize(proto.length)})`);
104
+ }
105
+
106
+ // Prepare signing
107
+ let publicKey: Buffer;
108
+ let signature: Buffer;
109
+ let mldsaLevel: CLIMldsaLevel;
110
+
111
+ if (options.sign) {
112
+ this.logger.info('Loading wallet for signing...');
113
+ const credentials = loadCredentials();
114
+
115
+ if (!credentials || !canSign(credentials)) {
116
+ this.logger.fail('No credentials configured');
117
+ this.logger.warn('To sign plugins, run: opnet login');
118
+ this.logger.warn('Or use --no-sign to skip signing.');
119
+ process.exit(1);
120
+ }
121
+
122
+ const wallet = CLIWallet.fromCredentials(credentials);
123
+ mldsaLevel = wallet.securityLevel;
124
+ publicKey = wallet.mldsaPublicKey;
125
+
126
+ this.logger.success(`Wallet loaded (MLDSA-${mldsaLevel})`);
127
+
128
+ // Compute checksum and sign
129
+ this.logger.info('Signing plugin...');
130
+ const metadataBytes = Buffer.from(JSON.stringify(manifest), 'utf-8');
131
+ const checksum = computeChecksum(metadataBytes, bytecode, proto);
132
+
133
+ signature = wallet.signMLDSA(checksum);
134
+ this.logger.success(
135
+ `Plugin signed (${formatFileSize(signature.length)} signature)`,
136
+ );
137
+ } else {
138
+ this.logger.warn('Skipping signing (--no-sign)');
139
+ // Use dummy values for unsigned binary
140
+ mldsaLevel = 44;
141
+ publicKey = Buffer.alloc(1312); // MLDSA-44 public key size
142
+ signature = Buffer.alloc(2420); // MLDSA-44 signature size
143
+ }
144
+
145
+ // Build .opnet binary
146
+ this.logger.info('Assembling .opnet binary...');
147
+ const binary = buildOpnetBinary({
148
+ mldsaLevel,
149
+ publicKey,
150
+ signature,
151
+ metadata: manifest,
152
+ bytecode,
153
+ proto,
154
+ });
155
+ this.logger.success(`Binary assembled (${formatFileSize(binary.length)})`);
156
+
157
+ // Write output
158
+ const outputPath =
159
+ options.output ||
160
+ path.join(
161
+ projectDir,
162
+ 'build',
163
+ `${manifest.name.replace(/^@/, '').replace(/\//g, '-')}.opnet`,
164
+ );
165
+ const outputDir = path.dirname(outputPath);
166
+ fs.mkdirSync(outputDir, { recursive: true });
167
+ fs.writeFileSync(outputPath, binary);
168
+
169
+ // Clean up bundle directory
170
+ fs.rmSync(bundleDir, { recursive: true, force: true });
171
+
172
+ // Summary
173
+ this.logger.log('');
174
+ this.logger.success('Compilation successful!');
175
+ this.logger.log('');
176
+ this.logger.log(`Output: ${outputPath}`);
177
+ this.logger.log(`Size: ${formatFileSize(binary.length)}`);
178
+ this.logger.log(`Plugin: ${manifest.name}@${manifest.version}`);
179
+ this.logger.log(`Type: ${manifest.pluginType}`);
180
+ this.logger.log(`MLDSA Level: ${mldsaLevel}`);
181
+ this.logger.log(`Signed: ${options.sign ? 'Yes' : 'No'}`);
182
+ this.logger.log('');
183
+
184
+ if (!options.sign) {
185
+ this.logger.warn('Note: This binary is unsigned and cannot be published.');
186
+ this.logger.warn('Use `opnet sign` to sign it, or compile with signing enabled.');
187
+ this.logger.log('');
188
+ }
189
+ } catch (error) {
190
+ this.logger.fail('Compilation failed');
191
+ this.exitWithError(this.formatError(error));
192
+ }
193
+ }
194
+ }
195
+
196
+ export const compileCommand = new CompileCommand().getCommand();
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Config command - Manage CLI configuration
3
+ *
4
+ * @module commands/ConfigCommand
5
+ */
6
+
7
+ import { Command } from 'commander';
8
+ import * as os from 'os';
9
+ import * as path from 'path';
10
+ import { BaseCommand } from './BaseCommand.js';
11
+ import { displayConfig, getConfigValue, saveConfig, setConfigValue } from '../lib/config.js';
12
+ import { CLIConfig } from '../types/index.js';
13
+
14
+ export class ConfigCommand extends BaseCommand {
15
+ constructor() {
16
+ super('config', 'Manage CLI configuration');
17
+ }
18
+
19
+ protected configure(): void {
20
+ this.command
21
+ .addCommand(this.createGetCommand())
22
+ .addCommand(this.createSetCommand())
23
+ .addCommand(this.createListCommand())
24
+ .addCommand(this.createResetCommand())
25
+ .addCommand(this.createPathCommand());
26
+ }
27
+
28
+ private createGetCommand(): Command {
29
+ return new Command('get')
30
+ .description('Get a configuration value')
31
+ .argument('[key]', 'Configuration key (dot notation, e.g., rpcUrls.mainnet)')
32
+ .action((key?: string) => {
33
+ this.handleGet(key);
34
+ });
35
+ }
36
+
37
+ private createSetCommand(): Command {
38
+ return new Command('set')
39
+ .description('Set a configuration value')
40
+ .argument('<key>', 'Configuration key (dot notation)')
41
+ .argument('<value>', 'Value to set')
42
+ .action((key: string, value: string) => {
43
+ this.handleSet(key, value);
44
+ });
45
+ }
46
+
47
+ private createListCommand(): Command {
48
+ return new Command('list').description('List all configuration values').action(() => {
49
+ this.handleList();
50
+ });
51
+ }
52
+
53
+ private createResetCommand(): Command {
54
+ return new Command('reset')
55
+ .description('Reset configuration to defaults')
56
+ .option('-y, --yes', 'Skip confirmation')
57
+ .action((options: { yes?: boolean }) => {
58
+ this.handleReset(options.yes);
59
+ });
60
+ }
61
+
62
+ private createPathCommand(): Command {
63
+ return new Command('path').description('Show configuration file path').action(() => {
64
+ this.handlePath();
65
+ });
66
+ }
67
+
68
+ private handleGet(key?: string): void {
69
+ if (!key) {
70
+ this.logger.log(displayConfig());
71
+ return;
72
+ }
73
+
74
+ const value = getConfigValue(key);
75
+ if (value === undefined) {
76
+ this.exitWithError(`Configuration key not found: ${key}`);
77
+ }
78
+
79
+ if (typeof value === 'object') {
80
+ this.logger.log(JSON.stringify(value, null, 2));
81
+ } else {
82
+ this.logger.log(String(value));
83
+ }
84
+ }
85
+
86
+ private handleSet(key: string, value: string): void {
87
+ let parsedValue: unknown = value;
88
+ try {
89
+ parsedValue = JSON.parse(value);
90
+ } catch {
91
+ // Keep as string if not valid JSON
92
+ }
93
+
94
+ setConfigValue(key, parsedValue);
95
+ this.logger.success(`Set ${key} = ${JSON.stringify(parsedValue)}`);
96
+ }
97
+
98
+ private handleList(): void {
99
+ this.logger.log(displayConfig());
100
+ }
101
+
102
+ private handleReset(confirmed?: boolean): void {
103
+ if (!confirmed) {
104
+ this.logger.warn('This will reset all configuration to defaults.');
105
+ this.logger.info('Use --yes to confirm.');
106
+ return;
107
+ }
108
+
109
+ const defaultConfig: CLIConfig = {
110
+ defaultNetwork: 'mainnet',
111
+ rpcUrls: {
112
+ mainnet: 'https://api.opnet.org',
113
+ testnet: 'https://testnet.opnet.org',
114
+ regtest: 'http://localhost:9001',
115
+ },
116
+ ipfsGateway: 'https://ipfs.opnet.org/ipfs/',
117
+ ipfsGateways: [
118
+ 'https://ipfs.opnet.org/ipfs/',
119
+ 'https://ipfs.io/ipfs/',
120
+ 'https://cloudflare-ipfs.com/ipfs/',
121
+ 'https://dweb.link/ipfs/',
122
+ ],
123
+ ipfsPinningEndpoint: 'https://ipfs.opnet.org/api/v0/add',
124
+ ipfsPinningApiKey: '',
125
+ ipfsPinningAuthHeader: 'Authorization',
126
+ registryAddresses: {
127
+ mainnet: '',
128
+ testnet: '',
129
+ regtest: '',
130
+ },
131
+ defaultMldsaLevel: 44,
132
+ indexerUrl: 'https://indexer.opnet.org',
133
+ };
134
+
135
+ saveConfig(defaultConfig);
136
+ this.logger.success('Configuration reset to defaults.');
137
+ }
138
+
139
+ private handlePath(): void {
140
+ this.logger.log(path.join(os.homedir(), '.opnet', 'config.json'));
141
+ }
142
+ }
143
+
144
+ export const configCommand = new ConfigCommand().getCommand();
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Deprecate command - Mark a package version as deprecated
3
+ *
4
+ * @module commands/DeprecateCommand
5
+ */
6
+
7
+ import { confirm, input } from '@inquirer/prompts';
8
+ import { BaseCommand } from './BaseCommand.js';
9
+ import { getPackage, getVersion, isVersionImmutable } from '../lib/registry.js';
10
+ import { canSign, loadCredentials } from '../lib/credentials.js';
11
+ import { CLIWallet } from '../lib/wallet.js';
12
+ import { NetworkName } from '../types/index.js';
13
+
14
+ interface DeprecateOptions {
15
+ message?: string;
16
+ network: string;
17
+ yes?: boolean;
18
+ }
19
+
20
+ export class DeprecateCommand extends BaseCommand {
21
+ constructor() {
22
+ super('deprecate', 'Mark a package version as deprecated');
23
+ }
24
+
25
+ protected configure(): void {
26
+ this.command
27
+ .argument('<package>', 'Package name (e.g., @scope/name or name)')
28
+ .argument('[version]', 'Version to deprecate (default: latest)')
29
+ .option('-m, --message <message>', 'Deprecation reason/message')
30
+ .option('-n, --network <network>', 'Network', 'mainnet')
31
+ .option('-y, --yes', 'Skip confirmation')
32
+ .action((packageName: string, version?: string, options?: DeprecateOptions) =>
33
+ this.execute(packageName, version, options || { network: 'mainnet' }),
34
+ );
35
+ }
36
+
37
+ private async execute(
38
+ packageName: string,
39
+ version?: string,
40
+ options?: DeprecateOptions,
41
+ ): Promise<void> {
42
+ try {
43
+ // Load credentials
44
+ this.logger.info('Loading wallet...');
45
+ const credentials = loadCredentials();
46
+ if (!credentials || !canSign(credentials)) {
47
+ this.logger.fail('No credentials configured');
48
+ this.logger.warn('Run `opnet login` to configure your wallet.');
49
+ process.exit(1);
50
+ }
51
+ CLIWallet.fromCredentials(credentials);
52
+ this.logger.success('Wallet loaded');
53
+
54
+ // Get package info
55
+ this.logger.info('Fetching package info...');
56
+ const network = (options?.network || 'mainnet') as NetworkName;
57
+ const packageInfo = await getPackage(packageName, network);
58
+
59
+ if (!packageInfo) {
60
+ this.logger.fail('Package not found');
61
+ this.logger.error(`Package "${packageName}" does not exist.`);
62
+ process.exit(1);
63
+ }
64
+
65
+ // Determine version
66
+ const targetVersion = version || packageInfo.latestVersion;
67
+ if (!targetVersion) {
68
+ this.logger.fail('No version specified');
69
+ this.logger.error('Package has no versions.');
70
+ process.exit(1);
71
+ }
72
+
73
+ // Get version info
74
+ const versionInfo = await getVersion(packageName, targetVersion, network);
75
+ if (!versionInfo) {
76
+ this.logger.fail('Version not found');
77
+ this.logger.error(`Version "${targetVersion}" does not exist.`);
78
+ process.exit(1);
79
+ }
80
+
81
+ if (versionInfo.deprecated) {
82
+ this.logger.warn('Already deprecated');
83
+ this.logger.log(`Version ${targetVersion} is already deprecated.`);
84
+ return;
85
+ }
86
+
87
+ // Check if immutable
88
+ const immutable = await isVersionImmutable(packageName, targetVersion, network);
89
+ if (immutable) {
90
+ this.logger.fail('Version is immutable');
91
+ this.logger.error('This version is past the 72-hour mutability window.');
92
+ this.logger.error('Immutable versions cannot be deprecated.');
93
+ process.exit(1);
94
+ }
95
+
96
+ this.logger.success(`Found: ${packageName}@${targetVersion}`);
97
+
98
+ // Get deprecation message
99
+ let message = options?.message;
100
+ if (!message && !options?.yes) {
101
+ message = await input({
102
+ message: 'Deprecation reason (optional):',
103
+ default: '',
104
+ });
105
+ }
106
+ message = message || 'No reason provided';
107
+
108
+ // Display summary
109
+ this.logger.log('');
110
+ this.logger.info('Deprecation Summary');
111
+ this.logger.log('─'.repeat(50));
112
+ this.logger.log(`Package: ${packageName}`);
113
+ this.logger.log(`Version: ${targetVersion}`);
114
+ this.logger.log(`Reason: ${message}`);
115
+ this.logger.log(`Network: ${options?.network}`);
116
+ this.logger.log('');
117
+
118
+ // Confirmation
119
+ if (!options?.yes) {
120
+ const confirmed = await confirm({
121
+ message: `Deprecate ${packageName}@${targetVersion}?`,
122
+ default: false,
123
+ });
124
+
125
+ if (!confirmed) {
126
+ this.logger.warn('Deprecation cancelled.');
127
+ return;
128
+ }
129
+ }
130
+
131
+ // Execute deprecation
132
+ this.logger.info('Deprecating version...');
133
+ this.logger.warn('Deprecation transaction required.');
134
+ this.logger.log('Transaction would call: deprecateVersion(');
135
+ this.logger.log(` packageName: "${packageName}",`);
136
+ this.logger.log(` version: "${targetVersion}",`);
137
+ this.logger.log(` reason: "${message}"`);
138
+ this.logger.log(')');
139
+ this.logger.info('Deprecation (transaction pending)');
140
+
141
+ this.logger.log('');
142
+ this.logger.success('Deprecation submitted!');
143
+ this.logger.warn('Note: Registry transaction support is coming soon.');
144
+ this.logger.log('');
145
+ } catch (error) {
146
+ this.logger.fail('Deprecation failed');
147
+ if (this.isUserCancelled(error)) {
148
+ this.logger.warn('Deprecation cancelled.');
149
+ process.exit(0);
150
+ }
151
+ this.exitWithError(this.formatError(error));
152
+ }
153
+ }
154
+ }
155
+
156
+ export const deprecateCommand = new DeprecateCommand().getCommand();