@qodalis/cli-server-logs 1.0.3 → 1.0.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/README.md CHANGED
@@ -1,24 +1,18 @@
1
- # ServerLogs
1
+ # Cli extension
2
2
 
3
- This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.2.0.
3
+ The `@qodalis/cli-server-logs` package is a CLI extension designed to provide seamless server log management and analysis capabilities for the Qodalis CLI.
4
4
 
5
- ## Code scaffolding
5
+ # Features
6
6
 
7
- Run `ng generate component component-name --project server-logs` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project server-logs`.
8
- > Note: Don't forget to add `--project server-logs` or else it will be added to the default project in your `angular.json` file.
7
+ View Logs: Fetch and display server logs directly in the CLI.
8
+ Filter Logs: Apply filters based on date, severity, or keywords.
9
+ Download Logs: Download logs to a local file for further analysis.
10
+ Integration: Integrates seamlessly with Qodalis CLI for server monitoring.
9
11
 
10
- ## Build
12
+ # Installation
11
13
 
12
- Run `ng build server-logs` to build the project. The build artifacts will be stored in the `dist/` directory.
14
+ ```bash
15
+ packages add @qodalis/cli-server-logs
16
+ ```
13
17
 
14
- ## Publishing
15
-
16
- After building your library with `ng build server-logs`, go to the dist folder `cd dist/server-logs` and run `npm publish`.
17
-
18
- ## Running unit tests
19
-
20
- Run `ng test server-logs` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
-
22
- ## Further help
23
-
24
- To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
18
+ This command downloads and registers the extension for use within the CLI environment.
@@ -40,6 +40,24 @@ export class CliLogsCommandProcessor {
40
40
  };
41
41
  },
42
42
  },
43
+ {
44
+ name: 'server',
45
+ type: 'string',
46
+ description: 'The server to connect to, e.g. "http://localhost:5000"',
47
+ required: false,
48
+ },
49
+ {
50
+ name: 'hub',
51
+ type: 'string',
52
+ description: 'The hub to connect to, e.g. "loghub" (default) or "loghub2"',
53
+ required: false,
54
+ },
55
+ {
56
+ name: 'file',
57
+ type: 'boolean',
58
+ description: 'Export logs to a file',
59
+ required: false,
60
+ },
43
61
  ];
44
62
  this.author = DefaultLibraryAuthor;
45
63
  this.processors?.push({
@@ -52,19 +70,26 @@ export class CliLogsCommandProcessor {
52
70
  }
53
71
  async processCommand(command, context) {
54
72
  let qs = '?';
55
- if (Object.keys(command.args).length > 0) {
56
- qs += toQueryString(command.args);
73
+ const args = this.excludeKeys(command.args, ['server', 'hub', 'file']);
74
+ if (Object.keys(args).length > 0) {
75
+ qs += toQueryString(args);
57
76
  }
77
+ const hub = command.args['hub'] || 'loghub';
78
+ let server = command.args['server'] || '';
79
+ server = server.replace(/\/+$/, '');
80
+ const url = `${server}/${hub}${qs}`;
81
+ console.log('Connecting to:', url);
58
82
  this.hubConnection = new signalR.HubConnectionBuilder()
59
- .withUrl('/loghub' + qs)
83
+ .withUrl(url)
60
84
  .build();
85
+ const buffer = [];
61
86
  await this.hubConnection
62
87
  .start()
63
88
  .then(() => {
64
89
  console.log('SignalR connection started');
65
90
  context.writer.writeWarning('Connected to live logs');
66
91
  if (qs.length) {
67
- Object.keys(command.args).forEach((key) => {
92
+ Object.keys(args).forEach((key) => {
68
93
  context.writer.writeWarning(`Filtering logs by: ${key}=${command.args[key]}`);
69
94
  });
70
95
  }
@@ -74,6 +99,7 @@ export class CliLogsCommandProcessor {
74
99
  if (firstLog) {
75
100
  context.writer.writeln('');
76
101
  }
102
+ buffer.push(log);
77
103
  context.writer.writeln(`\x1b[33m${++index}\x1b[0m. ` +
78
104
  (command.args['pattern']
79
105
  ? highlightTextWithBg(log, new RegExp(command.args['pattern'], 'g'))
@@ -83,17 +109,25 @@ export class CliLogsCommandProcessor {
83
109
  const subscription = context.onAbort.subscribe(() => {
84
110
  this.hubConnection.stop();
85
111
  context.writer.writeWarning('Disconnected from live logs');
112
+ if (command.args['file']) {
113
+ const filename = `logs-${new Date().toISOString()}.txt`;
114
+ context.writer.writeToFile(filename, buffer.join('\n'));
115
+ }
86
116
  subscription.unsubscribe();
87
117
  });
88
118
  })
89
119
  .catch((err) => {
90
120
  console.error('Error starting SignalR connection:', err);
91
121
  context.writer.writeError('Failed to connect to live logs');
122
+ context.writer.writeError(err?.toString());
92
123
  });
93
124
  }
94
125
  writeDescription(context) {
95
126
  context.writer.writeln('Show live logs');
96
127
  }
128
+ excludeKeys(record, keysToExclude) {
129
+ return Object.fromEntries(Object.entries(record).filter(([key]) => !keysToExclude.includes(key)));
130
+ }
97
131
  isValidRegex(pattern) {
98
132
  try {
99
133
  new RegExp(pattern);
@@ -112,4 +146,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
112
146
  providedIn: 'root',
113
147
  }]
114
148
  }], ctorParameters: function () { return []; } });
115
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWxvZ3MtY29tbWFuZC1wcm9jZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zZXJ2ZXItbG9ncy9zcmMvbGliL3Byb2Nlc3NvcnMvY2xpLWxvZ3MtY29tbWFuZC1wcm9jZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEtBQUssT0FBTyxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFFSCxvQkFBb0IsRUFDcEIsbUJBQW1CLEVBS25CLGFBQWEsR0FDaEIsTUFBTSxtQkFBbUIsQ0FBQzs7QUFFM0IsTUFBTSxNQUFNLEdBQUcsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBS2hGLE1BQU0sT0FBTyx1QkFBdUI7SUErQ2hDO1FBOUNBLFlBQU8sR0FBRyxNQUFNLENBQUM7UUFFakIsZ0JBQVcsR0FBd0IsZ0JBQWdCLENBQUM7UUFFcEQsZUFBVSxHQUF3QyxFQUFFLENBQUM7UUFFckQsZUFBVSxHQUFrRDtZQUN4RDtnQkFDSSxJQUFJLEVBQUUsU0FBUztnQkFDZixJQUFJLEVBQUUsUUFBUTtnQkFDZCxXQUFXLEVBQUUsNkNBQTZDO2dCQUMxRCxRQUFRLEVBQUUsS0FBSztnQkFDZixTQUFTLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRTtvQkFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDekMsT0FBTzt3QkFDSCxLQUFLLEVBQUUsT0FBTzt3QkFDZCxPQUFPLEVBQUUsT0FBTzs0QkFDWixDQUFDLENBQUMsU0FBUzs0QkFDWCxDQUFDLENBQUMsZ0NBQWdDO3FCQUN6QyxDQUFDO2dCQUNOLENBQUM7YUFDSjtZQUNEO2dCQUNJLElBQUksRUFBRSxPQUFPO2dC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Q0FBQyxDQUNqQixDQUFDO2dCQUNGLFFBQVEsR0FBRyxLQUFLLENBQUM7WUFDckIsQ0FBQyxDQUFDLENBQUM7WUFFSCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2hELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzFCLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLDZCQUE2QixDQUFDLENBQUM7Z0JBRTNELFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMvQixDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ1gsT0FBTyxDQUFDLEtBQUssQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUN6RCxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQ2hFLENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVELGdCQUFnQixDQUFDLE9BQTZCO1FBQzFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVPLFlBQVksQ0FBQyxPQUFlO1FBQ2hDLElBQUk7WUFDQSxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNwQixPQUFPLElBQUksQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDUixPQUFPLEtBQUssQ0FBQztTQUNoQjtJQUNMLENBQUM7K0dBaElRLHVCQUF1QjttSEFBdkIsdUJBQXVCLGNBRnBCLE1BQU07OzRGQUVULHVCQUF1QjtrQkFIbkMsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBzaWduYWxSIGZyb20gJ0BtaWNyb3NvZnQvc2lnbmFscic7XG5pbXBvcnQge1xuICAgIENsaVByb2Nlc3NDb21tYW5kLFxuICAgIERlZmF1bHRMaWJyYXJ5QXV0aG9yLFxuICAgIGhpZ2hsaWdodFRleHRXaXRoQmcsXG4gICAgSUNsaUNvbW1hbmRBdXRob3IsXG4gICAgSUNsaUNvbW1hbmRQYXJhbWV0ZXJEZXNjcmlwdG9yLFxuICAgIElDbGlDb21tYW5kUHJvY2Vzc29yLFxuICAgIElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgIHRvUXVlcnlTdHJpbmcsXG59IGZyb20gJ0Bxb2RhbGlzL2NsaS1jb3JlJztcblxuY29uc3QgbGV2ZWxzID0gWyd2ZXJib3NlJywgJ2RlYnVnJywgJ2luZm9ybWF0aW9uJywgJ3dhcm5pbmcnLCAnZXJyb3InLCAnZmF0YWwnXTtcblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgQ2xpTG9nc0NvbW1hbmRQcm9jZXNzb3IgaW1wbGVtZW50cyBJQ2xpQ29tbWFuZFByb2Nlc3NvciB7XG4gICAgY29tbWFuZCA9ICdsb2dzJztcblxuICAgIGRlc2NyaXB0aW9uPzogc3RyaW5nIHwgdW5kZWZpbmVkID0gJ1Nob3cgbGl2ZSBsb2dzJztcblxuICAgIHByb2Nlc3NvcnM/OiBJQ2xpQ29tbWFuZFByb2Nlc3NvcltdIHwgdW5kZWZpbmVkID0gW107XG5cbiAgICBwYXJhbWV0ZXJzPzogSUNsaUNvbW1hbmRQYXJhbWV0ZXJEZXNjcmlwdG9yW10gfCB1bmRlZmluZWQgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdwYXR0ZXJuJyxcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246ICdUaGUgcmVnZXggcGF0dGVybiB0byBzZWFyY2ggZm9yIGluIHRoZSBsb2dzJyxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbGlkYXRvcjogKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1ZhbGlkID0gdGhpcy5pc1ZhbGlkUmVnZXgodmFsdWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkOiBpc1ZhbGlkLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBpc1ZhbGlkXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgOiAnSW52YWxpZCByZWdleCBwYXR0ZXJuIHByb3ZpZGVkJyxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ2xldmVsJyxcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgJ1RoZSBsb2cgbGV2ZWwgdG8gZmlsdGVyIGJ5LCBlLmcuICcgKyBsZXZlbHMuam9pbignLCAnKSxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbGlkYXRvcjogKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1ZhbGlkID0gbGV2ZWxzLmluY2x1ZGVzKHZhbHVlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkOiBpc1ZhbGlkLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBpc1ZhbGlkXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgOiAnSW52YWxpZCBsb2cgbGV2ZWwgcHJvdmlkZWQsIG11c3QgYmUgb25lIG9mOiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzLmpvaW4oJywgJyksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgXTtcblxuICAgIGF1dGhvcj86IElDbGlDb21tYW5kQXV0aG9yIHwgdW5kZWZpbmVkID0gRGVmYXVsdExpYnJhcnlBdXRob3I7XG5cbiAgICBwcml2YXRlIGh1YkNvbm5lY3Rpb24hOiBzaWduYWxSLkh1YkNvbm5lY3Rpb247XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5wcm9jZXNzb3JzPy5wdXNoKHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdsaXZlJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uLFxuICAgICAgICAgICAgcGFyYW1ldGVyczogdGhpcy5wYXJhbWV0ZXJzLFxuICAgICAgICAgICAgcHJvY2Vzc0NvbW1hbmQ6IHRoaXMucHJvY2Vzc0NvbW1hbmQuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHdyaXRlRGVzY3JpcHRpb246IHRoaXMud3JpdGVEZXNjcmlwdGlvbi5iaW5kKHRoaXMpLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBwcm9jZXNzQ29tbWFuZChcbiAgICAgICAgY29tbWFuZDogQ2xpUHJvY2Vzc0NvbW1hbmQsXG4gICAgICAgIGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBsZXQgcXMgPSAnPyc7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhjb21tYW5kLmFyZ3MpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHFzICs9IHRvUXVlcnlTdHJpbmcoY29tbWFuZC5hcmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaHViQ29ubmVjdGlvbiA9IG5ldyBzaWduYWxSLkh1YkNvbm5lY3Rpb25CdWlsZGVyKClcbiAgICAgICAgICAgIC53aXRoVXJsKCcvbG9naHViJyArIHFzKVxuICAgICAgICAgICAgLmJ1aWxkKCk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5odWJDb25uZWN0aW9uXG4gICAgICAgICAgICAuc3RhcnQoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdTaWduYWxSIGNvbm5lY3Rpb24gc3RhcnRlZCcpO1xuXG4gICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVXYXJuaW5nKCdDb25uZWN0ZWQgdG8gbGl2ZSBsb2dzJyk7XG4gICAgICAgICAgICAgICAgaWYgKHFzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhjb21tYW5kLmFyZ3MpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVXYXJuaW5nKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBGaWx0ZXJpbmcgbG9ncyBieTogJHtrZXl9PSR7Y29tbWFuZC5hcmdzW2tleV19YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBmaXJzdExvZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcblxuICAgICAgICAgICAgICAgIHRoaXMuaHViQ29ubmVjdGlvbi5vbignbG9nJywgKGxvZzogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaXJzdExvZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZWxuKFxuICAgICAgICAgICAgICAgICAgICAgICAgYFxceDFiWzMzbSR7KytpbmRleH1cXHgxYlswbS4gYCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvbW1hbmQuYXJnc1sncGF0dGVybiddXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gaGlnaGxpZ2h0VGV4dFdpdGhCZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgUmVnRXhwKGNvbW1hbmQuYXJnc1sncGF0dGVybiddLCAnZycpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBsb2cpLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBmaXJzdExvZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gY29udGV4dC5vbkFib3J0LnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaHViQ29ubmVjdGlvbi5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlV2FybmluZygnRGlzY29ubmVjdGVkIGZyb20gbGl2ZSBsb2dzJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzdGFydGluZyBTaWduYWxSIGNvbm5lY3Rpb246JywgZXJyKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKCdGYWlsZWQgdG8gY29ubmVjdCB0byBsaXZlIGxvZ3MnKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHdyaXRlRGVzY3JpcHRpb24oY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQpOiB2b2lkIHtcbiAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbignU2hvdyBsaXZlIGxvZ3MnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGlzVmFsaWRSZWdleChwYXR0ZXJuOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG5ldyBSZWdFeHAocGF0dGVybik7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19
149
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWxvZ3MtY29tbWFuZC1wcm9jZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zZXJ2ZXItbG9ncy9zcmMvbGliL3Byb2Nlc3NvcnMvY2xpLWxvZ3MtY29tbWFuZC1wcm9jZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEtBQUssT0FBTyxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFFSCxvQkFBb0IsRUFDcEIsbUJBQW1CLEVBS25CLGFBQWEsR0FDaEIsTUFBTSxtQkFBbUIsQ0FBQzs7QUFFM0IsTUFBTSxNQUFNLEdBQUcsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBS2hGLE1BQU0sT0FBTyx1QkFBdUI7SUFtRWhDO1FBbEVBLFlBQU8sR0FBRyxNQUFNLENBQUM7UUFFakIsZ0JBQVcsR0FBd0IsZ0JBQWdCLENBQUM7UUFFcEQsZUFBVSxHQUF3QyxFQUFFLENBQUM7UUFFckQsZUFBVSxHQUFrRDtZQUN4RDtnQkFDSSxJQUFJLEVBQUUsU0FBUztnQkFDZixJQUFJLEVBQUUsUUFBUTtnQkFDZCxXQUFXLEVBQUUsNkNBQTZDO2dCQUMxRCxRQUFRLEVBQUUsS0FBSztnQkFDZixTQUFTLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRTtvQkFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDekMsT0FBTzt3QkFDSCxLQUFLLEVBQUUsT0FBTzt3QkFDZCxPQUFPLEVBQUUsT0FBTzs0QkFDWixDQUFDLENBQUMsU0FBUzs0QkFDWCxDQUFDLENBQUMsZ0NBQWdDO3FCQUN6QyxDQUFDO2dCQUNOLENBQUM7YUFDSjtZQUNEO2dCQUNJLElBQUksRUFBRSxPQUFPO2dC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QUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNwQixPQUFPLElBQUksQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDUixPQUFPLEtBQUssQ0FBQztTQUNoQjtJQUNMLENBQUM7K0dBckxRLHVCQUF1QjttSEFBdkIsdUJBQXVCLGNBRnBCLE1BQU07OzRGQUVULHVCQUF1QjtrQkFIbkMsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBzaWduYWxSIGZyb20gJ0BtaWNyb3NvZnQvc2lnbmFscic7XG5pbXBvcnQge1xuICAgIENsaVByb2Nlc3NDb21tYW5kLFxuICAgIERlZmF1bHRMaWJyYXJ5QXV0aG9yLFxuICAgIGhpZ2hsaWdodFRleHRXaXRoQmcsXG4gICAgSUNsaUNvbW1hbmRBdXRob3IsXG4gICAgSUNsaUNvbW1hbmRQYXJhbWV0ZXJEZXNjcmlwdG9yLFxuICAgIElDbGlDb21tYW5kUHJvY2Vzc29yLFxuICAgIElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgIHRvUXVlcnlTdHJpbmcsXG59IGZyb20gJ0Bxb2RhbGlzL2NsaS1jb3JlJztcblxuY29uc3QgbGV2ZWxzID0gWyd2ZXJib3NlJywgJ2RlYnVnJywgJ2luZm9ybWF0aW9uJywgJ3dhcm5pbmcnLCAnZXJyb3InLCAnZmF0YWwnXTtcblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgQ2xpTG9nc0NvbW1hbmRQcm9jZXNzb3IgaW1wbGVtZW50cyBJQ2xpQ29tbWFuZFByb2Nlc3NvciB7XG4gICAgY29tbWFuZCA9ICdsb2dzJztcblxuICAgIGRlc2NyaXB0aW9uPzogc3RyaW5nIHwgdW5kZWZpbmVkID0gJ1Nob3cgbGl2ZSBsb2dzJztcblxuICAgIHByb2Nlc3NvcnM/OiBJQ2xpQ29tbWFuZFByb2Nlc3NvcltdIHwgdW5kZWZpbmVkID0gW107XG5cbiAgICBwYXJhbWV0ZXJzPzogSUNsaUNvbW1hbmRQYXJhbWV0ZXJEZXNjcmlwdG9yW10gfCB1bmRlZmluZWQgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdwYXR0ZXJuJyxcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246ICdUaGUgcmVnZXggcGF0dGVybiB0byBzZWFyY2ggZm9yIGluIHRoZSBsb2dzJyxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbGlkYXRvcjogKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1ZhbGlkID0gdGhpcy5pc1ZhbGlkUmVnZXgodmFsdWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkOiBpc1ZhbGlkLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBpc1ZhbGlkXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgOiAnSW52YWxpZCByZWdleCBwYXR0ZXJuIHByb3ZpZGVkJyxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ2xldmVsJyxcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgJ1RoZSBsb2cgbGV2ZWwgdG8gZmlsdGVyIGJ5LCBlLmcuICcgKyBsZXZlbHMuam9pbignLCAnKSxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbGlkYXRvcjogKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1ZhbGlkID0gbGV2ZWxzLmluY2x1ZGVzKHZhbHVlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkOiBpc1ZhbGlkLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBpc1ZhbGlkXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgOiAnSW52YWxpZCBsb2cgbGV2ZWwgcHJvdmlkZWQsIG11c3QgYmUgb25lIG9mOiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzLmpvaW4oJywgJyksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdzZXJ2ZXInLFxuICAgICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAnVGhlIHNlcnZlciB0byBjb25uZWN0IHRvLCBlLmcuIFwiaHR0cDovL2xvY2FsaG9zdDo1MDAwXCInLFxuICAgICAgICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnaHViJyxcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgJ1RoZSBodWIgdG8gY29ubmVjdCB0bywgZS5nLiBcImxvZ2h1YlwiIChkZWZhdWx0KSBvciBcImxvZ2h1YjJcIicsXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdmaWxlJyxcbiAgICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnRXhwb3J0IGxvZ3MgdG8gYSBmaWxlJyxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICBdO1xuXG4gICAgYXV0aG9yPzogSUNsaUNvbW1hbmRBdXRob3IgfCB1bmRlZmluZWQgPSBEZWZhdWx0TGlicmFyeUF1dGhvcjtcblxuICAgIHByaXZhdGUgaHViQ29ubmVjdGlvbiE6IHNpZ25hbFIuSHViQ29ubmVjdGlvbjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnByb2Nlc3NvcnM/LnB1c2goe1xuICAgICAgICAgICAgY29tbWFuZDogJ2xpdmUnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24sXG4gICAgICAgICAgICBwYXJhbWV0ZXJzOiB0aGlzLnBhcmFtZXRlcnMsXG4gICAgICAgICAgICBwcm9jZXNzQ29tbWFuZDogdGhpcy5wcm9jZXNzQ29tbWFuZC5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgd3JpdGVEZXNjcmlwdGlvbjogdGhpcy53cml0ZURlc2NyaXB0aW9uLmJpbmQodGhpcyksXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIHByb2Nlc3NDb21tYW5kKFxuICAgICAgICBjb21tYW5kOiBDbGlQcm9jZXNzQ29tbWFuZCxcbiAgICAgICAgY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGxldCBxcyA9ICc/JztcblxuICAgICAgICBjb25zdCBhcmdzID0gdGhpcy5leGNsdWRlS2V5cyhjb21tYW5kLmFyZ3MsIFsnc2VydmVyJywgJ2h1YicsICdmaWxlJ10pO1xuXG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhhcmdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBxcyArPSB0b1F1ZXJ5U3RyaW5nKGFyZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaHViID0gY29tbWFuZC5hcmdzWydodWInXSB8fCAnbG9naHViJztcblxuICAgICAgICBsZXQgc2VydmVyID0gY29tbWFuZC5hcmdzWydzZXJ2ZXInXSB8fCAnJztcbiAgICAgICAgc2VydmVyID0gc2VydmVyLnJlcGxhY2UoL1xcLyskLywgJycpO1xuXG4gICAgICAgIGNvbnN0IHVybCA9IGAke3NlcnZlcn0vJHtodWJ9JHtxc31gO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCdDb25uZWN0aW5nIHRvOicsIHVybCk7XG5cbiAgICAgICAgdGhpcy5odWJDb25uZWN0aW9uID0gbmV3IHNpZ25hbFIuSHViQ29ubmVjdGlvbkJ1aWxkZXIoKVxuICAgICAgICAgICAgLndpdGhVcmwodXJsKVxuICAgICAgICAgICAgLmJ1aWxkKCk7XG5cbiAgICAgICAgY29uc3QgYnVmZmVyOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuaHViQ29ubmVjdGlvblxuICAgICAgICAgICAgLnN0YXJ0KClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnU2lnbmFsUiBjb25uZWN0aW9uIHN0YXJ0ZWQnKTtcblxuICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlV2FybmluZygnQ29ubmVjdGVkIHRvIGxpdmUgbG9ncycpO1xuICAgICAgICAgICAgICAgIGlmIChxcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoYXJncykuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZVdhcm5pbmcoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYEZpbHRlcmluZyBsb2dzIGJ5OiAke2tleX09JHtjb21tYW5kLmFyZ3Nba2V5XX1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGZpcnN0TG9nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5odWJDb25uZWN0aW9uLm9uKCdsb2cnLCAobG9nOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpcnN0TG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZWxuKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGxvZyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbihcbiAgICAgICAgICAgICAgICAgICAgICAgIGBcXHgxYlszM20keysraW5kZXh9XFx4MWJbMG0uIGAgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjb21tYW5kLmFyZ3NbJ3BhdHRlcm4nXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGhpZ2hsaWdodFRleHRXaXRoQmcoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IFJlZ0V4cChjb21tYW5kLmFyZ3NbJ3BhdHRlcm4nXSwgJ2cnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogbG9nKSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RMb2cgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IGNvbnRleHQub25BYm9ydC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmh1YkNvbm5lY3Rpb24uc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZVdhcm5pbmcoJ0Rpc2Nvbm5lY3RlZCBmcm9tIGxpdmUgbG9ncycpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb21tYW5kLmFyZ3NbJ2ZpbGUnXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsZW5hbWUgPSBgbG9ncy0ke25ldyBEYXRlKCkudG9JU09TdHJpbmcoKX0udHh0YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlVG9GaWxlKGZpbGVuYW1lLCBidWZmZXIuam9pbignXFxuJykpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzdGFydGluZyBTaWduYWxSIGNvbm5lY3Rpb246JywgZXJyKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKCdGYWlsZWQgdG8gY29ubmVjdCB0byBsaXZlIGxvZ3MnKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKGVycj8udG9TdHJpbmcoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB3cml0ZURlc2NyaXB0aW9uKGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0KTogdm9pZCB7XG4gICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlbG4oJ1Nob3cgbGl2ZSBsb2dzJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBleGNsdWRlS2V5czxUIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55Pj4oXG4gICAgICAgIHJlY29yZDogVCxcbiAgICAgICAga2V5c1RvRXhjbHVkZTogc3RyaW5nW10sXG4gICAgKTogUGFydGlhbDxUPiB7XG4gICAgICAgIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgICAgICBPYmplY3QuZW50cmllcyhyZWNvcmQpLmZpbHRlcihcbiAgICAgICAgICAgICAgICAoW2tleV0pID0+ICFrZXlzVG9FeGNsdWRlLmluY2x1ZGVzKGtleSksXG4gICAgICAgICAgICApLFxuICAgICAgICApIGFzIFBhcnRpYWw8VD47XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc1ZhbGlkUmVnZXgocGF0dGVybjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBuZXcgUmVnRXhwKHBhdHRlcm4pO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==
@@ -42,6 +42,24 @@ class CliLogsCommandProcessor {
42
42
  };
43
43
  },
44
44
  },
45
+ {
46
+ name: 'server',
47
+ type: 'string',
48
+ description: 'The server to connect to, e.g. "http://localhost:5000"',
49
+ required: false,
50
+ },
51
+ {
52
+ name: 'hub',
53
+ type: 'string',
54
+ description: 'The hub to connect to, e.g. "loghub" (default) or "loghub2"',
55
+ required: false,
56
+ },
57
+ {
58
+ name: 'file',
59
+ type: 'boolean',
60
+ description: 'Export logs to a file',
61
+ required: false,
62
+ },
45
63
  ];
46
64
  this.author = DefaultLibraryAuthor;
47
65
  this.processors?.push({
@@ -54,19 +72,26 @@ class CliLogsCommandProcessor {
54
72
  }
55
73
  async processCommand(command, context) {
56
74
  let qs = '?';
57
- if (Object.keys(command.args).length > 0) {
58
- qs += toQueryString(command.args);
75
+ const args = this.excludeKeys(command.args, ['server', 'hub', 'file']);
76
+ if (Object.keys(args).length > 0) {
77
+ qs += toQueryString(args);
59
78
  }
79
+ const hub = command.args['hub'] || 'loghub';
80
+ let server = command.args['server'] || '';
81
+ server = server.replace(/\/+$/, '');
82
+ const url = `${server}/${hub}${qs}`;
83
+ console.log('Connecting to:', url);
60
84
  this.hubConnection = new signalR.HubConnectionBuilder()
61
- .withUrl('/loghub' + qs)
85
+ .withUrl(url)
62
86
  .build();
87
+ const buffer = [];
63
88
  await this.hubConnection
64
89
  .start()
65
90
  .then(() => {
66
91
  console.log('SignalR connection started');
67
92
  context.writer.writeWarning('Connected to live logs');
68
93
  if (qs.length) {
69
- Object.keys(command.args).forEach((key) => {
94
+ Object.keys(args).forEach((key) => {
70
95
  context.writer.writeWarning(`Filtering logs by: ${key}=${command.args[key]}`);
71
96
  });
72
97
  }
@@ -76,6 +101,7 @@ class CliLogsCommandProcessor {
76
101
  if (firstLog) {
77
102
  context.writer.writeln('');
78
103
  }
104
+ buffer.push(log);
79
105
  context.writer.writeln(`\x1b[33m${++index}\x1b[0m. ` +
80
106
  (command.args['pattern']
81
107
  ? highlightTextWithBg(log, new RegExp(command.args['pattern'], 'g'))
@@ -85,17 +111,25 @@ class CliLogsCommandProcessor {
85
111
  const subscription = context.onAbort.subscribe(() => {
86
112
  this.hubConnection.stop();
87
113
  context.writer.writeWarning('Disconnected from live logs');
114
+ if (command.args['file']) {
115
+ const filename = `logs-${new Date().toISOString()}.txt`;
116
+ context.writer.writeToFile(filename, buffer.join('\n'));
117
+ }
88
118
  subscription.unsubscribe();
89
119
  });
90
120
  })
91
121
  .catch((err) => {
92
122
  console.error('Error starting SignalR connection:', err);
93
123
  context.writer.writeError('Failed to connect to live logs');
124
+ context.writer.writeError(err?.toString());
94
125
  });
95
126
  }
96
127
  writeDescription(context) {
97
128
  context.writer.writeln('Show live logs');
98
129
  }
130
+ excludeKeys(record, keysToExclude) {
131
+ return Object.fromEntries(Object.entries(record).filter(([key]) => !keysToExclude.includes(key)));
132
+ }
99
133
  isValidRegex(pattern) {
100
134
  try {
101
135
  new RegExp(pattern);
@@ -1 +1 @@
1
- {"version":3,"file":"qodalis-cli-server-logs.mjs","sources":["../../../projects/server-logs/src/lib/processors/cli-logs-command-processor.ts","../../../projects/server-logs/src/lib/cli-server-logs.module.ts","../../../projects/server-logs/src/public-api.ts","../../../projects/server-logs/src/qodalis-cli-server-logs.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport * as signalR from '@microsoft/signalr';\nimport {\n CliProcessCommand,\n DefaultLibraryAuthor,\n highlightTextWithBg,\n ICliCommandAuthor,\n ICliCommandParameterDescriptor,\n ICliCommandProcessor,\n ICliExecutionContext,\n toQueryString,\n} from '@qodalis/cli-core';\n\nconst levels = ['verbose', 'debug', 'information', 'warning', 'error', 'fatal'];\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CliLogsCommandProcessor implements ICliCommandProcessor {\n command = 'logs';\n\n description?: string | undefined = 'Show live logs';\n\n processors?: ICliCommandProcessor[] | undefined = [];\n\n parameters?: ICliCommandParameterDescriptor[] | undefined = [\n {\n name: 'pattern',\n type: 'string',\n description: 'The regex pattern to search for in the logs',\n required: false,\n validator: (value: string) => {\n const isValid = this.isValidRegex(value);\n return {\n valid: isValid,\n message: isValid\n ? undefined\n : 'Invalid regex pattern provided',\n };\n },\n },\n {\n name: 'level',\n type: 'string',\n description:\n 'The log level to filter by, e.g. ' + levels.join(', '),\n required: false,\n validator: (value: string) => {\n const isValid = levels.includes(value);\n\n return {\n valid: isValid,\n message: isValid\n ? undefined\n : 'Invalid log level provided, must be one of: ' +\n levels.join(', '),\n };\n },\n },\n ];\n\n author?: ICliCommandAuthor | undefined = DefaultLibraryAuthor;\n\n private hubConnection!: signalR.HubConnection;\n\n constructor() {\n this.processors?.push({\n command: 'live',\n description: this.description,\n parameters: this.parameters,\n processCommand: this.processCommand.bind(this),\n writeDescription: this.writeDescription.bind(this),\n });\n }\n\n async processCommand(\n command: CliProcessCommand,\n context: ICliExecutionContext,\n ): Promise<void> {\n let qs = '?';\n if (Object.keys(command.args).length > 0) {\n qs += toQueryString(command.args);\n }\n\n this.hubConnection = new signalR.HubConnectionBuilder()\n .withUrl('/loghub' + qs)\n .build();\n\n await this.hubConnection\n .start()\n .then(() => {\n console.log('SignalR connection started');\n\n context.writer.writeWarning('Connected to live logs');\n if (qs.length) {\n Object.keys(command.args).forEach((key) => {\n context.writer.writeWarning(\n `Filtering logs by: ${key}=${command.args[key]}`,\n );\n });\n }\n\n let firstLog = true;\n let index = 0;\n\n this.hubConnection.on('log', (log: string) => {\n if (firstLog) {\n context.writer.writeln('');\n }\n\n context.writer.writeln(\n `\\x1b[33m${++index}\\x1b[0m. ` +\n (command.args['pattern']\n ? highlightTextWithBg(\n log,\n new RegExp(command.args['pattern'], 'g'),\n )\n : log),\n );\n firstLog = false;\n });\n\n const subscription = context.onAbort.subscribe(() => {\n this.hubConnection.stop();\n context.writer.writeWarning('Disconnected from live logs');\n\n subscription.unsubscribe();\n });\n })\n .catch((err) => {\n console.error('Error starting SignalR connection:', err);\n context.writer.writeError('Failed to connect to live logs');\n });\n }\n\n writeDescription(context: ICliExecutionContext): void {\n context.writer.writeln('Show live logs');\n }\n\n private isValidRegex(pattern: string): boolean {\n try {\n new RegExp(pattern);\n return true;\n } catch (e) {\n return false;\n }\n }\n}\n","import { NgModule } from '@angular/core';\nimport { resolveCommandProcessorProvider } from '@qodalis/angular-cli';\nimport { CliLogsCommandProcessor } from './processors/cli-logs-command-processor';\n\n@NgModule({\n declarations: [],\n imports: [],\n exports: [],\n providers: [resolveCommandProcessorProvider(CliLogsCommandProcessor)],\n})\nexport class CliServerLogsModule {}\n","/*\n * Public API Surface of server-logs\n */\n\nexport * from './lib/cli-server-logs.module';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"qodalis-cli-server-logs.mjs","sources":["../../../projects/server-logs/src/lib/processors/cli-logs-command-processor.ts","../../../projects/server-logs/src/lib/cli-server-logs.module.ts","../../../projects/server-logs/src/public-api.ts","../../../projects/server-logs/src/qodalis-cli-server-logs.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport * as signalR from '@microsoft/signalr';\nimport {\n CliProcessCommand,\n DefaultLibraryAuthor,\n highlightTextWithBg,\n ICliCommandAuthor,\n ICliCommandParameterDescriptor,\n ICliCommandProcessor,\n ICliExecutionContext,\n toQueryString,\n} from '@qodalis/cli-core';\n\nconst levels = ['verbose', 'debug', 'information', 'warning', 'error', 'fatal'];\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CliLogsCommandProcessor implements ICliCommandProcessor {\n command = 'logs';\n\n description?: string | undefined = 'Show live logs';\n\n processors?: ICliCommandProcessor[] | undefined = [];\n\n parameters?: ICliCommandParameterDescriptor[] | undefined = [\n {\n name: 'pattern',\n type: 'string',\n description: 'The regex pattern to search for in the logs',\n required: false,\n validator: (value: string) => {\n const isValid = this.isValidRegex(value);\n return {\n valid: isValid,\n message: isValid\n ? undefined\n : 'Invalid regex pattern provided',\n };\n },\n },\n {\n name: 'level',\n type: 'string',\n description:\n 'The log level to filter by, e.g. ' + levels.join(', '),\n required: false,\n validator: (value: string) => {\n const isValid = levels.includes(value);\n\n return {\n valid: isValid,\n message: isValid\n ? undefined\n : 'Invalid log level provided, must be one of: ' +\n levels.join(', '),\n };\n },\n },\n {\n name: 'server',\n type: 'string',\n description:\n 'The server to connect to, e.g. \"http://localhost:5000\"',\n required: false,\n },\n {\n name: 'hub',\n type: 'string',\n description:\n 'The hub to connect to, e.g. \"loghub\" (default) or \"loghub2\"',\n required: false,\n },\n {\n name: 'file',\n type: 'boolean',\n description: 'Export logs to a file',\n required: false,\n },\n ];\n\n author?: ICliCommandAuthor | undefined = DefaultLibraryAuthor;\n\n private hubConnection!: signalR.HubConnection;\n\n constructor() {\n this.processors?.push({\n command: 'live',\n description: this.description,\n parameters: this.parameters,\n processCommand: this.processCommand.bind(this),\n writeDescription: this.writeDescription.bind(this),\n });\n }\n\n async processCommand(\n command: CliProcessCommand,\n context: ICliExecutionContext,\n ): Promise<void> {\n let qs = '?';\n\n const args = this.excludeKeys(command.args, ['server', 'hub', 'file']);\n\n if (Object.keys(args).length > 0) {\n qs += toQueryString(args);\n }\n\n const hub = command.args['hub'] || 'loghub';\n\n let server = command.args['server'] || '';\n server = server.replace(/\\/+$/, '');\n\n const url = `${server}/${hub}${qs}`;\n\n console.log('Connecting to:', url);\n\n this.hubConnection = new signalR.HubConnectionBuilder()\n .withUrl(url)\n .build();\n\n const buffer: string[] = [];\n\n await this.hubConnection\n .start()\n .then(() => {\n console.log('SignalR connection started');\n\n context.writer.writeWarning('Connected to live logs');\n if (qs.length) {\n Object.keys(args).forEach((key) => {\n context.writer.writeWarning(\n `Filtering logs by: ${key}=${command.args[key]}`,\n );\n });\n }\n\n let firstLog = true;\n let index = 0;\n\n this.hubConnection.on('log', (log: string) => {\n if (firstLog) {\n context.writer.writeln('');\n }\n\n buffer.push(log);\n\n context.writer.writeln(\n `\\x1b[33m${++index}\\x1b[0m. ` +\n (command.args['pattern']\n ? highlightTextWithBg(\n log,\n new RegExp(command.args['pattern'], 'g'),\n )\n : log),\n );\n firstLog = false;\n });\n\n const subscription = context.onAbort.subscribe(() => {\n this.hubConnection.stop();\n context.writer.writeWarning('Disconnected from live logs');\n\n if (command.args['file']) {\n const filename = `logs-${new Date().toISOString()}.txt`;\n context.writer.writeToFile(filename, buffer.join('\\n'));\n }\n\n subscription.unsubscribe();\n });\n })\n .catch((err) => {\n console.error('Error starting SignalR connection:', err);\n context.writer.writeError('Failed to connect to live logs');\n context.writer.writeError(err?.toString());\n });\n }\n\n writeDescription(context: ICliExecutionContext): void {\n context.writer.writeln('Show live logs');\n }\n\n private excludeKeys<T extends Record<string, any>>(\n record: T,\n keysToExclude: string[],\n ): Partial<T> {\n return Object.fromEntries(\n Object.entries(record).filter(\n ([key]) => !keysToExclude.includes(key),\n ),\n ) as Partial<T>;\n }\n\n private isValidRegex(pattern: string): boolean {\n try {\n new RegExp(pattern);\n return true;\n } catch (e) {\n return false;\n }\n }\n}\n","import { NgModule } from '@angular/core';\nimport { resolveCommandProcessorProvider } from '@qodalis/angular-cli';\nimport { CliLogsCommandProcessor } from './processors/cli-logs-command-processor';\n\n@NgModule({\n declarations: [],\n imports: [],\n exports: [],\n providers: [resolveCommandProcessorProvider(CliLogsCommandProcessor)],\n})\nexport class CliServerLogsModule {}\n","/*\n * Public API Surface of server-logs\n */\n\nexport * from './lib/cli-server-logs.module';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ export declare class CliLogsCommandProcessor implements ICliCommandProcessor {
10
10
  constructor();
11
11
  processCommand(command: CliProcessCommand, context: ICliExecutionContext): Promise<void>;
12
12
  writeDescription(context: ICliExecutionContext): void;
13
+ private excludeKeys;
13
14
  private isValidRegex;
14
15
  static ɵfac: i0.ɵɵFactoryDeclaration<CliLogsCommandProcessor, never>;
15
16
  static ɵprov: i0.ɵɵInjectableDeclaration<CliLogsCommandProcessor>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qodalis/cli-server-logs",
3
- "version": "1.0.3",
4
- "description": "An Angular CLI extension for generating and validating GUIDs.",
3
+ "version": "1.0.4",
4
+ "description": "An Angular CLI extension for server logs.",
5
5
  "author": "Nicolae Lupei, Qodalis Solutions",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -28,6 +28,14 @@
28
28
  "@microsoft/signalr": "^8.0.7"
29
29
  },
30
30
  "sideEffects": false,
31
+ "cliDependencies": [
32
+ {
33
+ "name": "signalR",
34
+ "globalName": "signalR",
35
+ "version": "latest",
36
+ "url": "https://unpkg.com/@microsoft/signalr@8.0.7/dist/browser/signalr.js"
37
+ }
38
+ ],
31
39
  "module": "fesm2022/qodalis-cli-server-logs.mjs",
32
40
  "typings": "index.d.ts",
33
41
  "exports": {
package/umd/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('@qodalis/cli-core'), require('@angular/core'), require('@microsoft/signalr')) :
3
3
  typeof define === 'function' && define.amd ? define(['@qodalis/cli-core', '@angular/core', '@microsoft/signalr'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.core, global.core, global.signalR));
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.core, global.ngCore, global.signalR));
5
5
  })(this, (function (cliCore, core, signalR) { 'use strict';
6
6
 
7
7
  function _interopNamespaceDefault(e) {
@@ -90,6 +90,24 @@
90
90
  };
91
91
  },
92
92
  },
93
+ {
94
+ name: 'server',
95
+ type: 'string',
96
+ description: 'The server to connect to, e.g. "http://localhost:5000"',
97
+ required: false,
98
+ },
99
+ {
100
+ name: 'hub',
101
+ type: 'string',
102
+ description: 'The hub to connect to, e.g. "loghub" (default) or "loghub2"',
103
+ required: false,
104
+ },
105
+ {
106
+ name: 'file',
107
+ type: 'boolean',
108
+ description: 'Export logs to a file',
109
+ required: false,
110
+ },
93
111
  ];
94
112
  this.author = cliCore.DefaultLibraryAuthor;
95
113
  this.processors?.push({
@@ -102,19 +120,26 @@
102
120
  }
103
121
  async processCommand(command, context) {
104
122
  let qs = '?';
105
- if (Object.keys(command.args).length > 0) {
106
- qs += cliCore.toQueryString(command.args);
123
+ const args = this.excludeKeys(command.args, ['server', 'hub', 'file']);
124
+ if (Object.keys(args).length > 0) {
125
+ qs += cliCore.toQueryString(args);
107
126
  }
127
+ const hub = command.args['hub'] || 'loghub';
128
+ let server = command.args['server'] || '';
129
+ server = server.replace(/\/+$/, '');
130
+ const url = `${server}/${hub}${qs}`;
131
+ console.log('Connecting to:', url);
108
132
  this.hubConnection = new signalR__namespace.HubConnectionBuilder()
109
- .withUrl('/loghub' + qs)
133
+ .withUrl(url)
110
134
  .build();
135
+ const buffer = [];
111
136
  await this.hubConnection
112
137
  .start()
113
138
  .then(() => {
114
139
  console.log('SignalR connection started');
115
140
  context.writer.writeWarning('Connected to live logs');
116
141
  if (qs.length) {
117
- Object.keys(command.args).forEach((key) => {
142
+ Object.keys(args).forEach((key) => {
118
143
  context.writer.writeWarning(`Filtering logs by: ${key}=${command.args[key]}`);
119
144
  });
120
145
  }
@@ -124,6 +149,7 @@
124
149
  if (firstLog) {
125
150
  context.writer.writeln('');
126
151
  }
152
+ buffer.push(log);
127
153
  context.writer.writeln(`\x1b[33m${++index}\x1b[0m. ` +
128
154
  (command.args['pattern']
129
155
  ? cliCore.highlightTextWithBg(log, new RegExp(command.args['pattern'], 'g'))
@@ -133,17 +159,25 @@
133
159
  const subscription = context.onAbort.subscribe(() => {
134
160
  this.hubConnection.stop();
135
161
  context.writer.writeWarning('Disconnected from live logs');
162
+ if (command.args['file']) {
163
+ const filename = `logs-${new Date().toISOString()}.txt`;
164
+ context.writer.writeToFile(filename, buffer.join('\n'));
165
+ }
136
166
  subscription.unsubscribe();
137
167
  });
138
168
  })
139
169
  .catch((err) => {
140
170
  console.error('Error starting SignalR connection:', err);
141
171
  context.writer.writeError('Failed to connect to live logs');
172
+ context.writer.writeError(err?.toString());
142
173
  });
143
174
  }
144
175
  writeDescription(context) {
145
176
  context.writer.writeln('Show live logs');
146
177
  }
178
+ excludeKeys(record, keysToExclude) {
179
+ return Object.fromEntries(Object.entries(record).filter(([key]) => !keysToExclude.includes(key)));
180
+ }
147
181
  isValidRegex(pattern) {
148
182
  try {
149
183
  new RegExp(pattern);
@@ -160,17 +194,9 @@
160
194
  })
161
195
  ], CliLogsCommandProcessor);
162
196
 
163
- const module = {
197
+ cliCore.bootUmdModule({
164
198
  name: '@qodalis/cli-server-logs',
165
199
  processors: [new CliLogsCommandProcessor()],
166
- dependencies: [
167
- {
168
- name: 'signalR',
169
- version: 'latest',
170
- url: 'https://unpkg.com/@microsoft/signalr@8.0.7/dist/browser/signalr.js',
171
- },
172
- ],
173
- };
174
- cliCore.bootUmdModule(module);
200
+ });
175
201
 
176
202
  }));