numux 1.10.3 → 1.11.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/dist/numux.js +94 -53
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
package/dist/numux.js
CHANGED
|
@@ -22,7 +22,7 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
|
|
|
22
22
|
var require_package = __commonJS((exports, module) => {
|
|
23
23
|
module.exports = {
|
|
24
24
|
name: "numux",
|
|
25
|
-
version: "1.
|
|
25
|
+
version: "1.11.0",
|
|
26
26
|
description: "Terminal multiplexer with dependency orchestration",
|
|
27
27
|
type: "module",
|
|
28
28
|
license: "MIT",
|
|
@@ -122,6 +122,16 @@ var FLAGS = [
|
|
|
122
122
|
key: "autoColors",
|
|
123
123
|
description: "Auto-assign colors to processes based on their name"
|
|
124
124
|
},
|
|
125
|
+
{
|
|
126
|
+
type: "value",
|
|
127
|
+
long: "--env-file",
|
|
128
|
+
short: "-e",
|
|
129
|
+
key: "envFile",
|
|
130
|
+
description: 'Env file path, or "false" to disable env file loading',
|
|
131
|
+
valueName: "<path|false>",
|
|
132
|
+
completionHint: "file",
|
|
133
|
+
parse: (raw) => raw === "false" ? false : raw
|
|
134
|
+
},
|
|
125
135
|
{
|
|
126
136
|
type: "value",
|
|
127
137
|
long: "--config",
|
|
@@ -970,7 +980,7 @@ function validateConfig(raw, warnings) {
|
|
|
970
980
|
throw new Error("Config must define at least one process");
|
|
971
981
|
}
|
|
972
982
|
const globalCwd = typeof config.cwd === "string" ? config.cwd : undefined;
|
|
973
|
-
const globalEnvFile =
|
|
983
|
+
const globalEnvFile = validateEnvFile(config.envFile);
|
|
974
984
|
let globalEnv;
|
|
975
985
|
if (config.env && typeof config.env === "object") {
|
|
976
986
|
for (const [k, v] of Object.entries(config.env)) {
|
|
@@ -1066,7 +1076,11 @@ function validateStringOrStringArray(value) {
|
|
|
1066
1076
|
return value;
|
|
1067
1077
|
return;
|
|
1068
1078
|
}
|
|
1069
|
-
|
|
1079
|
+
function validateEnvFile(value) {
|
|
1080
|
+
if (value === false)
|
|
1081
|
+
return false;
|
|
1082
|
+
return validateStringOrStringArray(value);
|
|
1083
|
+
}
|
|
1070
1084
|
function validateErrorMatcher(name, value) {
|
|
1071
1085
|
if (value === true)
|
|
1072
1086
|
return true;
|
|
@@ -2119,6 +2133,37 @@ var STATUS_ICON_HEX = {
|
|
|
2119
2133
|
skipped: "#888888"
|
|
2120
2134
|
};
|
|
2121
2135
|
var TERMINAL_STATUSES = new Set(["finished", "stopped", "failed", "skipped"]);
|
|
2136
|
+
function formatTab(name, status) {
|
|
2137
|
+
return `${STATUS_ICONS[status]} ${name}`;
|
|
2138
|
+
}
|
|
2139
|
+
function formatDescription(status, exitCode, restartCount) {
|
|
2140
|
+
let desc = status;
|
|
2141
|
+
if ((status === "failed" || status === "stopped") && exitCode != null && exitCode !== 0) {
|
|
2142
|
+
desc = `exit ${exitCode}`;
|
|
2143
|
+
}
|
|
2144
|
+
if (restartCount && restartCount > 0) {
|
|
2145
|
+
desc += ` \xD7${restartCount}`;
|
|
2146
|
+
}
|
|
2147
|
+
return desc;
|
|
2148
|
+
}
|
|
2149
|
+
function getDisplayOrder(originalNames, statuses) {
|
|
2150
|
+
const active = originalNames.filter((n) => !TERMINAL_STATUSES.has(statuses.get(n)));
|
|
2151
|
+
const terminal = originalNames.filter((n) => TERMINAL_STATUSES.has(statuses.get(n)));
|
|
2152
|
+
return [...active, ...terminal];
|
|
2153
|
+
}
|
|
2154
|
+
function resolveOptionColors(names, statuses, processColors, inputWaiting, erroredProcesses) {
|
|
2155
|
+
return names.map((name) => {
|
|
2156
|
+
const status = statuses.get(name);
|
|
2157
|
+
const waiting = inputWaiting.has(name);
|
|
2158
|
+
const errored = erroredProcesses.has(name);
|
|
2159
|
+
const statusHex = waiting ? "#ffaa00" : errored ? "#ff5555" : STATUS_ICON_HEX[status];
|
|
2160
|
+
const processHex = processColors.get(name);
|
|
2161
|
+
return {
|
|
2162
|
+
iconHex: statusHex ?? processHex ?? "#888888",
|
|
2163
|
+
nameHex: processHex ?? null
|
|
2164
|
+
};
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2122
2167
|
|
|
2123
2168
|
class ColoredSelectRenderable extends SelectRenderable {
|
|
2124
2169
|
_optionColors = [];
|
|
@@ -2126,12 +2171,11 @@ class ColoredSelectRenderable extends SelectRenderable {
|
|
|
2126
2171
|
this._optionColors = colors;
|
|
2127
2172
|
this.requestRender();
|
|
2128
2173
|
}
|
|
2129
|
-
renderSelf(
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
if (
|
|
2133
|
-
this.
|
|
2134
|
-
}
|
|
2174
|
+
renderSelf(_buffer, _deltaTime) {
|
|
2175
|
+
if (!(this.visible && this.frameBuffer))
|
|
2176
|
+
return;
|
|
2177
|
+
if (this.isDirty)
|
|
2178
|
+
this.renderOptions();
|
|
2135
2179
|
}
|
|
2136
2180
|
onMouseEvent(event) {
|
|
2137
2181
|
if (event.type === "down") {
|
|
@@ -2144,28 +2188,45 @@ class ColoredSelectRenderable extends SelectRenderable {
|
|
|
2144
2188
|
}
|
|
2145
2189
|
}
|
|
2146
2190
|
}
|
|
2147
|
-
|
|
2191
|
+
renderOptions() {
|
|
2192
|
+
if (!this.frameBuffer || this.options.length === 0)
|
|
2193
|
+
return;
|
|
2148
2194
|
const fb = this.frameBuffer;
|
|
2195
|
+
const bgColor = this._focused ? this._focusedBackgroundColor : this._backgroundColor;
|
|
2196
|
+
fb.clear(bgColor);
|
|
2149
2197
|
const scrollOffset = this.scrollOffset;
|
|
2150
2198
|
const maxVisibleItems = this.maxVisibleItems;
|
|
2151
2199
|
const linesPerItem = this.linesPerItem;
|
|
2200
|
+
const fontHeight = this.fontHeight;
|
|
2152
2201
|
const selectedIndex = this.getSelectedIndex();
|
|
2153
|
-
const
|
|
2154
|
-
const visibleCount = Math.min(maxVisibleItems, options.length - scrollOffset);
|
|
2202
|
+
const showDescription = this._showDescription;
|
|
2155
2203
|
const baseTextColor = this._focused ? this._focusedTextColor : this._textColor;
|
|
2156
2204
|
const selectedTextColor = this._selectedTextColor;
|
|
2157
|
-
const
|
|
2205
|
+
const descColor = this._descriptionColor;
|
|
2206
|
+
const selectedDescColor = this._selectedDescriptionColor;
|
|
2207
|
+
const selectedBgColor = this._selectedBackgroundColor;
|
|
2208
|
+
const itemSpacing = this._itemSpacing;
|
|
2209
|
+
const visibleCount = Math.min(maxVisibleItems, this.options.length - scrollOffset);
|
|
2158
2210
|
for (let i = 0;i < visibleCount; i++) {
|
|
2159
2211
|
const actualIndex = scrollOffset + i;
|
|
2160
|
-
const
|
|
2161
|
-
const optName = options[actualIndex].name;
|
|
2212
|
+
const option = this.options[actualIndex];
|
|
2162
2213
|
const isSelected = actualIndex === selectedIndex;
|
|
2163
|
-
const
|
|
2214
|
+
const itemY = i * linesPerItem;
|
|
2215
|
+
if (itemY + linesPerItem - 1 >= this.height)
|
|
2216
|
+
break;
|
|
2217
|
+
if (isSelected) {
|
|
2218
|
+
fb.fillRect(0, itemY, this.width, linesPerItem - itemSpacing, selectedBgColor);
|
|
2219
|
+
}
|
|
2164
2220
|
const colors = this._optionColors[actualIndex];
|
|
2165
|
-
const
|
|
2166
|
-
|
|
2221
|
+
const defaultColor = isSelected ? selectedTextColor : baseTextColor;
|
|
2222
|
+
const nameColor = colors?.name ?? defaultColor;
|
|
2223
|
+
fb.drawText(option.name, 1, itemY, nameColor);
|
|
2167
2224
|
if (colors?.icon) {
|
|
2168
|
-
fb.drawText(
|
|
2225
|
+
fb.drawText(option.name.charAt(0), 1, itemY, colors.icon);
|
|
2226
|
+
}
|
|
2227
|
+
if (showDescription && itemY + fontHeight < this.height) {
|
|
2228
|
+
const dc = isSelected ? selectedDescColor : descColor;
|
|
2229
|
+
fb.drawText(option.description, 3, itemY + fontHeight, dc);
|
|
2169
2230
|
}
|
|
2170
2231
|
}
|
|
2171
2232
|
}
|
|
@@ -2191,7 +2252,7 @@ class TabBar {
|
|
|
2191
2252
|
width: "100%",
|
|
2192
2253
|
height: "100%",
|
|
2193
2254
|
options: names.map((n) => ({
|
|
2194
|
-
name:
|
|
2255
|
+
name: formatTab(n, "pending"),
|
|
2195
2256
|
description: "pending"
|
|
2196
2257
|
})),
|
|
2197
2258
|
selectedBackgroundColor: "#334455",
|
|
@@ -2214,7 +2275,7 @@ class TabBar {
|
|
|
2214
2275
|
}
|
|
2215
2276
|
updateStatus(name, status, exitCode, restartCount) {
|
|
2216
2277
|
this.statuses.set(name, status);
|
|
2217
|
-
this.baseDescriptions.set(name,
|
|
2278
|
+
this.baseDescriptions.set(name, formatDescription(status, exitCode, restartCount));
|
|
2218
2279
|
if (TERMINAL_STATUSES.has(status) || status === "stopping") {
|
|
2219
2280
|
this.inputWaiting.delete(name);
|
|
2220
2281
|
}
|
|
@@ -2246,9 +2307,9 @@ class TabBar {
|
|
|
2246
2307
|
refreshOptions() {
|
|
2247
2308
|
const currentIdx = this.renderable.getSelectedIndex();
|
|
2248
2309
|
const currentName = this.names[currentIdx];
|
|
2249
|
-
this.names = this.
|
|
2310
|
+
this.names = getDisplayOrder(this.originalNames, this.statuses);
|
|
2250
2311
|
this.renderable.options = this.names.map((n) => ({
|
|
2251
|
-
name:
|
|
2312
|
+
name: formatTab(n, this.statuses.get(n)),
|
|
2252
2313
|
description: this.getDescription(n)
|
|
2253
2314
|
}));
|
|
2254
2315
|
const newIdx = this.names.indexOf(currentName);
|
|
@@ -2257,11 +2318,6 @@ class TabBar {
|
|
|
2257
2318
|
}
|
|
2258
2319
|
this.updateOptionColors();
|
|
2259
2320
|
}
|
|
2260
|
-
getDisplayOrder() {
|
|
2261
|
-
const active = this.originalNames.filter((n) => !TERMINAL_STATUSES.has(this.statuses.get(n)));
|
|
2262
|
-
const terminal = this.originalNames.filter((n) => TERMINAL_STATUSES.has(this.statuses.get(n)));
|
|
2263
|
-
return [...active, ...terminal];
|
|
2264
|
-
}
|
|
2265
2321
|
getDescription(name) {
|
|
2266
2322
|
if (this.inputWaiting.has(name))
|
|
2267
2323
|
return "awaiting input";
|
|
@@ -2270,33 +2326,13 @@ class TabBar {
|
|
|
2270
2326
|
return this.baseDescriptions.get(name) ?? "pending";
|
|
2271
2327
|
}
|
|
2272
2328
|
updateOptionColors() {
|
|
2273
|
-
const
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
const processHex = this.processColors.get(name);
|
|
2279
|
-
return {
|
|
2280
|
-
icon: parseColor(statusHex ?? processHex ?? "#888888"),
|
|
2281
|
-
name: processHex ? parseColor(processHex) : null
|
|
2282
|
-
};
|
|
2283
|
-
});
|
|
2329
|
+
const resolved = resolveOptionColors(this.names, this.statuses, this.processColors, this.inputWaiting, this.erroredProcesses);
|
|
2330
|
+
const colors = resolved.map((c) => ({
|
|
2331
|
+
icon: parseColor(c.iconHex),
|
|
2332
|
+
name: c.nameHex ? parseColor(c.nameHex) : null
|
|
2333
|
+
}));
|
|
2284
2334
|
this.renderable.setOptionColors(colors);
|
|
2285
2335
|
}
|
|
2286
|
-
formatDescription(status, exitCode, restartCount) {
|
|
2287
|
-
let desc = status;
|
|
2288
|
-
if ((status === "failed" || status === "stopped") && exitCode != null && exitCode !== 0) {
|
|
2289
|
-
desc = `exit ${exitCode}`;
|
|
2290
|
-
}
|
|
2291
|
-
if (restartCount && restartCount > 0) {
|
|
2292
|
-
desc += ` \xD7${restartCount}`;
|
|
2293
|
-
}
|
|
2294
|
-
return desc;
|
|
2295
|
-
}
|
|
2296
|
-
formatTab(name, status) {
|
|
2297
|
-
const icon = STATUS_ICONS[status];
|
|
2298
|
-
return `${icon} ${name}`;
|
|
2299
|
-
}
|
|
2300
2336
|
getSelectedIndex() {
|
|
2301
2337
|
return this.renderable.getSelectedIndex();
|
|
2302
2338
|
}
|
|
@@ -3114,6 +3150,11 @@ async function main() {
|
|
|
3114
3150
|
}
|
|
3115
3151
|
}
|
|
3116
3152
|
}
|
|
3153
|
+
if (parsed.envFile !== undefined) {
|
|
3154
|
+
for (const proc of Object.values(config.processes)) {
|
|
3155
|
+
proc.envFile = parsed.envFile;
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3117
3158
|
if (parsed.noWatch) {
|
|
3118
3159
|
for (const proc of Object.values(config.processes)) {
|
|
3119
3160
|
delete proc.watch;
|
package/dist/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export interface NumuxProcessConfig {
|
|
|
2
2
|
command: string;
|
|
3
3
|
cwd?: string;
|
|
4
4
|
env?: Record<string, string>;
|
|
5
|
-
envFile?: string | string[];
|
|
5
|
+
envFile?: string | string[] | false;
|
|
6
6
|
dependsOn?: string[];
|
|
7
7
|
readyPattern?: string;
|
|
8
8
|
persistent?: boolean;
|
|
@@ -24,7 +24,7 @@ export type NumuxScriptPattern = Omit<NumuxProcessConfig, 'command'> & {
|
|
|
24
24
|
export interface NumuxConfig {
|
|
25
25
|
cwd?: string;
|
|
26
26
|
env?: Record<string, string>;
|
|
27
|
-
envFile?: string | string[];
|
|
27
|
+
envFile?: string | string[] | false;
|
|
28
28
|
processes: Record<string, NumuxProcessConfig | NumuxScriptPattern | string>;
|
|
29
29
|
}
|
|
30
30
|
/** Validated config with all shorthand expanded to full objects */
|