tina4-nodejs 3.13.83 → 3.13.85
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/CLAUDE.md +2 -2
- package/package.json +11 -4
- package/packages/cli/dist/bin.js +40866 -0
- package/packages/cli/src/bin.ts +66 -10
- package/packages/cli/src/commands/init.ts +1 -1
- package/packages/core/dist/index.js +38006 -0
- package/packages/frond/dist/index.js +2543 -0
- package/packages/orm/dist/index.js +37850 -0
- package/packages/swagger/dist/index.js +445 -0
- package/packages/cli/bin/tina4nodejs +0 -10
- package/packages/core/public/js/tina4-dev-admin.js +0 -1124
package/packages/cli/src/bin.ts
CHANGED
|
@@ -45,21 +45,77 @@ function readCliVersion(): string {
|
|
|
45
45
|
|
|
46
46
|
// ── Port-kill helper ────────────────────────────────────────────────
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Whether this process is running inside a container.
|
|
50
|
+
*
|
|
51
|
+
* Reclaiming a port makes sense on a dev machine, where a previous serve may
|
|
52
|
+
* still hold it. Inside a container the server IS the container, so there is no
|
|
53
|
+
* stale sibling to reclaim from -- and trying is dangerous (see below).
|
|
54
|
+
*/
|
|
55
|
+
function inContainer(): boolean {
|
|
56
|
+
if (existsSync("/.dockerenv") || existsSync("/run/.containerenv")) return true;
|
|
57
|
+
try {
|
|
58
|
+
const blob = readFileSync("/proc/1/cgroup", "utf-8");
|
|
59
|
+
return blob.includes("docker") || blob.includes("containerd") || blob.includes("kubepods");
|
|
60
|
+
} catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Kill any process listening on `port`. Returns true if anything was killed.
|
|
67
|
+
*
|
|
68
|
+
* Every PID is validated first. `parseInt` on a non-numeric lsof field yields
|
|
69
|
+
* 1, and SIGTERM to PID 1 is the container's own init -- which is exactly how a
|
|
70
|
+
* production container logged "Killed existing process on port 7148 (PID: 1
|
|
71
|
+
* ...)" and then exited 143, killing itself on startup.
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* The PIDs from `lsof -ti` output that are safe to signal.
|
|
75
|
+
*
|
|
76
|
+
* Pure so the safety rule can be tested directly. An unvalidated parse is a
|
|
77
|
+
* footgun with real teeth: where lsof prints a different shape than -ti
|
|
78
|
+
* implies, a non-numeric field becomes 0, and signalling PID 0 hits EVERY
|
|
79
|
+
* process in the caller's own process group -- the server kills itself. That
|
|
80
|
+
* is what produced "Killed existing process on port 7148 (PID: 1 ...)" in a
|
|
81
|
+
* real image, where the container then exited 143.
|
|
82
|
+
*
|
|
83
|
+
* Accepts only all-digit tokens; never PID 0 (our group), PID 1 (init),
|
|
84
|
+
* ourselves, or our own process group.
|
|
85
|
+
*/
|
|
86
|
+
export function selectablePids(lsofOutput: string, me: number, myGroup?: number): number[] {
|
|
87
|
+
const pids: number[] = [];
|
|
88
|
+
for (const token of lsofOutput.split(/\s+/)) {
|
|
89
|
+
if (!/^\d+$/.test(token)) continue; // never coerce junk into a PID
|
|
90
|
+
const pid = Number(token);
|
|
91
|
+
if (pid <= 1 || pid === me) continue; // 0 = our group, 1 = init, me = suicide
|
|
92
|
+
if (myGroup !== undefined && pid === myGroup) continue;
|
|
93
|
+
if (!pids.includes(pid)) pids.push(pid);
|
|
94
|
+
}
|
|
95
|
+
return pids;
|
|
96
|
+
}
|
|
97
|
+
|
|
48
98
|
function killProcessOnPort(port: number): boolean {
|
|
99
|
+
if (inContainer()) return false;
|
|
49
100
|
try {
|
|
50
101
|
const result = execSync(`lsof -ti :${port}`, { encoding: "utf-8", timeout: 5000 }).trim();
|
|
51
|
-
if (result)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
102
|
+
if (!result) return false;
|
|
103
|
+
|
|
104
|
+
const killed: string[] = [];
|
|
105
|
+
// Node core exposes no getpgrp(), so myGroup stays unset here. The pid <= 1
|
|
106
|
+
// guard already covers the dangerous case (a junk field coercing to 0);
|
|
107
|
+
// Python and Ruby pass their real process group in addition.
|
|
108
|
+
for (const pid of selectablePids(result, process.pid)) {
|
|
109
|
+
try {
|
|
110
|
+
process.kill(pid, "SIGTERM");
|
|
111
|
+
killed.push(String(pid));
|
|
112
|
+
} catch {
|
|
113
|
+
// ignore ProcessLookupError / PermissionError
|
|
59
114
|
}
|
|
60
|
-
console.log(` Killed existing process on port ${port} (PID: ${pids.join(", ")})`);
|
|
61
|
-
return true;
|
|
62
115
|
}
|
|
116
|
+
if (killed.length === 0) return false;
|
|
117
|
+
console.log(` Killed existing process on port ${port} (PID: ${killed.join(", ")})`);
|
|
118
|
+
return true;
|
|
63
119
|
} catch {
|
|
64
120
|
// lsof not found or no process on port — that's fine
|
|
65
121
|
}
|