@hooklink/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 (62) hide show
  1. package/README.md +235 -0
  2. package/dist/commands/config.d.ts +3 -0
  3. package/dist/commands/config.d.ts.map +1 -0
  4. package/dist/commands/config.js +74 -0
  5. package/dist/commands/config.js.map +1 -0
  6. package/dist/commands/connect.d.ts +3 -0
  7. package/dist/commands/connect.d.ts.map +1 -0
  8. package/dist/commands/connect.js +169 -0
  9. package/dist/commands/connect.js.map +1 -0
  10. package/dist/commands/endpoints.d.ts +3 -0
  11. package/dist/commands/endpoints.d.ts.map +1 -0
  12. package/dist/commands/endpoints.js +58 -0
  13. package/dist/commands/endpoints.js.map +1 -0
  14. package/dist/commands/login.d.ts +3 -0
  15. package/dist/commands/login.d.ts.map +1 -0
  16. package/dist/commands/login.js +82 -0
  17. package/dist/commands/login.js.map +1 -0
  18. package/dist/commands/logout.d.ts +3 -0
  19. package/dist/commands/logout.d.ts.map +1 -0
  20. package/dist/commands/logout.js +17 -0
  21. package/dist/commands/logout.js.map +1 -0
  22. package/dist/commands/logs.d.ts +3 -0
  23. package/dist/commands/logs.d.ts.map +1 -0
  24. package/dist/commands/logs.js +77 -0
  25. package/dist/commands/logs.js.map +1 -0
  26. package/dist/commands/status.d.ts +3 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +43 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/core/http-forwarder.d.ts +10 -0
  31. package/dist/core/http-forwarder.d.ts.map +1 -0
  32. package/dist/core/http-forwarder.js +98 -0
  33. package/dist/core/http-forwarder.js.map +1 -0
  34. package/dist/core/websocket-client.d.ts +30 -0
  35. package/dist/core/websocket-client.d.ts.map +1 -0
  36. package/dist/core/websocket-client.js +167 -0
  37. package/dist/core/websocket-client.js.map +1 -0
  38. package/dist/index.d.ts +3 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +51 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/types/index.d.ts +69 -0
  43. package/dist/types/index.d.ts.map +1 -0
  44. package/dist/types/index.js +3 -0
  45. package/dist/types/index.js.map +1 -0
  46. package/dist/utils/api.d.ts +21 -0
  47. package/dist/utils/api.d.ts.map +1 -0
  48. package/dist/utils/api.js +62 -0
  49. package/dist/utils/api.js.map +1 -0
  50. package/dist/utils/config.d.ts +15 -0
  51. package/dist/utils/config.d.ts.map +1 -0
  52. package/dist/utils/config.js +58 -0
  53. package/dist/utils/config.js.map +1 -0
  54. package/dist/utils/logger.d.ts +10 -0
  55. package/dist/utils/logger.d.ts.map +1 -0
  56. package/dist/utils/logger.js +50 -0
  57. package/dist/utils/logger.js.map +1 -0
  58. package/dist/utils/sentry.d.ts +2 -0
  59. package/dist/utils/sentry.d.ts.map +1 -0
  60. package/dist/utils/sentry.js +21 -0
  61. package/dist/utils/sentry.js.map +1 -0
  62. package/package.json +64 -0
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loginCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const inquirer_1 = __importDefault(require("inquirer"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const config_1 = require("../utils/config");
12
+ const api_1 = require("../utils/api");
13
+ const logger_1 = require("../utils/logger");
14
+ exports.loginCommand = new commander_1.Command('login')
15
+ .description('Authenticate with your HookLink API key')
16
+ .option('-k, --key <key>', 'API key')
17
+ .action(async (options) => {
18
+ let apiKey = options.key;
19
+ // Prompt for API key if not provided
20
+ if (!apiKey) {
21
+ // Welcome message
22
+ logger_1.Logger.log('');
23
+ logger_1.Logger.log(chalk_1.default.cyan.bold('👋 Welcome to HookLink!'));
24
+ logger_1.Logger.log('');
25
+ logger_1.Logger.log('To authenticate, you\'ll need an API key.');
26
+ logger_1.Logger.log(chalk_1.default.gray('Create one at: ') + chalk_1.default.cyan('https://hooklink.net/dashboard/keys'));
27
+ logger_1.Logger.log('');
28
+ logger_1.Logger.log(chalk_1.default.gray('💡 Tip: Your API key is stored securely and you only need to enter it once.'));
29
+ logger_1.Logger.log('');
30
+ const answers = await inquirer_1.default.prompt([
31
+ {
32
+ type: 'password',
33
+ name: 'apiKey',
34
+ message: 'Please paste your API key:',
35
+ mask: '*',
36
+ validate: (input) => {
37
+ if (!input || input.trim().length === 0) {
38
+ return 'API key is required';
39
+ }
40
+ if (!input.startsWith('hlk_')) {
41
+ return 'Invalid API key format (should start with hlk_)';
42
+ }
43
+ return true;
44
+ },
45
+ },
46
+ ]);
47
+ apiKey = answers.apiKey;
48
+ }
49
+ // Verify API key
50
+ const spinner = (0, ora_1.default)('Verifying API key...').start();
51
+ try {
52
+ // Save temporarily to config for verification
53
+ config_1.config.set('apiKey', apiKey);
54
+ const isValid = await api_1.api.verifyApiKey();
55
+ if (!isValid) {
56
+ spinner.fail('Invalid API key');
57
+ config_1.config.delete('apiKey');
58
+ process.exit(1);
59
+ }
60
+ // Get user info
61
+ const user = await api_1.api.getCurrentUser();
62
+ spinner.succeed('Successfully authenticated');
63
+ logger_1.Logger.log('');
64
+ logger_1.Logger.success(`Logged in as ${chalk_1.default.cyan(user.user.email)}`);
65
+ logger_1.Logger.log('');
66
+ logger_1.Logger.log(chalk_1.default.gray('Your API key has been saved securely.'));
67
+ logger_1.Logger.log(chalk_1.default.gray(`Config location: ${config_1.config.getPath()}`));
68
+ logger_1.Logger.log('');
69
+ logger_1.Logger.log(chalk_1.default.bold('🚀 Next steps:'));
70
+ logger_1.Logger.log(` ${chalk_1.default.cyan('hooklink connect')} ${chalk_1.default.gray('- Connect to an endpoint')}`);
71
+ logger_1.Logger.log(` ${chalk_1.default.cyan('hooklink endpoints')} ${chalk_1.default.gray('- List your endpoints')}`);
72
+ logger_1.Logger.log(` ${chalk_1.default.cyan('hooklink status')} ${chalk_1.default.gray('- View your account info')}`);
73
+ logger_1.Logger.log('');
74
+ }
75
+ catch (error) {
76
+ spinner.fail('Authentication failed');
77
+ config_1.config.delete('apiKey');
78
+ logger_1.Logger.error(error instanceof Error ? error.message : 'Unknown error');
79
+ process.exit(1);
80
+ }
81
+ });
82
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const logoutCommand: Command;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SAUtB,CAAC"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logoutCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../utils/config");
6
+ const logger_1 = require("../utils/logger");
7
+ exports.logoutCommand = new commander_1.Command('logout')
8
+ .description('Clear stored credentials')
9
+ .action(() => {
10
+ if (!config_1.config.has('apiKey')) {
11
+ logger_1.Logger.warning('You are not logged in');
12
+ return;
13
+ }
14
+ config_1.config.delete('apiKey');
15
+ logger_1.Logger.success('Successfully logged out');
16
+ });
17
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,4CAAyC;AACzC,4CAAyC;AAE5B,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,GAAG,EAAE;IACX,IAAI,CAAC,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,eAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,eAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxB,eAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const logsCommand: Command;
3
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,WAAW,SAwEpB,CAAC"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.logsCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const cli_table3_1 = __importDefault(require("cli-table3"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const config_1 = require("../utils/config");
11
+ const api_1 = require("../utils/api");
12
+ const logger_1 = require("../utils/logger");
13
+ exports.logsCommand = new commander_1.Command('logs')
14
+ .description('View recent webhook request logs')
15
+ .option('-e, --endpoint <keyword>', 'Filter by endpoint keyword')
16
+ .option('-l, --limit <number>', 'Number of logs to fetch (default: 20)', parseInt)
17
+ .action(async (options) => {
18
+ const apiKey = config_1.config.get('apiKey');
19
+ if (!apiKey) {
20
+ logger_1.Logger.error('You must login first. Run: hooklink login');
21
+ process.exit(1);
22
+ }
23
+ try {
24
+ let endpointId;
25
+ // Get endpoint ID if keyword provided
26
+ if (options.endpoint) {
27
+ const endpoints = await api_1.api.getEndpoints();
28
+ const endpoint = endpoints.find((e) => e.keyword === options.endpoint);
29
+ if (!endpoint) {
30
+ logger_1.Logger.error(`Endpoint "${options.endpoint}" not found`);
31
+ process.exit(1);
32
+ }
33
+ endpointId = endpoint.id;
34
+ }
35
+ const logs = await api_1.api.getLogs(endpointId, options.limit || 20);
36
+ if (logs.length === 0) {
37
+ logger_1.Logger.info('No logs found');
38
+ return;
39
+ }
40
+ const table = new cli_table3_1.default({
41
+ head: [
42
+ chalk_1.default.cyan('Time'),
43
+ chalk_1.default.cyan('Method'),
44
+ chalk_1.default.cyan('Path'),
45
+ chalk_1.default.cyan('Status'),
46
+ chalk_1.default.cyan('Response Time'),
47
+ chalk_1.default.cyan('Forwarded'),
48
+ ],
49
+ colWidths: [20, 8, 35, 10, 15, 12],
50
+ });
51
+ logs.forEach((log) => {
52
+ const time = new Date(log.received_at).toLocaleTimeString();
53
+ const statusColor = log.status_code && log.status_code >= 200 && log.status_code < 300
54
+ ? chalk_1.default.green
55
+ : log.status_code && log.status_code >= 400
56
+ ? chalk_1.default.red
57
+ : chalk_1.default.yellow;
58
+ table.push([
59
+ time,
60
+ log.method,
61
+ log.path.substring(0, 32) + (log.path.length > 32 ? '...' : ''),
62
+ log.status_code ? statusColor(log.status_code.toString()) : '-',
63
+ log.response_time_ms ? `${log.response_time_ms}ms` : '-',
64
+ log.forwarded_to_cli ? chalk_1.default.green('Yes') : chalk_1.default.red('No'),
65
+ ]);
66
+ });
67
+ logger_1.Logger.log('');
68
+ logger_1.Logger.log(table.toString());
69
+ logger_1.Logger.log('');
70
+ logger_1.Logger.info(`Showing ${logs.length} recent log(s)`);
71
+ }
72
+ catch (error) {
73
+ logger_1.Logger.error(`Failed to fetch logs: ${error instanceof Error ? error.message : 'Unknown error'}`);
74
+ process.exit(1);
75
+ }
76
+ });
77
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAoC;AACpC,4DAA+B;AAC/B,kDAA0B;AAC1B,4CAAyC;AACzC,sCAAmC;AACnC,4CAAyC;AAE5B,QAAA,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,0BAA0B,EAAE,4BAA4B,CAAC;KAChE,MAAM,CAAC,sBAAsB,EAAE,uCAAuC,EAAE,QAAQ,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,MAAM,GAAG,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,eAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,IAAI,UAA8B,CAAC;QAEnC,sCAAsC;QACtC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,MAAM,SAAG,CAAC,YAAY,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;YACvE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,eAAM,CAAC,KAAK,CAAC,aAAa,OAAO,CAAC,QAAQ,aAAa,CAAC,CAAC;gBACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,UAAU,GAAG,QAAQ,CAAC,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,SAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAEhE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,eAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,oBAAK,CAAC;YACtB,IAAI,EAAE;gBACJ,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC;gBAClB,eAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACpB,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC;gBAClB,eAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACpB,eAAK,CAAC,IAAI,CAAC,eAAe,CAAC;gBAC3B,eAAK,CAAC,IAAI,CAAC,WAAW,CAAC;aACxB;YACD,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACnB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,kBAAkB,EAAE,CAAC;YAC5D,MAAM,WAAW,GACf,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,IAAI,GAAG,CAAC,WAAW,GAAG,GAAG;gBAChE,CAAC,CAAC,eAAK,CAAC,KAAK;gBACb,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG;oBAC3C,CAAC,CAAC,eAAK,CAAC,GAAG;oBACX,CAAC,CAAC,eAAK,CAAC,MAAM,CAAC;YAEnB,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI;gBACJ,GAAG,CAAC,MAAM;gBACV,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/D,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG;gBAC/D,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,GAAG;gBACxD,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC;aAC5D,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,eAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,eAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7B,eAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,eAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,eAAM,CAAC,KAAK,CAAC,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAClG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const statusCommand: Command;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,aAAa,SAgCtB,CAAC"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.statusCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const config_1 = require("../utils/config");
10
+ const api_1 = require("../utils/api");
11
+ const logger_1 = require("../utils/logger");
12
+ exports.statusCommand = new commander_1.Command('status')
13
+ .description('Show current configuration and connection status')
14
+ .action(async () => {
15
+ const apiKey = config_1.config.get('apiKey');
16
+ if (!apiKey) {
17
+ logger_1.Logger.warning('Not logged in');
18
+ logger_1.Logger.info('Run: hooklink login');
19
+ return;
20
+ }
21
+ try {
22
+ const user = await api_1.api.getCurrentUser();
23
+ const endpoints = await api_1.api.getEndpoints();
24
+ const activeEndpoints = endpoints.filter((e) => e.is_active);
25
+ logger_1.Logger.log('');
26
+ logger_1.Logger.log(chalk_1.default.bold('Status:'));
27
+ logger_1.Logger.log(` User: ${chalk_1.default.green(user.user.email)}`);
28
+ logger_1.Logger.log(` API Key: ${chalk_1.default.green('Active')}`);
29
+ logger_1.Logger.log(` Total Endpoints: ${chalk_1.default.cyan(endpoints.length.toString())}`);
30
+ logger_1.Logger.log(` Active Endpoints: ${chalk_1.default.cyan(activeEndpoints.length.toString())}`);
31
+ logger_1.Logger.log('');
32
+ logger_1.Logger.log(chalk_1.default.bold('Configuration:'));
33
+ logger_1.Logger.log(` API URL: ${chalk_1.default.cyan(config_1.config.get('apiUrl'))}`);
34
+ logger_1.Logger.log(` WebSocket URL: ${chalk_1.default.cyan(config_1.config.get('wsUrl'))}`);
35
+ logger_1.Logger.log(` Config Path: ${chalk_1.default.gray(config_1.config.getPath())}`);
36
+ logger_1.Logger.log('');
37
+ }
38
+ catch (error) {
39
+ logger_1.Logger.error(`Failed to fetch status: ${error instanceof Error ? error.message : 'Unknown error'}`);
40
+ process.exit(1);
41
+ }
42
+ });
43
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAoC;AACpC,kDAA0B;AAC1B,4CAAyC;AACzC,sCAAmC;AACnC,4CAAyC;AAE5B,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,MAAM,GAAG,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,eAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAChC,eAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAG,CAAC,cAAc,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,SAAG,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAE7D,eAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,eAAM,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAClC,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnE,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC5D,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9E,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACpF,eAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,eAAM,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACzC,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,IAAI,CAAC,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;QACvE,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,IAAI,CAAC,eAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QACtE,eAAM,CAAC,GAAG,CAAC,wBAAwB,eAAK,CAAC,IAAI,CAAC,eAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACnE,eAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,eAAM,CAAC,KAAK,CAAC,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACpG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { WSRequestMessage, WSResponseMessage } from '../types';
2
+ export declare class HttpForwarder {
3
+ private targetUrl;
4
+ constructor(targetUrl: string);
5
+ forward(request: WSRequestMessage): Promise<WSResponseMessage>;
6
+ private filterHeaders;
7
+ private sanitizeHeaders;
8
+ setTargetUrl(url: string): void;
9
+ }
10
+ //# sourceMappingURL=http-forwarder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-forwarder.d.ts","sourceRoot":"","sources":["../../src/core/http-forwarder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG/D,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAIvB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA0DpE,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,eAAe;IAevB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGhC"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HttpForwarder = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const logger_1 = require("../utils/logger");
9
+ class HttpForwarder {
10
+ constructor(targetUrl) {
11
+ this.targetUrl = targetUrl;
12
+ }
13
+ async forward(request) {
14
+ const startTime = Date.now();
15
+ try {
16
+ // Build full URL with query params
17
+ const url = new URL(request.path, this.targetUrl);
18
+ Object.entries(request.query).forEach(([key, value]) => {
19
+ url.searchParams.append(key, value);
20
+ });
21
+ // Forward the request
22
+ const response = await (0, axios_1.default)({
23
+ method: request.method,
24
+ url: url.toString(),
25
+ headers: this.filterHeaders(request.headers),
26
+ data: request.body,
27
+ validateStatus: () => true, // Accept any status code
28
+ maxRedirects: 0,
29
+ timeout: 30000,
30
+ });
31
+ const duration = Date.now() - startTime;
32
+ // Log the request
33
+ logger_1.Logger.request(request.method, request.path, response.status);
34
+ logger_1.Logger.debug(`Response time: ${duration}ms`);
35
+ // Return response
36
+ return {
37
+ type: 'response',
38
+ requestId: request.requestId,
39
+ statusCode: response.status,
40
+ headers: this.sanitizeHeaders(response.headers),
41
+ body: typeof response.data === 'string'
42
+ ? response.data
43
+ : JSON.stringify(response.data),
44
+ };
45
+ }
46
+ catch (error) {
47
+ const duration = Date.now() - startTime;
48
+ logger_1.Logger.error(`Failed to forward request: ${error instanceof Error ? error.message : 'Unknown error'} (${duration}ms)`);
49
+ // Return error response
50
+ return {
51
+ type: 'response',
52
+ requestId: request.requestId,
53
+ statusCode: 502,
54
+ headers: { 'content-type': 'application/json' },
55
+ body: JSON.stringify({
56
+ error: 'Bad Gateway',
57
+ message: `Failed to forward request to local server: ${error instanceof Error ? error.message : 'Unknown error'}`,
58
+ }),
59
+ };
60
+ }
61
+ }
62
+ filterHeaders(headers) {
63
+ const filtered = {};
64
+ const skipHeaders = [
65
+ 'host',
66
+ 'connection',
67
+ 'upgrade',
68
+ 'sec-websocket-key',
69
+ 'sec-websocket-version',
70
+ 'sec-websocket-extensions',
71
+ ];
72
+ for (const [key, value] of Object.entries(headers)) {
73
+ if (!skipHeaders.includes(key.toLowerCase())) {
74
+ filtered[key] = value;
75
+ }
76
+ }
77
+ return filtered;
78
+ }
79
+ sanitizeHeaders(headers) {
80
+ const sanitized = {};
81
+ if (typeof headers !== 'object' || headers === null)
82
+ return sanitized;
83
+ for (const [key, value] of Object.entries(headers)) {
84
+ if (typeof value === 'string') {
85
+ sanitized[key] = value;
86
+ }
87
+ else if (Array.isArray(value)) {
88
+ sanitized[key] = value.join(', ');
89
+ }
90
+ }
91
+ return sanitized;
92
+ }
93
+ setTargetUrl(url) {
94
+ this.targetUrl = url;
95
+ }
96
+ }
97
+ exports.HttpForwarder = HttpForwarder;
98
+ //# sourceMappingURL=http-forwarder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-forwarder.js","sourceRoot":"","sources":["../../src/core/http-forwarder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { EventEmitter } from 'events';
2
+ import { WSRequestMessage, WSResponseMessage } from '../types';
3
+ export interface WebSocketClientOptions {
4
+ wsUrl: string;
5
+ apiKey: string;
6
+ endpointId: string;
7
+ onRequest: (request: WSRequestMessage) => Promise<WSResponseMessage>;
8
+ }
9
+ export declare class WebSocketClient extends EventEmitter {
10
+ private ws;
11
+ private options;
12
+ private reconnectAttempts;
13
+ private maxReconnectAttempts;
14
+ private reconnectDelay;
15
+ private heartbeatInterval;
16
+ private isConnecting;
17
+ private shouldReconnect;
18
+ constructor(options: WebSocketClientOptions);
19
+ connect(): Promise<void>;
20
+ private authenticate;
21
+ private startHeartbeat;
22
+ private stopHeartbeat;
23
+ private scheduleReconnect;
24
+ private handleMessage;
25
+ private handleRequest;
26
+ private sendRaw;
27
+ disconnect(): void;
28
+ isConnected(): boolean;
29
+ }
30
+ //# sourceMappingURL=websocket-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-client.d.ts","sourceRoot":"","sources":["../../src/core/websocket-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG/D,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACtE;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAM;IAClC,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAQ;gBAEnB,OAAO,EAAE,sBAAsB;IAKrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0D9B,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,iBAAiB;YAoBX,aAAa;YAkCb,aAAa;IAuB3B,OAAO,CAAC,OAAO;IAMf,UAAU,IAAI,IAAI;IASlB,WAAW,IAAI,OAAO;CAGvB"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebSocketClient = void 0;
7
+ const ws_1 = __importDefault(require("ws"));
8
+ const events_1 = require("events");
9
+ const logger_1 = require("../utils/logger");
10
+ class WebSocketClient extends events_1.EventEmitter {
11
+ constructor(options) {
12
+ super();
13
+ this.ws = null;
14
+ this.reconnectAttempts = 0;
15
+ this.maxReconnectAttempts = 10;
16
+ this.reconnectDelay = 1000;
17
+ this.heartbeatInterval = null;
18
+ this.isConnecting = false;
19
+ this.shouldReconnect = true;
20
+ this.options = options;
21
+ }
22
+ async connect() {
23
+ if (this.isConnecting ||
24
+ (this.ws && this.ws.readyState === ws_1.default.OPEN)) {
25
+ return;
26
+ }
27
+ this.isConnecting = true;
28
+ return new Promise((resolve, reject) => {
29
+ try {
30
+ this.ws = new ws_1.default(this.options.wsUrl);
31
+ this.ws.on('open', () => {
32
+ logger_1.Logger.debug('WebSocket connection established');
33
+ this.isConnecting = false;
34
+ this.reconnectAttempts = 0;
35
+ this.authenticate();
36
+ this.startHeartbeat();
37
+ this.emit('connected');
38
+ resolve();
39
+ });
40
+ this.ws.on('message', (data) => {
41
+ this.handleMessage(data.toString());
42
+ });
43
+ this.ws.on('close', (code, reason) => {
44
+ logger_1.Logger.debug(`WebSocket closed: ${code} - ${reason}`);
45
+ this.isConnecting = false;
46
+ this.stopHeartbeat();
47
+ this.emit('disconnected');
48
+ if (this.shouldReconnect &&
49
+ this.reconnectAttempts < this.maxReconnectAttempts) {
50
+ this.scheduleReconnect();
51
+ }
52
+ });
53
+ this.ws.on('error', (error) => {
54
+ logger_1.Logger.debug(`WebSocket error: ${error instanceof Error ? error.message : 'Unknown error'}`);
55
+ this.isConnecting = false;
56
+ if (this.reconnectAttempts === 0) {
57
+ reject(error);
58
+ }
59
+ });
60
+ }
61
+ catch (error) {
62
+ this.isConnecting = false;
63
+ reject(error);
64
+ }
65
+ });
66
+ }
67
+ authenticate() {
68
+ this.sendRaw({
69
+ type: 'auth',
70
+ payload: {
71
+ apiKey: this.options.apiKey,
72
+ endpointId: this.options.endpointId,
73
+ },
74
+ });
75
+ }
76
+ startHeartbeat() {
77
+ this.heartbeatInterval = setInterval(() => {
78
+ this.sendRaw({
79
+ type: 'heartbeat',
80
+ payload: { timestamp: Date.now() },
81
+ });
82
+ }, 30000); // Every 30 seconds
83
+ }
84
+ stopHeartbeat() {
85
+ if (this.heartbeatInterval) {
86
+ clearInterval(this.heartbeatInterval);
87
+ this.heartbeatInterval = null;
88
+ }
89
+ }
90
+ scheduleReconnect() {
91
+ this.reconnectAttempts++;
92
+ const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000);
93
+ logger_1.Logger.warning(`Connection lost. Reconnecting in ${delay / 1000}s (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
94
+ setTimeout(() => {
95
+ this.connect().catch(() => {
96
+ // Error already logged
97
+ });
98
+ }, delay);
99
+ }
100
+ async handleMessage(data) {
101
+ try {
102
+ const message = JSON.parse(data);
103
+ switch (message.type) {
104
+ case 'authenticated':
105
+ logger_1.Logger.debug('Authentication successful');
106
+ break;
107
+ case 'request':
108
+ await this.handleRequest(message.payload);
109
+ break;
110
+ case 'heartbeat_ack':
111
+ logger_1.Logger.debug('Heartbeat acknowledged');
112
+ break;
113
+ case 'error':
114
+ logger_1.Logger.error(`Server error: ${message.payload?.error || message.message}`);
115
+ this.emit('error', new Error(message.payload?.error || message.message));
116
+ break;
117
+ case 'disconnect':
118
+ logger_1.Logger.warning(`Server disconnect: ${message.payload?.message || 'Unknown reason'}`);
119
+ break;
120
+ }
121
+ }
122
+ catch (error) {
123
+ logger_1.Logger.error(`Failed to parse message: ${error}`);
124
+ }
125
+ }
126
+ async handleRequest(payload) {
127
+ try {
128
+ const response = await this.options.onRequest(payload);
129
+ this.sendRaw({
130
+ type: 'response',
131
+ payload: {
132
+ requestId: response.requestId,
133
+ statusCode: response.statusCode,
134
+ headers: response.headers,
135
+ body: response.body,
136
+ },
137
+ });
138
+ }
139
+ catch (error) {
140
+ this.sendRaw({
141
+ type: 'error',
142
+ payload: {
143
+ requestId: payload.requestId,
144
+ error: error instanceof Error ? error.message : 'Unknown error',
145
+ },
146
+ });
147
+ }
148
+ }
149
+ sendRaw(message) {
150
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
151
+ this.ws.send(JSON.stringify(message));
152
+ }
153
+ }
154
+ disconnect() {
155
+ this.shouldReconnect = false;
156
+ this.stopHeartbeat();
157
+ if (this.ws) {
158
+ this.ws.close();
159
+ this.ws = null;
160
+ }
161
+ }
162
+ isConnected() {
163
+ return this.ws !== null && this.ws.readyState === ws_1.default.OPEN;
164
+ }
165
+ }
166
+ exports.WebSocketClient = WebSocketClient;
167
+ //# sourceMappingURL=websocket-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-client.js","sourceRoot":"","sources":["../../src/core/websocket-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}