relife2 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 relife2 contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # relife2 — your apps stay up. Period.
2
+
3
+ **The PM2 you wish you had from day one — without the gotchas.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/relife2)](https://www.npmjs.com/package/relife2) [![license: MIT](https://img.shields.io/badge/license-MIT-green)](./LICENSE) ![node ≥20](https://img.shields.io/badge/node-%3E%3D20-339933) ![bun first-class](https://img.shields.io/badge/bun-first--class-black) ![linux-first](https://img.shields.io/badge/linux-Oracle%209%20%7C%20Debian%20%7C%20Ubuntu-blue)
6
+
7
+ > You run 5–10 apps on one VPS. PM2 was great — until `pm2 update` silently spawned a second daemon, `pm2 save` was forgotten after a reboot, and bun apps ran as `node` with extra overhead. **relife2 is the fix.**
8
+
9
+ ---
10
+
11
+ ### Why teams switch from PM2
12
+
13
+ | PM2 pain you know | relife2 answer |
14
+ |---|---|
15
+ | `pm2 update` duplicates the God daemon → 2→4→8 daemons, OOM | **Exactly one daemon, always.** Socket bind + `flock`. Second daemon can't start. `daemon-upgrade` is explicit and locked. |
16
+ | Reboot wipes everything if you forgot `pm2 save` | **Autosave on by default.** Every change hits `snapshot.json` + journal. Reboot → `systemd` + linger → all apps back. |
17
+ | `interpreter: bun` actually runs as node | **Bun is first-class.** `bun <script>` directly, auto-detect via `bun.lockb`/`bun.lock`, `bun --hot` in dev. |
18
+ | Log files grow forever (needs pm2-logrotate) | **Built-in rotation:** `rotate --max-size --retain` with gzip, no plugin. |
19
+ | Unknown config fields silently ignored | **Honest errors:** warnings for unknown fields, errors for incompatible combos. |
20
+ | Daemon is heavy (God ~60–90 MB) | **Light:** ~20–30 MB RSS daemon, no God overhead. |
21
+
22
+ > **One command to prove it:**
23
+ > `relife2 doctor` — checks snapshot, lock, orphans, transport, uptime. PM2 has no equivalent.
24
+
25
+ ### Who is it for
26
+
27
+ - **Solo dev / small team** with 5–15 apps on a single Oracle Linux 9 / Debian / Ubuntu VPS (the primary target — developed on Windows, but **Linux-first**)
28
+ - You use **Caddy** for TLS/reverse proxy and want real supervision for the upstreams
29
+ - You ship **Bun + Node** mix (Nuxt, Astro, bots, Java services, Rust binaries)
30
+ - You are tired of babysitting processes
31
+
32
+ If you run Kubernetes for everything, you don't need this. If you run a VPS and want `systemd`-grade reliability without writing unit files by hand — you do.
33
+
34
+ ---
35
+
36
+ ### 30-second demo
37
+
38
+ ```sh
39
+ npm i -g relife2 # or: curl single binary → /usr/local/bin/relife2
40
+ relife2 start ecosystem.config.cjs
41
+ relife2 list
42
+ relife2 logs web -f # follow
43
+ relife2 doctor # 5 checks, exit 1 on error
44
+ relife2 startup # systemd user unit + loginctl enable-linger
45
+ # reboot → everything is back. No pm2 save dance.
46
+ ```
47
+
48
+ **Migrate from PM2 in one line:**
49
+
50
+ ```sh
51
+ relife2 import-pm2 ~/.pm2/dump.pm2 && relife2 list # reads PM2 dump, starts via relife2
52
+ relife2 from-caddy /etc/caddy/Caddyfile --dry-run # Caddyfile → relife2.config.cjs
53
+ ```
54
+
55
+ **Find forgotten configs (the PM2 paper trail):**
56
+
57
+ ```sh
58
+ relife2 find # scans $HOME depth 6
59
+ relife2 find --root /opt --depth 8 --json | jq .
60
+ relife2 find start # starts every stopped config it found
61
+ ```
62
+
63
+ ---
64
+
65
+ ### Features that sell themselves
66
+
67
+ - **Single binary deploy:** `bun build --compile` → `relife2-linux-x64` (~40–60 MB). No Node/Bun on the VPS. `tar.gz` / `.rpm` / `.deb` ready.
68
+ - **Forgotten-path healing:** moved from `/home/debian` to `/opt`? Configs with stale `cwd`/`script` auto-fix (tries `~/tail`, `sourceDir`, basename search) and logs `not found → auto-fixed` instead of crash-looping.
69
+ - **Caddy-native:** `from-caddy` parses `reverse_proxy`/`php_fastcgi` loopback upstreams, generates one app per port with `HOST`/`PORT`/`SITE_URL`, finds entry (`Nuxt .output/server/index.mjs` etc.), `--dry-run` plan before writing.
70
+ - **Dev that doesn't fight you:** `relife2 dev ./server.ts --watch ./src --hot` → `bun --hot` for `.ts`, `fs.watch` otherwise. `q` to quit.
71
+ - **Upgrade without drama:** `relife2 daemon-upgrade` — `save → shutdown old → spawn new → resurrect` under lock, protocol version checked. No silent second daemon.
72
+ - **Observability out of the box:** `list` / `describe` / `metrics` (daemon + per-app RSS) / `monit` TUI / `logs --lines -f`.
73
+ - **PM2-compatible config surface:** `ecosystem.config.{js,cjs,mjs,json}` + `relife2.config.ts`, all 8 `example/` configs work without edits (golden tests).
74
+
75
+ ---
76
+
77
+ ### Installation
78
+
79
+ **npm (any OS, Node ≥20):**
80
+ ```sh
81
+ npm i -g relife2
82
+ relife2 --version # relife2 1.0.0 (node)
83
+ rl2 --version # alias
84
+ ```
85
+
86
+ **Single binary (VPS — recommended, no runtime on target):**
87
+ ```sh
88
+ npm run build:single:linux # → dist/relife2-linux-x64
89
+ scp dist/relife2-linux-x64 vps:/usr/local/bin/relife2
90
+ ssh vps 'chmod +x /usr/local/bin/relife2 && relife2 --version'
91
+ # or from GitHub Releases:
92
+ curl -L https://github.com/<org>/relife2/releases/latest/download/relife2-linux-x64 -o /usr/local/bin/relife2
93
+ chmod +x /usr/local/bin/relife2
94
+ ```
95
+
96
+ **tar.gz / rpm / deb:**
97
+ ```sh
98
+ npm run dist:tar # → dist/relife2-1.0.0-linux-x64.tar.gz (binary + README + LICENSE)
99
+ npm run dist:rpm # → dist/relife2-1.0.0-1.x86_64.rpm (needs fpm)
100
+ npm run dist:deb # → dist/relife2_1.0.0_amd64.deb (uses dpkg-deb or fpm)
101
+ sudo dnf install ./dist/relife2-*.rpm # Oracle Linux / RHEL / Fedora
102
+ sudo apt install ./dist/relife2_*_amd64.deb # Debian / Ubuntu
103
+ ```
104
+ All packages install `/usr/bin/relife2` + `/usr/bin/rl2`; autostart is still `relife2 startup` (user unit) so it respects `XDG_RUNTIME_DIR`.
105
+
106
+ **Autostart (Linux):**
107
+ ```sh
108
+ relife2 startup # writes ~/.config/systemd/user/relife2.service + loginctl enable-linger
109
+ systemctl --user daemon-reload && systemctl --user enable --now relife2
110
+ systemctl --user status relife2
111
+ relife2 doctor
112
+ ```
113
+
114
+ ---
115
+
116
+ ### Quick Start
117
+
118
+ ```sh
119
+ # 1. From a config (PM2-compatible)
120
+ relife2 start ecosystem.config.cjs
121
+ relife2 list
122
+ relife2 logs myapp --lines 100
123
+ relife2 doctor
124
+
125
+ # 2. Single script
126
+ relife2 start ./server.js --name myapp -- --port 3000
127
+
128
+ # 3. Auto-discover relife2.config.* / ecosystem.config.* in cwd
129
+ relife2 start
130
+
131
+ # 4. Zero-downtime reload / scale
132
+ relife2 reload myapp
133
+ relife2 start --instances max --exec-mode cluster --env production
134
+
135
+ # 5. Find & rescue forgotten configs
136
+ relife2 find --root /opt --depth 8
137
+ relife2 find start
138
+
139
+ # 6. Caddyfile → relife2
140
+ relife2 from-caddy /etc/caddy/Caddyfile --dry-run
141
+ relife2 from-caddy /etc/caddy/Caddyfile -o relife2.config.cjs && relife2 start relife2.config.cjs
142
+ ```
143
+
144
+ More → [docs/CLI.md](./docs/CLI.md) · [docs/CONFIG.md](./docs/CONFIG.md) · [docs/INSTALL.md](./docs/INSTALL.md)
145
+
146
+ ---
147
+
148
+ ### Config at a glance
149
+
150
+ ```js
151
+ // ecosystem.config.cjs — same file you use for PM2
152
+ module.exports = {
153
+ apps: [{
154
+ name: "web",
155
+ script: "./dist/server/entry.mjs",
156
+ cwd: __dirname,
157
+ interpreter: "bun", // "bun" | "node" | "none" | "/usr/bin/python"
158
+ args: ["--port", "3000"], // string or string[]
159
+ instances: "max", // number | "max" (= cpu count)
160
+ exec_mode: "cluster",
161
+ env: { NODE_ENV: "production", PORT: "3000" },
162
+ env_production: { PORT: "4000" }, // merged with --env production
163
+ env_file: "./.env", // dotenv, does NOT override real env
164
+ out_file: "./logs/web-out.log",
165
+ error_file: "./logs/web-err.log",
166
+ merge_logs: true,
167
+ time: true,
168
+ log_date_format: "YYYY-MM-DD HH:mm:ss Z",
169
+ autorestart: true,
170
+ max_restarts: 15,
171
+ restart_delay: 3000,
172
+ min_uptime: "10s",
173
+ kill_timeout: 5000,
174
+ max_memory_restart: "512M",
175
+ cron_restart: "0 4 * * *",
176
+ watch: false, // true | false | ["./src", ".env"]
177
+ watch_delay: 1000,
178
+ wait_ready: false, // wait for process.send('ready')
179
+ }]
180
+ };
181
+ ```
182
+ Full matrix → [docs/CONFIG.md](./docs/CONFIG.md). CLI overrides: `relife2 start --env production --instances max`.
183
+
184
+ ---
185
+
186
+ ### Bun, Caddy, Linux — first-class
187
+
188
+ - **Bun:** `interpreter: "bun"` spawns `bun` directly; auto-detect via `bun.lockb`/`bun.lock` or `.ts` script; `relife2 dev ./app.ts` uses `bun --hot` (HMR); `bun relife2 ...` works (CI matrix `node`+`bun`).
189
+ - **Caddy:** Caddy does TLS/static/proxy, relife2 does supervision. `from-caddy` + `# relife2: dir=… name=…` hints.
190
+ - **Linux:** XDG-first data (`$XDG_DATA_HOME/relife2`) + runtime (`$XDG_RUNTIME_DIR/relife2`), `RELIFE2_DIR` override for tests, `/proc` RSS, `setsid` process groups, systemd `Restart=always` + `KillMode=process`. SELinux enforcing = experimental (default contexts, no custom policy — author has it disabled).
191
+
192
+ ---
193
+
194
+ ### Development & benchmark
195
+
196
+ ```sh
197
+ npm install
198
+ npm run build # → dist/cli.js (esbuild, single ESM, shebang)
199
+ npm run typecheck && npm run lint && npm test # 67 tests (m7 integrity inside)
200
+ bun dist/cli.js --version
201
+ npm run bench # startup latency + daemon RSS
202
+ npm run bench -- --pm2 # compare with PM2 (if installed)
203
+ ```
204
+ See [docs/BENCHMARK.md](./docs/BENCHMARK.md) — numbers are host-dependent, run on your VPS for truth.
205
+
206
+ ---
207
+
208
+ ### License
209
+
210
+ MIT — see [LICENSE](./LICENSE). Roadmap → [TODO.md](./TODO.md), decisions → [docs/DECISIONS.md](./docs/DECISIONS.md).