@qodalis/cli-server-node 1.0.0-beta.4 → 1.0.0-beta.6

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 (127) hide show
  1. package/README.md +315 -37
  2. package/dist/src/abstractions/index.d.ts +1 -1
  3. package/dist/src/abstractions/index.d.ts.map +1 -1
  4. package/dist/src/abstractions/index.js +4 -1
  5. package/dist/src/abstractions/index.js.map +1 -1
  6. package/dist/src/auth/cli-server-auth-gate.d.ts +31 -0
  7. package/dist/src/auth/cli-server-auth-gate.d.ts.map +1 -0
  8. package/dist/src/auth/cli-server-auth-gate.js +118 -0
  9. package/dist/src/auth/cli-server-auth-gate.js.map +1 -0
  10. package/dist/src/auth/cli-server-auth.d.ts +147 -0
  11. package/dist/src/auth/cli-server-auth.d.ts.map +1 -0
  12. package/dist/src/auth/cli-server-auth.js +143 -0
  13. package/dist/src/auth/cli-server-auth.js.map +1 -0
  14. package/dist/src/auth/index.d.ts +4 -0
  15. package/dist/src/auth/index.d.ts.map +1 -0
  16. package/dist/src/auth/index.js +19 -0
  17. package/dist/src/auth/index.js.map +1 -0
  18. package/dist/src/auth/ws-upgrade-auth.d.ts +30 -0
  19. package/dist/src/auth/ws-upgrade-auth.d.ts.map +1 -0
  20. package/dist/src/auth/ws-upgrade-auth.js +49 -0
  21. package/dist/src/auth/ws-upgrade-auth.js.map +1 -0
  22. package/dist/src/controllers/cli-controller.d.ts +8 -1
  23. package/dist/src/controllers/cli-controller.d.ts.map +1 -1
  24. package/dist/src/controllers/cli-controller.js +78 -3
  25. package/dist/src/controllers/cli-controller.js.map +1 -1
  26. package/dist/src/controllers/cli-version-controller.d.ts +16 -1
  27. package/dist/src/controllers/cli-version-controller.d.ts.map +1 -1
  28. package/dist/src/controllers/cli-version-controller.js +18 -5
  29. package/dist/src/controllers/cli-version-controller.js.map +1 -1
  30. package/dist/src/controllers/filesystem-controller.d.ts.map +1 -1
  31. package/dist/src/controllers/filesystem-controller.js +51 -7
  32. package/dist/src/controllers/filesystem-controller.js.map +1 -1
  33. package/dist/src/create-cli-server.d.ts +76 -5
  34. package/dist/src/create-cli-server.d.ts.map +1 -1
  35. package/dist/src/create-cli-server.js +88 -20
  36. package/dist/src/create-cli-server.js.map +1 -1
  37. package/dist/src/extensions/cli-builder.d.ts +19 -1
  38. package/dist/src/extensions/cli-builder.d.ts.map +1 -1
  39. package/dist/src/extensions/cli-builder.js +26 -0
  40. package/dist/src/extensions/cli-builder.js.map +1 -1
  41. package/dist/src/filesystem/filesystem-options.d.ts +1 -0
  42. package/dist/src/filesystem/filesystem-options.d.ts.map +1 -1
  43. package/dist/src/index.d.ts +5 -4
  44. package/dist/src/index.d.ts.map +1 -1
  45. package/dist/src/index.js +18 -3
  46. package/dist/src/index.js.map +1 -1
  47. package/dist/src/models/cli-server-command-descriptor.d.ts +2 -1
  48. package/dist/src/models/cli-server-command-descriptor.d.ts.map +1 -1
  49. package/dist/src/models/cli-server-output.d.ts +1 -22
  50. package/dist/src/models/cli-server-output.d.ts.map +1 -1
  51. package/dist/src/models/cli-server-response.d.ts +1 -5
  52. package/dist/src/models/cli-server-response.d.ts.map +1 -1
  53. package/dist/src/processors/cli-base64-command-processor.d.ts +1 -0
  54. package/dist/src/processors/cli-base64-command-processor.d.ts.map +1 -1
  55. package/dist/src/processors/cli-base64-command-processor.js +3 -0
  56. package/dist/src/processors/cli-base64-command-processor.js.map +1 -1
  57. package/dist/src/processors/cli-echo-command-processor.d.ts +1 -0
  58. package/dist/src/processors/cli-echo-command-processor.d.ts.map +1 -1
  59. package/dist/src/processors/cli-echo-command-processor.js +1 -0
  60. package/dist/src/processors/cli-echo-command-processor.js.map +1 -1
  61. package/dist/src/processors/cli-hash-command-processor.d.ts +1 -0
  62. package/dist/src/processors/cli-hash-command-processor.d.ts.map +1 -1
  63. package/dist/src/processors/cli-hash-command-processor.js +1 -0
  64. package/dist/src/processors/cli-hash-command-processor.js.map +1 -1
  65. package/dist/src/processors/cli-http-command-processor.d.ts +1 -0
  66. package/dist/src/processors/cli-http-command-processor.d.ts.map +1 -1
  67. package/dist/src/processors/cli-http-command-processor.js +85 -6
  68. package/dist/src/processors/cli-http-command-processor.js.map +1 -1
  69. package/dist/src/processors/cli-status-command-processor.d.ts +1 -0
  70. package/dist/src/processors/cli-status-command-processor.d.ts.map +1 -1
  71. package/dist/src/processors/cli-status-command-processor.js +1 -0
  72. package/dist/src/processors/cli-status-command-processor.js.map +1 -1
  73. package/dist/src/processors/cli-system-command-processor.d.ts +1 -0
  74. package/dist/src/processors/cli-system-command-processor.d.ts.map +1 -1
  75. package/dist/src/processors/cli-system-command-processor.js +1 -0
  76. package/dist/src/processors/cli-system-command-processor.js.map +1 -1
  77. package/dist/src/server.js +20 -6
  78. package/dist/src/server.js.map +1 -1
  79. package/dist/src/services/cli-command-executor-service.d.ts +24 -3
  80. package/dist/src/services/cli-command-executor-service.d.ts.map +1 -1
  81. package/dist/src/services/cli-command-executor-service.js +35 -3
  82. package/dist/src/services/cli-command-executor-service.js.map +1 -1
  83. package/dist/src/services/cli-command-registry.d.ts +11 -0
  84. package/dist/src/services/cli-command-registry.d.ts.map +1 -1
  85. package/dist/src/services/cli-command-registry.js +5 -0
  86. package/dist/src/services/cli-command-registry.js.map +1 -1
  87. package/dist/src/services/cli-event-socket-manager.d.ts +42 -0
  88. package/dist/src/services/cli-event-socket-manager.d.ts.map +1 -1
  89. package/dist/src/services/cli-event-socket-manager.js +139 -27
  90. package/dist/src/services/cli-event-socket-manager.js.map +1 -1
  91. package/dist/src/services/cli-log-socket-manager.d.ts +17 -1
  92. package/dist/src/services/cli-log-socket-manager.d.ts.map +1 -1
  93. package/dist/src/services/cli-log-socket-manager.js +59 -12
  94. package/dist/src/services/cli-log-socket-manager.js.map +1 -1
  95. package/dist/src/services/cli-response-builder.d.ts +9 -0
  96. package/dist/src/services/cli-response-builder.d.ts.map +1 -1
  97. package/dist/src/services/cli-response-builder.js +1 -0
  98. package/dist/src/services/cli-response-builder.js.map +1 -1
  99. package/dist/src/services/cli-shell-options.d.ts +107 -0
  100. package/dist/src/services/cli-shell-options.d.ts.map +1 -0
  101. package/dist/src/services/cli-shell-options.js +139 -0
  102. package/dist/src/services/cli-shell-options.js.map +1 -0
  103. package/dist/src/services/cli-shell-session-manager.d.ts +86 -2
  104. package/dist/src/services/cli-shell-session-manager.d.ts.map +1 -1
  105. package/dist/src/services/cli-shell-session-manager.js +493 -73
  106. package/dist/src/services/cli-shell-session-manager.js.map +1 -1
  107. package/dist/src/services/index.d.ts +2 -1
  108. package/dist/src/services/index.d.ts.map +1 -1
  109. package/dist/src/services/index.js +5 -1
  110. package/dist/src/services/index.js.map +1 -1
  111. package/dist/src/services/process-tree.d.ts +38 -0
  112. package/dist/src/services/process-tree.d.ts.map +1 -0
  113. package/dist/src/services/process-tree.js +249 -0
  114. package/dist/src/services/process-tree.js.map +1 -0
  115. package/dist/src/services/session-bound-sockets.d.ts +45 -0
  116. package/dist/src/services/session-bound-sockets.d.ts.map +1 -0
  117. package/dist/src/services/session-bound-sockets.js +129 -0
  118. package/dist/src/services/session-bound-sockets.js.map +1 -0
  119. package/dist/src/utils/logger.d.ts +11 -0
  120. package/dist/src/utils/logger.d.ts.map +1 -0
  121. package/dist/src/utils/logger.js +13 -0
  122. package/dist/src/utils/logger.js.map +1 -0
  123. package/package.json +12 -3
  124. package/dist/src/controllers/cli-controller-v2.d.ts +0 -4
  125. package/dist/src/controllers/cli-controller-v2.d.ts.map +0 -1
  126. package/dist/src/controllers/cli-controller-v2.js +0 -46
  127. package/dist/src/controllers/cli-controller-v2.js.map +0 -1
@@ -2,6 +2,7 @@ export { ICliCommandRegistry, CliCommandRegistry } from './cli-command-registry'
2
2
  export { ICliResponseBuilder, CliResponseBuilder } from './cli-response-builder';
3
3
  export { ICliCommandExecutorService, CliCommandExecutorService } from './cli-command-executor-service';
4
4
  export { CliEventSocketManager, CliWebSocketClientInfo } from './cli-event-socket-manager';
5
- export { CliShellSessionManager } from './cli-shell-session-manager';
5
+ export { CliShellSessionManager, CliShellSessionInfo } from './cli-shell-session-manager';
6
+ export { CliShellOptions, CliShellEnvOptions, CliShellAuthMode, CliShellAuthorizeContext, ShellCloseCodes, resolveShellAuthMode, buildShellEnv, } from './cli-shell-options';
6
7
  export { CliLogSocketManager, CliLogWebSocketClientInfo } from './cli-log-socket-manager';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AACvG,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AACvG,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EACH,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,aAAa,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CliLogSocketManager = exports.CliShellSessionManager = exports.CliEventSocketManager = exports.CliCommandExecutorService = exports.CliResponseBuilder = exports.CliCommandRegistry = void 0;
3
+ exports.CliLogSocketManager = exports.buildShellEnv = exports.resolveShellAuthMode = exports.ShellCloseCodes = exports.CliShellSessionManager = exports.CliEventSocketManager = exports.CliCommandExecutorService = exports.CliResponseBuilder = exports.CliCommandRegistry = void 0;
4
4
  var cli_command_registry_1 = require("./cli-command-registry");
5
5
  Object.defineProperty(exports, "CliCommandRegistry", { enumerable: true, get: function () { return cli_command_registry_1.CliCommandRegistry; } });
6
6
  var cli_response_builder_1 = require("./cli-response-builder");
@@ -11,6 +11,10 @@ var cli_event_socket_manager_1 = require("./cli-event-socket-manager");
11
11
  Object.defineProperty(exports, "CliEventSocketManager", { enumerable: true, get: function () { return cli_event_socket_manager_1.CliEventSocketManager; } });
12
12
  var cli_shell_session_manager_1 = require("./cli-shell-session-manager");
13
13
  Object.defineProperty(exports, "CliShellSessionManager", { enumerable: true, get: function () { return cli_shell_session_manager_1.CliShellSessionManager; } });
14
+ var cli_shell_options_1 = require("./cli-shell-options");
15
+ Object.defineProperty(exports, "ShellCloseCodes", { enumerable: true, get: function () { return cli_shell_options_1.ShellCloseCodes; } });
16
+ Object.defineProperty(exports, "resolveShellAuthMode", { enumerable: true, get: function () { return cli_shell_options_1.resolveShellAuthMode; } });
17
+ Object.defineProperty(exports, "buildShellEnv", { enumerable: true, get: function () { return cli_shell_options_1.buildShellEnv; } });
14
18
  var cli_log_socket_manager_1 = require("./cli-log-socket-manager");
15
19
  Object.defineProperty(exports, "CliLogSocketManager", { enumerable: true, get: function () { return cli_log_socket_manager_1.CliLogSocketManager; } });
16
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":";;;AAAA,+DAAiF;AAAnD,0HAAA,kBAAkB,OAAA;AAChD,+DAAiF;AAAnD,0HAAA,kBAAkB,OAAA;AAChD,+EAAuG;AAAlE,yIAAA,yBAAyB,OAAA;AAC9D,uEAA2F;AAAlF,iIAAA,qBAAqB,OAAA;AAC9B,yEAAqE;AAA5D,mIAAA,sBAAsB,OAAA;AAC/B,mEAA0F;AAAjF,6HAAA,mBAAmB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":";;;AAAA,+DAAiF;AAAnD,0HAAA,kBAAkB,OAAA;AAChD,+DAAiF;AAAnD,0HAAA,kBAAkB,OAAA;AAChD,+EAAuG;AAAlE,yIAAA,yBAAyB,OAAA;AAC9D,uEAA2F;AAAlF,iIAAA,qBAAqB,OAAA;AAC9B,yEAA0F;AAAjF,mIAAA,sBAAsB,OAAA;AAC/B,yDAQ6B;AAHzB,oHAAA,eAAe,OAAA;AACf,yHAAA,oBAAoB,OAAA;AACpB,kHAAA,aAAa,OAAA;AAEjB,mEAA0F;AAAjF,6HAAA,mBAAmB,OAAA"}
@@ -0,0 +1,38 @@
1
+ /** Delay between SIGHUP/SIGTERM and the final SIGKILL. */
2
+ export declare const PROCESS_TREE_KILL_GRACE_MS = 1000;
3
+ /**
4
+ * Environment variable that tags every process a shell starts. Children inherit
5
+ * it, so processes that escaped the tree (re-parented to init, new session) are
6
+ * still found on cleanup unless they deliberately unset it.
7
+ */
8
+ export declare const SHELL_ID_ENV = "QCLI_SHELL_ID";
9
+ /** A fresh, unguessable shell marker value (128-bit hex). */
10
+ export declare function newShellId(): string;
11
+ /** Linux: does a NUL-separated `/proc/<pid>/environ` contain exactly `QCLI_SHELL_ID=<id>`? */
12
+ export declare function environHasShellId(environ: string, shellId: string): boolean;
13
+ /**
14
+ * macOS / BSD: does a `ps -E -o command=` line (command line followed by the
15
+ * environment, space separated) contain `QCLI_SHELL_ID=<id>` as a whole token?
16
+ */
17
+ export declare function psLineHasShellId(line: string, shellId: string): boolean;
18
+ /** PIDs of every process whose environment carries `QCLI_SHELL_ID=<shellId>`. */
19
+ export declare function findMarkedProcesses(shellId: string): number[];
20
+ /**
21
+ * PIDs of everything a shell started: its process group, (Linux) its session,
22
+ * every descendant of those — including background jobs that interactive
23
+ * shells move to their own process groups and `setsid`/`nohup` children — and,
24
+ * when `shellId` is given, every process carrying the shell's
25
+ * `QCLI_SHELL_ID` marker (and their descendants), which also catches processes
26
+ * re-parented to init in a new session. Never includes `rootPid` itself, the
27
+ * server process or the server's process group.
28
+ */
29
+ export declare function collectProcessTree(rootPid: number, shellId?: string, extraSeeds?: number[]): number[];
30
+ /**
31
+ * Terminates a shell and everything it started (Unix): collects the targets
32
+ * first (the shell's death re-parents its children), then sends SIGHUP and
33
+ * SIGTERM to the shell's process group, the shell and every collected process,
34
+ * and SIGKILL after `graceMs`. The final pass re-collects so that children
35
+ * forked meanwhile by the collected processes die too.
36
+ */
37
+ export declare function terminateProcessTree(rootPid: number, graceMs?: number, shellId?: string): void;
38
+ //# sourceMappingURL=process-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-tree.d.ts","sourceRoot":"","sources":["../../../src/services/process-tree.ts"],"names":[],"mappings":"AAaA,0DAA0D;AAC1D,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,YAAY,kBAAkB,CAAC;AAE5C,6DAA6D;AAC7D,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAID,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG3E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAUvE;AA+BD,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAO7D;AA4ED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAMzG;AAUD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,SAA6B,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAYlH"}
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SHELL_ID_ENV = exports.PROCESS_TREE_KILL_GRACE_MS = void 0;
37
+ exports.newShellId = newShellId;
38
+ exports.environHasShellId = environHasShellId;
39
+ exports.psLineHasShellId = psLineHasShellId;
40
+ exports.findMarkedProcesses = findMarkedProcesses;
41
+ exports.collectProcessTree = collectProcessTree;
42
+ exports.terminateProcessTree = terminateProcessTree;
43
+ const child_process_1 = require("child_process");
44
+ const crypto_1 = require("crypto");
45
+ const fs = __importStar(require("fs"));
46
+ const os = __importStar(require("os"));
47
+ /** Delay between SIGHUP/SIGTERM and the final SIGKILL. */
48
+ exports.PROCESS_TREE_KILL_GRACE_MS = 1000;
49
+ /**
50
+ * Environment variable that tags every process a shell starts. Children inherit
51
+ * it, so processes that escaped the tree (re-parented to init, new session) are
52
+ * still found on cleanup unless they deliberately unset it.
53
+ */
54
+ exports.SHELL_ID_ENV = 'QCLI_SHELL_ID';
55
+ /** A fresh, unguessable shell marker value (128-bit hex). */
56
+ function newShellId() {
57
+ return (0, crypto_1.randomBytes)(16).toString('hex');
58
+ }
59
+ const SHELL_ID_RE = /^[0-9a-f]{32}$/;
60
+ /** Linux: does a NUL-separated `/proc/<pid>/environ` contain exactly `QCLI_SHELL_ID=<id>`? */
61
+ function environHasShellId(environ, shellId) {
62
+ const wanted = `${exports.SHELL_ID_ENV}=${shellId}`;
63
+ return environ.split('\0').some((entry) => entry === wanted);
64
+ }
65
+ /**
66
+ * macOS / BSD: does a `ps -E -o command=` line (command line followed by the
67
+ * environment, space separated) contain `QCLI_SHELL_ID=<id>` as a whole token?
68
+ */
69
+ function psLineHasShellId(line, shellId) {
70
+ const wanted = ` ${exports.SHELL_ID_ENV}=${shellId}`;
71
+ let from = 0;
72
+ for (;;) {
73
+ const at = line.indexOf(wanted, from);
74
+ if (at < 0)
75
+ return false;
76
+ const end = at + wanted.length;
77
+ if (end === line.length || /\s/.test(line[end]))
78
+ return true;
79
+ from = at + 1;
80
+ }
81
+ }
82
+ /** Linux: PIDs whose `/proc/<pid>/environ` carries the marker (unreadable entries are skipped). */
83
+ function markedFromProc(shellId) {
84
+ const found = [];
85
+ for (const name of fs.readdirSync('/proc')) {
86
+ if (!/^\d+$/.test(name))
87
+ continue;
88
+ try {
89
+ if (environHasShellId(fs.readFileSync(`/proc/${name}/environ`, 'latin1'), shellId))
90
+ found.push(Number(name));
91
+ }
92
+ catch {
93
+ // exited, or another user's process
94
+ }
95
+ }
96
+ return found;
97
+ }
98
+ /** macOS / BSD: `ps -A -E -ww -o pid=,command=` shows the environment of the same user's processes. */
99
+ function markedFromPs(shellId) {
100
+ const out = (0, child_process_1.execFileSync)('ps', ['-A', '-E', '-ww', '-o', 'pid=,command='], {
101
+ encoding: 'utf8',
102
+ timeout: 5000,
103
+ maxBuffer: 64 * 1024 * 1024,
104
+ });
105
+ const found = [];
106
+ for (const line of out.split('\n')) {
107
+ const m = /^\s*(\d+)\s/.exec(line);
108
+ if (m && psLineHasShellId(line, shellId))
109
+ found.push(Number(m[1]));
110
+ }
111
+ return found;
112
+ }
113
+ /** PIDs of every process whose environment carries `QCLI_SHELL_ID=<shellId>`. */
114
+ function findMarkedProcesses(shellId) {
115
+ if (!SHELL_ID_RE.test(shellId))
116
+ return [];
117
+ try {
118
+ return isProcLinux() ? markedFromProc(shellId) : markedFromPs(shellId);
119
+ }
120
+ catch {
121
+ return [];
122
+ }
123
+ }
124
+ function isProcLinux() {
125
+ return os.platform() === 'linux' && fs.existsSync('/proc/self/stat');
126
+ }
127
+ /** Linux: `/proc/<pid>/stat` (no `ps` needed, works in slim containers). */
128
+ function readProcTable() {
129
+ const entries = [];
130
+ for (const name of fs.readdirSync('/proc')) {
131
+ if (!/^\d+$/.test(name))
132
+ continue;
133
+ try {
134
+ const stat = fs.readFileSync(`/proc/${name}/stat`, 'utf8');
135
+ // "pid (comm) state ppid pgrp session ..." — comm may contain spaces and parentheses
136
+ const fields = stat.slice(stat.lastIndexOf(')') + 2).split(' ');
137
+ entries.push({ pid: Number(name), ppid: Number(fields[1]), pgid: Number(fields[2]), sid: Number(fields[3]) });
138
+ }
139
+ catch {
140
+ // exited while listing
141
+ }
142
+ }
143
+ return entries;
144
+ }
145
+ /** macOS / BSD: `ps -A -o pid=,ppid=,pgid=`. */
146
+ function readPsTable() {
147
+ const out = (0, child_process_1.execFileSync)('ps', ['-A', '-o', 'pid=,ppid=,pgid='], { encoding: 'utf8', timeout: 5000 });
148
+ const entries = [];
149
+ for (const line of out.split('\n')) {
150
+ const m = /^\s*(\d+)\s+(\d+)\s+(\d+)\s*$/.exec(line);
151
+ if (m)
152
+ entries.push({ pid: Number(m[1]), ppid: Number(m[2]), pgid: Number(m[3]) });
153
+ }
154
+ return entries;
155
+ }
156
+ function readProcessTable() {
157
+ try {
158
+ return isProcLinux() ? readProcTable() : readPsTable();
159
+ }
160
+ catch {
161
+ return [];
162
+ }
163
+ }
164
+ /** `seeds` (except `rootPid`) and all their descendants, by parent PID. */
165
+ function descendants(table, rootPid, seeds) {
166
+ const children = new Map();
167
+ for (const p of table) {
168
+ const list = children.get(p.ppid);
169
+ if (list)
170
+ list.push(p.pid);
171
+ else
172
+ children.set(p.ppid, [p.pid]);
173
+ }
174
+ const found = new Set();
175
+ const queue = [...seeds];
176
+ while (queue.length) {
177
+ const pid = queue.pop();
178
+ if (pid !== rootPid) {
179
+ if (found.has(pid))
180
+ continue;
181
+ found.add(pid);
182
+ }
183
+ for (const child of children.get(pid) ?? []) {
184
+ if (child !== rootPid && !found.has(child))
185
+ queue.push(child);
186
+ }
187
+ }
188
+ found.delete(process.pid);
189
+ const ownPgid = table.find((p) => p.pid === process.pid)?.pgid;
190
+ if (ownPgid !== undefined)
191
+ for (const p of table)
192
+ if (p.pgid === ownPgid)
193
+ found.delete(p.pid);
194
+ return found;
195
+ }
196
+ function treeSeeds(table, rootPid) {
197
+ const seeds = [rootPid];
198
+ for (const p of table) {
199
+ if (p.pgid === rootPid || p.sid === rootPid)
200
+ seeds.push(p.pid);
201
+ }
202
+ return seeds;
203
+ }
204
+ /**
205
+ * PIDs of everything a shell started: its process group, (Linux) its session,
206
+ * every descendant of those — including background jobs that interactive
207
+ * shells move to their own process groups and `setsid`/`nohup` children — and,
208
+ * when `shellId` is given, every process carrying the shell's
209
+ * `QCLI_SHELL_ID` marker (and their descendants), which also catches processes
210
+ * re-parented to init in a new session. Never includes `rootPid` itself, the
211
+ * server process or the server's process group.
212
+ */
213
+ function collectProcessTree(rootPid, shellId, extraSeeds = []) {
214
+ const table = readProcessTable();
215
+ const marked = shellId ? findMarkedProcesses(shellId) : [];
216
+ const alive = new Set(table.map((p) => p.pid));
217
+ const seeds = [...treeSeeds(table, rootPid), ...marked, ...extraSeeds.filter((pid) => alive.has(pid))];
218
+ return [...descendants(table, rootPid, seeds)];
219
+ }
220
+ function signal(pid, sig) {
221
+ try {
222
+ process.kill(pid, sig);
223
+ }
224
+ catch {
225
+ // already gone
226
+ }
227
+ }
228
+ /**
229
+ * Terminates a shell and everything it started (Unix): collects the targets
230
+ * first (the shell's death re-parents its children), then sends SIGHUP and
231
+ * SIGTERM to the shell's process group, the shell and every collected process,
232
+ * and SIGKILL after `graceMs`. The final pass re-collects so that children
233
+ * forked meanwhile by the collected processes die too.
234
+ */
235
+ function terminateProcessTree(rootPid, graceMs = exports.PROCESS_TREE_KILL_GRACE_MS, shellId) {
236
+ const pids = collectProcessTree(rootPid, shellId);
237
+ const send = (targets, sig) => {
238
+ if (rootPid !== process.pid) {
239
+ signal(-rootPid, sig);
240
+ signal(rootPid, sig);
241
+ }
242
+ for (const pid of targets)
243
+ signal(pid, sig);
244
+ };
245
+ send(pids, 'SIGHUP');
246
+ send(pids, 'SIGTERM');
247
+ setTimeout(() => send(collectProcessTree(rootPid, shellId, pids), 'SIGKILL'), graceMs);
248
+ }
249
+ //# sourceMappingURL=process-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-tree.js","sourceRoot":"","sources":["../../../src/services/process-tree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { WebSocket } from 'ws';
2
+ import { CliServerAuthContext, ICliServerAuth } from '../auth/cli-server-auth';
3
+ /** Close code and reason of a socket whose session ended. */
4
+ export declare const SESSION_ENDED_CLOSE_CODE = 4401;
5
+ export declare const SESSION_ENDED_REASON = "session ended";
6
+ export interface SessionBoundSocketsOptions {
7
+ /**
8
+ * Sockets that receive `session-kicked` (the events socket): a revocation
9
+ * closes them only after that event was sent ({@link kicked}), or after a
10
+ * short grace period when it never comes.
11
+ */
12
+ awaitKick?: boolean;
13
+ }
14
+ /**
15
+ * Binds authenticated events/logs WebSockets to the stored session behind
16
+ * their ticket: when it ends (logout, revoke, user disabled/deleted, expiry)
17
+ * the socket is closed with 4401 `session ended`. The auth provider's session
18
+ * events drive it: `session-ended` closes the session's sockets, any other
19
+ * event (users/groups changes, the expiry sweep) re-checks every bound socket.
20
+ * Identities without a stored session (external adapter) are not bound.
21
+ */
22
+ export declare class SessionBoundSockets {
23
+ private readonly _options;
24
+ private readonly _bound;
25
+ private _auth?;
26
+ private _unsubscribe?;
27
+ constructor(_options?: SessionBoundSocketsOptions);
28
+ /** Installs the auth provider and subscribes to its session events. */
29
+ setAuth(auth: ICliServerAuth | undefined): void;
30
+ /** Tracks `ws` when `ctx` comes from a stored session. */
31
+ bind(ws: WebSocket, ctx: CliServerAuthContext | undefined): void;
32
+ unbind(ws: WebSocket): void;
33
+ /** True once the socket's session ended (it must not receive server-wide events any more). */
34
+ isEnding(ws: WebSocket): boolean;
35
+ /** `session-kicked` was delivered to `ws` for its own session: close it now. */
36
+ kicked(ws: WebSocket): void;
37
+ /** Re-checks every bound socket (optionally only `userId`'s) and closes those whose session ended. */
38
+ recheck(userId?: string): Promise<void>;
39
+ dispose(): void;
40
+ private onSessionEvent;
41
+ /** The session behind `ws` ended; `mayBeKicked`: a `session-kicked` event may still follow. */
42
+ private ended;
43
+ private close;
44
+ }
45
+ //# sourceMappingURL=session-bound-sockets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bound-sockets.d.ts","sourceRoot":"","sources":["../../../src/services/session-bound-sockets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/B,OAAO,EAAE,oBAAoB,EAAyB,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAItG,6DAA6D;AAC7D,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAQpD,MAAM,WAAW,0BAA0B;IACvC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AASD;;;;;;;GAOG;AACH,qBAAa,mBAAmB;IAKhB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,KAAK,CAAC,CAAiB;IAC/B,OAAO,CAAC,YAAY,CAAC,CAAa;gBAEL,QAAQ,GAAE,0BAA+B;IAEtE,uEAAuE;IACvE,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI;IAS/C,0DAA0D;IAC1D,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI;IAIhE,MAAM,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAM3B,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO;IAIhC,gFAAgF;IAChF,MAAM,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAI3B,sGAAsG;IAChG,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB7C,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,cAAc;IAUtB,+FAA+F;IAC/F,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,KAAK;CAUhB"}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionBoundSockets = exports.SESSION_ENDED_REASON = exports.SESSION_ENDED_CLOSE_CODE = void 0;
4
+ const ws_1 = require("ws");
5
+ const logger_1 = require("../utils/logger");
6
+ const logger = (0, logger_1.createLogger)('SessionBoundSockets');
7
+ /** Close code and reason of a socket whose session ended. */
8
+ exports.SESSION_ENDED_CLOSE_CODE = 4401;
9
+ exports.SESSION_ENDED_REASON = 'session ended';
10
+ /**
11
+ * How long a socket waits for its `session-kicked` event once its session
12
+ * ended by a revocation (or a re-check found it dead) before it is closed anyway.
13
+ */
14
+ const KICK_GRACE_MS = 1000;
15
+ /**
16
+ * Binds authenticated events/logs WebSockets to the stored session behind
17
+ * their ticket: when it ends (logout, revoke, user disabled/deleted, expiry)
18
+ * the socket is closed with 4401 `session ended`. The auth provider's session
19
+ * events drive it: `session-ended` closes the session's sockets, any other
20
+ * event (users/groups changes, the expiry sweep) re-checks every bound socket.
21
+ * Identities without a stored session (external adapter) are not bound.
22
+ */
23
+ class SessionBoundSockets {
24
+ _options;
25
+ _bound = new Map();
26
+ _auth;
27
+ _unsubscribe;
28
+ constructor(_options = {}) {
29
+ this._options = _options;
30
+ }
31
+ /** Installs the auth provider and subscribes to its session events. */
32
+ setAuth(auth) {
33
+ this._unsubscribe?.();
34
+ this._unsubscribe = undefined;
35
+ this._auth = auth;
36
+ if (auth?.onSessionEvent) {
37
+ this._unsubscribe = auth.onSessionEvent((event) => this.onSessionEvent(event));
38
+ }
39
+ }
40
+ /** Tracks `ws` when `ctx` comes from a stored session. */
41
+ bind(ws, ctx) {
42
+ if (ctx?.sessionId)
43
+ this._bound.set(ws, { ctx });
44
+ }
45
+ unbind(ws) {
46
+ const entry = this._bound.get(ws);
47
+ if (entry?.ending)
48
+ clearTimeout(entry.ending);
49
+ this._bound.delete(ws);
50
+ }
51
+ /** True once the socket's session ended (it must not receive server-wide events any more). */
52
+ isEnding(ws) {
53
+ return !!this._bound.get(ws)?.ending;
54
+ }
55
+ /** `session-kicked` was delivered to `ws` for its own session: close it now. */
56
+ kicked(ws) {
57
+ this.close(ws);
58
+ }
59
+ /** Re-checks every bound socket (optionally only `userId`'s) and closes those whose session ended. */
60
+ async recheck(userId) {
61
+ const auth = this._auth;
62
+ if (!auth?.revalidate)
63
+ return;
64
+ const checks = [];
65
+ for (const [ws, entry] of this._bound) {
66
+ if (entry.ending || entry.checking || (userId && entry.ctx.userId !== userId))
67
+ continue;
68
+ entry.checking = true;
69
+ checks.push((async () => {
70
+ let alive;
71
+ try {
72
+ alive = !!(await auth.revalidate(entry.ctx));
73
+ }
74
+ catch (err) {
75
+ logger.warn('Socket session check failed; closing the socket: %s', err?.message ?? err);
76
+ alive = false;
77
+ }
78
+ entry.checking = false;
79
+ if (!alive && this._bound.get(ws) === entry)
80
+ this.ended(ws, entry, true);
81
+ })());
82
+ }
83
+ await Promise.all(checks);
84
+ }
85
+ dispose() {
86
+ this._unsubscribe?.();
87
+ this._unsubscribe = undefined;
88
+ for (const entry of this._bound.values()) {
89
+ if (entry.ending)
90
+ clearTimeout(entry.ending);
91
+ }
92
+ this._bound.clear();
93
+ }
94
+ onSessionEvent(event) {
95
+ if (event.type === 'session-ended') {
96
+ for (const [ws, entry] of [...this._bound]) {
97
+ if (entry.ctx.sessionId === event.sessionId)
98
+ this.ended(ws, entry, !!event.revoked);
99
+ }
100
+ }
101
+ else {
102
+ void this.recheck(event.userId);
103
+ }
104
+ }
105
+ /** The session behind `ws` ended; `mayBeKicked`: a `session-kicked` event may still follow. */
106
+ ended(ws, entry, mayBeKicked) {
107
+ if (!this._options.awaitKick || !mayBeKicked) {
108
+ this.close(ws);
109
+ return;
110
+ }
111
+ if (entry.ending)
112
+ return;
113
+ entry.ending = setTimeout(() => this.close(ws), KICK_GRACE_MS);
114
+ entry.ending.unref?.();
115
+ }
116
+ close(ws) {
117
+ this.unbind(ws);
118
+ if (ws.readyState === ws_1.WebSocket.OPEN || ws.readyState === ws_1.WebSocket.CONNECTING) {
119
+ try {
120
+ ws.close(exports.SESSION_ENDED_CLOSE_CODE, exports.SESSION_ENDED_REASON);
121
+ }
122
+ catch {
123
+ ws.terminate();
124
+ }
125
+ }
126
+ }
127
+ }
128
+ exports.SessionBoundSockets = SessionBoundSockets;
129
+ //# sourceMappingURL=session-bound-sockets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bound-sockets.js","sourceRoot":"","sources":["../../../src/services/session-bound-sockets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Simple structured logger with category prefixes.
3
+ */
4
+ export interface Logger {
5
+ debug(message: string, ...args: unknown[]): void;
6
+ info(message: string, ...args: unknown[]): void;
7
+ warn(message: string, ...args: unknown[]): void;
8
+ error(message: string, ...args: unknown[]): void;
9
+ }
10
+ export declare function createLogger(category: string): Logger;
11
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,MAAM;IACnB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACpD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrD"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLogger = createLogger;
4
+ function createLogger(category) {
5
+ const prefix = `[${category}]`;
6
+ return {
7
+ debug: (msg, ...args) => console.debug(`${prefix} ${msg}`, ...args),
8
+ info: (msg, ...args) => console.log(`${prefix} ${msg}`, ...args),
9
+ warn: (msg, ...args) => console.warn(`${prefix} ${msg}`, ...args),
10
+ error: (msg, ...args) => console.error(`${prefix} ${msg}`, ...args),
11
+ };
12
+ }
13
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":";;AAUA,oCAQC;AARD,SAAgB,YAAY,CAAC,QAAgB;IACzC,MAAM,MAAM,GAAG,IAAI,QAAQ,GAAG,CAAC;IAC/B,OAAO;QACH,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QACnE,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QAChE,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QACjE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;KACtE,CAAC;AACN,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qodalis/cli-server-node",
3
- "version": "1.0.0-beta.4",
3
+ "version": "1.0.0-beta.6",
4
4
  "description": "Node.js CLI server for Qodalis CLI ecosystem — use as a library in existing Express apps or run standalone",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -38,6 +38,7 @@
38
38
  "homepage": "https://qodalis.com/",
39
39
  "dependencies": {
40
40
  "@qodalis/cli-server-abstractions": "file:packages/abstractions",
41
+ "@qodalis/cli-server-plugin-data-explorer": "file:plugins/data-explorer",
41
42
  "@qodalis/cli-server-plugin-filesystem": "file:plugins/filesystem",
42
43
  "@qodalis/cli-server-plugin-jobs": "file:plugins/jobs",
43
44
  "cors": "^2.8.5",
@@ -47,17 +48,25 @@
47
48
  "ws": "^8.18.0"
48
49
  },
49
50
  "optionalDependencies": {
51
+ "@elastic/elasticsearch": "^8.16.0",
50
52
  "@qodalis/cli-server-plugin-filesystem-json": "file:plugins/filesystem-json",
51
53
  "@qodalis/cli-server-plugin-filesystem-s3": "file:plugins/filesystem-s3",
52
54
  "@qodalis/cli-server-plugin-filesystem-sqlite": "file:plugins/filesystem-sqlite",
53
- "better-sqlite3": "^11.0.0"
55
+ "better-sqlite3": "^11.10.0",
56
+ "ioredis": "^5.4.0",
57
+ "mongodb": "^6.0.0",
58
+ "mssql": "^11.0.0",
59
+ "mysql2": "^3.11.0",
60
+ "pg": "^8.13.0"
54
61
  },
55
62
  "devDependencies": {
56
- "@types/better-sqlite3": "^7.6.0",
63
+ "@types/better-sqlite3": "^7.6.13",
57
64
  "@types/cors": "^2.8.17",
58
65
  "@types/express": "^4.17.21",
66
+ "@types/mssql": "^9.1.9",
59
67
  "@types/multer": "^2.0.0",
60
68
  "@types/node": "^22.0.0",
69
+ "@types/pg": "^8.0.0",
61
70
  "@types/supertest": "^7.2.0",
62
71
  "@types/ws": "^8.5.13",
63
72
  "supertest": "^7.2.2",
@@ -1,4 +0,0 @@
1
- import { Router } from 'express';
2
- import { ICliCommandRegistry, ICliCommandExecutorService } from '../services';
3
- export declare function createCliControllerV2(registry: ICliCommandRegistry, executor: ICliCommandExecutorService): Router;
4
- //# sourceMappingURL=cli-controller-v2.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-controller-v2.d.ts","sourceRoot":"","sources":["../../../src/controllers/cli-controller-v2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAI9E,wBAAgB,qBAAqB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,QAAQ,EAAE,0BAA0B,GACrC,MAAM,CAqBR"}