hotsheet 0.17.0-beta.23 → 0.17.0-beta.25
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/dist/channel.js +303 -39
- package/dist/cli.js +423 -197
- package/dist/client/app.global.js +91 -91
- package/dist/client/styles.css +1 -1
- package/package.json +1 -1
package/dist/channel.js
CHANGED
|
@@ -34145,9 +34145,9 @@ var StdioServerTransport = class {
|
|
|
34145
34145
|
|
|
34146
34146
|
// src/channel.ts
|
|
34147
34147
|
init_zod();
|
|
34148
|
-
import { readFileSync as
|
|
34148
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
34149
34149
|
import { createServer } from "http";
|
|
34150
|
-
import { join as
|
|
34150
|
+
import { join as join5 } from "path";
|
|
34151
34151
|
|
|
34152
34152
|
// src/channel.tools.ts
|
|
34153
34153
|
init_zod();
|
|
@@ -34685,34 +34685,16 @@ async function callTool(name, args2, dataDir2, fetchFn = globalThis.fetch) {
|
|
|
34685
34685
|
}
|
|
34686
34686
|
|
|
34687
34687
|
// src/channel-config.ts
|
|
34688
|
-
import { basename as basename2, dirname, join as
|
|
34688
|
+
import { basename as basename2, dirname, join as join3, resolve } from "path";
|
|
34689
34689
|
init_zod();
|
|
34690
34690
|
|
|
34691
|
-
// src/claude-allow-rule.ts
|
|
34692
|
-
init_zod();
|
|
34693
|
-
init_file_settings();
|
|
34694
|
-
var ClaudeSettingsSchema = external_exports3.object({
|
|
34695
|
-
permissions: external_exports3.object({
|
|
34696
|
-
allow: external_exports3.array(external_exports3.string()).default([])
|
|
34697
|
-
}).loose().default(() => ({ allow: [] }))
|
|
34698
|
-
}).loose();
|
|
34699
|
-
|
|
34700
|
-
// src/channel-config.ts
|
|
34701
|
-
var McpConfigSchema = external_exports3.object({
|
|
34702
|
-
mcpServers: external_exports3.record(external_exports3.string(), external_exports3.unknown()).optional()
|
|
34703
|
-
}).loose();
|
|
34704
|
-
function slugifyDataDir(dataDir2) {
|
|
34705
|
-
const root = dataDir2.replace(/[\\/]\.hotsheet[\\/]?$/, "");
|
|
34706
|
-
const base = basename2(root) || "project";
|
|
34707
|
-
const slug = base.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
34708
|
-
return slug !== "" ? slug : "project";
|
|
34709
|
-
}
|
|
34710
|
-
|
|
34711
34691
|
// src/channelLog.ts
|
|
34712
34692
|
import { appendFileSync, renameSync, statSync } from "fs";
|
|
34693
|
+
import { join as join2 } from "path";
|
|
34713
34694
|
var CHANNEL_LOG_MAX_BYTES = 1048576;
|
|
34714
|
-
function createChannelLogger(logPath) {
|
|
34695
|
+
function createChannelLogger(logPath, options = {}) {
|
|
34715
34696
|
let injectedBlankLine = false;
|
|
34697
|
+
const pidSuffix = options.pidLabel !== void 0 && options.pidLabel !== "" ? ` ${options.pidLabel}` : "";
|
|
34716
34698
|
return {
|
|
34717
34699
|
log(event, details) {
|
|
34718
34700
|
try {
|
|
@@ -34727,7 +34709,7 @@ function createChannelLogger(logPath) {
|
|
|
34727
34709
|
const detailsText = details === void 0 || details === "" ? "" : ` ${details}`;
|
|
34728
34710
|
const prefix = !injectedBlankLine && size > 0 ? "\n" : "";
|
|
34729
34711
|
injectedBlankLine = true;
|
|
34730
|
-
appendFileSync(logPath, `${prefix}[${ts}] [pid ${process.pid}] ${event}:${detailsText}
|
|
34712
|
+
appendFileSync(logPath, `${prefix}[${ts}] [pid ${process.pid}${pidSuffix}] ${event}:${detailsText}
|
|
34731
34713
|
`, "utf-8");
|
|
34732
34714
|
} catch {
|
|
34733
34715
|
}
|
|
@@ -34742,6 +34724,94 @@ function safeStatSize(path) {
|
|
|
34742
34724
|
}
|
|
34743
34725
|
}
|
|
34744
34726
|
|
|
34727
|
+
// src/channelPortFile.ts
|
|
34728
|
+
import { closeSync, openSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
34729
|
+
function readChannelInfo(portFile2) {
|
|
34730
|
+
let raw;
|
|
34731
|
+
try {
|
|
34732
|
+
raw = readFileSync2(portFile2, "utf-8").trim();
|
|
34733
|
+
} catch {
|
|
34734
|
+
return null;
|
|
34735
|
+
}
|
|
34736
|
+
if (raw === "") return null;
|
|
34737
|
+
if (raw.startsWith("{")) {
|
|
34738
|
+
try {
|
|
34739
|
+
const parsed = JSON.parse(raw);
|
|
34740
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
34741
|
+
const obj = parsed;
|
|
34742
|
+
if (typeof obj.port !== "number" || !Number.isInteger(obj.port)) return null;
|
|
34743
|
+
return {
|
|
34744
|
+
port: obj.port,
|
|
34745
|
+
pid: typeof obj.pid === "number" && Number.isInteger(obj.pid) ? obj.pid : null,
|
|
34746
|
+
slug: typeof obj.slug === "string" && obj.slug !== "" ? obj.slug : null,
|
|
34747
|
+
startedAt: typeof obj.startedAt === "string" && obj.startedAt !== "" ? obj.startedAt : null
|
|
34748
|
+
};
|
|
34749
|
+
} catch {
|
|
34750
|
+
return null;
|
|
34751
|
+
}
|
|
34752
|
+
}
|
|
34753
|
+
const legacyPort = parseInt(raw, 10);
|
|
34754
|
+
if (isNaN(legacyPort)) return null;
|
|
34755
|
+
return { port: legacyPort, pid: null, slug: null, startedAt: null };
|
|
34756
|
+
}
|
|
34757
|
+
function writeChannelInfo(portFile2, info) {
|
|
34758
|
+
const tmp = `${portFile2}.tmp.${process.pid.toString(36)}`;
|
|
34759
|
+
const body = JSON.stringify({
|
|
34760
|
+
port: info.port,
|
|
34761
|
+
pid: info.pid,
|
|
34762
|
+
slug: info.slug,
|
|
34763
|
+
startedAt: info.startedAt
|
|
34764
|
+
});
|
|
34765
|
+
writeFileSync(tmp, body, "utf-8");
|
|
34766
|
+
renameSync2(tmp, portFile2);
|
|
34767
|
+
try {
|
|
34768
|
+
const slash = portFile2.lastIndexOf("/");
|
|
34769
|
+
if (slash > 0) {
|
|
34770
|
+
const fd = openSync(portFile2.slice(0, slash), "r");
|
|
34771
|
+
try {
|
|
34772
|
+
closeSync(fd);
|
|
34773
|
+
} catch {
|
|
34774
|
+
}
|
|
34775
|
+
}
|
|
34776
|
+
} catch {
|
|
34777
|
+
}
|
|
34778
|
+
}
|
|
34779
|
+
function maybeUnlinkPortFile(portFile2, myPort2, myPid = process.pid) {
|
|
34780
|
+
const info = readChannelInfo(portFile2);
|
|
34781
|
+
if (info === null) return false;
|
|
34782
|
+
if (info.pid !== null) {
|
|
34783
|
+
if (info.pid !== myPid) return false;
|
|
34784
|
+
} else {
|
|
34785
|
+
if (info.port !== myPort2) return false;
|
|
34786
|
+
}
|
|
34787
|
+
try {
|
|
34788
|
+
unlinkSync(portFile2);
|
|
34789
|
+
return true;
|
|
34790
|
+
} catch {
|
|
34791
|
+
return false;
|
|
34792
|
+
}
|
|
34793
|
+
}
|
|
34794
|
+
|
|
34795
|
+
// src/claude-allow-rule.ts
|
|
34796
|
+
init_zod();
|
|
34797
|
+
init_file_settings();
|
|
34798
|
+
var ClaudeSettingsSchema = external_exports3.object({
|
|
34799
|
+
permissions: external_exports3.object({
|
|
34800
|
+
allow: external_exports3.array(external_exports3.string()).default([])
|
|
34801
|
+
}).loose().default(() => ({ allow: [] }))
|
|
34802
|
+
}).loose();
|
|
34803
|
+
|
|
34804
|
+
// src/channel-config.ts
|
|
34805
|
+
var McpConfigSchema = external_exports3.object({
|
|
34806
|
+
mcpServers: external_exports3.record(external_exports3.string(), external_exports3.unknown()).optional()
|
|
34807
|
+
}).loose();
|
|
34808
|
+
function slugifyDataDir(dataDir2) {
|
|
34809
|
+
const root = dataDir2.replace(/[\\/]\.hotsheet[\\/]?$/, "");
|
|
34810
|
+
const base = basename2(root) || "project";
|
|
34811
|
+
const slug = base.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
34812
|
+
return slug !== "" ? slug : "project";
|
|
34813
|
+
}
|
|
34814
|
+
|
|
34745
34815
|
// src/channelPermissions.ts
|
|
34746
34816
|
var PERMISSION_TTL_MS = 12e4;
|
|
34747
34817
|
var queue = [];
|
|
@@ -34765,6 +34835,161 @@ function clearAllPermissions() {
|
|
|
34765
34835
|
queue.length = 0;
|
|
34766
34836
|
}
|
|
34767
34837
|
|
|
34838
|
+
// src/channelRegistry.ts
|
|
34839
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync as readFileSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
34840
|
+
import { join as join4 } from "path";
|
|
34841
|
+
function registryDir(dataDir2) {
|
|
34842
|
+
return join4(dataDir2, "channel-ports.d");
|
|
34843
|
+
}
|
|
34844
|
+
function entryPath(dataDir2, pid) {
|
|
34845
|
+
return join4(registryDir(dataDir2), `${String(pid)}.json`);
|
|
34846
|
+
}
|
|
34847
|
+
function defaultIsPidAlive(pid) {
|
|
34848
|
+
try {
|
|
34849
|
+
process.kill(pid, 0);
|
|
34850
|
+
return true;
|
|
34851
|
+
} catch {
|
|
34852
|
+
return false;
|
|
34853
|
+
}
|
|
34854
|
+
}
|
|
34855
|
+
function registerSelf(dataDir2, info) {
|
|
34856
|
+
if (info.pid === null) return;
|
|
34857
|
+
mkdirSync(registryDir(dataDir2), { recursive: true });
|
|
34858
|
+
const path = entryPath(dataDir2, info.pid);
|
|
34859
|
+
const body = JSON.stringify({
|
|
34860
|
+
port: info.port,
|
|
34861
|
+
pid: info.pid,
|
|
34862
|
+
slug: info.slug,
|
|
34863
|
+
startedAt: info.startedAt
|
|
34864
|
+
});
|
|
34865
|
+
writeFileSync2(path, body, "utf-8");
|
|
34866
|
+
}
|
|
34867
|
+
function unregisterSelf(dataDir2, pid) {
|
|
34868
|
+
try {
|
|
34869
|
+
unlinkSync2(entryPath(dataDir2, pid));
|
|
34870
|
+
} catch {
|
|
34871
|
+
}
|
|
34872
|
+
}
|
|
34873
|
+
function readEntry(path) {
|
|
34874
|
+
let raw;
|
|
34875
|
+
try {
|
|
34876
|
+
raw = readFileSync3(path, "utf-8");
|
|
34877
|
+
} catch {
|
|
34878
|
+
return null;
|
|
34879
|
+
}
|
|
34880
|
+
try {
|
|
34881
|
+
const parsed = JSON.parse(raw);
|
|
34882
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
34883
|
+
const obj = parsed;
|
|
34884
|
+
if (typeof obj.port !== "number" || !Number.isInteger(obj.port)) return null;
|
|
34885
|
+
if (typeof obj.pid !== "number" || !Number.isInteger(obj.pid)) return null;
|
|
34886
|
+
return {
|
|
34887
|
+
port: obj.port,
|
|
34888
|
+
pid: obj.pid,
|
|
34889
|
+
slug: typeof obj.slug === "string" && obj.slug !== "" ? obj.slug : null,
|
|
34890
|
+
startedAt: typeof obj.startedAt === "string" && obj.startedAt !== "" ? obj.startedAt : null
|
|
34891
|
+
};
|
|
34892
|
+
} catch {
|
|
34893
|
+
return null;
|
|
34894
|
+
}
|
|
34895
|
+
}
|
|
34896
|
+
function listAliveEntries(dataDir2, isPidAlive = defaultIsPidAlive) {
|
|
34897
|
+
const dir = registryDir(dataDir2);
|
|
34898
|
+
if (!existsSync(dir)) return [];
|
|
34899
|
+
let names;
|
|
34900
|
+
try {
|
|
34901
|
+
names = readdirSync(dir);
|
|
34902
|
+
} catch {
|
|
34903
|
+
return [];
|
|
34904
|
+
}
|
|
34905
|
+
const alive = [];
|
|
34906
|
+
for (const name of names) {
|
|
34907
|
+
if (!name.endsWith(".json")) continue;
|
|
34908
|
+
const path = join4(dir, name);
|
|
34909
|
+
const entry = readEntry(path);
|
|
34910
|
+
if (entry === null || entry.pid === null || !isPidAlive(entry.pid)) {
|
|
34911
|
+
try {
|
|
34912
|
+
unlinkSync2(path);
|
|
34913
|
+
} catch {
|
|
34914
|
+
}
|
|
34915
|
+
continue;
|
|
34916
|
+
}
|
|
34917
|
+
alive.push(entry);
|
|
34918
|
+
}
|
|
34919
|
+
alive.sort((a, b) => {
|
|
34920
|
+
if (a.startedAt === null && b.startedAt === null) return a.pid - b.pid;
|
|
34921
|
+
if (a.startedAt === null) return 1;
|
|
34922
|
+
if (b.startedAt === null) return -1;
|
|
34923
|
+
return a.startedAt < b.startedAt ? -1 : a.startedAt > b.startedAt ? 1 : 0;
|
|
34924
|
+
});
|
|
34925
|
+
return alive;
|
|
34926
|
+
}
|
|
34927
|
+
function pickLeader(entries) {
|
|
34928
|
+
return entries.length === 0 ? null : entries[0];
|
|
34929
|
+
}
|
|
34930
|
+
|
|
34931
|
+
// src/channelPortFileWatcher.ts
|
|
34932
|
+
function installPortFileWatcher(opts) {
|
|
34933
|
+
const intervalMs = opts.intervalMs ?? 5e3;
|
|
34934
|
+
const setIntervalFn = opts.setIntervalFn ?? setInterval;
|
|
34935
|
+
const clearIntervalFn = opts.clearIntervalFn ?? ((handle2) => {
|
|
34936
|
+
clearInterval(handle2);
|
|
34937
|
+
});
|
|
34938
|
+
const isPidAlive = opts.isPidAlive ?? defaultIsPidAlive;
|
|
34939
|
+
let lastRole = "unknown";
|
|
34940
|
+
let lastLeaderPid = null;
|
|
34941
|
+
const tick = () => {
|
|
34942
|
+
if (opts.info.pid !== null) {
|
|
34943
|
+
const allEntries = listAliveEntries(opts.dataDir, isPidAlive);
|
|
34944
|
+
const ourEntry = allEntries.find((e) => e.pid === opts.info.pid);
|
|
34945
|
+
if (ourEntry === void 0) {
|
|
34946
|
+
try {
|
|
34947
|
+
registerSelf(opts.dataDir, opts.info);
|
|
34948
|
+
opts.log?.("port-file-registry-heal", `pid=${String(opts.info.pid)}`);
|
|
34949
|
+
} catch (err) {
|
|
34950
|
+
opts.log?.("port-file-heal-error", `registerSelf: ${String(err)}`);
|
|
34951
|
+
return;
|
|
34952
|
+
}
|
|
34953
|
+
}
|
|
34954
|
+
}
|
|
34955
|
+
const alive = listAliveEntries(opts.dataDir, isPidAlive);
|
|
34956
|
+
const leader = pickLeader(alive);
|
|
34957
|
+
if (leader === null) {
|
|
34958
|
+
return;
|
|
34959
|
+
}
|
|
34960
|
+
const weAreLeader = leader.pid === opts.info.pid;
|
|
34961
|
+
if (weAreLeader) {
|
|
34962
|
+
const current = readChannelInfo(opts.portFile);
|
|
34963
|
+
const matches = current !== null && current.pid === opts.info.pid && current.port === opts.info.port && current.slug === opts.info.slug;
|
|
34964
|
+
if (!matches) {
|
|
34965
|
+
try {
|
|
34966
|
+
writeChannelInfo(opts.portFile, opts.info);
|
|
34967
|
+
const reason = current === null ? "missing" : `previous-leader-pid=${String(current.pid)}`;
|
|
34968
|
+
opts.log?.("port-file-leader-write", reason);
|
|
34969
|
+
opts.notify?.();
|
|
34970
|
+
} catch (err) {
|
|
34971
|
+
opts.log?.("port-file-heal-error", `writeChannelInfo: ${String(err)}`);
|
|
34972
|
+
return;
|
|
34973
|
+
}
|
|
34974
|
+
}
|
|
34975
|
+
if (lastRole !== "leader") {
|
|
34976
|
+
lastRole = "leader";
|
|
34977
|
+
lastLeaderPid = opts.info.pid;
|
|
34978
|
+
}
|
|
34979
|
+
} else {
|
|
34980
|
+
if (lastRole !== "follower" || lastLeaderPid !== leader.pid) {
|
|
34981
|
+
opts.log?.("port-file-follower-defer", `leader-pid=${String(leader.pid)} ours=${String(opts.info.pid)}`);
|
|
34982
|
+
lastRole = "follower";
|
|
34983
|
+
lastLeaderPid = leader.pid;
|
|
34984
|
+
}
|
|
34985
|
+
}
|
|
34986
|
+
};
|
|
34987
|
+
const handle = setIntervalFn(tick, intervalMs);
|
|
34988
|
+
return () => {
|
|
34989
|
+
clearIntervalFn(handle);
|
|
34990
|
+
};
|
|
34991
|
+
}
|
|
34992
|
+
|
|
34768
34993
|
// src/channelStdioWatcher.ts
|
|
34769
34994
|
function installStdioDisconnectHandler(opts) {
|
|
34770
34995
|
const { stdin, stdout, onDisconnect, log } = opts;
|
|
@@ -34808,7 +35033,7 @@ function installStdioDisconnectHandler(opts) {
|
|
|
34808
35033
|
}
|
|
34809
35034
|
|
|
34810
35035
|
// src/channel.ts
|
|
34811
|
-
var CHANNEL_VERSION =
|
|
35036
|
+
var CHANNEL_VERSION = 9;
|
|
34812
35037
|
var dataDir = ".hotsheet";
|
|
34813
35038
|
var args = process.argv.slice(2);
|
|
34814
35039
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -34817,10 +35042,11 @@ for (let i = 0; i < args.length; i++) {
|
|
|
34817
35042
|
i++;
|
|
34818
35043
|
}
|
|
34819
35044
|
}
|
|
34820
|
-
var portFile =
|
|
35045
|
+
var portFile = join5(dataDir, "channel-port");
|
|
34821
35046
|
var serverSlug = slugifyDataDir(dataDir);
|
|
34822
35047
|
var serverName = `hotsheet-channel-${serverSlug}`;
|
|
34823
|
-
var
|
|
35048
|
+
var processStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
35049
|
+
var channelLog = createChannelLogger(join5(dataDir, "mcp.log"));
|
|
34824
35050
|
channelLog.log("process-start", `argv=${process.argv.slice(2).join(" ")} dataDir=${dataDir} serverName=${serverName}`);
|
|
34825
35051
|
var mcp = new Server(
|
|
34826
35052
|
{ name: serverName, version: "0.1.0" },
|
|
@@ -34908,7 +35134,13 @@ var httpServer = createServer(async (req, res) => {
|
|
|
34908
35134
|
}
|
|
34909
35135
|
if (req.method === "GET" && req.url === "/health") {
|
|
34910
35136
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
34911
|
-
res.end(JSON.stringify({
|
|
35137
|
+
res.end(JSON.stringify({
|
|
35138
|
+
ok: true,
|
|
35139
|
+
version: CHANNEL_VERSION,
|
|
35140
|
+
pid: process.pid,
|
|
35141
|
+
slug: serverSlug,
|
|
35142
|
+
startedAt: processStartedAt
|
|
35143
|
+
}));
|
|
34912
35144
|
return;
|
|
34913
35145
|
}
|
|
34914
35146
|
if (req.method === "GET" && req.url === "/permission") {
|
|
@@ -35043,8 +35275,8 @@ var httpServer = createServer(async (req, res) => {
|
|
|
35043
35275
|
});
|
|
35044
35276
|
function notifyMainServer(abortSignal) {
|
|
35045
35277
|
try {
|
|
35046
|
-
const settingsPath =
|
|
35047
|
-
const settings = JSON.parse(
|
|
35278
|
+
const settingsPath = join5(dataDir, "settings.json");
|
|
35279
|
+
const settings = JSON.parse(readFileSync4(settingsPath, "utf-8"));
|
|
35048
35280
|
if (settings.port === void 0 || settings.port === 0) {
|
|
35049
35281
|
process.stderr.write(`[notify] no port in settings.json
|
|
35050
35282
|
`);
|
|
@@ -35068,14 +35300,44 @@ function notifyMainServer(abortSignal) {
|
|
|
35068
35300
|
return Promise.resolve();
|
|
35069
35301
|
}
|
|
35070
35302
|
}
|
|
35303
|
+
var myPort = null;
|
|
35304
|
+
var disposePortFileWatcher = null;
|
|
35071
35305
|
httpServer.listen(0, "127.0.0.1", () => {
|
|
35072
35306
|
const addr = httpServer.address();
|
|
35073
35307
|
if (addr !== null && typeof addr !== "string") {
|
|
35074
35308
|
const port = addr.port;
|
|
35309
|
+
myPort = port;
|
|
35310
|
+
const myInfo = {
|
|
35311
|
+
port,
|
|
35312
|
+
pid: process.pid,
|
|
35313
|
+
slug: serverSlug,
|
|
35314
|
+
startedAt: processStartedAt
|
|
35315
|
+
};
|
|
35316
|
+
try {
|
|
35317
|
+
registerSelf(dataDir, myInfo);
|
|
35318
|
+
} catch (err) {
|
|
35319
|
+
channelLog.log("registry-register-error", String(err));
|
|
35320
|
+
}
|
|
35075
35321
|
try {
|
|
35076
|
-
|
|
35322
|
+
const alive = listAliveEntries(dataDir);
|
|
35323
|
+
const leader = pickLeader(alive);
|
|
35324
|
+
if (leader === null || leader.pid === process.pid) {
|
|
35325
|
+
writeChannelInfo(portFile, myInfo);
|
|
35326
|
+
} else {
|
|
35327
|
+
channelLog.log("startup-follower", `leader-pid=${String(leader.pid)} aliveCount=${String(alive.length)}`);
|
|
35328
|
+
}
|
|
35077
35329
|
} catch {
|
|
35078
35330
|
}
|
|
35331
|
+
disposePortFileWatcher = installPortFileWatcher({
|
|
35332
|
+
portFile,
|
|
35333
|
+
dataDir,
|
|
35334
|
+
info: myInfo,
|
|
35335
|
+
intervalMs: 5e3,
|
|
35336
|
+
log: (event, details) => channelLog.log(event, details),
|
|
35337
|
+
notify: () => {
|
|
35338
|
+
void notifyMainServer();
|
|
35339
|
+
}
|
|
35340
|
+
});
|
|
35079
35341
|
process.stderr.write(`${serverName} listening on port ${port}
|
|
35080
35342
|
`);
|
|
35081
35343
|
channelLog.log("http-listen", `port=${port}`);
|
|
@@ -35087,13 +35349,18 @@ var heartbeatInterval = setInterval(() => {
|
|
|
35087
35349
|
channelLog.log("heartbeat", `uptime=${process.uptime().toFixed(1)}s rss=${(mem.rss / 1024 / 1024).toFixed(1)}MiB`);
|
|
35088
35350
|
}, 6e4);
|
|
35089
35351
|
heartbeatInterval.unref();
|
|
35352
|
+
var cleanupInFlight = false;
|
|
35090
35353
|
async function cleanup(reason = "unspecified") {
|
|
35354
|
+
if (cleanupInFlight) return;
|
|
35355
|
+
cleanupInFlight = true;
|
|
35091
35356
|
channelLog.log("cleanup-start", `reason=${reason}`);
|
|
35092
35357
|
clearInterval(heartbeatInterval);
|
|
35093
|
-
|
|
35094
|
-
|
|
35095
|
-
|
|
35358
|
+
if (disposePortFileWatcher !== null) {
|
|
35359
|
+
disposePortFileWatcher();
|
|
35360
|
+
disposePortFileWatcher = null;
|
|
35096
35361
|
}
|
|
35362
|
+
if (myPort !== null) maybeUnlinkPortFile(portFile, myPort);
|
|
35363
|
+
unregisterSelf(dataDir, process.pid);
|
|
35097
35364
|
try {
|
|
35098
35365
|
const controller = new AbortController();
|
|
35099
35366
|
setTimeout(() => controller.abort(), 1e3);
|
|
@@ -35117,10 +35384,7 @@ process.on("SIGHUP", () => {
|
|
|
35117
35384
|
});
|
|
35118
35385
|
process.on("exit", (code) => {
|
|
35119
35386
|
channelLog.log("exit", `code=${code}`);
|
|
35120
|
-
|
|
35121
|
-
unlinkSync(portFile);
|
|
35122
|
-
} catch {
|
|
35123
|
-
}
|
|
35387
|
+
if (myPort !== null) maybeUnlinkPortFile(portFile, myPort);
|
|
35124
35388
|
});
|
|
35125
35389
|
export {
|
|
35126
35390
|
CHANNEL_VERSION
|