@hienlh/ppm 0.12.10 → 0.12.11
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/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/src/cli/commands/autostart.ts +1 -3
- package/src/cli/commands/init.ts +5 -8
- package/src/cli/commands/restart.ts +4 -5
- package/src/index.ts +0 -5
- package/src/server/index.ts +8 -13
- package/src/services/autostart-generator.ts +1 -6
- package/src/services/config.service.ts +3 -96
- package/src/services/ppmbot/cli-reference-default.ts +1 -4
- package/src/services/supervisor.ts +4 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.12.11] - 2026-04-21
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Upgrade wiped user config back to defaults**: `configService.importFromYaml()` unconditionally overwrote SQLite config keys with `{...DEFAULT_CONFIG, ...yaml}` on every `load()` call. The upgrade path via supervisor `selfReplace()` re-ran the saved `originalArgv` — which contained `-c <yaml>` baked into systemd/launchd `ExecStart` — re-triggering the overwrite and resetting user config to defaults + stale YAML contents
|
|
7
|
+
|
|
8
|
+
### Removed
|
|
9
|
+
- **Legacy YAML config support**: Fully migrated to SQLite; removed `-c/--config <path>` CLI flag (from `start`, `restart`, `open`, `autostart enable`), YAML import/migration code, `configPath` in autostart ExecStart, and `__serve__`/`__supervise__` positional config slot. `js-yaml` dep retained (skill frontmatter only)
|
|
10
|
+
|
|
3
11
|
## [0.12.10] - 2026-04-21
|
|
4
12
|
|
|
5
13
|
### Fixed
|
package/package.json
CHANGED
|
@@ -11,12 +11,11 @@ export function registerAutoStartCommands(program: Command): void {
|
|
|
11
11
|
.description("Register PPM to start automatically on boot")
|
|
12
12
|
.option("-p, --port <port>", "Override port")
|
|
13
13
|
.option("-s, --share", "(deprecated) Tunnel is now always enabled")
|
|
14
|
-
.option("-c, --config <path>", "Config file path")
|
|
15
14
|
.option("--profile <name>", "DB profile name")
|
|
16
15
|
.action(async (options) => {
|
|
17
16
|
const { enableAutoStart } = await import("../../services/autostart-register.ts");
|
|
18
17
|
|
|
19
|
-
configService.load(
|
|
18
|
+
configService.load();
|
|
20
19
|
const port = parseInt(options.port ?? String(configService.get("port")), 10);
|
|
21
20
|
const host = configService.get("host") ?? "0.0.0.0";
|
|
22
21
|
|
|
@@ -24,7 +23,6 @@ export function registerAutoStartCommands(program: Command): void {
|
|
|
24
23
|
port,
|
|
25
24
|
host,
|
|
26
25
|
share: !!options.share,
|
|
27
|
-
configPath: options.config,
|
|
28
26
|
profile: options.profile,
|
|
29
27
|
};
|
|
30
28
|
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { resolve, basename } from "node:path";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { getPpmDir } from "../../services/ppm-dir.ts";
|
|
5
3
|
import { input, confirm, select, password } from "@inquirer/prompts";
|
|
6
4
|
import { configService } from "../../services/config.service.ts";
|
|
7
5
|
import { projectService } from "../../services/project.service.ts";
|
|
@@ -19,15 +17,14 @@ export interface InitOptions {
|
|
|
19
17
|
yes?: boolean;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
/** Check if config already exists */
|
|
23
|
-
/** Check if config already exists (DB or legacy YAML) */
|
|
20
|
+
/** Check if config already exists in SQLite */
|
|
24
21
|
export function hasConfig(): boolean {
|
|
25
22
|
try {
|
|
26
23
|
const dbConfig = getAllConfig();
|
|
27
|
-
|
|
28
|
-
} catch {
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
return Object.keys(dbConfig).length > 0;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
export async function initProject(options: InitOptions = {}) {
|
|
@@ -8,7 +8,7 @@ const restartingFlag = () => resolve(getPpmDir(), ".restarting");
|
|
|
8
8
|
const restartResult = () => resolve(getPpmDir(), ".restart-result");
|
|
9
9
|
|
|
10
10
|
/** Restart only the server process, keeping the tunnel alive */
|
|
11
|
-
export async function restartServer(options: {
|
|
11
|
+
export async function restartServer(options: { force?: boolean }) {
|
|
12
12
|
// Ignore SIGHUP so this process survives when PPM terminal dies
|
|
13
13
|
process.on("SIGHUP", () => {});
|
|
14
14
|
|
|
@@ -114,7 +114,7 @@ export async function restartServer(options: { config?: string; force?: boolean
|
|
|
114
114
|
: resolve(import.meta.dir, "../../server/index.ts");
|
|
115
115
|
|
|
116
116
|
const { configService } = await import("../../services/config.service.ts");
|
|
117
|
-
configService.load(
|
|
117
|
+
configService.load();
|
|
118
118
|
const port = status.port as number ?? configService.get("port");
|
|
119
119
|
const host = status.host as string ?? configService.get("host");
|
|
120
120
|
|
|
@@ -133,7 +133,6 @@ export async function restartServer(options: { config?: string; force?: boolean
|
|
|
133
133
|
// terminal (and its process group) to receive SIGHUP.
|
|
134
134
|
const params = JSON.stringify({
|
|
135
135
|
serverPid, port, host, serverScript,
|
|
136
|
-
config: options.config ?? "",
|
|
137
136
|
statusFile: statusFile(),
|
|
138
137
|
pidFile: pidFile(),
|
|
139
138
|
restartingFlag: restartingFlag(),
|
|
@@ -204,8 +203,8 @@ async function main() {
|
|
|
204
203
|
// Compiled binary: execPath IS the server, no "run script" needed
|
|
205
204
|
const isCompiled = !process.execPath.includes("bun");
|
|
206
205
|
const serverArgs = isCompiled
|
|
207
|
-
? ["__serve__", String(P.port), P.host
|
|
208
|
-
: ["run", P.serverScript, "__serve__", String(P.port), P.host
|
|
206
|
+
? ["__serve__", String(P.port), P.host]
|
|
207
|
+
: ["run", P.serverScript, "__serve__", String(P.port), P.host];
|
|
209
208
|
|
|
210
209
|
if (process.platform === "win32") {
|
|
211
210
|
const bunExe = process.execPath.replace(/\\\\/g, "\\\\\\\\");
|
package/src/index.ts
CHANGED
|
@@ -18,15 +18,12 @@ program
|
|
|
18
18
|
.description("Start the PPM server (background by default)")
|
|
19
19
|
.option("-p, --port <port>", "Port to listen on")
|
|
20
20
|
.option("-s, --share", "(deprecated) Tunnel is now always enabled")
|
|
21
|
-
.option("-c, --config <path>", "Path to config file (YAML import into DB)")
|
|
22
21
|
.option("--profile <name>", "DB profile name (e.g. 'dev' → ppm.dev.db)")
|
|
23
22
|
.action(async (options) => {
|
|
24
23
|
// Set DB profile before any DB access
|
|
25
24
|
const { setDbProfile } = await import("./services/db.service.ts");
|
|
26
25
|
if (options.profile) {
|
|
27
26
|
setDbProfile(options.profile);
|
|
28
|
-
} else if (options.config && /dev/i.test(options.config)) {
|
|
29
|
-
setDbProfile("dev");
|
|
30
27
|
}
|
|
31
28
|
// Auto-init on first run
|
|
32
29
|
const { hasConfig, initProject } = await import("./cli/commands/init.ts");
|
|
@@ -58,7 +55,6 @@ program
|
|
|
58
55
|
program
|
|
59
56
|
.command("restart")
|
|
60
57
|
.description("Restart the server (keeps tunnel alive)")
|
|
61
|
-
.option("-c, --config <path>", "Path to config file")
|
|
62
58
|
.option("--force", "Force resume from paused state")
|
|
63
59
|
.action(async (options) => {
|
|
64
60
|
const { restartServer } = await import("./cli/commands/restart.ts");
|
|
@@ -78,7 +74,6 @@ program
|
|
|
78
74
|
program
|
|
79
75
|
.command("open")
|
|
80
76
|
.description("Open PPM in browser")
|
|
81
|
-
.option("-c, --config <path>", "Path to config file")
|
|
82
77
|
.action(async () => {
|
|
83
78
|
const { openBrowser } = await import("./cli/commands/open.ts");
|
|
84
79
|
await openBrowser();
|
package/src/server/index.ts
CHANGED
|
@@ -219,14 +219,13 @@ async function waitForServerReady(statusFile: string, port: number) {
|
|
|
219
219
|
export async function startServer(options: {
|
|
220
220
|
port?: string;
|
|
221
221
|
share?: boolean;
|
|
222
|
-
config?: string;
|
|
223
222
|
profile?: string;
|
|
224
223
|
}) {
|
|
225
224
|
// Tunnel always enabled — cloudflared shares the server publicly
|
|
226
225
|
options.share = true;
|
|
227
226
|
|
|
228
227
|
// Load config
|
|
229
|
-
configService.load(
|
|
228
|
+
configService.load();
|
|
230
229
|
const port = parseInt(options.port ?? String(configService.get("port")), 10);
|
|
231
230
|
const host = configService.get("host");
|
|
232
231
|
|
|
@@ -368,11 +367,11 @@ export async function startServer(options: {
|
|
|
368
367
|
if (process.platform === "linux") {
|
|
369
368
|
// Update service file in case config changed (port, share, etc.)
|
|
370
369
|
const { enableAutoStart } = await import("../services/autostart-register.ts");
|
|
371
|
-
await enableAutoStart({ port, host, share: !!options.share,
|
|
370
|
+
await enableAutoStart({ port, host, share: !!options.share, profile: options.profile });
|
|
372
371
|
startedViaService = true;
|
|
373
372
|
} else if (process.platform === "darwin") {
|
|
374
373
|
const { enableAutoStart } = await import("../services/autostart-register.ts");
|
|
375
|
-
await enableAutoStart({ port, host, share: !!options.share,
|
|
374
|
+
await enableAutoStart({ port, host, share: !!options.share, profile: options.profile });
|
|
376
375
|
startedViaService = true;
|
|
377
376
|
}
|
|
378
377
|
}
|
|
@@ -392,7 +391,7 @@ export async function startServer(options: {
|
|
|
392
391
|
} else if (process.platform === "win32") {
|
|
393
392
|
const superviseArgs = [
|
|
394
393
|
"__supervise__", String(port), host,
|
|
395
|
-
options.
|
|
394
|
+
options.profile ?? "",
|
|
396
395
|
];
|
|
397
396
|
if (options.share) superviseArgs.push("--share");
|
|
398
397
|
while (superviseArgs.length > 1 && superviseArgs[superviseArgs.length - 1] === "") superviseArgs.pop();
|
|
@@ -423,7 +422,7 @@ export async function startServer(options: {
|
|
|
423
422
|
} else {
|
|
424
423
|
const superviseArgs = [
|
|
425
424
|
"__supervise__", String(port), host,
|
|
426
|
-
options.
|
|
425
|
+
options.profile ?? "",
|
|
427
426
|
];
|
|
428
427
|
if (options.share) superviseArgs.push("--share");
|
|
429
428
|
while (superviseArgs.length > 1 && superviseArgs[superviseArgs.length - 1] === "") superviseArgs.pop();
|
|
@@ -508,7 +507,6 @@ export async function startServer(options: {
|
|
|
508
507
|
const autoConfig = {
|
|
509
508
|
port, host,
|
|
510
509
|
share: !!options.share,
|
|
511
|
-
configPath: options.config,
|
|
512
510
|
profile: options.profile,
|
|
513
511
|
};
|
|
514
512
|
// skipStart: supervisor is already running from direct spawn above
|
|
@@ -532,18 +530,15 @@ if (process.argv.includes("__serve__")) {
|
|
|
532
530
|
const idx = process.argv.indexOf("__serve__");
|
|
533
531
|
const port = parseInt(process.argv[idx + 1] ?? "8080", 10);
|
|
534
532
|
const host = process.argv[idx + 2] ?? "0.0.0.0";
|
|
535
|
-
const
|
|
536
|
-
const profileArg = process.argv[idx + 4] && process.argv[idx + 4] !== "_" ? process.argv[idx + 4] : undefined;
|
|
533
|
+
const profileArg = process.argv[idx + 3] && process.argv[idx + 3] !== "_" ? process.argv[idx + 3] : undefined;
|
|
537
534
|
|
|
538
|
-
// Set DB profile for daemon child
|
|
535
|
+
// Set DB profile for daemon child
|
|
539
536
|
const { setDbProfile } = await import("../services/db.service.ts");
|
|
540
537
|
if (profileArg) {
|
|
541
538
|
setDbProfile(profileArg);
|
|
542
|
-
} else if (configPath && /dev/i.test(configPath)) {
|
|
543
|
-
setDbProfile("dev");
|
|
544
539
|
}
|
|
545
540
|
|
|
546
|
-
configService.load(
|
|
541
|
+
configService.load();
|
|
547
542
|
await setupLogFile();
|
|
548
543
|
|
|
549
544
|
// Sync externally-started tunnel URL + PID into tunnelService
|
|
@@ -5,7 +5,6 @@ export interface AutoStartConfig {
|
|
|
5
5
|
port: number;
|
|
6
6
|
host: string;
|
|
7
7
|
share: boolean;
|
|
8
|
-
configPath?: string;
|
|
9
8
|
profile?: string;
|
|
10
9
|
}
|
|
11
10
|
|
|
@@ -44,20 +43,16 @@ export function buildExecCommand(config: AutoStartConfig): string[] {
|
|
|
44
43
|
if (isCompiledBinary()) {
|
|
45
44
|
// Compiled binary: just run self with __supervise__ args
|
|
46
45
|
const args = [process.execPath, "__supervise__", String(config.port), config.host];
|
|
47
|
-
if (config.configPath) args.push(config.configPath);
|
|
48
46
|
if (config.profile) args.push(config.profile);
|
|
49
47
|
if (config.share) args.push("--share");
|
|
50
48
|
return args;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
// Bun runtime: bun run <script> __supervise__ <port> <host> [
|
|
51
|
+
// Bun runtime: bun run <script> __supervise__ <port> <host> [profile]
|
|
54
52
|
const bunPath = resolveBunPath();
|
|
55
53
|
const scriptPath = resolve(import.meta.dir, "supervisor.ts");
|
|
56
54
|
const args = [bunPath, "run", scriptPath, "__supervise__", String(config.port), config.host];
|
|
57
|
-
if (config.configPath) args.push(config.configPath);
|
|
58
|
-
else args.push(""); // placeholder
|
|
59
55
|
if (config.profile) args.push(config.profile);
|
|
60
|
-
else args.push(""); // placeholder
|
|
61
56
|
if (config.share) args.push("--share");
|
|
62
57
|
return args;
|
|
63
58
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { existsSync, readFileSync, renameSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
1
|
import { randomBytes } from "node:crypto";
|
|
4
2
|
import type { PpmConfig, ProjectConfig } from "../types/config.ts";
|
|
5
3
|
import { DEFAULT_CONFIG, sanitizeConfig } from "../types/config.ts";
|
|
@@ -15,7 +13,6 @@ import {
|
|
|
15
13
|
getProjectSettingsJson,
|
|
16
14
|
patchProjectSettingsJson,
|
|
17
15
|
} from "./db.service.ts";
|
|
18
|
-
import { getPpmDir } from "./ppm-dir.ts";
|
|
19
16
|
|
|
20
17
|
/** Top-level config keys stored in the config table (not projects) */
|
|
21
18
|
const CONFIG_TABLE_KEYS: (keyof PpmConfig)[] = [
|
|
@@ -32,20 +29,8 @@ export const FILE_CONFIG_KEYS = {
|
|
|
32
29
|
class ConfigService {
|
|
33
30
|
private config: PpmConfig = structuredClone(DEFAULT_CONFIG);
|
|
34
31
|
|
|
35
|
-
/** Load config from
|
|
36
|
-
load(
|
|
37
|
-
// Import explicit YAML if provided (e.g. `ppm start -c path`)
|
|
38
|
-
if (explicitPath && existsSync(explicitPath)) {
|
|
39
|
-
this.importFromYaml(explicitPath);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Auto-migrate: if config.yaml exists but DB has no config rows
|
|
43
|
-
// Skip migration when using in-memory DB (tests)
|
|
44
|
-
if (!getDbFilePath().includes(":memory:")) {
|
|
45
|
-
this.migrateYamlIfNeeded();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Load from DB
|
|
32
|
+
/** Load config from SQLite. Creates defaults if DB is empty. */
|
|
33
|
+
load(): PpmConfig {
|
|
49
34
|
const dbConfig = getAllConfig();
|
|
50
35
|
const dbProjects = getProjects();
|
|
51
36
|
|
|
@@ -102,7 +87,7 @@ class ConfigService {
|
|
|
102
87
|
return this.config;
|
|
103
88
|
}
|
|
104
89
|
|
|
105
|
-
/** Get the DB file path
|
|
90
|
+
/** Get the DB file path */
|
|
106
91
|
getConfigPath(): string {
|
|
107
92
|
return getDbFilePath();
|
|
108
93
|
}
|
|
@@ -184,84 +169,6 @@ class ConfigService {
|
|
|
184
169
|
stmt.run(p.path, p.name, p.color ?? null, i);
|
|
185
170
|
}
|
|
186
171
|
}
|
|
187
|
-
|
|
188
|
-
private migrateYamlIfNeeded(): void {
|
|
189
|
-
const yamlPaths = [
|
|
190
|
-
resolve(getPpmDir(), "config.yaml"),
|
|
191
|
-
resolve(getPpmDir(), "config.dev.yaml"),
|
|
192
|
-
];
|
|
193
|
-
for (const yamlPath of yamlPaths) {
|
|
194
|
-
if (!existsSync(yamlPath)) continue;
|
|
195
|
-
const existing = getAllConfig();
|
|
196
|
-
if (Object.keys(existing).length > 0) return;
|
|
197
|
-
this.importFromYaml(yamlPath);
|
|
198
|
-
try {
|
|
199
|
-
renameSync(yamlPath, yamlPath + ".bak");
|
|
200
|
-
console.log(`[config] Migrated ${yamlPath} → SQLite (backup: .bak)`);
|
|
201
|
-
} catch {}
|
|
202
|
-
}
|
|
203
|
-
this.migrateSessionMapIfNeeded();
|
|
204
|
-
this.migratePushSubsIfNeeded();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
private importFromYaml(path: string): void {
|
|
208
|
-
try {
|
|
209
|
-
const yaml = require("js-yaml");
|
|
210
|
-
const raw = readFileSync(path, "utf-8");
|
|
211
|
-
const parsed = yaml.load(raw) as Partial<PpmConfig> | null;
|
|
212
|
-
if (!parsed) return;
|
|
213
|
-
const merged = { ...structuredClone(DEFAULT_CONFIG), ...parsed };
|
|
214
|
-
for (const key of CONFIG_TABLE_KEYS) {
|
|
215
|
-
const value = (merged as any)[key];
|
|
216
|
-
if (value !== undefined) {
|
|
217
|
-
setConfigValue(String(key), JSON.stringify(value));
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (merged.projects?.length) {
|
|
221
|
-
this.syncProjectsToDb(merged.projects);
|
|
222
|
-
}
|
|
223
|
-
} catch (err) {
|
|
224
|
-
console.error(`[config] Error importing YAML ${path}:`, (err as Error).message);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
private migrateSessionMapIfNeeded(): void {
|
|
229
|
-
const mapPath = resolve(getPpmDir(), "session-map.json");
|
|
230
|
-
if (!existsSync(mapPath)) return;
|
|
231
|
-
try {
|
|
232
|
-
const { setSessionMetadata } = require("./db.service.ts");
|
|
233
|
-
const map = JSON.parse(readFileSync(mapPath, "utf-8")) as Record<string, string>;
|
|
234
|
-
for (const [_ppmId, sdkId] of Object.entries(map)) {
|
|
235
|
-
// Use SDK ID as canonical session ID (ppmId is legacy)
|
|
236
|
-
setSessionMetadata(sdkId);
|
|
237
|
-
}
|
|
238
|
-
renameSync(mapPath, mapPath + ".bak");
|
|
239
|
-
console.log("[config] Migrated session-map.json → SQLite");
|
|
240
|
-
} catch {}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private migratePushSubsIfNeeded(): void {
|
|
244
|
-
const subsPath = resolve(getPpmDir(), "push-subscriptions.json");
|
|
245
|
-
if (!existsSync(subsPath)) return;
|
|
246
|
-
try {
|
|
247
|
-
const { upsertPushSubscription } = require("./db.service.ts");
|
|
248
|
-
const subs = JSON.parse(readFileSync(subsPath, "utf-8")) as Array<{
|
|
249
|
-
endpoint: string;
|
|
250
|
-
keys: { p256dh: string; auth: string };
|
|
251
|
-
expirationTime?: number | null;
|
|
252
|
-
}>;
|
|
253
|
-
for (const sub of subs) {
|
|
254
|
-
upsertPushSubscription(
|
|
255
|
-
sub.endpoint,
|
|
256
|
-
sub.keys.p256dh,
|
|
257
|
-
sub.keys.auth,
|
|
258
|
-
sub.expirationTime != null ? String(sub.expirationTime) : null,
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
renameSync(subsPath, subsPath + ".bak");
|
|
262
|
-
console.log("[config] Migrated push-subscriptions.json → SQLite");
|
|
263
|
-
} catch {}
|
|
264
|
-
}
|
|
265
172
|
}
|
|
266
173
|
|
|
267
174
|
/** Singleton config service */
|
|
@@ -13,7 +13,7 @@ ppm start
|
|
|
13
13
|
Start the PPM server (background by default)
|
|
14
14
|
-p, --port <port> — Port to listen on
|
|
15
15
|
-s, --share — (deprecated) Tunnel is now always enabled
|
|
16
|
-
|
|
16
|
+
--profile <name> — DB profile name (e.g. 'dev' → ppm.dev.db)
|
|
17
17
|
|
|
18
18
|
ppm stop
|
|
19
19
|
Stop the PPM server (supervisor stays alive)
|
|
@@ -25,7 +25,6 @@ ppm down
|
|
|
25
25
|
|
|
26
26
|
ppm restart
|
|
27
27
|
Restart the server (keeps tunnel alive)
|
|
28
|
-
-c, --config <path> — Path to config file
|
|
29
28
|
--force — Force resume from paused state
|
|
30
29
|
|
|
31
30
|
ppm status
|
|
@@ -35,7 +34,6 @@ ppm status
|
|
|
35
34
|
|
|
36
35
|
ppm open
|
|
37
36
|
Open PPM in browser
|
|
38
|
-
-c, --config <path> — Path to config file
|
|
39
37
|
|
|
40
38
|
ppm logs
|
|
41
39
|
View PPM daemon logs
|
|
@@ -203,7 +201,6 @@ ppm autostart enable
|
|
|
203
201
|
Register PPM to start automatically on boot
|
|
204
202
|
-p, --port <port> — Override port
|
|
205
203
|
-s, --share — (deprecated) Tunnel is now always enabled
|
|
206
|
-
-c, --config <path> — Config file path
|
|
207
204
|
--profile <name> — DB profile name
|
|
208
205
|
|
|
209
206
|
ppm autostart disable
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Supervisor process — long-lived parent that manages server child + tunnel child.
|
|
3
3
|
* Respawns children on crash with exponential backoff.
|
|
4
4
|
* Health-checks server (/api/health) and tunnel URL (public probe).
|
|
5
|
-
* Entry: __supervise__ <port> <host> [
|
|
5
|
+
* Entry: __supervise__ <port> <host> [profile] [--share]
|
|
6
6
|
*/
|
|
7
7
|
import type { Subprocess } from "bun";
|
|
8
8
|
import { resolve } from "node:path";
|
|
@@ -782,7 +782,6 @@ export function shutdown() {
|
|
|
782
782
|
export async function runSupervisor(opts: {
|
|
783
783
|
port: number;
|
|
784
784
|
host: string;
|
|
785
|
-
config?: string;
|
|
786
785
|
profile?: string;
|
|
787
786
|
share: boolean;
|
|
788
787
|
}) {
|
|
@@ -822,7 +821,7 @@ export async function runSupervisor(opts: {
|
|
|
822
821
|
// Build __serve__ args
|
|
823
822
|
const serverArgs = [
|
|
824
823
|
"__serve__", String(opts.port), opts.host,
|
|
825
|
-
opts.
|
|
824
|
+
opts.profile ?? "",
|
|
826
825
|
];
|
|
827
826
|
// Strip trailing empty args
|
|
828
827
|
while (serverArgs.length > 0 && serverArgs[serverArgs.length - 1] === "") serverArgs.pop();
|
|
@@ -950,8 +949,7 @@ if (process.argv.includes("__supervise__")) {
|
|
|
950
949
|
const idx = process.argv.indexOf("__supervise__");
|
|
951
950
|
const port = parseInt(process.argv[idx + 1] ?? "8080", 10);
|
|
952
951
|
const host = process.argv[idx + 2] ?? "0.0.0.0";
|
|
953
|
-
const
|
|
954
|
-
const profile = process.argv[idx + 4] && process.argv[idx + 4] !== "_" ? process.argv[idx + 4] : undefined;
|
|
952
|
+
const profile = process.argv[idx + 3] && process.argv[idx + 3] !== "_" ? process.argv[idx + 3] : undefined;
|
|
955
953
|
const share = process.argv.includes("--share");
|
|
956
954
|
|
|
957
955
|
// Set DB profile for supervisor (needed to read config)
|
|
@@ -960,5 +958,5 @@ if (process.argv.includes("__supervise__")) {
|
|
|
960
958
|
setDbProfile(profile);
|
|
961
959
|
}
|
|
962
960
|
|
|
963
|
-
runSupervisor({ port, host,
|
|
961
|
+
runSupervisor({ port, host, profile, share });
|
|
964
962
|
}
|