@hamedb89/localghost 0.3.0 → 0.4.1
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 +30 -4
- package/dist/cli.js +133 -39
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +57 -22
- package/dist/index.js.map +1 -1
- package/docs/flows.md +11 -0
- package/docs/localghost.1.md +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,23 @@ Then keep using the command your repo already expects:
|
|
|
45
45
|
npm exec localghost
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
If Localghost is not installed in the repository yet, use an explicit package-manager launcher:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
npm exec --yes --package=@hamedb89/localghost -- localghost
|
|
52
|
+
pnpm dlx @hamedb89/localghost
|
|
53
|
+
yarn dlx @hamedb89/localghost
|
|
54
|
+
bunx --package @hamedb89/localghost localghost
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
From a Localghost checkout, test a real consumer repository against the local checkout without changing the consumer's manifest or working tree. This is repository development tooling and is not part of the installed npm package:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
./bin/ghost consumer test faaast --repo /path/to/faaast-landing -- pnpm run bench:noop
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The command creates a detached worktree, installs its dependencies, builds and links the local Localghost checkout, runs the command inside the worktree, and removes the worktree afterward. Add `--keep` before `--` when inspecting the isolated checkout after a failure. The FAAAST adapter uses a separate `.consumer.test` hostname suffix to avoid colliding with a normal `.localhost` development session.
|
|
64
|
+
|
|
48
65
|
On the first interactive run, Localghost can create `.localghost`, explain the `/etc/hosts` change, write `ops/local/Caddyfile`, and print the browser-facing URL:
|
|
49
66
|
|
|
50
67
|
```txt
|
|
@@ -87,6 +104,14 @@ Create the repo-local hostname contract:
|
|
|
87
104
|
localghost init --write-scripts
|
|
88
105
|
```
|
|
89
106
|
|
|
107
|
+
Install or update Localghost in the current repository at any time:
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
npm exec --yes --package=@hamedb89/localghost -- localghost upgrade
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Once the package is installed locally, use `localghost upgrade` or the package manager's normal update command.
|
|
114
|
+
|
|
90
115
|
Check whether the machine is ready:
|
|
91
116
|
|
|
92
117
|
```sh
|
|
@@ -603,9 +628,10 @@ localghost teardown [--project name] [--remove-caddyfile]
|
|
|
603
628
|
localghost status [--ready] [--json]
|
|
604
629
|
localghost ps [--json]
|
|
605
630
|
localghost update [--json]
|
|
606
|
-
localghost
|
|
607
|
-
localghost
|
|
608
|
-
localghost
|
|
631
|
+
localghost upgrade [--cwd path]
|
|
632
|
+
localghost release [patch|minor|major]
|
|
633
|
+
localghost dev [--config file] [--config-pattern regex] [--https|--ssl] [--auto-repair yes|no] [--clean-caddy] [--trust]
|
|
634
|
+
localghost run [--config file] [--config-pattern regex] [--https|--ssl] [--auto-repair yes|no] [--clean-caddy] [--trust] [--dynamic-port yes|no] -- command
|
|
609
635
|
localghost routes [--https|--ssl]
|
|
610
636
|
localghost print [--config file] [--config-pattern regex]
|
|
611
637
|
```
|
|
@@ -640,7 +666,7 @@ import { localGhostPlugin } from "@hamedb89/localghost/vite";
|
|
|
640
666
|
- Preview the exact Pages artifact locally with `npm run site:serve`, then open `http://127.0.0.1:4173/`.
|
|
641
667
|
- npm publish is guarded by `prepublishOnly` and the release workflow publishes with npm provenance.
|
|
642
668
|
- To release the CLI, run `localghost release patch`, `localghost release minor`, or `localghost release major`. The command dispatches the **Release** workflow from `main`; it synchronizes version metadata, verifies the package and runtime matrix, commits and tags the bump, publishes npm, and creates a GitHub Release with generated notes. GitHub CLI must be installed and authenticated.
|
|
643
|
-
- From this repository, `./bin/ghost release minor` (or the shorter `./bin/c release minor`) pushes `main` and dispatches the same guarded GitHub release workflow. Use `./bin/ghost check` for the release verification locally, `./bin/ghost release status` to inspect recent runs, or `./bin/ghost release retry v0.
|
|
669
|
+
- From this repository, `./bin/ghost release minor` (or the shorter `./bin/c release minor`) pushes `main` and dispatches the same guarded GitHub release workflow. Use `./bin/ghost check` for the release verification locally, `./bin/ghost release status` to inspect recent runs, or `./bin/ghost release retry v0.4.0` to retry publishing an existing tag.
|
|
644
670
|
- Runtime dependencies are intentionally small: `commander` and `execa`. Vite is an optional peer dependency.
|
|
645
671
|
- No postinstall scripts, hidden Homebrew installs, surprise browser tabs, or broad hosts-file rewrites.
|
|
646
672
|
- Update checks are best-effort, cached for 24 hours, and can be disabled with `LOCALGHOST_NO_UPDATE_CHECK=1` or `--no-update-check`.
|
package/dist/cli.js
CHANGED
|
@@ -1821,30 +1821,44 @@ function shellQuote(value) {
|
|
|
1821
1821
|
function getConfigFlag(configFile) {
|
|
1822
1822
|
return configFile === LOCALGHOST_CONFIG_FILE ? "" : ` --config ${shellQuote(configFile)}`;
|
|
1823
1823
|
}
|
|
1824
|
-
function
|
|
1824
|
+
function hasLocalghostDependency(pkg) {
|
|
1825
|
+
return ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"].some((field) => {
|
|
1826
|
+
const dependencies = pkg[field];
|
|
1827
|
+
return typeof dependencies === "object" && dependencies !== null && "@hamedb89/localghost" in dependencies;
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
function localghostCommand(packageManager, installed) {
|
|
1831
|
+
if (installed) return "localghost";
|
|
1832
|
+
if (packageManager === "pnpm") return "pnpm dlx @hamedb89/localghost";
|
|
1833
|
+
if (packageManager === "yarn") return "yarn dlx @hamedb89/localghost";
|
|
1834
|
+
if (packageManager === "bun") return "bunx --package @hamedb89/localghost localghost";
|
|
1835
|
+
return "npm exec --yes --package=@hamedb89/localghost -- localghost";
|
|
1836
|
+
}
|
|
1837
|
+
function updatePackageScripts(packageJsonPath, configFile, packageManager) {
|
|
1825
1838
|
const pkg = readPackageJson2(packageJsonPath);
|
|
1826
1839
|
if (!pkg) return false;
|
|
1827
1840
|
const scripts = typeof pkg.scripts === "object" && pkg.scripts ? pkg.scripts : {};
|
|
1828
1841
|
const configFlag = getConfigFlag(configFile);
|
|
1842
|
+
const command = localghostCommand(packageManager, hasLocalghostDependency(pkg));
|
|
1829
1843
|
const nextScripts = {
|
|
1830
1844
|
...scripts,
|
|
1831
|
-
"localghost:setup": scripts["localghost:setup"] ??
|
|
1832
|
-
"localghost:proxy": scripts["localghost:proxy"] ??
|
|
1833
|
-
"localghost:proxy:https": scripts["localghost:proxy:https"] ??
|
|
1834
|
-
"localghost:run": scripts["localghost:run"] ??
|
|
1835
|
-
"localghost:ready": scripts["localghost:ready"] ??
|
|
1836
|
-
"localghost:repair": scripts["localghost:repair"] ??
|
|
1837
|
-
"localghost:trust": scripts["localghost:trust"] ??
|
|
1838
|
-
"localghost:ps": scripts["localghost:ps"] ??
|
|
1839
|
-
"localghost:print": scripts["localghost:print"] ??
|
|
1840
|
-
"localghost:routes": scripts["localghost:routes"] ??
|
|
1841
|
-
"localghost:status": scripts["localghost:status"] ??
|
|
1842
|
-
"localghost:reset": scripts["localghost:reset"] ??
|
|
1843
|
-
"localghost:teardown": scripts["localghost:teardown"] ??
|
|
1844
|
-
"localghost:doctor": scripts["localghost:doctor"] ??
|
|
1845
|
-
"localghost:update": scripts["localghost:update"] ??
|
|
1846
|
-
"caddy:setup": scripts["caddy:setup"] ??
|
|
1847
|
-
"caddy:dev": scripts["caddy:dev"] ??
|
|
1845
|
+
"localghost:setup": scripts["localghost:setup"] ?? `${command} setup${configFlag}`,
|
|
1846
|
+
"localghost:proxy": scripts["localghost:proxy"] ?? `${command} dev${configFlag}`,
|
|
1847
|
+
"localghost:proxy:https": scripts["localghost:proxy:https"] ?? `${command} dev${configFlag} --https`,
|
|
1848
|
+
"localghost:run": scripts["localghost:run"] ?? `${command} run${configFlag} --`,
|
|
1849
|
+
"localghost:ready": scripts["localghost:ready"] ?? `${command} status${configFlag} --ready`,
|
|
1850
|
+
"localghost:repair": scripts["localghost:repair"] ?? `${command} repair${configFlag}`,
|
|
1851
|
+
"localghost:trust": scripts["localghost:trust"] ?? `${command} trust${configFlag}`,
|
|
1852
|
+
"localghost:ps": scripts["localghost:ps"] ?? `${command} ps`,
|
|
1853
|
+
"localghost:print": scripts["localghost:print"] ?? `${command} print${configFlag}`,
|
|
1854
|
+
"localghost:routes": scripts["localghost:routes"] ?? `${command} routes${configFlag}`,
|
|
1855
|
+
"localghost:status": scripts["localghost:status"] ?? `${command} status`,
|
|
1856
|
+
"localghost:reset": scripts["localghost:reset"] ?? `${command} reset`,
|
|
1857
|
+
"localghost:teardown": scripts["localghost:teardown"] ?? `${command} teardown`,
|
|
1858
|
+
"localghost:doctor": scripts["localghost:doctor"] ?? `${command} doctor`,
|
|
1859
|
+
"localghost:update": scripts["localghost:update"] ?? `${command} update`,
|
|
1860
|
+
"caddy:setup": scripts["caddy:setup"] ?? `${command} setup${configFlag}`,
|
|
1861
|
+
"caddy:dev": scripts["caddy:dev"] ?? `${command} dev${configFlag}`
|
|
1848
1862
|
};
|
|
1849
1863
|
const changed = JSON.stringify(scripts) !== JSON.stringify(nextScripts);
|
|
1850
1864
|
if (!changed) return false;
|
|
@@ -1880,7 +1894,7 @@ function initLocalghost(options = {}) {
|
|
|
1880
1894
|
}
|
|
1881
1895
|
writeTextFile(configPath, renderConfig({ host, port, apiHost, apiPort }));
|
|
1882
1896
|
const packageJsonPath = join8(cwd, "package.json");
|
|
1883
|
-
const packageJsonChanged = options.writeScripts ? updatePackageScripts(packageJsonPath, configFile) : false;
|
|
1897
|
+
const packageJsonChanged = options.writeScripts ? updatePackageScripts(packageJsonPath, configFile, packageManager) : false;
|
|
1884
1898
|
return {
|
|
1885
1899
|
configPath,
|
|
1886
1900
|
configCreated: true,
|
|
@@ -1903,10 +1917,17 @@ Localghost owns the local development proxy and the app process boundary.
|
|
|
1903
1917
|
|
|
1904
1918
|
## Preferred repository setup
|
|
1905
1919
|
|
|
1906
|
-
For a normal repository, use this package script:
|
|
1920
|
+
For a normal repository with Localghost installed as a dev dependency, use this package script:
|
|
1907
1921
|
|
|
1908
1922
|
"dev": "localghost"
|
|
1909
1923
|
|
|
1924
|
+
If the repository does not have a local CLI yet, use the package-manager launcher:
|
|
1925
|
+
|
|
1926
|
+
npm exec --yes --package=@hamedb89/localghost -- localghost
|
|
1927
|
+
pnpm dlx @hamedb89/localghost
|
|
1928
|
+
yarn dlx @hamedb89/localghost
|
|
1929
|
+
bunx --package @hamedb89/localghost localghost
|
|
1930
|
+
|
|
1910
1931
|
For an explicit app command, keep the raw command separate:
|
|
1911
1932
|
|
|
1912
1933
|
"dev": "localghost run -- vite"
|
|
@@ -1926,6 +1947,11 @@ Use \`localghost dev\` only when the Caddy proxy should run without starting the
|
|
|
1926
1947
|
- \`localghost doctor\`: check machine prerequisites, ports, and registry state.
|
|
1927
1948
|
- \`localghost repair --reallocate-port\`: move an occupied project port to a stable available port.
|
|
1928
1949
|
|
|
1950
|
+
- \`localghost update\`: check npm for a newer Localghost release.
|
|
1951
|
+
- \`localghost upgrade\`: install or update Localghost as a repository dev dependency.
|
|
1952
|
+
|
|
1953
|
+
Use \`localghost\` directly when the package is installed locally. Use \`npm exec --yes --package=@hamedb89/localghost -- localghost <command>\`, \`pnpm dlx @hamedb89/localghost <command>\`, \`yarn dlx @hamedb89/localghost <command>\`, or \`bunx --package @hamedb89/localghost localghost <command>\` when it is not.
|
|
1954
|
+
|
|
1929
1955
|
## Configuration
|
|
1930
1956
|
|
|
1931
1957
|
- Commit repository defaults in \`localghost.config.mjs\`.
|
|
@@ -1942,6 +1968,14 @@ function formatLocalghostAgentGuide(format = "text") {
|
|
|
1942
1968
|
if (format === "json") {
|
|
1943
1969
|
return JSON.stringify({
|
|
1944
1970
|
preferredScript: "localghost",
|
|
1971
|
+
packageInstall: "npm install -D @hamedb89/localghost",
|
|
1972
|
+
packageUpgrade: "localghost upgrade",
|
|
1973
|
+
packageLaunchers: {
|
|
1974
|
+
npm: "npm exec --yes --package=@hamedb89/localghost -- localghost",
|
|
1975
|
+
pnpm: "pnpm dlx @hamedb89/localghost",
|
|
1976
|
+
yarn: "yarn dlx @hamedb89/localghost",
|
|
1977
|
+
bun: "bunx --package @hamedb89/localghost localghost"
|
|
1978
|
+
},
|
|
1945
1979
|
explicitScript: "localghost run -- <command>",
|
|
1946
1980
|
proxyOnlyCommand: "localghost dev",
|
|
1947
1981
|
inspectionCommands: ["localghost status --ready", "localghost ps --json", "localghost routes", "localghost doctor"],
|
|
@@ -2068,7 +2102,7 @@ import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as rea
|
|
|
2068
2102
|
import { homedir as homedir3 } from "os";
|
|
2069
2103
|
import { dirname as dirname4, join as join10 } from "path";
|
|
2070
2104
|
var LOCALGHOST_PACKAGE_NAME = "@hamedb89/localghost";
|
|
2071
|
-
var LOCALGHOST_VERSION = "0.
|
|
2105
|
+
var LOCALGHOST_VERSION = "0.4.1";
|
|
2072
2106
|
var UPDATE_CHECK_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2073
2107
|
var UPDATE_CHECK_NOTIFY_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2074
2108
|
var UPDATE_CHECK_TIMEOUT_MS = 900;
|
|
@@ -2196,7 +2230,8 @@ function formatUpdateMessage(result) {
|
|
|
2196
2230
|
if (!result.updateAvailable || !result.latestVersion) return null;
|
|
2197
2231
|
return [
|
|
2198
2232
|
`localghost ${result.latestVersion} is available. Current: ${result.currentVersion}`,
|
|
2199
|
-
|
|
2233
|
+
"Update a repository with: npm exec --yes --package=@hamedb89/localghost -- localghost upgrade",
|
|
2234
|
+
"If Localghost is already installed locally, run: localghost upgrade"
|
|
2200
2235
|
].join("\n");
|
|
2201
2236
|
}
|
|
2202
2237
|
function shouldNotifyAboutUpdate(result, cachePath = getUpdateCheckCachePath(), now = Date.now()) {
|
|
@@ -2508,6 +2543,21 @@ function registerCleanup(id) {
|
|
|
2508
2543
|
process.off("exit", cleanup);
|
|
2509
2544
|
};
|
|
2510
2545
|
}
|
|
2546
|
+
function registerSignalShutdown(stop) {
|
|
2547
|
+
let requested = false;
|
|
2548
|
+
const request = () => {
|
|
2549
|
+
if (requested) return;
|
|
2550
|
+
requested = true;
|
|
2551
|
+
stop();
|
|
2552
|
+
};
|
|
2553
|
+
process.once("SIGINT", request);
|
|
2554
|
+
process.once("SIGTERM", request);
|
|
2555
|
+
return () => {
|
|
2556
|
+
process.off("SIGINT", request);
|
|
2557
|
+
process.off("SIGTERM", request);
|
|
2558
|
+
request();
|
|
2559
|
+
};
|
|
2560
|
+
}
|
|
2511
2561
|
async function resolveServiceRuntimeEntries(services, dynamicPort, projectCwd) {
|
|
2512
2562
|
const usedPorts = /* @__PURE__ */ new Set();
|
|
2513
2563
|
const resolved = [];
|
|
@@ -2563,6 +2613,24 @@ async function waitForPortsToBeAvailable(entries, timeoutMs = 1e4) {
|
|
|
2563
2613
|
}
|
|
2564
2614
|
return false;
|
|
2565
2615
|
}
|
|
2616
|
+
async function waitForProcessShutdown(processes, forceStop, timeoutMs = 1e4) {
|
|
2617
|
+
const settled = Promise.allSettled(processes);
|
|
2618
|
+
const completed = await Promise.race([
|
|
2619
|
+
settled.then(() => true),
|
|
2620
|
+
wait2(timeoutMs).then(() => false)
|
|
2621
|
+
]);
|
|
2622
|
+
if (completed) return true;
|
|
2623
|
+
console.warn("Localghost: timed out waiting for managed processes to stop; escalating termination.");
|
|
2624
|
+
forceStop("SIGTERM");
|
|
2625
|
+
const terminated = await Promise.race([
|
|
2626
|
+
settled.then(() => true),
|
|
2627
|
+
wait2(2e3).then(() => false)
|
|
2628
|
+
]);
|
|
2629
|
+
if (terminated) return true;
|
|
2630
|
+
forceStop("SIGKILL");
|
|
2631
|
+
await Promise.race([settled, wait2(1e3)]);
|
|
2632
|
+
return false;
|
|
2633
|
+
}
|
|
2566
2634
|
async function runDetectedServices(options) {
|
|
2567
2635
|
assertLocalDevelopment("run");
|
|
2568
2636
|
await assertCaddyReady();
|
|
@@ -2628,6 +2696,13 @@ async function runDetectedServices(options) {
|
|
|
2628
2696
|
});
|
|
2629
2697
|
const cleanupRun = registerCleanup(runRecord.id);
|
|
2630
2698
|
const processExit = Promise.race([caddyExit, ...children]);
|
|
2699
|
+
const stopManaged = (signal) => {
|
|
2700
|
+
for (const child of children) {
|
|
2701
|
+
signalManagedProcess(child, signal);
|
|
2702
|
+
}
|
|
2703
|
+
signalManagedProcess(caddy, signal);
|
|
2704
|
+
};
|
|
2705
|
+
const finishShutdown = registerSignalShutdown(() => stopManaged("SIGINT"));
|
|
2631
2706
|
try {
|
|
2632
2707
|
const ready = await Promise.race([
|
|
2633
2708
|
waitForServicePorts(entries),
|
|
@@ -2639,13 +2714,17 @@ async function runDetectedServices(options) {
|
|
|
2639
2714
|
}
|
|
2640
2715
|
await processExit;
|
|
2641
2716
|
} finally {
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2717
|
+
finishShutdown();
|
|
2718
|
+
await waitForProcessShutdown(
|
|
2719
|
+
[caddyExit, ...children],
|
|
2720
|
+
stopManaged
|
|
2721
|
+
);
|
|
2647
2722
|
if (!await waitForPortsToBeAvailable(entries)) {
|
|
2648
2723
|
console.warn("Localghost: timed out waiting for service ports to be released.");
|
|
2724
|
+
stopManaged("SIGTERM");
|
|
2725
|
+
if (!await waitForPortsToBeAvailable(entries, 2e3)) {
|
|
2726
|
+
stopManaged("SIGKILL");
|
|
2727
|
+
}
|
|
2649
2728
|
}
|
|
2650
2729
|
cleanupRun();
|
|
2651
2730
|
}
|
|
@@ -2746,7 +2825,7 @@ function formatInstanceViews(instances) {
|
|
|
2746
2825
|
var program = new Command();
|
|
2747
2826
|
program.name("localghost").description("Buh. Friendly local hostnames for app repos.").version(LOCALGHOST_VERSION).option("--no-update-check", "Skip the npm update check for this run");
|
|
2748
2827
|
program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
2749
|
-
if (
|
|
2828
|
+
if (["update", "upgrade", "release"].includes(actionCommand.name())) return;
|
|
2750
2829
|
const options = program.opts();
|
|
2751
2830
|
await maybeNotifyAboutUpdate({ disabled: options.updateCheck === false });
|
|
2752
2831
|
});
|
|
@@ -2825,7 +2904,15 @@ program.command("update").description("Check npm for a newer localghost release"
|
|
|
2825
2904
|
}
|
|
2826
2905
|
console.log(`localghost is up to date. Current: ${result.currentVersion}`);
|
|
2827
2906
|
});
|
|
2828
|
-
program.command("
|
|
2907
|
+
program.command("upgrade").description("Install or update Localghost in the current repository").option("--cwd <path>", "Consumer repository", process.cwd()).action(async (options) => {
|
|
2908
|
+
const packageManager = detectPackageManager(options.cwd);
|
|
2909
|
+
const packageName = "@hamedb89/localghost@latest";
|
|
2910
|
+
const args = packageManager === "yarn" ? ["add", "--dev", packageName] : packageManager === "pnpm" ? ["add", "--save-dev", packageName] : packageManager === "bun" ? ["add", "--dev", packageName] : ["install", "--save-dev", packageName];
|
|
2911
|
+
console.log(`Upgrading ${packageName} with ${packageManager}...`);
|
|
2912
|
+
await execa4(packageManager, args, { cwd: options.cwd, stdio: "inherit" });
|
|
2913
|
+
console.log(`Localghost is upgraded in ${options.cwd}.`);
|
|
2914
|
+
});
|
|
2915
|
+
program.command("release").description("Dispatch an automated Localghost CLI release").argument("[bump]", "Semantic version increment: patch, minor, or major (default: patch)", parseReleaseBump, "patch").action(async (bump) => {
|
|
2829
2916
|
const repository = "hamedb89/localghost";
|
|
2830
2917
|
try {
|
|
2831
2918
|
await execa4("gh", [
|
|
@@ -3223,20 +3310,25 @@ program.command("run").description("Run Caddy and a dev command from the same Lo
|
|
|
3223
3310
|
entries: context.entries
|
|
3224
3311
|
});
|
|
3225
3312
|
const cleanupRun = registerCleanup(runRecord.id);
|
|
3226
|
-
const
|
|
3227
|
-
signalManagedProcess(
|
|
3228
|
-
|
|
3229
|
-
const stopChild = () => {
|
|
3230
|
-
signalManagedProcess(child, "SIGINT");
|
|
3313
|
+
const stopManaged = (signal) => {
|
|
3314
|
+
signalManagedProcess(child, signal);
|
|
3315
|
+
signalManagedProcess(caddy, signal);
|
|
3231
3316
|
};
|
|
3317
|
+
const finishShutdown = registerSignalShutdown(() => stopManaged("SIGINT"));
|
|
3232
3318
|
try {
|
|
3233
3319
|
await Promise.race([child, caddyExit]);
|
|
3234
3320
|
} finally {
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3321
|
+
finishShutdown();
|
|
3322
|
+
await waitForProcessShutdown(
|
|
3323
|
+
[child, caddyExit],
|
|
3324
|
+
stopManaged
|
|
3325
|
+
);
|
|
3238
3326
|
if (!await waitForPortsToBeAvailable(context.entries)) {
|
|
3239
3327
|
console.warn("Localghost: timed out waiting for service ports to be released.");
|
|
3328
|
+
stopManaged("SIGTERM");
|
|
3329
|
+
if (!await waitForPortsToBeAvailable(context.entries, 2e3)) {
|
|
3330
|
+
stopManaged("SIGKILL");
|
|
3331
|
+
}
|
|
3240
3332
|
}
|
|
3241
3333
|
cleanupRun();
|
|
3242
3334
|
await context.releasePort?.();
|
|
@@ -3415,9 +3507,11 @@ async function main() {
|
|
|
3415
3507
|
...detected.command
|
|
3416
3508
|
]);
|
|
3417
3509
|
}
|
|
3418
|
-
main().
|
|
3510
|
+
main().then(() => {
|
|
3511
|
+
process.exit(process.exitCode ?? 0);
|
|
3512
|
+
}).catch((error) => {
|
|
3419
3513
|
const message = error instanceof Error ? error.message : String(error);
|
|
3420
3514
|
console.error(message);
|
|
3421
|
-
process.
|
|
3515
|
+
process.exit(1);
|
|
3422
3516
|
});
|
|
3423
3517
|
//# sourceMappingURL=cli.js.map
|