api-response-manager 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.
package/README.md ADDED
@@ -0,0 +1,356 @@
1
+ # ARM CLI - API Response Manager Command Line Interface
2
+
3
+ Command-line interface for API Response Manager. Manage tunnels, webhooks, and projects from your terminal.
4
+
5
+ ## Installation
6
+
7
+ ### Option 1: Install from npm (Recommended)
8
+ ```bash
9
+ npm install -g @arm/cli
10
+ ```
11
+
12
+ After installation, verify:
13
+ ```bash
14
+ arm --version
15
+ arm --help
16
+ ```
17
+
18
+ ### Option 2: Install from Source
19
+ ```bash
20
+ # Clone the repository
21
+ git clone https://github.com/vijaypurohit322/api-response-manager.git
22
+ cd api-response-manager/cli
23
+
24
+ # Install dependencies
25
+ npm install
26
+
27
+ # Link globally
28
+ npm link
29
+
30
+ # Verify installation
31
+ arm --version
32
+ ```
33
+
34
+ ### Option 3: Use with npx (No Installation)
35
+ ```bash
36
+ npx @arm/cli login
37
+ npx @arm/cli tunnel 3000
38
+ npx @arm/cli webhook
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ### 1. Login
44
+ ```bash
45
+ arm login
46
+ # Or provide credentials directly
47
+ arm login -e your@email.com -p yourpassword
48
+ ```
49
+
50
+ ### 2. Start a Tunnel
51
+ ```bash
52
+ # Expose local port 3000
53
+ arm tunnel 3000
54
+
55
+ # With custom subdomain
56
+ arm tunnel 3000 --subdomain myapi
57
+
58
+ # With authentication
59
+ arm tunnel 3000 --auth --rate-limit 100
60
+ ```
61
+
62
+ ### 3. Create a Webhook
63
+ ```bash
64
+ # Basic webhook
65
+ arm webhook
66
+
67
+ # With forwarding to URL
68
+ arm webhook --forward http://localhost:4000/webhook
69
+
70
+ # With forwarding to tunnel
71
+ arm webhook --tunnel <tunnel-id>
72
+ ```
73
+
74
+ ## Commands
75
+
76
+ ### Authentication
77
+
78
+ #### `arm login`
79
+ Authenticate with API Response Manager
80
+ ```bash
81
+ arm login
82
+ arm login -e email@example.com -p password
83
+ ```
84
+
85
+ #### `arm logout`
86
+ Logout from API Response Manager
87
+ ```bash
88
+ arm logout
89
+ ```
90
+
91
+ ### Tunnels
92
+
93
+ #### `arm tunnel <port>`
94
+ Start a tunnel to expose local server
95
+ ```bash
96
+ arm tunnel 3000
97
+ arm tunnel 3000 --subdomain myapi --name "My API"
98
+ arm tunnel 3000 --auth --rate-limit 100
99
+ ```
100
+
101
+ Options:
102
+ - `-s, --subdomain <subdomain>` - Custom subdomain
103
+ - `-n, --name <name>` - Tunnel name
104
+ - `-a, --auth` - Enable basic authentication
105
+ - `-r, --rate-limit <limit>` - Rate limit (requests per minute, default: 60)
106
+
107
+ #### `arm tunnel:list`
108
+ List all active tunnels
109
+ ```bash
110
+ arm tunnel:list
111
+ ```
112
+
113
+ #### `arm tunnel:stop <tunnelId>`
114
+ Stop a tunnel
115
+ ```bash
116
+ arm tunnel:stop 507f1f77bcf86cd799439011
117
+ ```
118
+
119
+ #### `arm tunnel:logs <tunnelId>`
120
+ View tunnel request logs
121
+ ```bash
122
+ arm tunnel:logs 507f1f77bcf86cd799439011
123
+ arm tunnel:logs 507f1f77bcf86cd799439011 --follow
124
+ arm tunnel:logs 507f1f77bcf86cd799439011 --lines 100
125
+ ```
126
+
127
+ Options:
128
+ - `-f, --follow` - Follow log output (real-time)
129
+ - `-n, --lines <number>` - Number of lines to show (default: 50)
130
+
131
+ ### Webhooks
132
+
133
+ #### `arm webhook`
134
+ Create a new webhook
135
+ ```bash
136
+ arm webhook
137
+ arm webhook --name "GitHub Webhook"
138
+ arm webhook --forward http://localhost:4000/webhook
139
+ arm webhook --tunnel 507f1f77bcf86cd799439011
140
+ arm webhook --expires 48
141
+ ```
142
+
143
+ Options:
144
+ - `-n, --name <name>` - Webhook name
145
+ - `-f, --forward <url>` - Forward URL
146
+ - `-t, --tunnel <tunnelId>` - Forward to tunnel
147
+ - `-e, --expires <hours>` - Expiration time in hours (default: 24)
148
+
149
+ #### `arm webhook:list`
150
+ List all webhooks
151
+ ```bash
152
+ arm webhook:list
153
+ ```
154
+
155
+ #### `arm webhook:delete <webhookId>`
156
+ Delete a webhook
157
+ ```bash
158
+ arm webhook:delete a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
159
+ ```
160
+
161
+ #### `arm webhook:logs <webhookId>`
162
+ View webhook request logs
163
+ ```bash
164
+ arm webhook:logs a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
165
+ arm webhook:logs a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 --follow
166
+ arm webhook:logs a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 --lines 100
167
+ ```
168
+
169
+ Options:
170
+ - `-f, --follow` - Follow log output (real-time)
171
+ - `-n, --lines <number>` - Number of lines to show (default: 50)
172
+
173
+ #### `arm webhook:replay <webhookId> <requestId>`
174
+ Replay a webhook request
175
+ ```bash
176
+ arm webhook:replay a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 507f1f77bcf86cd799439011
177
+ ```
178
+
179
+ ### Projects
180
+
181
+ #### `arm projects`
182
+ List all projects
183
+ ```bash
184
+ arm projects
185
+ ```
186
+
187
+ #### `arm project:create <name>`
188
+ Create a new project
189
+ ```bash
190
+ arm project:create "My API Project"
191
+ arm project:create "My API Project" --description "Testing API endpoints"
192
+ ```
193
+
194
+ Options:
195
+ - `-d, --description <description>` - Project description
196
+
197
+ #### `arm project:share <projectId>`
198
+ Get shareable link for a project
199
+ ```bash
200
+ arm project:share 507f1f77bcf86cd799439011
201
+ ```
202
+
203
+ #### `arm project:responses <projectId>`
204
+ View project API responses
205
+ ```bash
206
+ arm project:responses 507f1f77bcf86cd799439011
207
+ arm project:responses 507f1f77bcf86cd799439011 --limit 20
208
+ ```
209
+
210
+ Options:
211
+ - `-n, --limit <number>` - Number of responses to show (default: 10)
212
+
213
+ ### Logs
214
+
215
+ #### `arm logs <id>`
216
+ View logs for tunnels or webhooks (auto-detects type)
217
+ ```bash
218
+ arm logs 507f1f77bcf86cd799439011
219
+ arm logs a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 --follow
220
+ ```
221
+
222
+ Options:
223
+ - `-f, --follow` - Follow log output (real-time)
224
+ - `-n, --lines <number>` - Number of lines to show (default: 50)
225
+
226
+ ### Configuration
227
+
228
+ #### `arm config:set <key> <value>`
229
+ Set configuration value
230
+ ```bash
231
+ arm config:set apiUrl http://localhost:5000/api
232
+ arm config:set defaultTunnelPort 8080
233
+ ```
234
+
235
+ #### `arm config:get [key]`
236
+ Get configuration value (omit key to show all)
237
+ ```bash
238
+ arm config:get apiUrl
239
+ arm config:get
240
+ ```
241
+
242
+ #### `arm config:delete <key>`
243
+ Delete configuration value
244
+ ```bash
245
+ arm config:delete apiUrl
246
+ ```
247
+
248
+ ## Configuration
249
+
250
+ Configuration is stored in `~/.config/arm-cli/config.json`
251
+
252
+ Default configuration:
253
+ ```json
254
+ {
255
+ "apiUrl": "http://localhost:5000/api",
256
+ "token": null,
257
+ "userId": null,
258
+ "email": null,
259
+ "defaultTunnelPort": 3000,
260
+ "defaultWebhookExpiry": 86400
261
+ }
262
+ ```
263
+
264
+ ## Examples
265
+
266
+ ### Expose Local Development Server
267
+ ```bash
268
+ # Login
269
+ arm login
270
+
271
+ # Start tunnel on port 3000
272
+ arm tunnel 3000 --subdomain myapp
273
+
274
+ # Your local server is now accessible at:
275
+ # https://myapp.tunnel.arm.dev
276
+ ```
277
+
278
+ ### Test Webhooks Locally
279
+ ```bash
280
+ # Create webhook that forwards to local server
281
+ arm webhook --forward http://localhost:4000/webhook --name "Test Webhook"
282
+
283
+ # Send test request
284
+ curl -X POST <webhook-url> -d '{"test": "data"}'
285
+
286
+ # View logs
287
+ arm webhook:logs <webhook-id>
288
+ ```
289
+
290
+ ### CI/CD Integration
291
+ ```bash
292
+ # In your CI/CD pipeline
293
+ export ARM_TOKEN="your-auth-token"
294
+
295
+ # Start tunnel for testing
296
+ arm tunnel 3000 --subdomain ci-test-${CI_BUILD_ID}
297
+
298
+ # Run your tests against the public URL
299
+ npm test
300
+
301
+ # Stop tunnel
302
+ arm tunnel:stop <tunnel-id>
303
+ ```
304
+
305
+ ## Troubleshooting
306
+
307
+ ### Authentication Issues
308
+ ```bash
309
+ # Check if logged in
310
+ arm config:get email
311
+
312
+ # Re-login
313
+ arm logout
314
+ arm login
315
+ ```
316
+
317
+ ### Connection Issues
318
+ ```bash
319
+ # Check API URL
320
+ arm config:get apiUrl
321
+
322
+ # Update API URL
323
+ arm config:set apiUrl https://your-api-url.com/api
324
+ ```
325
+
326
+ ### View All Configuration
327
+ ```bash
328
+ arm config:get
329
+ ```
330
+
331
+ ## Publishing to npm
332
+
333
+ See [PUBLISHING.md](./PUBLISHING.md) for detailed instructions on publishing this package to npm.
334
+
335
+ ### Quick Publish
336
+
337
+ ```bash
338
+ # Login to npm
339
+ npm login
340
+
341
+ # Update version
342
+ npm version patch # or minor/major
343
+
344
+ # Publish
345
+ npm publish --access public
346
+ ```
347
+
348
+ ## Support
349
+
350
+ - GitHub: https://github.com/vijaypurohit322/api-response-manager
351
+ - Issues: https://github.com/vijaypurohit322/api-response-manager/issues
352
+ - Email: vijaypurohit322@gmail.com
353
+
354
+ ## License
355
+
356
+ MIT License - see LICENSE file for details
package/bin/arm.js ADDED
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const chalk = require('chalk');
5
+ const pkg = require('../package.json');
6
+
7
+ // Check for updates (optional feature, can be added later with dynamic import)
8
+ // const updateNotifier = require('update-notifier');
9
+ // const notifier = updateNotifier({ pkg });
10
+ // notifier.notify();
11
+
12
+ // Import commands
13
+ const loginCommand = require('../commands/login');
14
+ const logoutCommand = require('../commands/logout');
15
+ const tunnelCommand = require('../commands/tunnel');
16
+ const webhookCommand = require('../commands/webhook');
17
+ const projectCommand = require('../commands/project');
18
+ const logsCommand = require('../commands/logs');
19
+ const configCommand = require('../commands/config');
20
+
21
+ // CLI setup
22
+ program
23
+ .name('arm')
24
+ .description('API Response Manager CLI - Tunneling, Webhooks, and API Testing')
25
+ .version(pkg.version);
26
+
27
+ // Login command
28
+ program
29
+ .command('login')
30
+ .description('Authenticate with API Response Manager')
31
+ .option('-e, --email <email>', 'Email address')
32
+ .option('-p, --password <password>', 'Password')
33
+ .action(loginCommand);
34
+
35
+ // Logout command
36
+ program
37
+ .command('logout')
38
+ .description('Logout from API Response Manager')
39
+ .action(logoutCommand);
40
+
41
+ // Tunnel commands
42
+ program
43
+ .command('tunnel')
44
+ .description('Manage tunnels')
45
+ .argument('[port]', 'Local port to expose')
46
+ .option('-s, --subdomain <subdomain>', 'Custom subdomain')
47
+ .option('-n, --name <name>', 'Tunnel name')
48
+ .option('-a, --auth', 'Enable basic authentication')
49
+ .option('-r, --rate-limit <limit>', 'Rate limit (requests per minute)', '60')
50
+ .action(tunnelCommand.start);
51
+
52
+ program
53
+ .command('tunnel:list')
54
+ .description('List all active tunnels')
55
+ .action(tunnelCommand.list);
56
+
57
+ program
58
+ .command('tunnel:stop')
59
+ .description('Stop a tunnel')
60
+ .argument('<tunnelId>', 'Tunnel ID to stop')
61
+ .action(tunnelCommand.stop);
62
+
63
+ program
64
+ .command('tunnel:logs')
65
+ .description('View tunnel request logs')
66
+ .argument('<tunnelId>', 'Tunnel ID')
67
+ .option('-f, --follow', 'Follow log output')
68
+ .option('-n, --lines <number>', 'Number of lines to show', '50')
69
+ .action(tunnelCommand.logs);
70
+
71
+ // Webhook commands
72
+ program
73
+ .command('webhook')
74
+ .description('Create a new webhook')
75
+ .option('-n, --name <name>', 'Webhook name')
76
+ .option('-f, --forward <url>', 'Forward URL')
77
+ .option('-t, --tunnel <tunnelId>', 'Forward to tunnel')
78
+ .option('-e, --expires <hours>', 'Expiration time in hours', '24')
79
+ .action(webhookCommand.create);
80
+
81
+ program
82
+ .command('webhook:list')
83
+ .description('List all webhooks')
84
+ .action(webhookCommand.list);
85
+
86
+ program
87
+ .command('webhook:id')
88
+ .description('Get webhook ID by name')
89
+ .argument('<name>', 'Webhook name')
90
+ .action(webhookCommand.getIdByName);
91
+
92
+ program
93
+ .command('webhook:delete')
94
+ .description('Delete a webhook')
95
+ .argument('<webhookId>', 'Webhook ID to delete')
96
+ .action(webhookCommand.delete);
97
+
98
+ program
99
+ .command('webhook:logs')
100
+ .description('View webhook request logs')
101
+ .argument('<webhookId>', 'Webhook ID')
102
+ .option('-f, --follow', 'Follow log output')
103
+ .option('-n, --lines <number>', 'Number of lines to show', '50')
104
+ .action(webhookCommand.logs);
105
+
106
+ program
107
+ .command('webhook:replay')
108
+ .description('Replay a webhook request')
109
+ .argument('<webhookId>', 'Webhook ID')
110
+ .argument('<requestId>', 'Request ID to replay')
111
+ .action(webhookCommand.replay);
112
+
113
+ // Project commands
114
+ program
115
+ .command('projects')
116
+ .description('List all projects')
117
+ .action(projectCommand.list);
118
+
119
+ program
120
+ .command('project:create')
121
+ .description('Create a new project')
122
+ .argument('<name>', 'Project name')
123
+ .option('-d, --description <description>', 'Project description')
124
+ .action(projectCommand.create);
125
+
126
+ program
127
+ .command('project:id')
128
+ .description('Get project ID by name')
129
+ .argument('<name>', 'Project name')
130
+ .action(projectCommand.getIdByName);
131
+
132
+ program
133
+ .command('project:share')
134
+ .description('Get shareable link for a project')
135
+ .argument('<projectId>', 'Project ID')
136
+ .action(projectCommand.share);
137
+
138
+ program
139
+ .command('project:responses')
140
+ .description('View project API responses')
141
+ .argument('<projectId>', 'Project ID')
142
+ .option('-n, --limit <number>', 'Number of responses to show', '10')
143
+ .action(projectCommand.responses);
144
+
145
+ // Logs command
146
+ program
147
+ .command('logs')
148
+ .description('View logs for tunnels or webhooks')
149
+ .argument('<id>', 'Tunnel or Webhook ID')
150
+ .option('-f, --follow', 'Follow log output')
151
+ .option('-n, --lines <number>', 'Number of lines to show', '50')
152
+ .action(logsCommand);
153
+
154
+ // Config commands
155
+ program
156
+ .command('config:set')
157
+ .description('Set configuration value')
158
+ .argument('<key>', 'Configuration key')
159
+ .argument('<value>', 'Configuration value')
160
+ .action(configCommand.set);
161
+
162
+ program
163
+ .command('config:get')
164
+ .description('Get configuration value')
165
+ .argument('[key]', 'Configuration key (omit to show all)')
166
+ .action(configCommand.get);
167
+
168
+ program
169
+ .command('config:delete')
170
+ .description('Delete configuration value')
171
+ .argument('<key>', 'Configuration key')
172
+ .action(configCommand.delete);
173
+
174
+ // Parse arguments
175
+ program.parse(process.argv);
176
+
177
+ // Show help if no command provided
178
+ if (!process.argv.slice(2).length) {
179
+ program.outputHelp();
180
+ }
@@ -0,0 +1,76 @@
1
+ const chalk = require('chalk');
2
+ const config = require('../utils/config');
3
+ const Table = require('cli-table3');
4
+
5
+ // Set config value
6
+ function set(key, value) {
7
+ try {
8
+ config.set(key, value);
9
+ console.log(chalk.green(`\n✓ Configuration updated: ${key} = ${value}\n`));
10
+ } catch (error) {
11
+ console.error(chalk.red(`\n✗ Failed to set configuration: ${error.message}\n`));
12
+ process.exit(1);
13
+ }
14
+ }
15
+
16
+ // Get config value
17
+ function get(key) {
18
+ try {
19
+ if (key) {
20
+ const value = config.get(key);
21
+ if (value === undefined) {
22
+ console.log(chalk.yellow(`\n⚠ Configuration key '${key}' not found\n`));
23
+ } else {
24
+ console.log(chalk.white(`\n${key}: ${value}\n`));
25
+ }
26
+ } else {
27
+ // Show all config
28
+ const allConfig = config.store;
29
+
30
+ console.log(chalk.blue.bold('\n⚙️ Configuration\n'));
31
+
32
+ const table = new Table({
33
+ head: ['Key', 'Value'],
34
+ style: {
35
+ head: ['cyan']
36
+ }
37
+ });
38
+
39
+ Object.entries(allConfig).forEach(([key, value]) => {
40
+ // Hide sensitive values
41
+ const displayValue = key === 'token' && value
42
+ ? value.substring(0, 20) + '...'
43
+ : String(value);
44
+ table.push([key, displayValue]);
45
+ });
46
+
47
+ console.log(table.toString());
48
+ console.log(chalk.gray(`\nConfig file: ${config.path}\n`));
49
+ }
50
+ } catch (error) {
51
+ console.error(chalk.red(`\n✗ Failed to get configuration: ${error.message}\n`));
52
+ process.exit(1);
53
+ }
54
+ }
55
+
56
+ // Delete config value
57
+ function deleteConfig(key) {
58
+ try {
59
+ if (!config.has(key)) {
60
+ console.log(chalk.yellow(`\n⚠ Configuration key '${key}' not found\n`));
61
+ return;
62
+ }
63
+
64
+ config.delete(key);
65
+ console.log(chalk.green(`\n✓ Configuration deleted: ${key}\n`));
66
+ } catch (error) {
67
+ console.error(chalk.red(`\n✗ Failed to delete configuration: ${error.message}\n`));
68
+ process.exit(1);
69
+ }
70
+ }
71
+
72
+ module.exports = {
73
+ set,
74
+ get,
75
+ delete: deleteConfig
76
+ };
@@ -0,0 +1,88 @@
1
+ const inquirer = require('inquirer');
2
+ const chalk = require('chalk');
3
+ const ora = require('ora');
4
+ const api = require('../utils/api');
5
+ const config = require('../utils/config');
6
+
7
+ async function login(options) {
8
+ console.log(chalk.blue.bold('\n🔐 API Response Manager - Login\n'));
9
+
10
+ let email = options.email;
11
+ let password = options.password;
12
+
13
+ // Prompt for credentials if not provided
14
+ if (!email || !password) {
15
+ const answers = await inquirer.prompt([
16
+ {
17
+ type: 'input',
18
+ name: 'email',
19
+ message: 'Email:',
20
+ when: !email,
21
+ validate: (input) => {
22
+ if (!input) return 'Email is required';
23
+ if (!/\S+@\S+\.\S+/.test(input)) return 'Invalid email format';
24
+ return true;
25
+ }
26
+ },
27
+ {
28
+ type: 'password',
29
+ name: 'password',
30
+ message: 'Password:',
31
+ when: !password,
32
+ mask: '*',
33
+ validate: (input) => {
34
+ if (!input) return 'Password is required';
35
+ if (input.length < 6) return 'Password must be at least 6 characters';
36
+ return true;
37
+ }
38
+ }
39
+ ]);
40
+
41
+ email = email || answers.email;
42
+ password = password || answers.password;
43
+ }
44
+
45
+ const spinner = ora('Authenticating...').start();
46
+
47
+ try {
48
+ const response = await api.login(email, password);
49
+
50
+ if (!response.token) {
51
+ throw new Error('No token received from server');
52
+ }
53
+
54
+ // Store credentials
55
+ api.setToken(response.token);
56
+
57
+ const userId = response.user?._id || response.user?.id;
58
+ const userEmail = response.user?.email || email;
59
+
60
+ if (userId) {
61
+ config.set('userId', userId);
62
+ }
63
+ if (userEmail) {
64
+ config.set('email', userEmail);
65
+ }
66
+
67
+ spinner.succeed(chalk.green('Login successful!'));
68
+
69
+ console.log(chalk.gray('\nUser:'), chalk.white(userEmail));
70
+ console.log(chalk.gray('Token saved to:'), chalk.white(config.path));
71
+ console.log(chalk.green('\n✓ You can now use all ARM CLI commands\n'));
72
+
73
+ } catch (error) {
74
+ spinner.fail(chalk.red('Login failed'));
75
+
76
+ if (error.response?.status === 401) {
77
+ console.error(chalk.red('\n✗ Invalid email or password\n'));
78
+ } else if (error.response?.data?.msg) {
79
+ console.error(chalk.red(`\n✗ ${error.response.data.msg}\n`));
80
+ } else {
81
+ console.error(chalk.red(`\n✗ ${error.message}\n`));
82
+ }
83
+
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+ module.exports = login;
@@ -0,0 +1,21 @@
1
+ const chalk = require('chalk');
2
+ const api = require('../utils/api');
3
+ const config = require('../utils/config');
4
+
5
+ async function logout() {
6
+ const email = config.get('email');
7
+
8
+ if (!email) {
9
+ console.log(chalk.yellow('\n⚠ You are not logged in\n'));
10
+ return;
11
+ }
12
+
13
+ // Clear stored credentials
14
+ api.clearToken();
15
+ config.delete('userId');
16
+ config.delete('email');
17
+
18
+ console.log(chalk.green(`\n✓ Logged out successfully (${email})\n`));
19
+ }
20
+
21
+ module.exports = logout;