@nu-art/commando 0.400.14 → 0.401.1
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/cli-params/CLIParamsResolver.d.ts +56 -3
- package/cli-params/CLIParamsResolver.js +61 -4
- package/cli-params/consts.d.ts +37 -0
- package/cli-params/consts.js +38 -1
- package/cli-params/types.d.ts +29 -1
- package/package.json +23 -11
- package/shell/core/BaseCommando.d.ts +36 -6
- package/shell/core/BaseCommando.js +36 -6
- package/shell/core/CliError.d.ts +35 -0
- package/shell/core/CliError.js +36 -1
- package/shell/core/CommandBuilder.d.ts +27 -2
- package/shell/core/CommandBuilder.js +32 -3
- package/shell/core/CommandoPool.d.ts +33 -0
- package/shell/core/CommandoPool.js +34 -0
- package/shell/core/class-merger.d.ts +29 -10
- package/shell/core/class-merger.js +23 -8
- package/shell/interactive/CommandoInteractive.d.ts +66 -6
- package/shell/interactive/CommandoInteractive.js +69 -6
- package/shell/interactive/InteractiveShell.d.ts +38 -0
- package/shell/interactive/InteractiveShell.js +25 -0
- package/shell/plugins/basic.d.ts +90 -9
- package/shell/plugins/basic.js +90 -9
- package/shell/plugins/git.d.ts +115 -0
- package/shell/plugins/git.js +124 -9
- package/shell/plugins/nvm.d.ts +47 -0
- package/shell/plugins/nvm.js +47 -0
- package/shell/plugins/pnpm.d.ts +31 -0
- package/shell/plugins/pnpm.js +31 -0
- package/shell/plugins/programming.d.ts +23 -3
- package/shell/plugins/programming.js +23 -3
- package/shell/plugins/python.d.ts +31 -0
- package/shell/plugins/python.js +32 -0
- package/shell/services/nvm.d.ts +59 -1
- package/shell/services/nvm.js +67 -6
- package/shell/services/pnpm.d.ts +41 -0
- package/shell/services/pnpm.js +41 -0
- package/shell/simple/Commando.d.ts +75 -0
- package/shell/simple/Commando.js +75 -0
- package/shell/simple/SimpleShell.d.ts +29 -2
- package/shell/simple/SimpleShell.js +32 -2
- package/shell/tools.d.ts +30 -0
- package/shell/tools.js +30 -0
- package/shell/types.d.ts +14 -0
|
@@ -5,9 +5,26 @@ const defaultOptions = {
|
|
|
5
5
|
newlineDelimiter: '\n',
|
|
6
6
|
indentation: 2,
|
|
7
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* Builds shell commands with indentation and formatting support.
|
|
10
|
+
*
|
|
11
|
+
* Accumulates commands in an array and formats them with proper indentation.
|
|
12
|
+
* Supports custom newline delimiters and indentation levels. Commands can
|
|
13
|
+
* be split across multiple lines using the newline delimiter.
|
|
14
|
+
*
|
|
15
|
+
* **Behavior**:
|
|
16
|
+
* - Commands are trimmed before adding
|
|
17
|
+
* - Empty commands are preserved (for spacing)
|
|
18
|
+
* - Indentation is applied per line when commands contain newlines
|
|
19
|
+
* - `reset()` returns the accumulated command and clears the builder
|
|
20
|
+
*/
|
|
8
21
|
export class CommandBuilder {
|
|
9
|
-
|
|
22
|
+
initialCommands = [];
|
|
23
|
+
/** Array of accumulated command strings */
|
|
24
|
+
commands;
|
|
25
|
+
/** Current indentation level (number of indent steps) */
|
|
10
26
|
indentation = 0;
|
|
27
|
+
/** Configuration options for formatting */
|
|
11
28
|
option = defaultOptions;
|
|
12
29
|
/**
|
|
13
30
|
* Constructs a CommandBuilder instance with given options.
|
|
@@ -15,6 +32,7 @@ export class CommandBuilder {
|
|
|
15
32
|
*/
|
|
16
33
|
constructor(options = defaultOptions) {
|
|
17
34
|
this.option = options;
|
|
35
|
+
this.commands = [...this.initialCommands];
|
|
18
36
|
}
|
|
19
37
|
/**
|
|
20
38
|
* Generates a string of spaces for indentation based on the current indentation level.
|
|
@@ -23,6 +41,9 @@ export class CommandBuilder {
|
|
|
23
41
|
getIndentation = () => {
|
|
24
42
|
return ' '.repeat(this.option.indentation * this.indentation);
|
|
25
43
|
};
|
|
44
|
+
setMark() {
|
|
45
|
+
this.initialCommands = [...this.commands];
|
|
46
|
+
}
|
|
26
47
|
/**
|
|
27
48
|
* Increases the current indentation level by one.
|
|
28
49
|
*/
|
|
@@ -45,8 +66,15 @@ export class CommandBuilder {
|
|
|
45
66
|
}
|
|
46
67
|
/**
|
|
47
68
|
* Appends a command to the command list with proper indentation.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
69
|
+
*
|
|
70
|
+
* **Behavior**:
|
|
71
|
+
* - Splits the command by the newline delimiter (allows multi-line commands)
|
|
72
|
+
* - Trims each line
|
|
73
|
+
* - Applies current indentation to non-empty lines
|
|
74
|
+
* - Preserves empty lines as-is (for spacing)
|
|
75
|
+
*
|
|
76
|
+
* @param command - Command string to append (can contain newlines)
|
|
77
|
+
* @returns This instance for method chaining
|
|
50
78
|
*/
|
|
51
79
|
append = (command) => {
|
|
52
80
|
const commands = command.split(this.option.newlineDelimiter);
|
|
@@ -73,6 +101,7 @@ export class CommandBuilder {
|
|
|
73
101
|
reset() {
|
|
74
102
|
const command = this.getCommand();
|
|
75
103
|
this.commands.length = 0;
|
|
104
|
+
this.commands.push(...this.initialCommands);
|
|
76
105
|
return command;
|
|
77
106
|
}
|
|
78
107
|
}
|
|
@@ -3,7 +3,40 @@ import { CommandoInteractive } from '../interactive/CommandoInteractive.js';
|
|
|
3
3
|
import { BaseCommando } from './BaseCommando.js';
|
|
4
4
|
import { Commando_Basic } from '../plugins/basic.js';
|
|
5
5
|
import { MergeTypes } from './class-merger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Pool manager for Commando instances with lifecycle management.
|
|
8
|
+
*
|
|
9
|
+
* Tracks all allocated Commando instances and provides a way to kill
|
|
10
|
+
* all of them at once. Useful for cleanup in long-running processes
|
|
11
|
+
* or test teardown.
|
|
12
|
+
*
|
|
13
|
+
* **Behavior**:
|
|
14
|
+
* - All allocated commandos are stored in an internal pool
|
|
15
|
+
* - `allocateCommando()` always includes Commando_Basic plugin
|
|
16
|
+
* - `killAll()` terminates all tracked commandos asynchronously
|
|
17
|
+
*
|
|
18
|
+
* **Use Case**: Managing multiple interactive commandos that need
|
|
19
|
+
* to be cleaned up together (e.g., test suites, long-running scripts).
|
|
20
|
+
*/
|
|
6
21
|
export declare const CommandoPool: {
|
|
22
|
+
/**
|
|
23
|
+
* Allocates a new Commando instance and adds it to the pool.
|
|
24
|
+
*
|
|
25
|
+
* Creates a CommandoInteractive instance with the provided plugins
|
|
26
|
+
* plus Commando_Basic (always included). The instance is tracked
|
|
27
|
+
* in the pool for later cleanup.
|
|
28
|
+
*
|
|
29
|
+
* @template T - Array of plugin constructor types
|
|
30
|
+
* @param uid - Unique identifier for this commando instance
|
|
31
|
+
* @param plugins - Plugin classes to merge with the commando
|
|
32
|
+
* @returns Merged commando instance with all plugins
|
|
33
|
+
*/
|
|
7
34
|
allocateCommando: <T extends Constructor<any>[]>(uid: string, ...plugins: T) => MergeTypes<[...T]> & CommandoInteractive & BaseCommando & Commando_Basic;
|
|
35
|
+
/**
|
|
36
|
+
* Kills all allocated commando instances.
|
|
37
|
+
*
|
|
38
|
+
* Calls `kill()` on all commandos in the pool asynchronously.
|
|
39
|
+
* Useful for cleanup in test teardown or application shutdown.
|
|
40
|
+
*/
|
|
8
41
|
killAll: () => Promise<void>;
|
|
9
42
|
};
|
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
import { CommandoInteractive } from '../interactive/CommandoInteractive.js';
|
|
2
2
|
import { Commando_Basic } from '../plugins/basic.js';
|
|
3
|
+
/** Internal pool of allocated commando instances */
|
|
3
4
|
const commandoPool = [];
|
|
5
|
+
/**
|
|
6
|
+
* Pool manager for Commando instances with lifecycle management.
|
|
7
|
+
*
|
|
8
|
+
* Tracks all allocated Commando instances and provides a way to kill
|
|
9
|
+
* all of them at once. Useful for cleanup in long-running processes
|
|
10
|
+
* or test teardown.
|
|
11
|
+
*
|
|
12
|
+
* **Behavior**:
|
|
13
|
+
* - All allocated commandos are stored in an internal pool
|
|
14
|
+
* - `allocateCommando()` always includes Commando_Basic plugin
|
|
15
|
+
* - `killAll()` terminates all tracked commandos asynchronously
|
|
16
|
+
*
|
|
17
|
+
* **Use Case**: Managing multiple interactive commandos that need
|
|
18
|
+
* to be cleaned up together (e.g., test suites, long-running scripts).
|
|
19
|
+
*/
|
|
4
20
|
export const CommandoPool = {
|
|
21
|
+
/**
|
|
22
|
+
* Allocates a new Commando instance and adds it to the pool.
|
|
23
|
+
*
|
|
24
|
+
* Creates a CommandoInteractive instance with the provided plugins
|
|
25
|
+
* plus Commando_Basic (always included). The instance is tracked
|
|
26
|
+
* in the pool for later cleanup.
|
|
27
|
+
*
|
|
28
|
+
* @template T - Array of plugin constructor types
|
|
29
|
+
* @param uid - Unique identifier for this commando instance
|
|
30
|
+
* @param plugins - Plugin classes to merge with the commando
|
|
31
|
+
* @returns Merged commando instance with all plugins
|
|
32
|
+
*/
|
|
5
33
|
allocateCommando: (uid, ...plugins) => {
|
|
6
34
|
const commando = CommandoInteractive.create(...plugins, Commando_Basic);
|
|
7
35
|
commando.setUID(uid);
|
|
8
36
|
commandoPool.push(commando);
|
|
9
37
|
return commando;
|
|
10
38
|
},
|
|
39
|
+
/**
|
|
40
|
+
* Kills all allocated commando instances.
|
|
41
|
+
*
|
|
42
|
+
* Calls `kill()` on all commandos in the pool asynchronously.
|
|
43
|
+
* Useful for cleanup in test teardown or application shutdown.
|
|
44
|
+
*/
|
|
11
45
|
killAll: async () => {
|
|
12
46
|
await Promise.all(commandoPool.map(c => c.kill()));
|
|
13
47
|
}
|
|
@@ -1,20 +1,39 @@
|
|
|
1
1
|
import { Constructor } from '@nu-art/ts-common';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Recursively merges the instance types of multiple constructors.
|
|
4
|
+
*
|
|
5
|
+
* Creates an intersection type of all constructor instance types.
|
|
6
|
+
* Used for the plugin system to combine multiple classes into one.
|
|
7
|
+
*
|
|
8
|
+
* @template T - Array of constructor types
|
|
5
9
|
*/
|
|
6
10
|
export type MergeTypes<T extends Constructor<any>[]> = T extends [a: Constructor<infer A>, ...rest: infer R] ? R extends Constructor<any>[] ? A & MergeTypes<R> : {} : {};
|
|
7
11
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
+
* Merges multiple classes into a single class constructor.
|
|
13
|
+
*
|
|
14
|
+
* Creates a new class that combines all properties and methods from
|
|
15
|
+
* the provided plugin classes. Properties are copied from prototype
|
|
16
|
+
* descriptors during construction.
|
|
17
|
+
*
|
|
18
|
+
* **Use Case**: Plugin system for Commando - allows combining
|
|
19
|
+
* BaseCommando with plugin classes (e.g., Commando_Git, Commando_NVM).
|
|
20
|
+
*
|
|
21
|
+
* **Limitation**: Only copies own properties from prototypes, not
|
|
22
|
+
* inherited properties or static members.
|
|
23
|
+
*
|
|
24
|
+
* @template T - Array of constructor types
|
|
25
|
+
* @param plugins - Constructor classes to merge
|
|
26
|
+
* @returns New constructor that merges all plugin classes
|
|
12
27
|
*/
|
|
13
28
|
export declare function MergeClass<T extends Constructor<any>[]>(...plugins: T): Constructor<MergeTypes<T>>;
|
|
14
29
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
30
|
+
* Creates an instance of a merged class from multiple constructors.
|
|
31
|
+
*
|
|
32
|
+
* Convenience function that merges classes and immediately instantiates
|
|
33
|
+
* the result. Used by BaseCommando._create() to create plugin instances.
|
|
34
|
+
*
|
|
35
|
+
* @template T - Array of constructor types
|
|
36
|
+
* @param plugins - Constructor classes to merge and instantiate
|
|
37
|
+
* @returns Instance of the merged class
|
|
19
38
|
*/
|
|
20
39
|
export declare function CreateMergedInstance<T extends Constructor<any>[]>(...plugins: T): MergeTypes<T>;
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Merges multiple classes into a single class constructor.
|
|
3
|
+
*
|
|
4
|
+
* Creates a new class that combines all properties and methods from
|
|
5
|
+
* the provided plugin classes. Properties are copied from prototype
|
|
6
|
+
* descriptors during construction.
|
|
7
|
+
*
|
|
8
|
+
* **Use Case**: Plugin system for Commando - allows combining
|
|
9
|
+
* BaseCommando with plugin classes (e.g., Commando_Git, Commando_NVM).
|
|
10
|
+
*
|
|
11
|
+
* **Limitation**: Only copies own properties from prototypes, not
|
|
12
|
+
* inherited properties or static members.
|
|
13
|
+
*
|
|
14
|
+
* @template T - Array of constructor types
|
|
15
|
+
* @param plugins - Constructor classes to merge
|
|
16
|
+
* @returns New constructor that merges all plugin classes
|
|
6
17
|
*/
|
|
7
18
|
export function MergeClass(...plugins) {
|
|
8
19
|
class SuperClass {
|
|
@@ -24,10 +35,14 @@ export function MergeClass(...plugins) {
|
|
|
24
35
|
return SuperClass;
|
|
25
36
|
}
|
|
26
37
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
38
|
+
* Creates an instance of a merged class from multiple constructors.
|
|
39
|
+
*
|
|
40
|
+
* Convenience function that merges classes and immediately instantiates
|
|
41
|
+
* the result. Used by BaseCommando._create() to create plugin instances.
|
|
42
|
+
*
|
|
43
|
+
* @template T - Array of constructor types
|
|
44
|
+
* @param plugins - Constructor classes to merge and instantiate
|
|
45
|
+
* @returns Instance of the merged class
|
|
31
46
|
*/
|
|
32
47
|
export function CreateMergedInstance(...plugins) {
|
|
33
48
|
const SuperClass = MergeClass(...plugins);
|
|
@@ -2,12 +2,37 @@ import { Constructor, LogLevel } from '@nu-art/ts-common';
|
|
|
2
2
|
import { ShellLogProcessor, ShellPidListener } from './InteractiveShell.js';
|
|
3
3
|
import { LogTypes } from '../types.js';
|
|
4
4
|
import { BaseCommando } from '../core/BaseCommando.js';
|
|
5
|
+
/**
|
|
6
|
+
* Interactive shell command executor extending BaseCommando.
|
|
7
|
+
*
|
|
8
|
+
* Maintains a persistent bash session and executes commands in sequence,
|
|
9
|
+
* allowing state to persist between commands. Provides advanced features:
|
|
10
|
+
* - Log processing and filtering
|
|
11
|
+
* - Exit code extraction
|
|
12
|
+
* - Background process management
|
|
13
|
+
* - PID tracking for subprocesses
|
|
14
|
+
*
|
|
15
|
+
* **Key Differences from Commando**:
|
|
16
|
+
* - Uses InteractiveShell (persistent session) vs SimpleShell (one-shot)
|
|
17
|
+
* - Commands execute in the same shell context (variables persist)
|
|
18
|
+
* - Supports log processors for reactive command execution
|
|
19
|
+
* - Can run background processes and track their PIDs
|
|
20
|
+
*
|
|
21
|
+
* **Exit Code Extraction**:
|
|
22
|
+
* Uses a unique key pattern (`echo ${key}=$?`) to extract exit codes
|
|
23
|
+
* from both stdout and stderr, ensuring accurate exit code detection.
|
|
24
|
+
*/
|
|
5
25
|
export declare class CommandoInteractive extends BaseCommando {
|
|
26
|
+
/** Interactive shell instance managing the persistent session */
|
|
6
27
|
private shell;
|
|
7
28
|
/**
|
|
8
|
-
* Creates a
|
|
9
|
-
*
|
|
10
|
-
*
|
|
29
|
+
* Creates a CommandoInteractive instance with plugins.
|
|
30
|
+
*
|
|
31
|
+
* Initializes the InteractiveShell after merging plugins.
|
|
32
|
+
*
|
|
33
|
+
* @template T - Array of plugin constructor types
|
|
34
|
+
* @param plugins - Plugin classes to merge
|
|
35
|
+
* @returns Merged CommandoInteractive instance with plugins
|
|
11
36
|
*/
|
|
12
37
|
static create<T extends Constructor<any>[]>(...plugins: T): import("../core/class-merger.js").MergeTypes<[typeof BaseCommando, typeof CommandoInteractive, ...T]> & BaseCommando & CommandoInteractive;
|
|
13
38
|
/**
|
|
@@ -50,9 +75,27 @@ export declare class CommandoInteractive extends BaseCommando {
|
|
|
50
75
|
*/
|
|
51
76
|
onLog(filter: string | RegExp, callback: (match: RegExpMatchArray) => any): this;
|
|
52
77
|
/**
|
|
53
|
-
* Executes commands and
|
|
54
|
-
*
|
|
55
|
-
*
|
|
78
|
+
* Executes accumulated commands and extracts exit code from shell output.
|
|
79
|
+
*
|
|
80
|
+
* **Exit Code Extraction Strategy**:
|
|
81
|
+
* - Appends `echo ${uniqueKey}=$?` to both stdout and stderr
|
|
82
|
+
* - Uses log processors to detect the unique key pattern
|
|
83
|
+
* - Waits for both outputs (stdout and stderr) to capture exit code
|
|
84
|
+
* - Falls back to shell close event if pattern not detected
|
|
85
|
+
*
|
|
86
|
+
* **Log Processing**:
|
|
87
|
+
* - Adds temporary log processors to capture stdout/stderr
|
|
88
|
+
* - Accumulates all output until exit code is detected
|
|
89
|
+
* - Removes processors after execution (in finally block)
|
|
90
|
+
*
|
|
91
|
+
* **Behavior**:
|
|
92
|
+
* - Resolves when exit code is detected or shell closes
|
|
93
|
+
* - Calls callback with accumulated stdout, stderr, and exit code
|
|
94
|
+
* - Always cleans up log processors (even on error)
|
|
95
|
+
*
|
|
96
|
+
* @template T - Return type of callback
|
|
97
|
+
* @param callback - Function to process command output
|
|
98
|
+
* @returns Promise resolving to callback result
|
|
56
99
|
*/
|
|
57
100
|
execute<T>(callback?: (stdout: string, stderr: string, exitCode: number) => T): Promise<T>;
|
|
58
101
|
/**
|
|
@@ -75,6 +118,23 @@ export declare class CommandoInteractive extends BaseCommando {
|
|
|
75
118
|
* @returns {this} - The CommandoInteractive instance for method chaining.
|
|
76
119
|
*/
|
|
77
120
|
append(command: string): this;
|
|
121
|
+
mark(): this;
|
|
122
|
+
/**
|
|
123
|
+
* Appends a command to run in the background and tracks its PID.
|
|
124
|
+
*
|
|
125
|
+
* **Behavior**:
|
|
126
|
+
* - Runs command with `&` (background)
|
|
127
|
+
* - Captures PID using `pid=$!` and echoes it with unique key
|
|
128
|
+
* - Waits for the process to complete
|
|
129
|
+
* - Calls pidListener when PID is detected
|
|
130
|
+
*
|
|
131
|
+
* **Use Case**: Running long-running processes while continuing
|
|
132
|
+
* to execute other commands in the same shell session.
|
|
133
|
+
*
|
|
134
|
+
* @param command - Command to run in background
|
|
135
|
+
* @param pidListener - Optional callback when PID is detected
|
|
136
|
+
* @returns This instance for method chaining
|
|
137
|
+
*/
|
|
78
138
|
appendAsync(command: string, pidListener?: ShellPidListener): this;
|
|
79
139
|
getCommand(): string;
|
|
80
140
|
}
|
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
import { generateHex } from '@nu-art/ts-common';
|
|
2
2
|
import { InteractiveShell } from './InteractiveShell.js';
|
|
3
3
|
import { BaseCommando } from '../core/BaseCommando.js';
|
|
4
|
+
/**
|
|
5
|
+
* Interactive shell command executor extending BaseCommando.
|
|
6
|
+
*
|
|
7
|
+
* Maintains a persistent bash session and executes commands in sequence,
|
|
8
|
+
* allowing state to persist between commands. Provides advanced features:
|
|
9
|
+
* - Log processing and filtering
|
|
10
|
+
* - Exit code extraction
|
|
11
|
+
* - Background process management
|
|
12
|
+
* - PID tracking for subprocesses
|
|
13
|
+
*
|
|
14
|
+
* **Key Differences from Commando**:
|
|
15
|
+
* - Uses InteractiveShell (persistent session) vs SimpleShell (one-shot)
|
|
16
|
+
* - Commands execute in the same shell context (variables persist)
|
|
17
|
+
* - Supports log processors for reactive command execution
|
|
18
|
+
* - Can run background processes and track their PIDs
|
|
19
|
+
*
|
|
20
|
+
* **Exit Code Extraction**:
|
|
21
|
+
* Uses a unique key pattern (`echo ${key}=$?`) to extract exit codes
|
|
22
|
+
* from both stdout and stderr, ensuring accurate exit code detection.
|
|
23
|
+
*/
|
|
4
24
|
export class CommandoInteractive extends BaseCommando {
|
|
25
|
+
/** Interactive shell instance managing the persistent session */
|
|
5
26
|
shell;
|
|
6
27
|
/**
|
|
7
|
-
* Creates a
|
|
8
|
-
*
|
|
9
|
-
*
|
|
28
|
+
* Creates a CommandoInteractive instance with plugins.
|
|
29
|
+
*
|
|
30
|
+
* Initializes the InteractiveShell after merging plugins.
|
|
31
|
+
*
|
|
32
|
+
* @template T - Array of plugin constructor types
|
|
33
|
+
* @param plugins - Plugin classes to merge
|
|
34
|
+
* @returns Merged CommandoInteractive instance with plugins
|
|
10
35
|
*/
|
|
11
36
|
static create(...plugins) {
|
|
12
37
|
const _commando = BaseCommando._create(CommandoInteractive, ...plugins);
|
|
@@ -80,9 +105,27 @@ export class CommandoInteractive extends BaseCommando {
|
|
|
80
105
|
return this;
|
|
81
106
|
}
|
|
82
107
|
/**
|
|
83
|
-
* Executes commands and
|
|
84
|
-
*
|
|
85
|
-
*
|
|
108
|
+
* Executes accumulated commands and extracts exit code from shell output.
|
|
109
|
+
*
|
|
110
|
+
* **Exit Code Extraction Strategy**:
|
|
111
|
+
* - Appends `echo ${uniqueKey}=$?` to both stdout and stderr
|
|
112
|
+
* - Uses log processors to detect the unique key pattern
|
|
113
|
+
* - Waits for both outputs (stdout and stderr) to capture exit code
|
|
114
|
+
* - Falls back to shell close event if pattern not detected
|
|
115
|
+
*
|
|
116
|
+
* **Log Processing**:
|
|
117
|
+
* - Adds temporary log processors to capture stdout/stderr
|
|
118
|
+
* - Accumulates all output until exit code is detected
|
|
119
|
+
* - Removes processors after execution (in finally block)
|
|
120
|
+
*
|
|
121
|
+
* **Behavior**:
|
|
122
|
+
* - Resolves when exit code is detected or shell closes
|
|
123
|
+
* - Calls callback with accumulated stdout, stderr, and exit code
|
|
124
|
+
* - Always cleans up log processors (even on error)
|
|
125
|
+
*
|
|
126
|
+
* @template T - Return type of callback
|
|
127
|
+
* @param callback - Function to process command output
|
|
128
|
+
* @returns Promise resolving to callback result
|
|
86
129
|
*/
|
|
87
130
|
async execute(callback) {
|
|
88
131
|
let logProcessor;
|
|
@@ -171,6 +214,26 @@ export class CommandoInteractive extends BaseCommando {
|
|
|
171
214
|
this.builder.append(command);
|
|
172
215
|
return this;
|
|
173
216
|
}
|
|
217
|
+
mark() {
|
|
218
|
+
this.builder.setMark();
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Appends a command to run in the background and tracks its PID.
|
|
223
|
+
*
|
|
224
|
+
* **Behavior**:
|
|
225
|
+
* - Runs command with `&` (background)
|
|
226
|
+
* - Captures PID using `pid=$!` and echoes it with unique key
|
|
227
|
+
* - Waits for the process to complete
|
|
228
|
+
* - Calls pidListener when PID is detected
|
|
229
|
+
*
|
|
230
|
+
* **Use Case**: Running long-running processes while continuing
|
|
231
|
+
* to execute other commands in the same shell session.
|
|
232
|
+
*
|
|
233
|
+
* @param command - Command to run in background
|
|
234
|
+
* @param pidListener - Optional callback when PID is detected
|
|
235
|
+
* @returns This instance for method chaining
|
|
236
|
+
*/
|
|
174
237
|
appendAsync(command, pidListener) {
|
|
175
238
|
const pidUniqueKey = generateHex(16);
|
|
176
239
|
const regexp = new RegExp(`${pidUniqueKey}=(\\d+)`);
|
|
@@ -1,8 +1,46 @@
|
|
|
1
1
|
import { Logger, LogLevel } from '@nu-art/ts-common';
|
|
2
2
|
import { LogTypes } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Function that processes log messages from shell output.
|
|
5
|
+
*
|
|
6
|
+
* Returns `false` to consume the log (prevent default logging),
|
|
7
|
+
* `true` to continue processing, or a Promise resolving to boolean.
|
|
8
|
+
*
|
|
9
|
+
* Processors are called in order until one returns `false`.
|
|
10
|
+
*/
|
|
3
11
|
export type ShellLogProcessor = (log: string, std: LogTypes) => (Promise<boolean> | boolean);
|
|
12
|
+
/**
|
|
13
|
+
* Function called when a subprocess PID is detected.
|
|
14
|
+
*
|
|
15
|
+
* Used with `appendAsync()` to notify when a background process starts.
|
|
16
|
+
*/
|
|
4
17
|
export type ShellPidListener = (pid: number) => (Promise<any> | any);
|
|
18
|
+
/**
|
|
19
|
+
* Listener called when the shell process closes.
|
|
20
|
+
*/
|
|
5
21
|
type OnCloseListener = (exitCode: number) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Interactive shell session manager using Node.js child_process spawn.
|
|
24
|
+
*
|
|
25
|
+
* Maintains a persistent bash session and provides:
|
|
26
|
+
* - Command execution in the same shell context
|
|
27
|
+
* - Log processing pipeline (multiple processors)
|
|
28
|
+
* - Subprocess management (PID tracking, killing)
|
|
29
|
+
* - Exit code extraction via echo commands
|
|
30
|
+
*
|
|
31
|
+
* **Key Features**:
|
|
32
|
+
* - Detached process (session leader) for proper signal handling
|
|
33
|
+
* - Log processors can consume or pass through messages
|
|
34
|
+
* - Automatic log level filtering (stderr=Error, stdout=Info)
|
|
35
|
+
* - PID tracking for background processes
|
|
36
|
+
* - Graceful shutdown with timeout
|
|
37
|
+
*
|
|
38
|
+
* **Process Management**:
|
|
39
|
+
* - Spawns `/bin/bash` as detached process
|
|
40
|
+
* - Removes NODE_OPTIONS to prevent debug flags from propagating
|
|
41
|
+
* - Tracks process lifecycle (alive state)
|
|
42
|
+
* - Supports killing main shell or subprocesses independently
|
|
43
|
+
*/
|
|
6
44
|
export declare class InteractiveShell extends Logger {
|
|
7
45
|
private _debug;
|
|
8
46
|
private logProcessors;
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import { addItemToArrayAtIndex, currentTimeMillis, generateHex, Logger, LogLevel, removeItemFromArray } from '@nu-art/ts-common';
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
|
+
/**
|
|
4
|
+
* Default log level filter: Error for stderr, Info for stdout.
|
|
5
|
+
*/
|
|
3
6
|
const defaultLogLevelFilter = (log, std) => std === 'err' ? LogLevel.Error : LogLevel.Info;
|
|
7
|
+
/**
|
|
8
|
+
* Interactive shell session manager using Node.js child_process spawn.
|
|
9
|
+
*
|
|
10
|
+
* Maintains a persistent bash session and provides:
|
|
11
|
+
* - Command execution in the same shell context
|
|
12
|
+
* - Log processing pipeline (multiple processors)
|
|
13
|
+
* - Subprocess management (PID tracking, killing)
|
|
14
|
+
* - Exit code extraction via echo commands
|
|
15
|
+
*
|
|
16
|
+
* **Key Features**:
|
|
17
|
+
* - Detached process (session leader) for proper signal handling
|
|
18
|
+
* - Log processors can consume or pass through messages
|
|
19
|
+
* - Automatic log level filtering (stderr=Error, stdout=Info)
|
|
20
|
+
* - PID tracking for background processes
|
|
21
|
+
* - Graceful shutdown with timeout
|
|
22
|
+
*
|
|
23
|
+
* **Process Management**:
|
|
24
|
+
* - Spawns `/bin/bash` as detached process
|
|
25
|
+
* - Removes NODE_OPTIONS to prevent debug flags from propagating
|
|
26
|
+
* - Tracks process lifecycle (alive state)
|
|
27
|
+
* - Supports killing main shell or subprocesses independently
|
|
28
|
+
*/
|
|
4
29
|
export class InteractiveShell extends Logger {
|
|
5
30
|
_debug = false;
|
|
6
31
|
logProcessors = [];
|
package/shell/plugins/basic.d.ts
CHANGED
|
@@ -15,16 +15,43 @@ type Cli_CpdirOptions = {
|
|
|
15
15
|
contentOnly?: boolean;
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Basic shell command plugin for Commando.
|
|
19
|
+
*
|
|
20
|
+
* Provides common file system and shell operations:
|
|
21
|
+
* - Directory navigation (`cd`, `pwd`)
|
|
22
|
+
* - File operations (`ls`, `cat`, `mkdir`, `rm`, `rmdir`, `cpdir`)
|
|
23
|
+
* - Variable assignment
|
|
24
|
+
* - Echo with options (escape sequences, file output)
|
|
25
|
+
*
|
|
26
|
+
* **Usage**: Merge with BaseCommando or other Commando classes to add
|
|
27
|
+
* these methods. Typically included via `CommandoPool.allocateCommando()`.
|
|
19
28
|
*/
|
|
20
29
|
export declare class Commando_Basic extends BaseCommando {
|
|
21
30
|
/**
|
|
22
|
-
* Changes directory and optionally executes
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
31
|
+
* Changes directory and optionally executes commands in that directory.
|
|
32
|
+
*
|
|
33
|
+
* **Behavior**:
|
|
34
|
+
* - Changes to the specified directory
|
|
35
|
+
* - Increases indentation (for script readability)
|
|
36
|
+
* - If `toRun` provided, executes the block and returns to previous directory
|
|
37
|
+
* - If `toRun` not provided, caller must call `cd_()` to return
|
|
38
|
+
*
|
|
39
|
+
* **Note**: Uses `cd -` to return to previous directory (OLDPWD).
|
|
40
|
+
*
|
|
41
|
+
* @param folderName - Directory path to change to
|
|
42
|
+
* @param toRun - Optional command block to execute in the directory
|
|
43
|
+
* @returns This instance for method chaining
|
|
26
44
|
*/
|
|
27
45
|
cd(folderName: string, toRun?: CliBlock<this>): this;
|
|
46
|
+
/**
|
|
47
|
+
* Appends a custom command string.
|
|
48
|
+
*
|
|
49
|
+
* Allows adding arbitrary shell commands that aren't covered by
|
|
50
|
+
* the built-in methods.
|
|
51
|
+
*
|
|
52
|
+
* @param command - Custom shell command to append
|
|
53
|
+
* @returns This instance for method chaining
|
|
54
|
+
*/
|
|
28
55
|
custom(command: string): this;
|
|
29
56
|
/**
|
|
30
57
|
* Changes directory back to the previous directory.
|
|
@@ -37,11 +64,62 @@ export declare class Commando_Basic extends BaseCommando {
|
|
|
37
64
|
* @returns {this} - The Cli instance for method chaining.
|
|
38
65
|
*/
|
|
39
66
|
ls(params?: string): this;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a directory (with parent directories if needed).
|
|
69
|
+
*
|
|
70
|
+
* Uses `mkdir -p` to create directory and all parent directories.
|
|
71
|
+
*
|
|
72
|
+
* @param dirName - Directory path to create
|
|
73
|
+
* @returns This instance for method chaining
|
|
74
|
+
*/
|
|
40
75
|
mkdir(dirName: string): this;
|
|
76
|
+
/**
|
|
77
|
+
* Removes a file or directory.
|
|
78
|
+
*
|
|
79
|
+
* @param dirPath - Path to remove
|
|
80
|
+
* @param options - Optional force flag
|
|
81
|
+
* @returns This instance for method chaining
|
|
82
|
+
*/
|
|
41
83
|
rm(dirPath: string, options?: Cli_RmdirOptions): this;
|
|
84
|
+
/**
|
|
85
|
+
* Removes a directory recursively.
|
|
86
|
+
*
|
|
87
|
+
* @param dirPath - Directory path to remove
|
|
88
|
+
* @param options - Optional force flag
|
|
89
|
+
* @returns This instance for method chaining
|
|
90
|
+
*/
|
|
42
91
|
rmdir(dirPath: string, options?: Cli_RmdirOptions): this;
|
|
92
|
+
/**
|
|
93
|
+
* Copies a directory.
|
|
94
|
+
*
|
|
95
|
+
* @param srcPath - Source directory path
|
|
96
|
+
* @param destPath - Destination directory path
|
|
97
|
+
* @param options - Optional contentOnly flag (copies contents, not directory itself)
|
|
98
|
+
* @returns This instance for method chaining
|
|
99
|
+
*/
|
|
43
100
|
cpdir(srcPath: string, destPath: string, options?: Cli_CpdirOptions): this;
|
|
101
|
+
/**
|
|
102
|
+
* Displays file contents.
|
|
103
|
+
*
|
|
104
|
+
* @param fileName - File path to display
|
|
105
|
+
* @returns This instance for method chaining
|
|
106
|
+
*/
|
|
44
107
|
cat(fileName: string): this;
|
|
108
|
+
/**
|
|
109
|
+
* Echoes text with optional escape sequences and file output.
|
|
110
|
+
*
|
|
111
|
+
* **Escape Sequences**: When `escape` is true, enables interpretation
|
|
112
|
+
* of backslash escapes (e.g., `\n`, `\t`).
|
|
113
|
+
*
|
|
114
|
+
* **File Output**: Can append or overwrite to a file.
|
|
115
|
+
*
|
|
116
|
+
* **Escaping**: Automatically escapes backslashes, newlines, and tabs
|
|
117
|
+
* in the log string for safe shell execution.
|
|
118
|
+
*
|
|
119
|
+
* @param log - Text to echo
|
|
120
|
+
* @param options - Optional echo configuration
|
|
121
|
+
* @returns This instance for method chaining
|
|
122
|
+
*/
|
|
45
123
|
echo(log: string, options?: Cli_EchoOptions): this;
|
|
46
124
|
/**
|
|
47
125
|
* Appends a 'pwd' command to print the current directory.
|
|
@@ -49,10 +127,13 @@ export declare class Commando_Basic extends BaseCommando {
|
|
|
49
127
|
*/
|
|
50
128
|
pwd(): this;
|
|
51
129
|
/**
|
|
52
|
-
* Assigns a value to a variable
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
130
|
+
* Assigns a value to a shell variable (array or scalar).
|
|
131
|
+
*
|
|
132
|
+
* Creates a bash array if value is an array, otherwise creates a scalar variable.
|
|
133
|
+
*
|
|
134
|
+
* @param varName - Variable name
|
|
135
|
+
* @param value - Value(s) to assign (string or array of strings)
|
|
136
|
+
* @returns This instance for method chaining
|
|
56
137
|
*/
|
|
57
138
|
assignVar(varName: string, value: string | string[]): this;
|
|
58
139
|
}
|