api-response-manager 2.5.3 → 2.5.4

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/bin/arm.js CHANGED
@@ -24,6 +24,8 @@ const healthCommand = require('../commands/health');
24
24
  const gatewayCommand = require('../commands/gateway');
25
25
  const ingressCommand = require('../commands/ingress');
26
26
  const accountCommand = require('../commands/account');
27
+ const installCommand = require('../commands/install');
28
+ const uninstallCommand = require('../commands/uninstall');
27
29
 
28
30
  // CLI setup
29
31
  program
@@ -56,7 +58,7 @@ program
56
58
  .option('-n, --name <name>', 'Tunnel name')
57
59
  .option('-a, --auth', 'Enable basic authentication')
58
60
  .option('-r, --rate-limit <limit>', 'Rate limit (requests per minute)', '60')
59
- .option('-p, --protocol <protocol>', 'Protocol (http, https, tcp, ws, wss)', 'http')
61
+ .option('-p, --protocol <protocol>', 'Protocol (http, https, tcp, ssh, ws, wss)', 'http')
60
62
  .option('--ssl', 'Enable SSL/HTTPS')
61
63
  .option('-d, --domain <domain>', 'Custom domain')
62
64
  .option('--json', 'Output in JSON format (for CI/CD automation)')
@@ -429,6 +431,18 @@ program
429
431
  .argument('<yamlFile>', 'Path to YAML file')
430
432
  .action(ingressCommand.validate);
431
433
 
434
+ // Install command (self-install with PATH configuration)
435
+ program
436
+ .command('install')
437
+ .description('Install CLI to system and configure PATH')
438
+ .action(installCommand);
439
+
440
+ // Uninstall command (remove CLI and PATH configuration)
441
+ program
442
+ .command('uninstall')
443
+ .description('Uninstall CLI from system and remove from PATH')
444
+ .action(uninstallCommand);
445
+
432
446
  // Account commands
433
447
  program
434
448
  .command('account')
@@ -0,0 +1,136 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const { execSync } = require('child_process');
6
+
7
+ const install = async () => {
8
+ const platform = os.platform();
9
+ const currentPath = process.execPath;
10
+
11
+ console.log('');
12
+ console.log(chalk.cyan(' TunnelAPI CLI Installer'));
13
+ console.log(chalk.cyan(' ======================='));
14
+ console.log('');
15
+
16
+ // Determine if running as standalone binary or via Node
17
+ const isStandalone = !currentPath.includes('node');
18
+
19
+ if (!isStandalone) {
20
+ console.log(chalk.yellow(' You are running via npm/Node.js.'));
21
+ console.log(chalk.yellow(' The CLI is already installed globally via npm.'));
22
+ console.log('');
23
+ console.log(' To verify: ' + chalk.white('arm --version'));
24
+ console.log('');
25
+ return;
26
+ }
27
+
28
+ try {
29
+ if (platform === 'win32') {
30
+ await installWindows(currentPath);
31
+ } else if (platform === 'darwin' || platform === 'linux') {
32
+ await installUnix(currentPath, platform);
33
+ } else {
34
+ console.log(chalk.red(` Unsupported platform: ${platform}`));
35
+ process.exit(1);
36
+ }
37
+ } catch (error) {
38
+ console.log(chalk.red(` Installation failed: ${error.message}`));
39
+ process.exit(1);
40
+ }
41
+ };
42
+
43
+ async function installWindows(currentPath) {
44
+ const installDir = path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'TunnelAPI');
45
+ const targetPath = path.join(installDir, 'arm.exe');
46
+
47
+ console.log(chalk.yellow('[1/3] Creating install directory...'));
48
+ if (!fs.existsSync(installDir)) {
49
+ fs.mkdirSync(installDir, { recursive: true });
50
+ }
51
+ console.log(chalk.gray(` ${installDir}`));
52
+
53
+ console.log(chalk.yellow('[2/3] Copying binary...'));
54
+ if (currentPath !== targetPath) {
55
+ fs.copyFileSync(currentPath, targetPath);
56
+ }
57
+ console.log(chalk.green(' Copied successfully'));
58
+
59
+ console.log(chalk.yellow('[3/3] Configuring PATH...'));
60
+ try {
61
+ // Get current user PATH
62
+ const currentUserPath = execSync('powershell -Command "[Environment]::GetEnvironmentVariable(\'Path\', \'User\')"', { encoding: 'utf8' }).trim();
63
+
64
+ if (!currentUserPath.includes(installDir)) {
65
+ // Add to user PATH
66
+ const newPath = currentUserPath ? `${currentUserPath};${installDir}` : installDir;
67
+ execSync(`powershell -Command "[Environment]::SetEnvironmentVariable('Path', '${newPath.replace(/'/g, "''")}', 'User')"`, { encoding: 'utf8' });
68
+ console.log(chalk.green(' Added to user PATH'));
69
+ } else {
70
+ console.log(chalk.gray(' Already in PATH'));
71
+ }
72
+ } catch (err) {
73
+ console.log(chalk.yellow(' Could not update PATH automatically.'));
74
+ console.log(chalk.yellow(` Please add this to your PATH manually: ${installDir}`));
75
+ }
76
+
77
+ printSuccess('Windows');
78
+ }
79
+
80
+ async function installUnix(currentPath, platform) {
81
+ const installDir = '/usr/local/bin';
82
+ const targetPath = path.join(installDir, 'arm');
83
+ const needsSudo = !isWritable(installDir);
84
+
85
+ console.log(chalk.yellow('[1/2] Copying binary...'));
86
+
87
+ try {
88
+ if (needsSudo) {
89
+ console.log(chalk.gray(' (requires sudo)'));
90
+ execSync(`sudo cp "${currentPath}" "${targetPath}"`, { stdio: 'inherit' });
91
+ execSync(`sudo chmod +x "${targetPath}"`, { stdio: 'inherit' });
92
+ } else {
93
+ fs.copyFileSync(currentPath, targetPath);
94
+ fs.chmodSync(targetPath, '755');
95
+ }
96
+ console.log(chalk.green(' Installed to ' + targetPath));
97
+ } catch (err) {
98
+ throw new Error(`Failed to copy binary: ${err.message}`);
99
+ }
100
+
101
+ console.log(chalk.yellow('[2/2] Verifying installation...'));
102
+ try {
103
+ const version = execSync(`"${targetPath}" --version`, { encoding: 'utf8' }).trim();
104
+ console.log(chalk.green(` Installed: arm v${version}`));
105
+ } catch (err) {
106
+ console.log(chalk.yellow(' Could not verify installation'));
107
+ }
108
+
109
+ printSuccess(platform === 'darwin' ? 'macOS' : 'Linux');
110
+ }
111
+
112
+ function isWritable(dir) {
113
+ try {
114
+ fs.accessSync(dir, fs.constants.W_OK);
115
+ return true;
116
+ } catch {
117
+ return false;
118
+ }
119
+ }
120
+
121
+ function printSuccess(platform) {
122
+ console.log('');
123
+ console.log(chalk.green(' ✓ Installation complete!'));
124
+ console.log('');
125
+ console.log(chalk.cyan(' To get started:'));
126
+ if (platform === 'Windows') {
127
+ console.log(chalk.white(' 1. Open a NEW terminal window'));
128
+ }
129
+ console.log(chalk.white(' 1. Run: arm login'));
130
+ console.log(chalk.white(' 2. Run: arm tunnel 3000'));
131
+ console.log('');
132
+ console.log(chalk.gray(' Documentation: https://docs.tunnelapi.in'));
133
+ console.log('');
134
+ }
135
+
136
+ module.exports = install;
@@ -3,9 +3,13 @@ const ora = require('ora');
3
3
  const WebSocket = require('ws');
4
4
  const Table = require('cli-table3');
5
5
  const axios = require('axios');
6
+ const net = require('net');
6
7
  const api = require('../utils/api');
7
8
  const config = require('../utils/config');
8
9
 
10
+ // Track TCP connections for SSH/TCP tunnels
11
+ const tcpConnections = new Map();
12
+
9
13
  // Start tunnel
10
14
  async function start(port, options) {
11
15
  const jsonOutput = options.json || false;
@@ -77,7 +81,7 @@ async function start(port, options) {
77
81
 
78
82
  // Connect tunnel client
79
83
  console.log(chalk.blue('Connecting tunnel client...\n'));
80
- await connectTunnelClient(tunnel.id || tunnel._id, tunnel.subdomain, tunnel.localPort, false);
84
+ await connectTunnelClient(tunnel.id || tunnel._id, tunnel.subdomain, tunnel.localPort, options.protocol || 'http', false);
81
85
 
82
86
  } catch (error) {
83
87
  if (spinner) spinner.fail(chalk.red('Failed to create tunnel'));
@@ -100,7 +104,7 @@ async function start(port, options) {
100
104
  }
101
105
 
102
106
  // Connect tunnel client
103
- async function connectTunnelClient(tunnelId, subdomain, localPort, silent = false) {
107
+ async function connectTunnelClient(tunnelId, subdomain, localPort, protocol = 'http', silent = false) {
104
108
  const tunnelServerUrl = config.get('tunnelServerUrl') || 'ws://localhost:8080';
105
109
  const token = api.getToken();
106
110
  const userId = config.get('userId');
@@ -108,6 +112,7 @@ async function connectTunnelClient(tunnelId, subdomain, localPort, silent = fals
108
112
  const ws = new WebSocket(tunnelServerUrl);
109
113
 
110
114
  let heartbeatInterval;
115
+ const isTcpTunnel = protocol === 'tcp' || protocol === 'ssh';
111
116
 
112
117
  ws.on('open', () => {
113
118
  if (!silent) console.log(chalk.green('✓ Connected to tunnel server'));
@@ -117,6 +122,7 @@ async function connectTunnelClient(tunnelId, subdomain, localPort, silent = fals
117
122
  tunnelId,
118
123
  subdomain,
119
124
  localPort,
125
+ protocol,
120
126
  authToken: token,
121
127
  userId
122
128
  }));
@@ -137,8 +143,33 @@ async function connectTunnelClient(tunnelId, subdomain, localPort, silent = fals
137
143
  console.log(chalk.green.bold('\n🎉 Tunnel Active!\n'));
138
144
  console.log(chalk.white('Your local server is now accessible at:'));
139
145
  console.log(chalk.cyan.bold(` ${message.publicUrl}\n`));
146
+
147
+ // Show TCP/SSH specific info
148
+ if (isTcpTunnel && message.tcpHost && message.tcpPort) {
149
+ console.log(chalk.yellow.bold('🔌 TCP/SSH Connection Info:\n'));
150
+ console.log(chalk.white(` TCP Host: ${message.tcpHost}`));
151
+ console.log(chalk.white(` TCP Port: ${message.tcpPort}\n`));
152
+ if (message.sshCommand) {
153
+ console.log(chalk.gray('SSH Command (Linux/Mac):'));
154
+ console.log(chalk.cyan(` ${message.sshCommand}\n`));
155
+ console.log(chalk.gray('SSH Command (Windows with ncat):'));
156
+ console.log(chalk.cyan(` ssh -o ProxyCommand="ncat ${message.tcpHost} ${message.tcpPort}" user@${message.tcpHost}\n`));
157
+ console.log(chalk.gray('SSH with Key (passwordless):'));
158
+ console.log(chalk.cyan(` ssh -i ~/.ssh/your_key.pem -o ProxyCommand="echo 'SUBDOMAIN:${subdomain}' | nc %h %p" user@${message.tcpHost} -p ${message.tcpPort}\n`));
159
+ }
160
+ }
161
+
140
162
  console.log(chalk.gray('Press Ctrl+C to stop the tunnel\n'));
141
163
  }
164
+ } else if (message.type === 'tcp-connect') {
165
+ // Handle new TCP connection for SSH/TCP tunnels
166
+ handleTcpConnect(message, localPort, ws, silent);
167
+ } else if (message.type === 'tcp-data') {
168
+ // Handle TCP data from tunnel server
169
+ handleTcpData(message, ws, silent);
170
+ } else if (message.type === 'tcp-end') {
171
+ // Handle TCP connection close
172
+ handleTcpEnd(message, silent);
142
173
  } else if (message.type === 'request') {
143
174
  if (!silent) {
144
175
  const timestamp = new Date().toLocaleTimeString();
@@ -155,15 +186,34 @@ async function connectTunnelClient(tunnelId, subdomain, localPort, silent = fals
155
186
  delete forwardHeaders['connection'];
156
187
  delete forwardHeaders['accept-encoding']; // Prevent compression issues
157
188
 
189
+ // Handle body - check if it's base64 encoded (binary/multipart data)
190
+ let requestBody = message.body;
191
+ if (message.body && typeof message.body === 'object' && message.body._isBase64) {
192
+ // Decode base64 body back to Buffer
193
+ requestBody = Buffer.from(message.body.data, 'base64');
194
+ if (!silent) {
195
+ console.log(chalk.gray(` 📎 Decoded ${message.body._isMultipart ? 'multipart' : 'binary'} body: ${requestBody.length} bytes`));
196
+ }
197
+ // For multipart, keep the original content-length
198
+ if (!message.body._isMultipart) {
199
+ delete forwardHeaders['content-length'];
200
+ }
201
+ } else {
202
+ // For non-binary data, let axios calculate content-length
203
+ delete forwardHeaders['content-length'];
204
+ }
205
+
158
206
  const response = await axios({
159
207
  method: message.method.toLowerCase(),
160
208
  url: localUrl,
161
209
  headers: forwardHeaders,
162
- data: message.body,
210
+ data: requestBody,
163
211
  validateStatus: () => true, // Accept any status code
164
212
  responseType: 'arraybuffer', // Handle binary data properly
165
213
  maxRedirects: 0, // Don't follow redirects, let the client handle them
166
- timeout: 25000 // 25 second timeout
214
+ timeout: 25000, // 25 second timeout
215
+ maxBodyLength: Infinity, // Allow large file uploads
216
+ maxContentLength: Infinity // Allow large responses
167
217
  });
168
218
 
169
219
  // Clean up headers to avoid conflicts
@@ -503,6 +553,101 @@ async function configureIngress(tunnelId, rules, options) {
503
553
  }
504
554
  }
505
555
 
556
+ // TCP connection handlers for SSH/TCP tunnels
557
+ function handleTcpConnect(message, localPort, ws, silent) {
558
+ const { connectionId, remoteAddress, remotePort } = message;
559
+
560
+ if (!silent) {
561
+ const timestamp = new Date().toLocaleTimeString();
562
+ console.log(chalk.gray(`[${timestamp}]`), chalk.magenta('TCP'), chalk.white(`Connection from ${remoteAddress}:${remotePort}`));
563
+ }
564
+
565
+ // Create connection to local server (e.g., SSH on port 22)
566
+ const localSocket = net.createConnection({
567
+ host: 'localhost',
568
+ port: localPort
569
+ });
570
+
571
+ tcpConnections.set(connectionId, localSocket);
572
+
573
+ localSocket.on('connect', () => {
574
+ if (!silent) {
575
+ console.log(chalk.green(` ✓ Connected to local port ${localPort}`));
576
+ }
577
+ });
578
+
579
+ localSocket.on('data', (data) => {
580
+ // Forward data back to tunnel server
581
+ if (ws.readyState === WebSocket.OPEN) {
582
+ ws.send(JSON.stringify({
583
+ type: 'tcp-response',
584
+ connectionId,
585
+ data: data.toString('base64')
586
+ }));
587
+ }
588
+ });
589
+
590
+ localSocket.on('end', () => {
591
+ if (!silent) {
592
+ console.log(chalk.gray(` TCP connection ended: ${connectionId.substring(0, 8)}...`));
593
+ }
594
+ tcpConnections.delete(connectionId);
595
+
596
+ // Notify tunnel server
597
+ if (ws.readyState === WebSocket.OPEN) {
598
+ ws.send(JSON.stringify({
599
+ type: 'tcp-close',
600
+ connectionId
601
+ }));
602
+ }
603
+ });
604
+
605
+ localSocket.on('error', (error) => {
606
+ console.error(chalk.red(` TCP error: ${error.message}`));
607
+ tcpConnections.delete(connectionId);
608
+
609
+ // Notify tunnel server
610
+ if (ws.readyState === WebSocket.OPEN) {
611
+ ws.send(JSON.stringify({
612
+ type: 'tcp-close',
613
+ connectionId
614
+ }));
615
+ }
616
+ });
617
+ }
618
+
619
+ function handleTcpData(message, ws, silent) {
620
+ const { connectionId, data } = message;
621
+
622
+ const localSocket = tcpConnections.get(connectionId);
623
+ if (!localSocket) {
624
+ if (!silent) {
625
+ console.warn(chalk.yellow(` No local socket found for ${connectionId.substring(0, 8)}...`));
626
+ }
627
+ return;
628
+ }
629
+
630
+ try {
631
+ const buffer = Buffer.from(data, 'base64');
632
+ localSocket.write(buffer);
633
+ } catch (error) {
634
+ console.error(chalk.red(` Error writing to local socket: ${error.message}`));
635
+ }
636
+ }
637
+
638
+ function handleTcpEnd(message, silent) {
639
+ const { connectionId } = message;
640
+
641
+ const localSocket = tcpConnections.get(connectionId);
642
+ if (localSocket) {
643
+ localSocket.end();
644
+ tcpConnections.delete(connectionId);
645
+ if (!silent) {
646
+ console.log(chalk.gray(` TCP connection closed: ${connectionId.substring(0, 8)}...`));
647
+ }
648
+ }
649
+ }
650
+
506
651
  module.exports = {
507
652
  start,
508
653
  list,
@@ -0,0 +1,153 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+ const { execSync } = require('child_process');
6
+
7
+ const uninstall = async () => {
8
+ const platform = os.platform();
9
+
10
+ console.log('');
11
+ console.log(chalk.cyan(' TunnelAPI CLI Uninstaller'));
12
+ console.log(chalk.cyan(' ========================='));
13
+ console.log('');
14
+
15
+ try {
16
+ if (platform === 'win32') {
17
+ await uninstallWindows();
18
+ } else if (platform === 'darwin' || platform === 'linux') {
19
+ await uninstallUnix(platform);
20
+ } else {
21
+ console.log(chalk.red(` Unsupported platform: ${platform}`));
22
+ process.exit(1);
23
+ }
24
+ } catch (error) {
25
+ console.log(chalk.red(` Uninstall failed: ${error.message}`));
26
+ process.exit(1);
27
+ }
28
+ };
29
+
30
+ async function uninstallWindows() {
31
+ const installDir = path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'TunnelAPI');
32
+ const binaryPath = path.join(installDir, 'arm.exe');
33
+
34
+ console.log(chalk.yellow('[1/3] Removing from PATH...'));
35
+ try {
36
+ const currentUserPath = execSync('powershell -Command "[Environment]::GetEnvironmentVariable(\'Path\', \'User\')"', { encoding: 'utf8' }).trim();
37
+
38
+ if (currentUserPath.includes(installDir)) {
39
+ // Remove install dir from PATH
40
+ const pathParts = currentUserPath.split(';').filter(p => p && !p.includes('TunnelAPI'));
41
+ const newPath = pathParts.join(';');
42
+ execSync(`powershell -Command "[Environment]::SetEnvironmentVariable('Path', '${newPath.replace(/'/g, "''")}', 'User')"`, { encoding: 'utf8' });
43
+ console.log(chalk.green(' Removed from user PATH'));
44
+ } else {
45
+ console.log(chalk.gray(' Not in PATH'));
46
+ }
47
+ } catch (err) {
48
+ console.log(chalk.yellow(' Could not update PATH automatically'));
49
+ }
50
+
51
+ console.log(chalk.yellow('[2/3] Removing binary...'));
52
+ if (fs.existsSync(binaryPath)) {
53
+ try {
54
+ fs.unlinkSync(binaryPath);
55
+ console.log(chalk.green(' Removed ' + binaryPath));
56
+ } catch (err) {
57
+ console.log(chalk.yellow(' Could not remove binary (may be in use)'));
58
+ console.log(chalk.yellow(` Please manually delete: ${binaryPath}`));
59
+ }
60
+ } else {
61
+ console.log(chalk.gray(' Binary not found at ' + binaryPath));
62
+ }
63
+
64
+ console.log(chalk.yellow('[3/3] Cleaning up install directory...'));
65
+ if (fs.existsSync(installDir)) {
66
+ try {
67
+ const files = fs.readdirSync(installDir);
68
+ if (files.length === 0) {
69
+ fs.rmdirSync(installDir);
70
+ console.log(chalk.green(' Removed install directory'));
71
+ } else {
72
+ console.log(chalk.gray(' Directory not empty, keeping it'));
73
+ }
74
+ } catch (err) {
75
+ console.log(chalk.gray(' Could not remove directory'));
76
+ }
77
+ }
78
+
79
+ printSuccess('Windows');
80
+ }
81
+
82
+ async function uninstallUnix(platform) {
83
+ const binaryPath = '/usr/local/bin/arm';
84
+ const needsSudo = !isWritable('/usr/local/bin');
85
+
86
+ console.log(chalk.yellow('[1/2] Checking for binary...'));
87
+
88
+ if (!fs.existsSync(binaryPath)) {
89
+ console.log(chalk.gray(' Binary not found at ' + binaryPath));
90
+ console.log(chalk.yellow(' Checking other locations...'));
91
+
92
+ // Check common locations
93
+ const altPaths = [
94
+ path.join(os.homedir(), '.local', 'bin', 'arm'),
95
+ '/usr/bin/arm',
96
+ '/opt/tunnelapi/arm'
97
+ ];
98
+
99
+ let found = false;
100
+ for (const altPath of altPaths) {
101
+ if (fs.existsSync(altPath)) {
102
+ console.log(chalk.gray(` Found at ${altPath}`));
103
+ found = true;
104
+ }
105
+ }
106
+
107
+ if (!found) {
108
+ console.log(chalk.gray(' No installation found'));
109
+ }
110
+
111
+ printSuccess(platform === 'darwin' ? 'macOS' : 'Linux');
112
+ return;
113
+ }
114
+
115
+ console.log(chalk.yellow('[2/2] Removing binary...'));
116
+ try {
117
+ if (needsSudo) {
118
+ console.log(chalk.gray(' (requires sudo)'));
119
+ execSync(`sudo rm -f "${binaryPath}"`, { stdio: 'inherit' });
120
+ } else {
121
+ fs.unlinkSync(binaryPath);
122
+ }
123
+ console.log(chalk.green(' Removed ' + binaryPath));
124
+ } catch (err) {
125
+ console.log(chalk.red(` Failed to remove: ${err.message}`));
126
+ console.log(chalk.yellow(` Try manually: sudo rm ${binaryPath}`));
127
+ }
128
+
129
+ printSuccess(platform === 'darwin' ? 'macOS' : 'Linux');
130
+ }
131
+
132
+ function isWritable(dir) {
133
+ try {
134
+ fs.accessSync(dir, fs.constants.W_OK);
135
+ return true;
136
+ } catch {
137
+ return false;
138
+ }
139
+ }
140
+
141
+ function printSuccess(platform) {
142
+ console.log('');
143
+ console.log(chalk.green(' ✓ Uninstall complete!'));
144
+ console.log('');
145
+ if (platform === 'Windows') {
146
+ console.log(chalk.cyan(' Note: Open a NEW terminal for PATH changes to take effect.'));
147
+ }
148
+ console.log(chalk.gray(' Thank you for using TunnelAPI!'));
149
+ console.log(chalk.gray(' Feedback: info@tunnelapi.in'));
150
+ console.log('');
151
+ }
152
+
153
+ module.exports = uninstall;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-response-manager",
3
- "version": "2.5.3",
3
+ "version": "2.5.4",
4
4
  "description": "Command-line interface for API Response Manager",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -9,7 +9,30 @@
9
9
  "scripts": {
10
10
  "test": "jest",
11
11
  "link": "npm link",
12
- "prepublishOnly": "echo 'Publishing api-response-manager CLI...'"
12
+ "prepublishOnly": "echo 'Publishing api-response-manager CLI...'",
13
+ "build": "pkg . --out-path dist",
14
+ "build:win": "pkg . -t node18-win-x64 --out-path dist",
15
+ "build:mac": "pkg . -t node18-macos-x64 --out-path dist",
16
+ "build:mac-arm": "pkg . -t node18-macos-arm64 --out-path dist",
17
+ "build:linux": "pkg . -t node18-linux-x64 --out-path dist",
18
+ "build:all": "pkg . -t node18-win-x64,node18-macos-x64,node18-macos-arm64,node18-linux-x64 --out-path dist"
19
+ },
20
+ "pkg": {
21
+ "scripts": [
22
+ "bin/**/*.js",
23
+ "commands/**/*.js",
24
+ "utils/**/*.js"
25
+ ],
26
+ "assets": [
27
+ "node_modules/**/*"
28
+ ],
29
+ "targets": [
30
+ "node18-win-x64",
31
+ "node18-macos-x64",
32
+ "node18-macos-arm64",
33
+ "node18-linux-x64"
34
+ ],
35
+ "outputPath": "dist"
13
36
  },
14
37
  "files": [
15
38
  "bin/",
@@ -45,7 +68,9 @@
45
68
  "ws": "^8.14.2"
46
69
  },
47
70
  "devDependencies": {
48
- "jest": "^29.7.0"
71
+ "@yao-pkg/pkg": "^5.11.0",
72
+ "jest": "^29.7.0",
73
+ "rcedit": "^5.0.2"
49
74
  },
50
75
  "engines": {
51
76
  "node": ">=14.0.0"