numux 2.7.2 → 2.9.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/README.md +8 -0
- package/dist/numux.js +72 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@ numux
|
|
|
73
73
|
numux init # Create a starter numux.config.ts
|
|
74
74
|
numux validate # Validate config and show process dependency graph
|
|
75
75
|
numux exec <name> [--] <command> # Run a command in a process's environment
|
|
76
|
+
numux logs [name] # Open log directory or view a process log
|
|
76
77
|
numux completions <shell> # Generate shell completions (bash, zsh, fish)
|
|
77
78
|
```
|
|
78
79
|
|
|
@@ -85,6 +86,13 @@ numux exec api -- npx prisma migrate
|
|
|
85
86
|
numux exec web npm run build
|
|
86
87
|
```
|
|
87
88
|
|
|
89
|
+
`logs` prints the log directory path, or a specific process's log contents:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
numux logs # Print log directory path
|
|
93
|
+
numux logs api # Print the api process log
|
|
94
|
+
```
|
|
95
|
+
|
|
88
96
|
Set up completions for your shell:
|
|
89
97
|
|
|
90
98
|
```sh
|
package/dist/numux.js
CHANGED
|
@@ -31,12 +31,13 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
31
31
|
return to;
|
|
32
32
|
};
|
|
33
33
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
|
+
var __require = import.meta.require;
|
|
34
35
|
|
|
35
36
|
// package.json
|
|
36
37
|
var require_package = __commonJS((exports, module) => {
|
|
37
38
|
module.exports = {
|
|
38
39
|
name: "numux",
|
|
39
|
-
version: "2.
|
|
40
|
+
version: "2.9.0",
|
|
40
41
|
description: "Terminal multiplexer with dependency orchestration",
|
|
41
42
|
type: "module",
|
|
42
43
|
license: "MIT",
|
|
@@ -95,7 +96,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
95
96
|
});
|
|
96
97
|
|
|
97
98
|
// src/index.ts
|
|
98
|
-
import { existsSync as
|
|
99
|
+
import { existsSync as existsSync6, writeFileSync } from "fs";
|
|
99
100
|
import { resolve as resolve8 } from "path";
|
|
100
101
|
|
|
101
102
|
// src/cli-flags.ts
|
|
@@ -300,6 +301,20 @@ var SUBCOMMANDS = [
|
|
|
300
301
|
return "break";
|
|
301
302
|
}
|
|
302
303
|
},
|
|
304
|
+
{
|
|
305
|
+
name: "logs",
|
|
306
|
+
description: "Open the log directory or a specific process log",
|
|
307
|
+
usage: "logs [name]",
|
|
308
|
+
parse: (args, i, result) => {
|
|
309
|
+
result.logs = true;
|
|
310
|
+
const next = args[i + 1];
|
|
311
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
312
|
+
result.logsProcess = next;
|
|
313
|
+
i++;
|
|
314
|
+
}
|
|
315
|
+
return i;
|
|
316
|
+
}
|
|
317
|
+
},
|
|
303
318
|
{
|
|
304
319
|
name: "completions",
|
|
305
320
|
description: "Generate shell completions (bash, zsh, fish)",
|
|
@@ -364,6 +379,7 @@ function parseArgs(argv) {
|
|
|
364
379
|
init: false,
|
|
365
380
|
validate: false,
|
|
366
381
|
exec: false,
|
|
382
|
+
logs: false,
|
|
367
383
|
prefix: false,
|
|
368
384
|
killOthers: false,
|
|
369
385
|
killOthersOnFail: false,
|
|
@@ -3876,6 +3892,26 @@ class LogWriter {
|
|
|
3876
3892
|
}
|
|
3877
3893
|
}
|
|
3878
3894
|
|
|
3895
|
+
// src/utils/project-name.ts
|
|
3896
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
3897
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
3898
|
+
import { basename as basename3, join as join2 } from "path";
|
|
3899
|
+
function resolveProjectName(cwd) {
|
|
3900
|
+
try {
|
|
3901
|
+
const pkgPath = join2(cwd, "package.json");
|
|
3902
|
+
if (existsSync5(pkgPath)) {
|
|
3903
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
3904
|
+
if (typeof pkg.name === "string" && pkg.name.trim()) {
|
|
3905
|
+
return pkg.name.replace(/^@[^/]+\//, "").trim();
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
} catch {}
|
|
3909
|
+
return basename3(cwd);
|
|
3910
|
+
}
|
|
3911
|
+
function defaultLogDir(cwd) {
|
|
3912
|
+
return join2(tmpdir2(), "numux", resolveProjectName(cwd));
|
|
3913
|
+
}
|
|
3914
|
+
|
|
3879
3915
|
// src/utils/shutdown.ts
|
|
3880
3916
|
function setupShutdownHandlers(app, logWriter) {
|
|
3881
3917
|
let shuttingDown = false;
|
|
@@ -3953,7 +3989,7 @@ async function main() {
|
|
|
3953
3989
|
}
|
|
3954
3990
|
if (parsed.init) {
|
|
3955
3991
|
const target = resolve8("numux.config.ts");
|
|
3956
|
-
if (
|
|
3992
|
+
if (existsSync6(target)) {
|
|
3957
3993
|
console.error(`Already exists: ${target}`);
|
|
3958
3994
|
process.exit(1);
|
|
3959
3995
|
}
|
|
@@ -3965,6 +4001,28 @@ async function main() {
|
|
|
3965
4001
|
console.info(generateCompletions(parsed.completions));
|
|
3966
4002
|
process.exit(0);
|
|
3967
4003
|
}
|
|
4004
|
+
if (parsed.logs) {
|
|
4005
|
+
const logDir2 = parsed.logDir ?? await resolveLogDir(parsed.configPath);
|
|
4006
|
+
const latestDir = resolve8(logDir2, "latest");
|
|
4007
|
+
const target = existsSync6(latestDir) ? latestDir : logDir2;
|
|
4008
|
+
if (parsed.logsProcess) {
|
|
4009
|
+
const logFile2 = resolve8(target, `${parsed.logsProcess}.log`);
|
|
4010
|
+
if (!existsSync6(logFile2)) {
|
|
4011
|
+
const { readdirSync } = await import("fs");
|
|
4012
|
+
const files = readdirSync(target).filter((f) => f.endsWith(".log")).map((f) => f.replace(/\.log$/, ""));
|
|
4013
|
+
const available = files.length > 0 ? `Available: ${files.join(", ")}` : "No log files found";
|
|
4014
|
+
console.error(`No log file for "${parsed.logsProcess}". ${available}`);
|
|
4015
|
+
process.exit(1);
|
|
4016
|
+
}
|
|
4017
|
+
const child = Bun.spawn(["cat", logFile2], {
|
|
4018
|
+
stdout: "inherit",
|
|
4019
|
+
stderr: "inherit"
|
|
4020
|
+
});
|
|
4021
|
+
process.exit(await child.exited);
|
|
4022
|
+
}
|
|
4023
|
+
console.info(target);
|
|
4024
|
+
process.exit(0);
|
|
4025
|
+
}
|
|
3968
4026
|
if (parsed.validate) {
|
|
3969
4027
|
const raw = expandWorkspaces(expandScriptPatterns(await loadConfig(parsed.configPath)));
|
|
3970
4028
|
const warnings2 = [];
|
|
@@ -4114,8 +4172,8 @@ async function main() {
|
|
|
4114
4172
|
}
|
|
4115
4173
|
}
|
|
4116
4174
|
const manager = new ProcessManager(config);
|
|
4117
|
-
const logDir = parsed.logDir ?? config.logDir;
|
|
4118
|
-
const logWriter =
|
|
4175
|
+
const logDir = parsed.logDir ?? config.logDir ?? defaultLogDir(process.cwd());
|
|
4176
|
+
const logWriter = LogWriter.createPersistent(logDir);
|
|
4119
4177
|
printWarnings(warnings);
|
|
4120
4178
|
const timestamps = parsed.timestamps || config.timestamps;
|
|
4121
4179
|
const usePrefix = parsed.prefix || config.prefix;
|
|
@@ -4141,6 +4199,15 @@ function printWarnings(warnings) {
|
|
|
4141
4199
|
console.warn(`Warning: process "${w.process}": ${w.message}`);
|
|
4142
4200
|
}
|
|
4143
4201
|
}
|
|
4202
|
+
async function resolveLogDir(configPath) {
|
|
4203
|
+
try {
|
|
4204
|
+
const raw = await loadConfig(configPath);
|
|
4205
|
+
if (typeof raw.logDir === "string" && raw.logDir.trim()) {
|
|
4206
|
+
return resolve8(raw.logDir.trim());
|
|
4207
|
+
}
|
|
4208
|
+
} catch {}
|
|
4209
|
+
return defaultLogDir(process.cwd());
|
|
4210
|
+
}
|
|
4144
4211
|
main().catch((err) => {
|
|
4145
4212
|
console.error(err instanceof Error ? err.message : err);
|
|
4146
4213
|
process.exit(1);
|