refactor: bundle sense-generator to dist/ via esbuild

- Add esbuild build script to package.json
- Add .gitignore for dist/
- Remove stale tsc-generated .js files (now bundled)
- Include sense files generated by workflow run (hermes-gateway-health update, worker-process-metrics)
- Clean up nerve.yaml (remove deleted workflows, migrate reflexes to interval)
This commit is contained in:
小橘 2026-04-28 05:31:04 +00:00
parent 2c77f7ffc2
commit 1940ccedd6
11 changed files with 442 additions and 25 deletions

View File

@ -2,19 +2,24 @@
senses: senses:
linux-system-health: linux-system-health:
group: system group: system
interval: 30s
throttle: 10s throttle: 10s
timeout: 15s timeout: 15s
grace_period: null
hermes-gateway-health: hermes-gateway-health:
group: system group: system
interval: 2m
throttle: 30s throttle: 30s
timeout: 30s timeout: 30s
grace_period: null
hermes-session-message-stats: hermes-session-message-stats:
group: hermes group: hermes
interval: 15m
throttle: 30s throttle: 30s
timeout: 60s timeout: 60s
grace_period: null worker-process-metrics:
group: system
interval: 1m
throttle: 15s
timeout: 5s
workflows: workflows:
sense-generator: sense-generator:
@ -23,26 +28,6 @@ workflows:
workflow-generator: workflow-generator:
concurrency: 1 concurrency: 1
overflow: drop overflow: drop
pr-summarizer:
concurrency: 1
overflow: drop
pr-code-reviewer:
concurrency: 1
overflow: drop
hello-world:
concurrency: 1
overflow: drop
gitea-issue-solver: gitea-issue-solver:
concurrency: 1 concurrency: 1
overflow: drop overflow: drop
reflexes:
- kind: sense
sense: linux-system-health
interval: 30s
- kind: sense
sense: hermes-gateway-health
interval: 2m
- kind: sense
sense: hermes-session-message-stats
interval: 15m

View File

@ -4,6 +4,69 @@ import { hermesGatewayHealth } from "./schema.ts";
/** Keep subprocess deadlines slightly under typical sense timeout (30s). */ /** Keep subprocess deadlines slightly under typical sense timeout (30s). */
const EXEC_TIMEOUT_MS = 25_000; const EXEC_TIMEOUT_MS = 25_000;
/** HTTP probe stays below EXEC_TIMEOUT_MS and sense timeout (30s). */
const HTTP_TIMEOUT_MS = Math.min(23_000, EXEC_TIMEOUT_MS - 2000);
const HTTP_ERROR_MAX_LEN = 256;
function gatewayProbeUrl() {
const u =
process.env.HERMES_GATEWAY_HEALTH_URL ??
process.env.NERVE_HERMES_GATEWAY_URL ??
"";
return String(u).trim();
}
function truncateHttpError(err) {
const raw =
err && typeof err === "object" && "code" in err && err.code
? String(err.code)
: String(err?.message ?? err ?? "error");
const s = raw.trim() || "error";
return s.length > HTTP_ERROR_MAX_LEN ? s.slice(0, HTTP_ERROR_MAX_LEN) : s;
}
/**
* GET the gateway URL; success = HTTP 200399.
* URL must be set via HERMES_GATEWAY_HEALTH_URL or NERVE_HERMES_GATEWAY_URL.
*/
async function probeGatewayHttp(url) {
if (!url) {
return {
httpOk: 0,
httpStatusCode: 0,
httpLatencyMs: 0,
httpError: "missing_url",
};
}
const t0 = Date.now();
try {
const signal = AbortSignal.timeout(HTTP_TIMEOUT_MS);
const res = await fetch(url, {
method: "GET",
signal,
redirect: "follow",
});
const httpLatencyMs = Date.now() - t0;
const code = res.status;
const ok = code >= 200 && code < 400;
return {
httpOk: ok ? 1 : 0,
httpStatusCode: code,
httpLatencyMs,
httpError: ok ? "" : truncateHttpError({ message: `HTTP ${code}` }),
};
} catch (err) {
const httpLatencyMs = Date.now() - t0;
return {
httpOk: 0,
httpStatusCode: 0,
httpLatencyMs,
httpError: truncateHttpError(err),
};
}
}
/** /**
* When `ps` lacks `etimes` (wall-clock seconds since start), parse `etime` * When `ps` lacks `etimes` (wall-clock seconds since start), parse `etime`
* ([[dd-]hh:]mm:ss) into seconds. See ps(1) `etime` field description. * ([[dd-]hh:]mm:ss) into seconds. See ps(1) `etime` field description.
@ -293,6 +356,23 @@ export async function compute(db, _peers) {
} }
} }
let httpOk = 0;
let httpStatusCode = 0;
let httpLatencyMs = 0;
let httpError = "";
try {
const h = await probeGatewayHttp(gatewayProbeUrl());
httpOk = h.httpOk;
httpStatusCode = h.httpStatusCode;
httpLatencyMs = h.httpLatencyMs;
httpError = h.httpError;
} catch {
httpOk = 0;
httpStatusCode = 0;
httpLatencyMs = 0;
httpError = "probe_failed";
}
const storedMainPid = mainPid > 0 ? mainPid : 0; const storedMainPid = mainPid > 0 ? mainPid : 0;
const row = { const row = {
@ -304,6 +384,10 @@ export async function compute(db, _peers) {
uptimeSec: alive ? uptimeSec : 0, uptimeSec: alive ? uptimeSec : 0,
activeSessions, activeSessions,
childProcessCount: alive ? childProcessCount : 0, childProcessCount: alive ? childProcessCount : 0,
httpOk,
httpStatusCode,
httpLatencyMs,
httpError,
}; };
await db.insert(hermesGatewayHealth).values(row); await db.insert(hermesGatewayHealth).values(row);
@ -317,5 +401,9 @@ export async function compute(db, _peers) {
uptimeSec: row.uptimeSec, uptimeSec: row.uptimeSec,
activeSessions: row.activeSessions, activeSessions: row.activeSessions,
childProcessCount: row.childProcessCount, childProcessCount: row.childProcessCount,
httpOk: row.httpOk,
httpStatusCode: row.httpStatusCode,
httpLatencyMs: row.httpLatencyMs,
httpError: row.httpError,
}; };
} }

View File

@ -0,0 +1,7 @@
-- Migration: 0002_add_http_probe
-- HTTP reachability columns for hermes-gateway-health sense.
ALTER TABLE hermes_gateway_health ADD COLUMN http_ok INTEGER NOT NULL DEFAULT 0;
ALTER TABLE hermes_gateway_health ADD COLUMN http_status_code INTEGER NOT NULL DEFAULT 0;
ALTER TABLE hermes_gateway_health ADD COLUMN http_latency_ms INTEGER NOT NULL DEFAULT 0;
ALTER TABLE hermes_gateway_health ADD COLUMN http_error TEXT NOT NULL DEFAULT '';

View File

@ -1,4 +1,4 @@
import { integer, real, sqliteTable } from "drizzle-orm/sqlite-core"; import { integer, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const hermesGatewayHealth = sqliteTable("hermes_gateway_health", { export const hermesGatewayHealth = sqliteTable("hermes_gateway_health", {
id: integer("id").primaryKey({ autoIncrement: true }), id: integer("id").primaryKey({ autoIncrement: true }),
@ -10,4 +10,8 @@ export const hermesGatewayHealth = sqliteTable("hermes_gateway_health", {
uptimeSec: integer("uptime_sec").notNull(), uptimeSec: integer("uptime_sec").notNull(),
activeSessions: integer("active_sessions").notNull(), activeSessions: integer("active_sessions").notNull(),
childProcessCount: integer("child_process_count").notNull(), childProcessCount: integer("child_process_count").notNull(),
httpOk: integer("http_ok").notNull(),
httpStatusCode: integer("http_status_code").notNull(),
httpLatencyMs: integer("http_latency_ms").notNull(),
httpError: text("http_error").notNull(),
}); });

View File

@ -0,0 +1,35 @@
import { workerProcessMetrics } from "./schema.ts";
function round2(n) {
return Math.round(n * 100) / 100;
}
export async function compute(db, _peers) {
const ts = Date.now();
const pid = process.pid;
const uptimeSec = process.uptime();
const m = process.memoryUsage();
const heapUsedMB = round2(m.heapUsed / 1024 / 1024);
const rssMB = round2(m.rss / 1024 / 1024);
const externalMB = round2(m.external / 1024 / 1024);
const row = {
ts,
pid,
uptimeSec,
heapUsedMB,
rssMB,
externalMB,
};
await db.insert(workerProcessMetrics).values(row);
return {
ts: row.ts,
pid: row.pid,
uptimeSec: row.uptimeSec,
heapUsedMB: row.heapUsedMB,
rssMB: row.rssMB,
externalMB: row.externalMB,
};
}

View File

@ -0,0 +1,11 @@
-- Migration: 0001_init
-- Creates the worker_process_metrics table for worker-process-metrics sense.
CREATE TABLE IF NOT EXISTS worker_process_metrics (
ts INTEGER PRIMARY KEY,
pid INTEGER NOT NULL,
uptime_sec REAL NOT NULL,
heap_used_mb REAL NOT NULL,
rss_mb REAL NOT NULL,
external_mb REAL NOT NULL
);

View File

@ -0,0 +1,10 @@
import { integer, real, sqliteTable } from "drizzle-orm/sqlite-core";
export const workerProcessMetrics = sqliteTable("worker_process_metrics", {
ts: integer("ts").primaryKey(),
pid: integer("pid").notNull(),
uptimeSec: real("uptime_sec").notNull(),
heapUsedMB: real("heap_used_mb").notNull(),
rssMB: real("rss_mb").notNull(),
externalMB: real("external_mb").notNull(),
});

1
workflows/sense-generator/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
dist/

View File

@ -3,6 +3,9 @@
"version": "0.0.1", "version": "0.0.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": {
"build": "esbuild index.ts --bundle --platform=node --format=esm --outdir=dist --packages=external"
},
"dependencies": { "dependencies": {
"@uncaged/nerve-core": "latest", "@uncaged/nerve-core": "latest",
"@uncaged/nerve-workflow-utils": "latest", "@uncaged/nerve-workflow-utils": "latest",
@ -10,6 +13,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"esbuild": "^0.27.0",
"typescript": "^5.7.0" "typescript": "^5.7.0"
}, },
"pnpm": { "pnpm": {

View File

@ -26,15 +26,179 @@ importers:
'@types/node': '@types/node':
specifier: ^22.0.0 specifier: ^22.0.0
version: 22.19.17 version: 22.19.17
esbuild:
specifier: ^0.27.0
version: 0.27.7
typescript: typescript:
specifier: ^5.7.0 specifier: ^5.7.0
version: 5.9.3 version: 5.9.3
packages: packages:
'@esbuild/aix-ppc64@0.27.7':
resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.27.7':
resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.27.7':
resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.27.7':
resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.27.7':
resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.27.7':
resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.27.7':
resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.27.7':
resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.27.7':
resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.27.7':
resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.27.7':
resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.27.7':
resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.27.7':
resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.27.7':
resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.27.7':
resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.27.7':
resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.27.7':
resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-arm64@0.27.7':
resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.27.7':
resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.27.7':
resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.27.7':
resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openharmony-arm64@0.27.7':
resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
'@esbuild/sunos-x64@0.27.7':
resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.27.7':
resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.27.7':
resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.27.7':
resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@types/node@22.19.17': '@types/node@22.19.17':
resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==} resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==}
esbuild@0.27.7:
resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==}
engines: {node: '>=18'}
hasBin: true
typescript@5.9.3: typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
@ -48,10 +212,117 @@ packages:
snapshots: snapshots:
'@esbuild/aix-ppc64@0.27.7':
optional: true
'@esbuild/android-arm64@0.27.7':
optional: true
'@esbuild/android-arm@0.27.7':
optional: true
'@esbuild/android-x64@0.27.7':
optional: true
'@esbuild/darwin-arm64@0.27.7':
optional: true
'@esbuild/darwin-x64@0.27.7':
optional: true
'@esbuild/freebsd-arm64@0.27.7':
optional: true
'@esbuild/freebsd-x64@0.27.7':
optional: true
'@esbuild/linux-arm64@0.27.7':
optional: true
'@esbuild/linux-arm@0.27.7':
optional: true
'@esbuild/linux-ia32@0.27.7':
optional: true
'@esbuild/linux-loong64@0.27.7':
optional: true
'@esbuild/linux-mips64el@0.27.7':
optional: true
'@esbuild/linux-ppc64@0.27.7':
optional: true
'@esbuild/linux-riscv64@0.27.7':
optional: true
'@esbuild/linux-s390x@0.27.7':
optional: true
'@esbuild/linux-x64@0.27.7':
optional: true
'@esbuild/netbsd-arm64@0.27.7':
optional: true
'@esbuild/netbsd-x64@0.27.7':
optional: true
'@esbuild/openbsd-arm64@0.27.7':
optional: true
'@esbuild/openbsd-x64@0.27.7':
optional: true
'@esbuild/openharmony-arm64@0.27.7':
optional: true
'@esbuild/sunos-x64@0.27.7':
optional: true
'@esbuild/win32-arm64@0.27.7':
optional: true
'@esbuild/win32-ia32@0.27.7':
optional: true
'@esbuild/win32-x64@0.27.7':
optional: true
'@types/node@22.19.17': '@types/node@22.19.17':
dependencies: dependencies:
undici-types: 6.21.0 undici-types: 6.21.0
esbuild@0.27.7:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.7
'@esbuild/android-arm': 0.27.7
'@esbuild/android-arm64': 0.27.7
'@esbuild/android-x64': 0.27.7
'@esbuild/darwin-arm64': 0.27.7
'@esbuild/darwin-x64': 0.27.7
'@esbuild/freebsd-arm64': 0.27.7
'@esbuild/freebsd-x64': 0.27.7
'@esbuild/linux-arm': 0.27.7
'@esbuild/linux-arm64': 0.27.7
'@esbuild/linux-ia32': 0.27.7
'@esbuild/linux-loong64': 0.27.7
'@esbuild/linux-mips64el': 0.27.7
'@esbuild/linux-ppc64': 0.27.7
'@esbuild/linux-riscv64': 0.27.7
'@esbuild/linux-s390x': 0.27.7
'@esbuild/linux-x64': 0.27.7
'@esbuild/netbsd-arm64': 0.27.7
'@esbuild/netbsd-x64': 0.27.7
'@esbuild/openbsd-arm64': 0.27.7
'@esbuild/openbsd-x64': 0.27.7
'@esbuild/openharmony-arm64': 0.27.7
'@esbuild/sunos-x64': 0.27.7
'@esbuild/win32-arm64': 0.27.7
'@esbuild/win32-ia32': 0.27.7
'@esbuild/win32-x64': 0.27.7
typescript@5.9.3: {} typescript@5.9.3: {}
undici-types@6.21.0: {} undici-types@6.21.0: {}

View File

@ -6,7 +6,8 @@
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"strict": true, "strict": true,
"skipLibCheck": true, "skipLibCheck": true,
"noEmit": true, "noEmit": false,
"declaration": false,
"types": ["node"] "types": ["node"]
}, },
"include": ["./**/*.ts"] "include": ["./**/*.ts"]