kourou 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,7 +26,7 @@ $ npm install -g kourou
26
26
  $ kourou COMMAND
27
27
  running command...
28
28
  $ kourou (-v|--version|version)
29
- kourou/0.22.0 linux-x64 node-v16.15.0
29
+ kourou/0.23.0 linux-x64 node-v14.18.2
30
30
  $ kourou --help [COMMAND]
31
31
  USAGE
32
32
  $ kourou COMMAND
@@ -129,6 +129,7 @@ All other arguments and options will be passed as-is to the `sdk:query` method.
129
129
  * [`kourou api-key:create USER`](#kourou-api-keycreate-user)
130
130
  * [`kourou api-key:delete USER ID`](#kourou-api-keydelete-user-id)
131
131
  * [`kourou api-key:search USER`](#kourou-api-keysearch-user)
132
+ * [`kourou app:debug-proxy`](#kourou-appdebug-proxy)
132
133
  * [`kourou app:scaffold DESTINATION`](#kourou-appscaffold-destination)
133
134
  * [`kourou app:start-services`](#kourou-appstart-services)
134
135
  * [`kourou autocomplete [SHELL]`](#kourou-autocomplete-shell)
@@ -288,6 +289,41 @@ OPTIONS
288
289
 
289
290
  _See code: [src/commands/api-key/search.ts](src/commands/api-key/search.ts)_
290
291
 
292
+ ## `kourou app:debug-proxy`
293
+
294
+ Create a Proxy Server that allows Chrome to debug Kuzzle remotely using the DebugController
295
+
296
+ ```
297
+ USAGE
298
+ $ kourou app:debug-proxy
299
+
300
+ OPTIONS
301
+ --api-key=api-key Kuzzle user api-key
302
+ --as=as Impersonate a user
303
+ --forwardPort=forwardPort [default: 9222] Port of the forwarding server
304
+ --help show CLI help
305
+ --host=host [default: localhost] Kuzzle server host
306
+
307
+ --nonoAutoEnableDebugger True if Kourou should not enable and disable the Debugger automatically before and after
308
+ usage
309
+
310
+ --password=password Kuzzle user password
311
+
312
+ --port=port [default: 7512] Kuzzle server port
313
+
314
+ --protocol=protocol [default: ws] Kuzzle protocol (http or ws)
315
+
316
+ --showDebuggerEvents Verbose mode to display events sent to the Chrome Debugger
317
+
318
+ --showDebuggerPayloads Verbose mode to display payloads sent by and to the Chrome Debugger
319
+
320
+ --ssl Use SSL to connect to Kuzzle
321
+
322
+ --username=username [default: anonymous] Kuzzle username (local strategy)
323
+ ```
324
+
325
+ _See code: [src/commands/app/debug-proxy.ts](src/commands/app/debug-proxy.ts)_
326
+
291
327
  ## `kourou app:scaffold DESTINATION`
292
328
 
293
329
  Scaffolds a new Kuzzle application
@@ -342,7 +378,7 @@ EXAMPLES
342
378
  $ kourou autocomplete --refresh-cache
343
379
  ```
344
380
 
345
- _See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.2.0/src/commands/autocomplete/index.ts)_
381
+ _See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.3.0/src/commands/autocomplete/index.ts)_
346
382
 
347
383
  ## `kourou collection:create INDEX COLLECTION [BODY]`
348
384
 
@@ -0,0 +1,24 @@
1
+ import { flags } from '@oclif/command';
2
+ import { Kommand } from '../../common';
3
+ export default class DebugProxy extends Kommand {
4
+ static description: string;
5
+ static flags: {
6
+ host: flags.IOptionFlag<string>;
7
+ port: flags.IOptionFlag<string>;
8
+ ssl: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
9
+ username: flags.IOptionFlag<string>;
10
+ password: flags.IOptionFlag<string | undefined>;
11
+ protocol: flags.IOptionFlag<string>;
12
+ as: flags.IOptionFlag<string | undefined>;
13
+ 'api-key': flags.IOptionFlag<string | undefined>;
14
+ help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
15
+ forwardPort: import("@oclif/parser/lib/flags").IOptionFlag<number>;
16
+ nonoAutoEnableDebugger: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
17
+ showDebuggerEvents: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
18
+ showDebuggerPayloads: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
19
+ };
20
+ static sdkOptions: {
21
+ protocol: string;
22
+ };
23
+ runSafe(): Promise<void>;
24
+ }
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const command_1 = require("@oclif/command");
5
+ const common_1 = require("../../common");
6
+ const kuzzle_1 = require("../../support/kuzzle");
7
+ const http_1 = tslib_1.__importDefault(require("http"));
8
+ const ws_1 = tslib_1.__importDefault(require("ws"));
9
+ // Add the proper headers and send the body in the response
10
+ function sendResponse(response, bodyObject) {
11
+ response.setHeader('Content-Type', 'application/json; charset=UTF-8');
12
+ response.setHeader('Cache-Control', 'no-cache');
13
+ const body = JSON.stringify(bodyObject);
14
+ response.setHeader('Content-Length', Buffer.byteLength(body));
15
+ response.writeHead(200);
16
+ response.end(body);
17
+ }
18
+ class DebugProxy extends common_1.Kommand {
19
+ async runSafe() {
20
+ const nodeVersionResponse = await this.sdk.query({
21
+ controller: 'debug',
22
+ action: 'nodeVersion'
23
+ });
24
+ this.logInfo(`Connected to Kuzzle node: ${nodeVersionResponse.node}`);
25
+ /**
26
+ * To allow the Chrome Debugger to see the proxy server we must implement the following routes:
27
+ * - /json/version
28
+ * - /json
29
+ */
30
+ const server = http_1.default.createServer((request, response) => {
31
+ if (request.url === '/json/version') {
32
+ sendResponse(response, {
33
+ Browser: `node.js/${nodeVersionResponse.result}`,
34
+ "Protocol-Version": "1.1"
35
+ });
36
+ return;
37
+ }
38
+ else if (request.url === '/json') {
39
+ // Here we send a bunch of information about the Remote Target to the Chrome Debugger
40
+ // Those are the informations that the Chrome Debugger uses to know how to connect to Remote Target
41
+ // We give the Chrome Inspector our own Websocket endpoint so that it can connect to our proxy server
42
+ sendResponse(response, [{
43
+ description: 'node.js instance',
44
+ devtoolsFrontendUrl: `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=${request.headers.host}/kuzzle-debugger`,
45
+ devtoolsFrontendUrlCompat: `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${request.headers.host}/kuzzle-debugger`,
46
+ faviconUrl: 'https://nodejs.org/static/images/favicons/favicon.ico',
47
+ id: 'kuzzle-debugger',
48
+ title: `Kuzzle Debugger - ${this.flags.host}:${this.flags.port}`,
49
+ type: 'node',
50
+ webSocketDebuggerUrl: `ws://${request.headers.host}/kuzzle-debugger`
51
+ }]);
52
+ return;
53
+ }
54
+ response.writeHead(404);
55
+ });
56
+ const closeServer = async () => {
57
+ this.logInfo('Connection closed.');
58
+ if (!this.flags.noAutoEnableDebugger) {
59
+ await this.sdk.query({
60
+ controller: 'debug',
61
+ action: 'disable'
62
+ });
63
+ }
64
+ this.sdk.disconnect();
65
+ server.close();
66
+ };
67
+ const wss = new ws_1.default.Server({
68
+ server
69
+ });
70
+ if (!this.flags.noAutoEnableDebugger) {
71
+ await this.sdk.query({
72
+ controller: 'debug',
73
+ action: 'enable'
74
+ });
75
+ }
76
+ // Listen to all events emitted by the Debug Controller
77
+ await this.sdk.query({
78
+ controller: 'debug',
79
+ action: 'addListener',
80
+ body: {
81
+ event: '*'
82
+ }
83
+ });
84
+ wss.on('connection', ws => {
85
+ this.logInfo('Connection established.');
86
+ /**
87
+ * Listen to the room were events from the DebugController are sent
88
+ * and only forward events from the Chrome Devtools Protocol
89
+ */
90
+ this.sdk.sdk.protocol.on('kuzzle-debugger-event', (payload) => {
91
+ if (!payload.event || payload.event.startsWith('Kuzzle')) {
92
+ return;
93
+ }
94
+ if (this.flags.showDebuggerEvents) {
95
+ this.logInfo(JSON.stringify(payload.result, null, 2));
96
+ }
97
+ ws.send(JSON.stringify(payload.result));
98
+ });
99
+ // When receiving message from Chrome Devtools Protocol, we forward it to the DebugController
100
+ ws.on('message', async (message) => {
101
+ try {
102
+ const json = JSON.parse(message.toString());
103
+ if (json.id === undefined || json.method === undefined) {
104
+ return;
105
+ }
106
+ if (this.flags.showDebuggerPayloads) {
107
+ this.logInfo(JSON.stringify({
108
+ method: json.method,
109
+ params: json.params,
110
+ }, null, 2));
111
+ }
112
+ const response = await this.sdk.query({
113
+ controller: 'debug',
114
+ action: 'post',
115
+ body: {
116
+ method: json.method,
117
+ params: json.params,
118
+ }
119
+ });
120
+ if (this.flags.showDebuggerPayloads) {
121
+ this.logInfo(JSON.stringify({
122
+ id: json.id,
123
+ result: response.result
124
+ }, null, 2));
125
+ }
126
+ // Send back the response using the same ID received
127
+ ws.send(JSON.stringify({
128
+ id: json.id,
129
+ result: response.result
130
+ }));
131
+ }
132
+ catch (e) {
133
+ this.logKo(`${e}`);
134
+ }
135
+ });
136
+ ws.on('close', closeServer);
137
+ });
138
+ server.on('error', async (err) => {
139
+ this.logKo(err.message);
140
+ this.logKo(err.stack);
141
+ await closeServer();
142
+ });
143
+ server.listen(this.flags.forwardPort, () => {
144
+ this.logOk(`Listening on port ${this.flags.forwardPort}, forwarding to Kuzzle at ${this.flags.host}:${this.flags.port}`);
145
+ this.logInfo(`Showing to Chrome Debugger as "Kuzzle Debugger - ${this.flags.host}:${this.flags.port}"`);
146
+ this.logInfo('Waiting for Chrome Debugger to connect...');
147
+ });
148
+ let resolve;
149
+ const promise = new Promise(res => {
150
+ resolve = res;
151
+ });
152
+ server.on('close', () => {
153
+ resolve();
154
+ });
155
+ await promise;
156
+ }
157
+ }
158
+ exports.default = DebugProxy;
159
+ DebugProxy.description = 'Create a Proxy Server that allows Chrome to debug Kuzzle remotely using the DebugController';
160
+ DebugProxy.flags = Object.assign({ help: command_1.flags.help(), forwardPort: command_1.flags.integer({
161
+ description: 'Port of the forwarding server',
162
+ default: 9222
163
+ }), nonoAutoEnableDebugger: command_1.flags.boolean({
164
+ description: 'True if Kourou should not enable and disable the Debugger automatically before and after usage',
165
+ default: true
166
+ }), showDebuggerEvents: command_1.flags.boolean({
167
+ description: 'Verbose mode to display events sent to the Chrome Debugger',
168
+ default: false,
169
+ }), showDebuggerPayloads: command_1.flags.boolean({
170
+ description: 'Verbose mode to display payloads sent by and to the Chrome Debugger',
171
+ default: false,
172
+ }) }, kuzzle_1.kuzzleFlags);
173
+ // Force the usage of Websocket otherwise each request might end up executed on a different Kuzzle Node
174
+ DebugProxy.sdkOptions = {
175
+ protocol: 'ws'
176
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kourou",
3
3
  "description": "The CLI that helps you manage your Kuzzle instances",
4
- "version": "0.22.0",
4
+ "version": "0.23.0",
5
5
  "author": "The Kuzzle Team <support@kuzzle.io>",
6
6
  "bin": {
7
7
  "kourou": "./bin/run"
@@ -43,7 +43,8 @@
43
43
  "production": "0.0.2",
44
44
  "strip-json-comments": "^3.1.1",
45
45
  "tmp": "^0.2.1",
46
- "tslib": "^2.3.1"
46
+ "tslib": "^2.3.1",
47
+ "ws": "^8.8.0"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@istanbuljs/nyc-config-typescript": "^1.0.1",
@@ -56,6 +57,7 @@
56
57
  "@types/node": "^14.14.41",
57
58
  "@types/node-emoji": "^1.8.1",
58
59
  "@types/node-fetch": "^2.6.1",
60
+ "@types/ws": "^8.5.3",
59
61
  "@typescript-eslint/eslint-plugin": "^4.22.0",
60
62
  "@typescript-eslint/parser": "^4.22.0",
61
63
  "chai": "^4.3.4",