mage-remote-run 0.11.0 → 0.12.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/bin/mage-remote-run.js +10 -65
- package/lib/command-helper.js +100 -0
- package/package.json +1 -1
package/bin/mage-remote-run.js
CHANGED
|
@@ -89,70 +89,7 @@ program.hook('preAction', async (thisCommand, actionCommand) => {
|
|
|
89
89
|
}
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
const tokenLower = token.toLowerCase();
|
|
94
|
-
|
|
95
|
-
// Check for exact match first
|
|
96
|
-
const exactMatch = parent.commands.find((cmd) => {
|
|
97
|
-
return cmd.name().toLowerCase() === tokenLower;
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (exactMatch) {
|
|
101
|
-
return {
|
|
102
|
-
match: exactMatch,
|
|
103
|
-
matches: [exactMatch]
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const matches = parent.commands.filter((cmd) => {
|
|
108
|
-
const name = cmd.name().toLowerCase();
|
|
109
|
-
if (name.startsWith(tokenLower)) return true;
|
|
110
|
-
const aliases = cmd.aliases ? cmd.aliases() : [];
|
|
111
|
-
return aliases.some((alias) => alias.toLowerCase().startsWith(tokenLower));
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
match: matches.length === 1 ? matches[0] : null,
|
|
116
|
-
matches
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function expandCommandAbbreviations(rootCommand, argv) {
|
|
121
|
-
const expanded = [];
|
|
122
|
-
let current = rootCommand;
|
|
123
|
-
const path = [];
|
|
124
|
-
|
|
125
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
126
|
-
const token = argv[i];
|
|
127
|
-
if (token.startsWith('-')) {
|
|
128
|
-
expanded.push(token);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (!current.commands || current.commands.length === 0) {
|
|
133
|
-
expanded.push(...argv.slice(i));
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const { match, matches } = resolveCommandMatch(current, token);
|
|
138
|
-
if (!match) {
|
|
139
|
-
if (matches.length > 1) {
|
|
140
|
-
const parentName = path.length > 0 ? path.join(' ') : current.name();
|
|
141
|
-
const options = matches.map((cmd) => cmd.name()).join(', ');
|
|
142
|
-
console.error(`Ambiguous command "${token}" under "${parentName}". Options: ${options}.`);
|
|
143
|
-
process.exit(1);
|
|
144
|
-
}
|
|
145
|
-
expanded.push(token);
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
expanded.push(match.name());
|
|
150
|
-
current = match;
|
|
151
|
-
path.push(match.name());
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return expanded;
|
|
155
|
-
}
|
|
92
|
+
import { expandCommandAbbreviations } from '../lib/command-helper.js';
|
|
156
93
|
|
|
157
94
|
// Check for first run (no profiles configured and no arguments or just help)
|
|
158
95
|
// We need to check args length.
|
|
@@ -177,7 +114,15 @@ if (!hasProfiles && args.length === 0) {
|
|
|
177
114
|
args = ['connection', 'add'];
|
|
178
115
|
}
|
|
179
116
|
|
|
180
|
-
|
|
117
|
+
try {
|
|
118
|
+
args = expandCommandAbbreviations(program, args);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
if (e.isAmbiguous) {
|
|
121
|
+
console.error(e.message);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
181
126
|
process.argv = [...process.argv.slice(0, 2), ...args];
|
|
182
127
|
|
|
183
128
|
program.parse(process.argv);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
|
|
2
|
+
export function resolveCommandMatch(parent, token) {
|
|
3
|
+
const tokenLower = token.toLowerCase();
|
|
4
|
+
|
|
5
|
+
// Check for exact match first
|
|
6
|
+
const exactMatch = parent.commands.find((cmd) => {
|
|
7
|
+
return cmd.name().toLowerCase() === tokenLower;
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
if (exactMatch) {
|
|
11
|
+
return {
|
|
12
|
+
match: exactMatch,
|
|
13
|
+
matches: [exactMatch]
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const matches = parent.commands.filter((cmd) => {
|
|
18
|
+
const name = cmd.name().toLowerCase();
|
|
19
|
+
if (name.startsWith(tokenLower)) return true;
|
|
20
|
+
const aliases = cmd.aliases ? cmd.aliases() : [];
|
|
21
|
+
return aliases.some((alias) => alias.toLowerCase().startsWith(tokenLower));
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
match: matches.length === 1 ? matches[0] : null,
|
|
26
|
+
matches
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function expandCommandAbbreviations(rootCommand, argv) {
|
|
31
|
+
const expanded = [];
|
|
32
|
+
let current = rootCommand;
|
|
33
|
+
const path = [];
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
36
|
+
const token = argv[i];
|
|
37
|
+
if (token.startsWith('-')) {
|
|
38
|
+
expanded.push(token);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!current.commands || current.commands.length === 0) {
|
|
43
|
+
expanded.push(...argv.slice(i));
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Feature: Support colon separators
|
|
48
|
+
// If the token contains colons, try to split it and resolve parts
|
|
49
|
+
if (token.includes(':')) {
|
|
50
|
+
const parts = token.split(':');
|
|
51
|
+
const originalArgv = argv.slice(0); // copy
|
|
52
|
+
|
|
53
|
+
// Modify argv effectively for this lookahead
|
|
54
|
+
const remainingArgv = [...parts, ...argv.slice(i + 1)];
|
|
55
|
+
|
|
56
|
+
// Recursively expand the new sequence from current point
|
|
57
|
+
// We need to resolve from 'current' but since expandCommandAbbreviations takes rootCommand,
|
|
58
|
+
// we should probably just verify if these parts are valid commands.
|
|
59
|
+
// But expandCommandAbbreviations is designed to walk from root.
|
|
60
|
+
// However, we are currently at 'current'.
|
|
61
|
+
|
|
62
|
+
// To properly handle "cust:list" where "cust" is from root, we can just replace the token in the list
|
|
63
|
+
// and continue loop, IF the first part matches something.
|
|
64
|
+
|
|
65
|
+
// Let's check if the first part matches a command in current scope
|
|
66
|
+
const firstPart = parts[0];
|
|
67
|
+
const result = resolveCommandMatch(current, firstPart);
|
|
68
|
+
|
|
69
|
+
if (result.match) {
|
|
70
|
+
// If the first part matches, we replace the current token with the split parts
|
|
71
|
+
// and effectively 'restart' processing or just insert them into argv and decrement i to re-process first part
|
|
72
|
+
argv.splice(i, 1, ...parts);
|
|
73
|
+
i--; // Stay on same index to process the first part of the split
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { match, matches } = resolveCommandMatch(current, token);
|
|
79
|
+
if (!match) {
|
|
80
|
+
if (matches.length > 1) {
|
|
81
|
+
const parentName = path.length > 0 ? path.join(' ') : (current.name() !== 'mage-remote-run' ? current.name() : 'root');
|
|
82
|
+
const options = matches.map((cmd) => cmd.name()).join(', ');
|
|
83
|
+
let errorMessage = `Ambiguous command "${token}" under "${parentName}". Options: ${options}.`;
|
|
84
|
+
// If this is a script, we might not want to console.error directly if we want to test it easily,
|
|
85
|
+
// but complying with original code which did process.exit
|
|
86
|
+
const error = new Error(errorMessage);
|
|
87
|
+
error.isAmbiguous = true;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
expanded.push(token);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
expanded.push(match.name());
|
|
95
|
+
current = match;
|
|
96
|
+
path.push(match.name());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return expanded;
|
|
100
|
+
}
|