numux 1.17.0 → 1.18.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.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/dist/numux.js +38 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -311,7 +311,7 @@ Persistent processes that crash are auto-restarted with exponential backoff (1s
311
311
 
312
312
  ### Dependency output capture
313
313
 
314
- When `readyPattern` is a `RegExp` (not a string), capture groups are extracted on match and expanded into dependent process commands using `$process.group` syntax:
314
+ When `readyPattern` is a `RegExp` (not a string), capture groups are extracted on match and expanded into dependent process `command` and `env` values using `$process.group` syntax:
315
315
 
316
316
  ```ts
317
317
  export default defineConfig({
@@ -323,6 +323,7 @@ export default defineConfig({
323
323
  api: {
324
324
  command: 'node server.js --db-port $db.port',
325
325
  dependsOn: ['db'],
326
+ env: { DB_PORT: '$db.port' },
326
327
  },
327
328
  },
328
329
  })
package/dist/numux.js CHANGED
@@ -36,7 +36,7 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
36
36
  var require_package = __commonJS((exports, module) => {
37
37
  module.exports = {
38
38
  name: "numux",
39
- version: "1.17.0",
39
+ version: "1.18.0",
40
40
  description: "Terminal multiplexer with dependency orchestration",
41
41
  type: "module",
42
42
  license: "MIT",
@@ -1419,6 +1419,7 @@ class ProcessRunner {
1419
1419
  restarting = false;
1420
1420
  readyTimedOut = false;
1421
1421
  commandOverride;
1422
+ envOverride;
1422
1423
  constructor(name, config, handler) {
1423
1424
  this.name = name;
1424
1425
  this.config = config;
@@ -1432,9 +1433,11 @@ class ProcessRunner {
1432
1433
  get signal() {
1433
1434
  return this.config.stopSignal ?? "SIGTERM";
1434
1435
  }
1435
- start(cols, rows, commandOverride) {
1436
+ start(cols, rows, commandOverride, envOverride) {
1436
1437
  if (commandOverride !== undefined)
1437
1438
  this.commandOverride = commandOverride;
1439
+ if (envOverride !== undefined)
1440
+ this.envOverride = envOverride;
1438
1441
  const command = this.commandOverride ?? this.config.command;
1439
1442
  const gen = ++this.generation;
1440
1443
  this.stopping = false;
@@ -1449,7 +1452,7 @@ class ProcessRunner {
1449
1452
  ...noColor ? {} : { FORCE_COLOR: "1" },
1450
1453
  TERM: "xterm-256color",
1451
1454
  ...envFromFile,
1452
- ...this.config.env
1455
+ ...this.envOverride ?? this.config.env
1453
1456
  };
1454
1457
  this.proc = Bun.spawn(["sh", "-c", command], {
1455
1458
  cwd,
@@ -1567,7 +1570,7 @@ class ProcessRunner {
1567
1570
  this.handler.onStatus("ready");
1568
1571
  this.handler.onReady(this.readiness.captures);
1569
1572
  }
1570
- async restart(cols, rows, commandOverride) {
1573
+ async restart(cols, rows, commandOverride, envOverride) {
1571
1574
  if (this.restarting)
1572
1575
  return;
1573
1576
  this.restarting = true;
@@ -1592,7 +1595,7 @@ class ProcessRunner {
1592
1595
  this.readyTimedOut = false;
1593
1596
  this.readiness = createReadinessChecker(this.config);
1594
1597
  this.errorChecker = createErrorChecker(this.config);
1595
- this.start(cols, rows, commandOverride);
1598
+ this.start(cols, rows, commandOverride, envOverride);
1596
1599
  }
1597
1600
  async stop(timeoutMs = 5000) {
1598
1601
  if (!this.proc)
@@ -1737,7 +1740,7 @@ class ProcessManager {
1737
1740
  this.setupWatchers();
1738
1741
  }
1739
1742
  startProcess(name, cols, rows) {
1740
- const commandOverride = this.expandDependencyCaptures(name);
1743
+ const { command, env } = this.expandDependencyCaptures(name);
1741
1744
  const delay = this.config.processes[name].delay;
1742
1745
  if (delay) {
1743
1746
  log(`[${name}] Delaying start by ${delay}ms`);
@@ -1746,12 +1749,12 @@ class ProcessManager {
1746
1749
  if (this.stopping)
1747
1750
  return;
1748
1751
  this.startTimes.set(name, Date.now());
1749
- this.runners.get(name).start(cols, rows, commandOverride);
1752
+ this.runners.get(name).start(cols, rows, command, env);
1750
1753
  }, delay);
1751
1754
  this.restartTimers.set(name, timer);
1752
1755
  } else {
1753
1756
  this.startTimes.set(name, Date.now());
1754
- this.runners.get(name).start(cols, rows, commandOverride);
1757
+ this.runners.get(name).start(cols, rows, command, env);
1755
1758
  }
1756
1759
  }
1757
1760
  createRunner(name, onInitialReady) {
@@ -1860,7 +1863,7 @@ class ProcessManager {
1860
1863
  const proc = this.config.processes[name];
1861
1864
  const deps = proc.dependsOn;
1862
1865
  if (!deps?.length)
1863
- return;
1866
+ return {};
1864
1867
  const allCaptures = new Map;
1865
1868
  for (const dep of deps) {
1866
1869
  const captures = this.readyCaptures.get(dep);
@@ -1868,19 +1871,33 @@ class ProcessManager {
1868
1871
  allCaptures.set(dep, captures);
1869
1872
  }
1870
1873
  if (allCaptures.size === 0)
1871
- return;
1874
+ return {};
1872
1875
  const depNames = [...allCaptures.keys()].map((n) => escapeRegExp(n)).join("|");
1873
1876
  const refPattern = new RegExp(`\\$(${depNames})\\.(\\w+)`, "g");
1874
- let hadReplacement = false;
1875
- const expanded = proc.command.replace(refPattern, (match, dep, key) => {
1877
+ const replacer = (match, dep, key) => {
1876
1878
  const captures = allCaptures.get(dep);
1877
- if (captures && key in captures) {
1878
- hadReplacement = true;
1879
+ if (captures && key in captures)
1879
1880
  return captures[key];
1880
- }
1881
1881
  return match;
1882
- });
1883
- return hadReplacement ? expanded : undefined;
1882
+ };
1883
+ let command;
1884
+ const expandedCmd = proc.command.replace(refPattern, replacer);
1885
+ if (expandedCmd !== proc.command)
1886
+ command = expandedCmd;
1887
+ let env;
1888
+ if (proc.env) {
1889
+ const expandedEnv = {};
1890
+ let hadReplacement = false;
1891
+ for (const [k, v] of Object.entries(proc.env)) {
1892
+ const expanded = v.replace(refPattern, replacer);
1893
+ expandedEnv[k] = expanded;
1894
+ if (expanded !== v)
1895
+ hadReplacement = true;
1896
+ }
1897
+ if (hadReplacement)
1898
+ env = expandedEnv;
1899
+ }
1900
+ return { command, env };
1884
1901
  }
1885
1902
  updateStatus(name, status) {
1886
1903
  const state = this.states.get(name);
@@ -1908,7 +1925,8 @@ class ProcessManager {
1908
1925
  state.exitCode = null;
1909
1926
  state.restartCount++;
1910
1927
  this.startTimes.set(name, Date.now());
1911
- runner.restart(cols, rows, this.expandDependencyCaptures(name));
1928
+ const { command, env } = this.expandDependencyCaptures(name);
1929
+ runner.restart(cols, rows, command, env);
1912
1930
  }
1913
1931
  async stop(name) {
1914
1932
  const state = this.states.get(name);
@@ -1946,7 +1964,8 @@ class ProcessManager {
1946
1964
  state.exitCode = null;
1947
1965
  state.restartCount++;
1948
1966
  this.startTimes.set(name, Date.now());
1949
- this.runners.get(name)?.restart(cols, rows, this.expandDependencyCaptures(name));
1967
+ const { command, env } = this.expandDependencyCaptures(name);
1968
+ this.runners.get(name)?.restart(cols, rows, command, env);
1950
1969
  }
1951
1970
  restartAll(cols, rows) {
1952
1971
  log("Restarting all processes");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numux",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "Terminal multiplexer with dependency orchestration",
5
5
  "type": "module",
6
6
  "license": "MIT",