hooktunnel-cli 0.1.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 (58) hide show
  1. package/README.md +404 -0
  2. package/dist/commands/connect.d.ts +11 -0
  3. package/dist/commands/connect.d.ts.map +1 -0
  4. package/dist/commands/connect.js +59 -0
  5. package/dist/commands/connect.js.map +1 -0
  6. package/dist/commands/hooks.d.ts +6 -0
  7. package/dist/commands/hooks.d.ts.map +1 -0
  8. package/dist/commands/hooks.js +51 -0
  9. package/dist/commands/hooks.js.map +1 -0
  10. package/dist/commands/login.d.ts +10 -0
  11. package/dist/commands/login.d.ts.map +1 -0
  12. package/dist/commands/login.js +36 -0
  13. package/dist/commands/login.js.map +1 -0
  14. package/dist/commands/logout.d.ts +6 -0
  15. package/dist/commands/logout.d.ts.map +1 -0
  16. package/dist/commands/logout.js +16 -0
  17. package/dist/commands/logout.js.map +1 -0
  18. package/dist/commands/logs.d.ts +10 -0
  19. package/dist/commands/logs.d.ts.map +1 -0
  20. package/dist/commands/logs.js +64 -0
  21. package/dist/commands/logs.js.map +1 -0
  22. package/dist/commands/replay.d.ts +10 -0
  23. package/dist/commands/replay.d.ts.map +1 -0
  24. package/dist/commands/replay.js +43 -0
  25. package/dist/commands/replay.js.map +1 -0
  26. package/dist/commands/status.d.ts +6 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +56 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +120 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/lib/api.d.ts +12 -0
  35. package/dist/lib/api.d.ts.map +1 -0
  36. package/dist/lib/api.js +75 -0
  37. package/dist/lib/api.js.map +1 -0
  38. package/dist/lib/config.d.ts +24 -0
  39. package/dist/lib/config.d.ts.map +1 -0
  40. package/dist/lib/config.js +44 -0
  41. package/dist/lib/config.js.map +1 -0
  42. package/dist/lib/errors.d.ts +14 -0
  43. package/dist/lib/errors.d.ts.map +1 -0
  44. package/dist/lib/errors.js +97 -0
  45. package/dist/lib/errors.js.map +1 -0
  46. package/dist/lib/tunnel.d.ts +30 -0
  47. package/dist/lib/tunnel.d.ts.map +1 -0
  48. package/dist/lib/tunnel.js +237 -0
  49. package/dist/lib/tunnel.js.map +1 -0
  50. package/dist/types/api.d.ts +47 -0
  51. package/dist/types/api.d.ts.map +1 -0
  52. package/dist/types/api.js +5 -0
  53. package/dist/types/api.js.map +1 -0
  54. package/dist/types/tunnel.d.ts +82 -0
  55. package/dist/types/tunnel.d.ts.map +1 -0
  56. package/dist/types/tunnel.js +6 -0
  57. package/dist/types/tunnel.js.map +1 -0
  58. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,404 @@
1
+ # HookTunnel CLI
2
+
3
+ **Webhook infrastructure that never drops a request.**
4
+
5
+ Webhooks are the weakest link in every platform integration. HookTunnel fixes that — reliable ingress, full history, instant replay. For development and production.
6
+
7
+ ```bash
8
+ npx hooktunnel-cli connect dev 3000
9
+ ```
10
+
11
+ ---
12
+
13
+ ## The Problem
14
+
15
+ Webhooks are fire-and-forget. When they fail, you're blind.
16
+
17
+ ```
18
+ Provider ──────────────────────────────────▶ Your Server
19
+ If down, webhook lost forever 💀
20
+ ```
21
+
22
+ **Every team hits these:**
23
+
24
+ | Failure Mode | What Happens |
25
+ |--------------|--------------|
26
+ | **Server down** | Webhook gone. Stripe retries 8x, GitHub gives you 1 shot. |
27
+ | **Handler bug** | You need the exact payload to debug. It's gone. |
28
+ | **URL changed** | Redeployed? New infra? Webhooks silently fail. |
29
+ | **No visibility** | Something broke. What was in that payload? Who knows. |
30
+ | **Can't replay** | Fixed the bug, but need to wait for a real event to test. |
31
+
32
+ **Traditional tools don't solve this:**
33
+
34
+ | Tool | Problem |
35
+ |------|---------|
36
+ | **ngrok** | URL changes on restart. Dev only. No history. |
37
+ | **localtunnel** | Unstable. No persistence. Dev only. |
38
+ | **RequestBin** | View-only. Can't forward or replay. |
39
+ | **Custom logging** | You built it. You maintain it. It's missing features. |
40
+
41
+ ---
42
+
43
+ ## The Solution
44
+
45
+ HookTunnel is infrastructure between providers and your servers.
46
+
47
+ ```
48
+ WITHOUT WITH HOOKTUNNEL
49
+
50
+ Provider ────────▶ Your Server Provider ────▶ HookTunnel ────▶ Your Server
51
+ (if down, lost) (always on) (can be down)
52
+ ✓ Captured ✓ Process later
53
+ ✓ Logged ✓ Debug anytime
54
+ ✓ Replayable ✓ Test fixes
55
+ ✓ Stable URL ✓ Redeploy freely
56
+ ```
57
+
58
+ **What you get:**
59
+
60
+ - **Stable URLs** — Configure once in Stripe/Twilio/GitHub. Never change again.
61
+ - **Never lose webhooks** — Captured even when your server is down.
62
+ - **Full history** — See every request. Search by content. Debug with context.
63
+ - **Instant replay** — Re-send any webhook to test your fix. No waiting.
64
+ - **Local forwarding** — Forward to localhost for development.
65
+
66
+ ---
67
+
68
+ ## Use Cases
69
+
70
+ ### Development: Forward to Localhost
71
+
72
+ Test against real webhooks while building:
73
+
74
+ ```bash
75
+ # Terminal 1: Your server
76
+ npm run dev
77
+
78
+ # Terminal 2: Forward webhooks to localhost
79
+ hooktunnel connect dev 3000
80
+ ```
81
+
82
+ Every Stripe/Twilio webhook instantly hits your local machine.
83
+
84
+ ### Production: Debug Incidents
85
+
86
+ 2am. Payments are failing. What's in those webhooks?
87
+
88
+ ```bash
89
+ # See what's hitting your webhook endpoint
90
+ hooktunnel logs abc123 --limit 50
91
+
92
+ # Find the problematic request
93
+ # Note the log ID of the 500 error
94
+
95
+ # After fixing, replay to verify
96
+ hooktunnel replay log_xyz123 --to https://your-server.com/webhook
97
+ ```
98
+
99
+ ### Recovery: Server Was Down
100
+
101
+ Your server crashed for 10 minutes. Providers sent webhooks. They're not lost.
102
+
103
+ ```bash
104
+ # See what came in while you were down
105
+ hooktunnel logs abc123 --limit 100
106
+
107
+ # Everything is there
108
+ # Process them now, or replay to your recovered server
109
+ ```
110
+
111
+ ### AI-Assisted Debugging
112
+
113
+ Use with Claude Code for intelligent troubleshooting:
114
+
115
+ **Prompt:** *"Use hooktunnel to find recent webhook errors and explain what's wrong"*
116
+
117
+ ```bash
118
+ # Claude runs:
119
+ hooktunnel logs abc123 --limit 20
120
+
121
+ # Analyzes the 500 errors
122
+ # Explains what payload caused failure
123
+ # Suggests fixes
124
+ ```
125
+
126
+ **Prompt:** *"Replay the failed payment webhook and debug my handler"*
127
+
128
+ ```bash
129
+ # Claude runs:
130
+ hooktunnel replay log_abc123 --to http://localhost:3000
131
+
132
+ # Shows the response
133
+ # Explains the error
134
+ # Helps you fix it
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Quick Start
140
+
141
+ ### 1. Get Your Free Account
142
+
143
+ ```bash
144
+ # Go to hooktunnel.com
145
+ # Sign up (or sign in with GitHub)
146
+ # Generate a webhook URL
147
+ ```
148
+
149
+ ### 2. Get Your API Key
150
+
151
+ ```bash
152
+ # Go to hooktunnel.com/app/settings
153
+ # Generate an API key
154
+ ```
155
+
156
+ ### 3. Connect
157
+
158
+ ```bash
159
+ # Install and login
160
+ npx hooktunnel-cli login --key ht_your_api_key
161
+
162
+ # Start forwarding to localhost:3000
163
+ npx hooktunnel-cli connect dev 3000
164
+ ```
165
+
166
+ ### 4. Configure Your Provider
167
+
168
+ Add your HookTunnel URL to Stripe/Twilio/GitHub webhook settings:
169
+
170
+ ```
171
+ https://hooks.hooktunnel.com/h/your-hook-id
172
+ ```
173
+
174
+ **Done.** Webhooks flow through HookTunnel to your server.
175
+
176
+ ---
177
+
178
+ ## Installation
179
+
180
+ ```bash
181
+ # Use directly with npx (recommended)
182
+ npx hooktunnel-cli <command>
183
+
184
+ # Or install globally
185
+ npm install -g hooktunnel-cli
186
+ hooktunnel <command>
187
+ ```
188
+
189
+ **Requirements:** Node.js 18+
190
+
191
+ ---
192
+
193
+ ## Commands
194
+
195
+ ### `hooktunnel login`
196
+
197
+ Authenticate with your API key.
198
+
199
+ ```bash
200
+ hooktunnel login --key ht_abc123...
201
+ ```
202
+
203
+ Get your API key from [hooktunnel.com/app/settings](https://hooktunnel.com/app/settings)
204
+
205
+ ### `hooktunnel connect <env> <port>`
206
+
207
+ Forward webhooks to your local server.
208
+
209
+ ```bash
210
+ # Basic usage
211
+ hooktunnel connect dev 3000
212
+
213
+ # Custom host
214
+ hooktunnel connect dev 3000 --host 127.0.0.1
215
+
216
+ # Verbose mode (shows all request details)
217
+ hooktunnel connect dev 3000 --verbose
218
+ ```
219
+
220
+ **Output:**
221
+ ```
222
+ 🔗 HookTunnel
223
+ Environment: dev
224
+ Local port: 3000
225
+
226
+ ✓ Connected to HookTunnel
227
+ Session: abc12345...
228
+ Forwarding to: http://localhost:3000
229
+
230
+ Waiting for webhooks... (Ctrl+C to stop)
231
+
232
+ [12:00:01] POST /webhook 200 (45ms)
233
+ [12:00:05] POST /webhook 500 (12ms)
234
+ ```
235
+
236
+ **Environments:**
237
+ - `dev` - Development
238
+ - `staging` - Staging
239
+ - `prod` - Production
240
+
241
+ ### `hooktunnel hooks`
242
+
243
+ List your webhook endpoints.
244
+
245
+ ```bash
246
+ hooktunnel hooks
247
+ ```
248
+
249
+ **Output:**
250
+ ```
251
+ 📌 Your Hooks (2)
252
+
253
+ ID Provider Status Requests
254
+ ------------------------------------------------------------
255
+ abc123def456ghi789 stripe active 142
256
+ xyz789abc123def456 twilio active 57
257
+
258
+ Webhook URL: https://hooks.hooktunnel.com/h/<hook_id>
259
+ ```
260
+
261
+ ### `hooktunnel logs <hookId>`
262
+
263
+ View request history for a hook.
264
+
265
+ ```bash
266
+ # Last 20 requests
267
+ hooktunnel logs abc123def456
268
+
269
+ # Last 100 requests
270
+ hooktunnel logs abc123def456 --limit 100
271
+ ```
272
+
273
+ **Output:**
274
+ ```
275
+ 📋 Request Logs for abc123def456... (20)
276
+
277
+ Time Method Path Status Size
278
+ ---------------------------------------------------------------------------
279
+ 1/11/2026 12:00:05 POST /webhook 200 1.2KB
280
+ 1/11/2026 11:58:32 POST /webhook 500 0.8KB
281
+
282
+ Log ID (for replay): log_abc123...
283
+ ```
284
+
285
+ ### `hooktunnel replay <logId>` (Pro)
286
+
287
+ Re-send a captured webhook.
288
+
289
+ ```bash
290
+ # Replay to connected tunnel
291
+ hooktunnel replay log_abc123
292
+
293
+ # Replay to specific URL (including production)
294
+ hooktunnel replay log_abc123 --to https://your-server.com/webhook
295
+ ```
296
+
297
+ ### `hooktunnel status`
298
+
299
+ Check your connection and account status.
300
+
301
+ ```bash
302
+ hooktunnel status
303
+ ```
304
+
305
+ ### `hooktunnel logout`
306
+
307
+ Clear stored credentials.
308
+
309
+ ```bash
310
+ hooktunnel logout
311
+ ```
312
+
313
+ ---
314
+
315
+ ## How It Works
316
+
317
+ ```
318
+ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
319
+ │ │ │ │ │ │
320
+ │ Stripe/Twilio │────▶│ HookTunnel │────▶│ Your Server │
321
+ │ GitHub/etc │ │ (always on) │ │ (or CLI) │
322
+ │ │ │ │ │ │
323
+ └─────────────────┘ └──────────────────┘ └─────────────────┘
324
+
325
+
326
+ ┌──────────────────┐
327
+ │ Request History │
328
+ │ • Full payloads │
329
+ │ • Searchable │
330
+ │ • Replayable │
331
+ └──────────────────┘
332
+ ```
333
+
334
+ 1. **Provider sends webhook** to your stable HookTunnel URL
335
+ 2. **HookTunnel captures and logs** — stored even if your server is down
336
+ 3. **Request forwarded** to your server (or CLI for local dev)
337
+ 4. **Full history available** — debug, search, replay anytime
338
+
339
+ The URL never changes. No webhook is ever lost.
340
+
341
+ ---
342
+
343
+ ## Pricing
344
+
345
+ | Feature | Free | Pro ($19/mo) |
346
+ |---------|:----:|:------------:|
347
+ | Webhook URLs | 1 | 10 |
348
+ | Requests/day | 100 | Unlimited |
349
+ | History | 24 hours | 30 days |
350
+ | CLI Access | ✓ | ✓ |
351
+ | Request Replay | - | ✓ |
352
+ | Payload Storage | - | ✓ |
353
+
354
+ **Start free:** [hooktunnel.com](https://hooktunnel.com)
355
+
356
+ ---
357
+
358
+ ## Configuration
359
+
360
+ Credentials stored in:
361
+ - **Linux/macOS:** `~/.config/hooktunnel-cli/config.json`
362
+ - **Windows:** `%APPDATA%/hooktunnel-cli/config.json`
363
+
364
+ ---
365
+
366
+ ## Troubleshooting
367
+
368
+ ### "Authentication required"
369
+
370
+ ```bash
371
+ hooktunnel login --key <your-api-key>
372
+ ```
373
+
374
+ ### "Connection failed"
375
+
376
+ 1. Check internet connection
377
+ 2. Verify API key: `hooktunnel status`
378
+ 3. Try verbose mode: `hooktunnel connect dev 3000 --verbose`
379
+
380
+ ### 502 errors in terminal
381
+
382
+ Your local server isn't responding:
383
+ 1. Make sure it's running
384
+ 2. Check the port number
385
+ 3. Verify it's listening on localhost
386
+
387
+ ### "Pro tier required"
388
+
389
+ Replay requires Pro. Upgrade at [hooktunnel.com/#pricing](https://hooktunnel.com/#pricing)
390
+
391
+ ---
392
+
393
+ ## Links
394
+
395
+ - **Website:** [hooktunnel.com](https://hooktunnel.com)
396
+ - **Dashboard:** [hooktunnel.com/app](https://hooktunnel.com/app)
397
+ - **Documentation:** [hulupeep.github.io/hooktunnel-help](https://hulupeep.github.io/hooktunnel-help)
398
+ - **Issues:** [github.com/Hulupeep/hooktunnel-cli/issues](https://github.com/Hulupeep/hooktunnel-cli/issues)
399
+
400
+ ---
401
+
402
+ ## License
403
+
404
+ MIT
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Connect Command
3
+ * CLI-CMD-001: Connect command
4
+ */
5
+ interface ConnectOptions {
6
+ verbose?: boolean;
7
+ host?: string;
8
+ }
9
+ export declare function connectCommand(env: string, port: string, options: ConnectOptions): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAyDf"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Connect Command
3
+ * CLI-CMD-001: Connect command
4
+ */
5
+ import chalk from 'chalk';
6
+ import { getApiKey, isAuthenticated } from '../lib/config.js';
7
+ import { TunnelClient } from '../lib/tunnel.js';
8
+ import { CLIError } from '../lib/errors.js';
9
+ export async function connectCommand(env, port, options) {
10
+ // Validate auth
11
+ if (!isAuthenticated()) {
12
+ throw new CLIError('AUTH_REQUIRED');
13
+ }
14
+ // Validate environment
15
+ const validEnvs = ['dev', 'staging', 'prod'];
16
+ if (!validEnvs.includes(env)) {
17
+ console.log(chalk.red(`Invalid environment: ${env}`));
18
+ console.log(chalk.gray(`Valid environments: ${validEnvs.join(', ')}`));
19
+ process.exit(1);
20
+ }
21
+ // Validate port
22
+ const portNum = parseInt(port, 10);
23
+ if (isNaN(portNum) || portNum < 1 || portNum > 65535) {
24
+ throw new CLIError('INVALID_PORT');
25
+ }
26
+ const apiKey = getApiKey();
27
+ console.log(chalk.cyan('\n🔗 HookTunnel'));
28
+ console.log(chalk.gray(` Environment: ${env}`));
29
+ console.log(chalk.gray(` Local port: ${portNum}`));
30
+ if (options.host) {
31
+ console.log(chalk.gray(` Local host: ${options.host}`));
32
+ }
33
+ console.log();
34
+ const client = new TunnelClient({
35
+ env: env,
36
+ port: portNum,
37
+ host: options.host,
38
+ verbose: options.verbose,
39
+ apiKey,
40
+ });
41
+ // Handle graceful shutdown
42
+ const shutdown = () => {
43
+ console.log(chalk.yellow('\n\nDisconnecting...'));
44
+ client.disconnect();
45
+ process.exit(0);
46
+ };
47
+ process.on('SIGINT', shutdown);
48
+ process.on('SIGTERM', shutdown);
49
+ try {
50
+ await client.connect();
51
+ console.log(chalk.gray('Waiting for webhooks... (Ctrl+C to stop)\n'));
52
+ // Keep the process alive
53
+ await new Promise(() => { });
54
+ }
55
+ catch (error) {
56
+ throw error;
57
+ }
58
+ }
59
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Hooks Command
3
+ * CLI-CMD-003: Hooks command
4
+ */
5
+ export declare function hooksCommand(): Promise<void>;
6
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAoDlD"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Hooks Command
3
+ * CLI-CMD-003: Hooks command
4
+ */
5
+ import chalk from 'chalk';
6
+ import ora from 'ora';
7
+ import { isAuthenticated } from '../lib/config.js';
8
+ import { fetchHooks } from '../lib/api.js';
9
+ import { CLIError } from '../lib/errors.js';
10
+ export async function hooksCommand() {
11
+ if (!isAuthenticated()) {
12
+ throw new CLIError('AUTH_REQUIRED');
13
+ }
14
+ const spinner = ora('Fetching hooks...').start();
15
+ try {
16
+ const hooks = await fetchHooks();
17
+ spinner.stop();
18
+ if (hooks.length === 0) {
19
+ console.log(chalk.yellow('\nNo hooks found.'));
20
+ console.log(chalk.gray('Create one at https://hooktunnel.com/app\n'));
21
+ return;
22
+ }
23
+ console.log(chalk.cyan(`\n📌 Your Hooks (${hooks.length})\n`));
24
+ // Table header
25
+ console.log(chalk.gray(' ') +
26
+ chalk.gray('ID'.padEnd(24)) +
27
+ chalk.gray('Provider'.padEnd(12)) +
28
+ chalk.gray('Status'.padEnd(10)) +
29
+ chalk.gray('Requests'));
30
+ console.log(chalk.gray(' ' + '-'.repeat(60)));
31
+ for (const hook of hooks) {
32
+ const statusColor = hook.status === 'active' ? chalk.green : chalk.yellow;
33
+ const providerColor = hook.provider === 'stripe' ? chalk.magenta :
34
+ hook.provider === 'twilio' ? chalk.red :
35
+ chalk.blue;
36
+ console.log(' ' +
37
+ chalk.white(hook.hook_id.padEnd(24)) +
38
+ providerColor(hook.provider.padEnd(12)) +
39
+ statusColor(hook.status.padEnd(10)) +
40
+ chalk.gray(hook.request_count.toString()));
41
+ }
42
+ console.log();
43
+ console.log(chalk.gray(' Webhook URL: https://hooks.hooktunnel.com/h/<hook_id>'));
44
+ console.log(chalk.gray(' To forward: hooktunnel connect dev <port>\n'));
45
+ }
46
+ catch (error) {
47
+ spinner.fail('Failed to fetch hooks');
48
+ throw error;
49
+ }
50
+ }
51
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAC;QACjC,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;QAE/D,eAAe;QACf,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CACvB,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;YAC1E,MAAM,aAAa,GACjB,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC5C,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBACxC,KAAK,CAAC,IAAI,CAAC;YAEb,OAAO,CAAC,GAAG,CACT,IAAI;gBACJ,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACpC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACvC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACnC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAC1C,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Login Command
3
+ * CLI-CMD-002: Login command
4
+ */
5
+ interface LoginOptions {
6
+ key?: string;
7
+ }
8
+ export declare function loginCommand(options: LoginOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,UAAU,YAAY;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BvE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Login Command
3
+ * CLI-CMD-002: Login command
4
+ */
5
+ import chalk from 'chalk';
6
+ import ora from 'ora';
7
+ import { setApiKey, getConfigPath } from '../lib/config.js';
8
+ import { validateApiKey } from '../lib/api.js';
9
+ import { CLIError } from '../lib/errors.js';
10
+ export async function loginCommand(options) {
11
+ const apiKey = options.key;
12
+ if (!apiKey) {
13
+ console.log(chalk.yellow('\nTo get an API key:'));
14
+ console.log(chalk.gray(' 1. Go to https://hooktunnel.com/app/settings'));
15
+ console.log(chalk.gray(' 2. Generate an API key'));
16
+ console.log(chalk.gray(' 3. Run: hooktunnel login --key <your-api-key>\n'));
17
+ throw new CLIError('AUTH_REQUIRED', 'API key is required');
18
+ }
19
+ const spinner = ora('Validating API key...').start();
20
+ try {
21
+ const isValid = await validateApiKey(apiKey);
22
+ if (!isValid) {
23
+ spinner.fail('Invalid API key');
24
+ throw new CLIError('AUTH_INVALID');
25
+ }
26
+ setApiKey(apiKey);
27
+ spinner.succeed('Logged in successfully');
28
+ console.log(chalk.gray(`\nCredentials saved to: ${getConfigPath()}`));
29
+ console.log(chalk.gray('You can now run: hooktunnel connect dev <port>\n'));
30
+ }
31
+ catch (error) {
32
+ spinner.fail('Login failed');
33
+ throw error;
34
+ }
35
+ }
36
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAM5C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC,CAAC;QAC7E,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,uBAAuB,CAAC,CAAC,KAAK,EAAE,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;QAE7C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAChC,MAAM,IAAI,QAAQ,CAAC,cAAc,CAAC,CAAC;QACrC,CAAC;QAED,SAAS,CAAC,MAAM,CAAC,CAAC;QAClB,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QAE1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Logout Command
3
+ * CLI-CMD-007: Logout command
4
+ */
5
+ export declare function logoutCommand(): Promise<void>;
6
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CASnD"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Logout Command
3
+ * CLI-CMD-007: Logout command
4
+ */
5
+ import chalk from 'chalk';
6
+ import { clearApiKey, isAuthenticated } from '../lib/config.js';
7
+ export async function logoutCommand() {
8
+ if (!isAuthenticated()) {
9
+ console.log(chalk.yellow('Not logged in'));
10
+ return;
11
+ }
12
+ clearApiKey();
13
+ console.log(chalk.green('✓ Logged out successfully'));
14
+ console.log(chalk.gray(' Your API key has been removed from this device\n'));
15
+ }
16
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,WAAW,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Logs Command
3
+ * CLI-CMD-004: Logs command
4
+ */
5
+ interface LogsOptions {
6
+ limit?: string;
7
+ }
8
+ export declare function logsCommand(hookId: string, options: LogsOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqErF"}