@cliftonc/cfld 0.2.1 → 0.2.2
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 +2 -0
- package/dist/cli.js +43 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# cfld
|
|
2
2
|
|
|
3
|
+
**`cfld` = cloudflare local dev.**
|
|
4
|
+
|
|
3
5
|
**One command to give your localhost a permanent public HTTPS URL — no API tokens, no teardown.**
|
|
4
6
|
|
|
5
7
|
`cfld` wraps [`cloudflared`](https://github.com/cloudflare/cloudflared) into a frictionless dev experience: the **same** custom URL every run (not a random `trycloudflare.com` one), authorized with a **browser login** (zero API tokens), reusing the same named tunnel and DNS record across restarts instead of churning them. It runs a **live dashboard** (URL, connection count, request/latency counters, tailing logs), **auto-reconnects** on edge blips, and **guards** against stealing a DNS record that belongs to another tunnel.
|
package/dist/cli.js
CHANGED
|
@@ -700,9 +700,20 @@ function startChild(options) {
|
|
|
700
700
|
const exited = new Promise((resolve) => {
|
|
701
701
|
markExited = resolve;
|
|
702
702
|
});
|
|
703
|
+
const trackedPgids = /* @__PURE__ */ new Set();
|
|
704
|
+
const trackTree = () => {
|
|
705
|
+
const pid = child.pid;
|
|
706
|
+
if (pid === void 0) return;
|
|
707
|
+
for (const g of descendantPgids(pid)) {
|
|
708
|
+
if (g > 1 && g !== process.pid) trackedPgids.add(g);
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
const poll = setInterval(trackTree, options.pollTreeMs ?? 1500);
|
|
712
|
+
poll.unref();
|
|
703
713
|
wireLines2(child, "stdout", options.onLine);
|
|
704
714
|
wireLines2(child, "stderr", options.onLine);
|
|
705
715
|
child.on("error", (err) => {
|
|
716
|
+
clearInterval(poll);
|
|
706
717
|
markExited();
|
|
707
718
|
if (stopped) return;
|
|
708
719
|
stopped = true;
|
|
@@ -710,11 +721,18 @@ function startChild(options) {
|
|
|
710
721
|
options.onLine?.(String(err.message ?? err), "stderr");
|
|
711
722
|
});
|
|
712
723
|
child.on("exit", (code, signal) => {
|
|
724
|
+
clearInterval(poll);
|
|
713
725
|
markExited();
|
|
714
726
|
if (stopped) return;
|
|
715
727
|
stopped = true;
|
|
716
728
|
options.onExit?.(code, signal);
|
|
717
729
|
});
|
|
730
|
+
const signalTree = (signal) => {
|
|
731
|
+
trackTree();
|
|
732
|
+
const pid = child.pid;
|
|
733
|
+
if (pid !== void 0) trySignalGroup(pid, signal);
|
|
734
|
+
for (const g of trackedPgids) trySignalGroup(g, signal);
|
|
735
|
+
};
|
|
718
736
|
return {
|
|
719
737
|
exited,
|
|
720
738
|
get pid() {
|
|
@@ -723,63 +741,64 @@ function startChild(options) {
|
|
|
723
741
|
stop() {
|
|
724
742
|
if (stopped) return;
|
|
725
743
|
stopped = true;
|
|
726
|
-
|
|
744
|
+
clearInterval(poll);
|
|
745
|
+
signalTree("SIGINT");
|
|
727
746
|
const t = setTimeout(() => {
|
|
728
|
-
if (child.exitCode === null && !child.signalCode)
|
|
747
|
+
if (child.exitCode === null && !child.signalCode) signalTree("SIGKILL");
|
|
729
748
|
}, 4e3);
|
|
730
749
|
t.unref();
|
|
731
750
|
},
|
|
732
751
|
kill() {
|
|
733
|
-
|
|
752
|
+
clearInterval(poll);
|
|
753
|
+
signalTree("SIGKILL");
|
|
734
754
|
}
|
|
735
755
|
};
|
|
736
756
|
}
|
|
737
|
-
function
|
|
757
|
+
function descendantPgids(pid) {
|
|
738
758
|
let out = "";
|
|
739
759
|
try {
|
|
740
|
-
out = execSync("ps -A -o pid=,ppid=", { encoding: "utf8" });
|
|
760
|
+
out = execSync("ps -A -o pid=,ppid=,pgid=", { encoding: "utf8" });
|
|
741
761
|
} catch {
|
|
742
762
|
return [];
|
|
743
763
|
}
|
|
744
764
|
const childrenOf = /* @__PURE__ */ new Map();
|
|
765
|
+
const pgidOf = /* @__PURE__ */ new Map();
|
|
745
766
|
for (const line of out.split("\n")) {
|
|
746
|
-
const m = line.trim().match(/^(\d+)\s+(\d+)$/);
|
|
767
|
+
const m = line.trim().match(/^(\d+)\s+(\d+)\s+(\d+)$/);
|
|
747
768
|
if (!m) continue;
|
|
748
|
-
const
|
|
769
|
+
const proc = Number(m[1]);
|
|
749
770
|
const parent = Number(m[2]);
|
|
771
|
+
pgidOf.set(proc, Number(m[3]));
|
|
750
772
|
const list = childrenOf.get(parent);
|
|
751
|
-
if (list) list.push(
|
|
752
|
-
else childrenOf.set(parent, [
|
|
773
|
+
if (list) list.push(proc);
|
|
774
|
+
else childrenOf.set(parent, [proc]);
|
|
753
775
|
}
|
|
754
|
-
const
|
|
776
|
+
const pgids = /* @__PURE__ */ new Set();
|
|
777
|
+
const seen = /* @__PURE__ */ new Set();
|
|
755
778
|
const stack = [pid];
|
|
756
779
|
while (stack.length) {
|
|
757
780
|
for (const child of childrenOf.get(stack.pop()) ?? []) {
|
|
758
|
-
if (
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
781
|
+
if (seen.has(child)) continue;
|
|
782
|
+
seen.add(child);
|
|
783
|
+
stack.push(child);
|
|
784
|
+
const g = pgidOf.get(child);
|
|
785
|
+
if (g !== void 0) pgids.add(g);
|
|
762
786
|
}
|
|
763
787
|
}
|
|
764
|
-
return
|
|
788
|
+
return [...pgids];
|
|
765
789
|
}
|
|
766
|
-
function
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
} catch {
|
|
771
|
-
}
|
|
790
|
+
function trySignalGroup(pgid, signal) {
|
|
791
|
+
try {
|
|
792
|
+
process.kill(-pgid, signal);
|
|
793
|
+
} catch {
|
|
772
794
|
}
|
|
773
795
|
}
|
|
774
796
|
function reapChild(child, graceMs = 3e3) {
|
|
775
|
-
const tree = child.pid ? descendantPids(child.pid) : [];
|
|
776
797
|
child.stop();
|
|
777
|
-
signalPids(tree, "SIGINT");
|
|
778
798
|
return new Promise((resolve) => {
|
|
779
799
|
const done2 = () => {
|
|
780
800
|
clearTimeout(grace);
|
|
781
801
|
child.kill();
|
|
782
|
-
signalPids(tree, "SIGKILL");
|
|
783
802
|
resolve();
|
|
784
803
|
};
|
|
785
804
|
const grace = setTimeout(done2, graceMs);
|
|
@@ -787,18 +806,6 @@ function reapChild(child, graceMs = 3e3) {
|
|
|
787
806
|
child.exited.then(done2);
|
|
788
807
|
});
|
|
789
808
|
}
|
|
790
|
-
function killGroup(child, signal) {
|
|
791
|
-
const pid = child.pid;
|
|
792
|
-
if (pid === void 0) return;
|
|
793
|
-
try {
|
|
794
|
-
process.kill(-pid, signal);
|
|
795
|
-
} catch {
|
|
796
|
-
try {
|
|
797
|
-
child.kill(signal);
|
|
798
|
-
} catch {
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
809
|
function wireLines2(child, stream, onLine) {
|
|
803
810
|
const source = stream === "stdout" ? child.stdout : child.stderr;
|
|
804
811
|
if (!source || !onLine) return;
|