@wizeworks/lens-hub 0.3.0-alpha.2 → 0.3.0-alpha.4
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/alerts/api.d.ts +5 -0
- package/dist/alerts/api.d.ts.map +1 -0
- package/dist/alerts/api.js +87 -0
- package/dist/alerts/api.js.map +1 -0
- package/dist/alerts/deliver.d.ts +54 -0
- package/dist/alerts/deliver.d.ts.map +1 -0
- package/dist/alerts/deliver.js +66 -0
- package/dist/alerts/deliver.js.map +1 -0
- package/dist/alerts/evaluate.d.ts +16 -0
- package/dist/alerts/evaluate.d.ts.map +1 -0
- package/dist/alerts/evaluate.js +76 -0
- package/dist/alerts/evaluate.js.map +1 -0
- package/dist/alerts/loop.d.ts +10 -0
- package/dist/alerts/loop.d.ts.map +1 -0
- package/dist/alerts/loop.js +27 -0
- package/dist/alerts/loop.js.map +1 -0
- package/dist/alerts/store.d.ts +32 -0
- package/dist/alerts/store.d.ts.map +1 -0
- package/dist/alerts/store.js +38 -0
- package/dist/alerts/store.js.map +1 -0
- package/dist/alerts/target.d.ts +3 -0
- package/dist/alerts/target.d.ts.map +1 -0
- package/dist/alerts/target.js +23 -0
- package/dist/alerts/target.js.map +1 -0
- package/dist/api.d.ts +5 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +46 -4
- package/dist/api.js.map +1 -1
- package/dist/body.d.ts +2 -2
- package/dist/body.d.ts.map +1 -1
- package/dist/body.js +4 -4
- package/dist/body.js.map +1 -1
- package/dist/changes-api.d.ts +5 -0
- package/dist/changes-api.d.ts.map +1 -0
- package/dist/changes-api.js +21 -0
- package/dist/changes-api.js.map +1 -0
- package/dist/cli-args.d.ts +1 -1
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +32 -1
- package/dist/cli-args.js.map +1 -1
- package/dist/data.js +1 -1
- package/dist/data.js.map +1 -1
- package/dist/hub.d.ts.map +1 -1
- package/dist/hub.js +15 -3
- package/dist/hub.js.map +1 -1
- package/dist/infra-read.d.ts +11 -0
- package/dist/infra-read.d.ts.map +1 -0
- package/dist/infra-read.js +30 -0
- package/dist/infra-read.js.map +1 -0
- package/dist/ingest.d.ts.map +1 -1
- package/dist/ingest.js +14 -3
- package/dist/ingest.js.map +1 -1
- package/dist/issues.d.ts +10 -0
- package/dist/issues.d.ts.map +1 -0
- package/dist/issues.js +34 -0
- package/dist/issues.js.map +1 -0
- package/dist/kit.d.ts +6 -0
- package/dist/kit.d.ts.map +1 -1
- package/dist/kit.js +4 -0
- package/dist/kit.js.map +1 -1
- package/dist/list-search.d.ts +10 -0
- package/dist/list-search.d.ts.map +1 -0
- package/dist/list-search.js +13 -0
- package/dist/list-search.js.map +1 -0
- package/dist/mcp.d.ts +3 -2
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +59 -8
- package/dist/mcp.js.map +1 -1
- package/dist/metrics-read.js +1 -1
- package/dist/metrics-read.js.map +1 -1
- package/dist/models-api.d.ts +11 -1
- package/dist/models-api.d.ts.map +1 -1
- package/dist/models-api.js +41 -15
- package/dist/models-api.js.map +1 -1
- package/dist/options.d.ts +23 -2
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +10 -1
- package/dist/options.js.map +1 -1
- package/dist/otlp/db-params.d.ts +7 -0
- package/dist/otlp/db-params.d.ts.map +1 -0
- package/dist/otlp/db-params.js +74 -0
- package/dist/otlp/db-params.js.map +1 -0
- package/dist/otlp/logs.d.ts +1 -1
- package/dist/otlp/logs.d.ts.map +1 -1
- package/dist/otlp/logs.js +8 -7
- package/dist/otlp/logs.js.map +1 -1
- package/dist/otlp/metrics.d.ts +3 -3
- package/dist/otlp/metrics.d.ts.map +1 -1
- package/dist/otlp/metrics.js +7 -6
- package/dist/otlp/metrics.js.map +1 -1
- package/dist/otlp/nested.d.ts +4 -0
- package/dist/otlp/nested.d.ts.map +1 -0
- package/dist/otlp/nested.js +19 -0
- package/dist/otlp/nested.js.map +1 -0
- package/dist/otlp/semconv.d.ts +17 -0
- package/dist/otlp/semconv.d.ts.map +1 -0
- package/dist/otlp/semconv.js +68 -0
- package/dist/otlp/semconv.js.map +1 -0
- package/dist/otlp/spans.d.ts +3 -3
- package/dist/otlp/spans.d.ts.map +1 -1
- package/dist/otlp/spans.js +15 -7
- package/dist/otlp/spans.js.map +1 -1
- package/dist/otlp/values.d.ts +5 -10
- package/dist/otlp/values.d.ts.map +1 -1
- package/dist/otlp/values.js +32 -24
- package/dist/otlp/values.js.map +1 -1
- package/dist/saved.d.ts +7 -0
- package/dist/saved.d.ts.map +1 -0
- package/dist/saved.js +49 -0
- package/dist/saved.js.map +1 -0
- package/dist/scale-exec.d.ts +2 -2
- package/dist/scale-exec.d.ts.map +1 -1
- package/dist/scale-exec.js +4 -4
- package/dist/scale-exec.js.map +1 -1
- package/dist/schema-fts.d.ts +4 -0
- package/dist/schema-fts.d.ts.map +1 -0
- package/dist/schema-fts.js +20 -0
- package/dist/schema-fts.js.map +1 -0
- package/dist/schema-saved.d.ts +15 -0
- package/dist/schema-saved.d.ts.map +1 -0
- package/dist/schema-saved.js +43 -0
- package/dist/schema-saved.js.map +1 -0
- package/dist/schema-scale.d.ts.map +1 -1
- package/dist/schema-scale.js +27 -2
- package/dist/schema-scale.js.map +1 -1
- package/dist/schema.d.ts +2 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +20 -1
- package/dist/schema.js.map +1 -1
- package/dist/search-api.d.ts +7 -0
- package/dist/search-api.d.ts.map +1 -0
- package/dist/search-api.js +25 -0
- package/dist/search-api.js.map +1 -0
- package/dist/settings-prune.d.ts +12 -0
- package/dist/settings-prune.d.ts.map +1 -0
- package/dist/settings-prune.js +15 -0
- package/dist/settings-prune.js.map +1 -0
- package/dist/settings.d.ts +27 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +64 -0
- package/dist/settings.js.map +1 -0
- package/dist/settle.d.ts +3 -3
- package/dist/settle.d.ts.map +1 -1
- package/dist/settle.js +12 -6
- package/dist/settle.js.map +1 -1
- package/dist/slos.d.ts +14 -0
- package/dist/slos.d.ts.map +1 -0
- package/dist/slos.js +73 -0
- package/dist/slos.js.map +1 -0
- package/dist/sourcemaps-api.d.ts +15 -0
- package/dist/sourcemaps-api.d.ts.map +1 -0
- package/dist/sourcemaps-api.js +55 -0
- package/dist/sourcemaps-api.js.map +1 -0
- package/dist/sourcemaps.d.ts +10 -0
- package/dist/sourcemaps.d.ts.map +1 -0
- package/dist/sourcemaps.js +41 -0
- package/dist/sourcemaps.js.map +1 -0
- package/dist/store-read.d.ts +2 -0
- package/dist/store-read.d.ts.map +1 -1
- package/dist/store-read.js +3 -1
- package/dist/store-read.js.map +1 -1
- package/dist/store.d.ts +13 -3
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +35 -10
- package/dist/store.js.map +1 -1
- package/dist/tags-api.d.ts +5 -0
- package/dist/tags-api.d.ts.map +1 -0
- package/dist/tags-api.js +94 -0
- package/dist/tags-api.js.map +1 -0
- package/dist/tags.d.ts +11 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +31 -0
- package/dist/tags.js.map +1 -0
- package/dist/uptime/api.d.ts +5 -0
- package/dist/uptime/api.d.ts.map +1 -0
- package/dist/uptime/api.js +78 -0
- package/dist/uptime/api.js.map +1 -0
- package/dist/uptime/cert.d.ts +5 -0
- package/dist/uptime/cert.d.ts.map +1 -0
- package/dist/uptime/cert.js +26 -0
- package/dist/uptime/cert.js.map +1 -0
- package/dist/uptime/guard.d.ts +13 -0
- package/dist/uptime/guard.d.ts.map +1 -0
- package/dist/uptime/guard.js +38 -0
- package/dist/uptime/guard.js.map +1 -0
- package/dist/uptime/run.d.ts +11 -0
- package/dist/uptime/run.d.ts.map +1 -0
- package/dist/uptime/run.js +96 -0
- package/dist/uptime/run.js.map +1 -0
- package/dist/uptime/schedule.d.ts +15 -0
- package/dist/uptime/schedule.d.ts.map +1 -0
- package/dist/uptime/schedule.js +26 -0
- package/dist/uptime/schedule.js.map +1 -0
- package/dist/uptime/store.d.ts +25 -0
- package/dist/uptime/store.d.ts.map +1 -0
- package/dist/uptime/store.js +80 -0
- package/dist/uptime/store.js.map +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAiD,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAW,MAAM,sBAAsB,CAAC;AAa3H,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,EAAE,CAInD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAIjF;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAG7F;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAKlF"}
|
package/dist/tags.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { BUILT_IN_PREFIX, isBuiltInName, tagList } from "@wizeworks/lens-core";
|
|
3
|
+
const ruleOf = (r) => ({ id: r.id, name: r.name, color: r.color, query: r.query, builtIn: false, enabled: true });
|
|
4
|
+
/** Built-ins first (minus those turned off), then the hub's rules by name. */
|
|
5
|
+
export function hubTags(db) {
|
|
6
|
+
const rules = db.prepare("SELECT id, name, color, query FROM tag_rules").all().map(ruleOf);
|
|
7
|
+
const off = db.prepare("SELECT name FROM tag_builtins WHERE enabled = 0").all();
|
|
8
|
+
return tagList(rules, new Set(off.map((r) => r.name)));
|
|
9
|
+
}
|
|
10
|
+
export function createTag(db, input, now) {
|
|
11
|
+
const id = randomUUID();
|
|
12
|
+
db.prepare("INSERT INTO tag_rules (id, name, color, query, created_ms, updated_ms) VALUES (?, ?, ?, ?, ?, ?)").run(id, input.name, input.color, input.query, now, now);
|
|
13
|
+
return { id, ...input, builtIn: false, enabled: true };
|
|
14
|
+
}
|
|
15
|
+
/** Change a rule; false when there is none with this id. */
|
|
16
|
+
export function updateTag(db, id, input, now) {
|
|
17
|
+
const r = db.prepare("UPDATE tag_rules SET name = ?, color = ?, query = ?, updated_ms = ? WHERE id = ?").run(input.name, input.color, input.query, now, id);
|
|
18
|
+
return Number(r.changes) > 0;
|
|
19
|
+
}
|
|
20
|
+
export function deleteTag(db, id) {
|
|
21
|
+
return Number(db.prepare("DELETE FROM tag_rules WHERE id = ?").run(id).changes) > 0;
|
|
22
|
+
}
|
|
23
|
+
/** Turn a built-in on or off; false when `id` is not a built-in. */
|
|
24
|
+
export function setBuiltIn(db, id, enabled) {
|
|
25
|
+
const name = id.startsWith(BUILT_IN_PREFIX) ? id.slice(BUILT_IN_PREFIX.length) : "";
|
|
26
|
+
if (!isBuiltInName(name))
|
|
27
|
+
return false;
|
|
28
|
+
db.prepare("INSERT INTO tag_builtins (name, enabled) VALUES (?, ?) ON CONFLICT(name) DO UPDATE SET enabled = excluded.enabled").run(name, enabled ? 1 : 0);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=tags.js.map
|
package/dist/tags.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,aAAa,EAA8C,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAW3H,MAAM,MAAM,GAAG,CAAC,CAAU,EAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAiB,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAEhJ,8EAA8E;AAC9E,MAAM,UAAU,OAAO,CAAC,EAAgB;IACtC,MAAM,KAAK,GAAI,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,EAA2B,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,EAAwB,CAAC;IACtG,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAgB,EAAE,KAAe,EAAE,GAAW;IACtE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,EAAE,CAAC,OAAO,CAAC,kGAAkG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACvK,OAAO,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,SAAS,CAAC,EAAgB,EAAE,EAAU,EAAE,KAAe,EAAE,GAAW;IAClF,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,kFAAkF,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5J,OAAO,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAgB,EAAE,EAAU;IACpD,OAAO,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AACtF,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,EAAgB,EAAE,EAAU,EAAE,OAAgB;IACvE,MAAM,IAAI,GAAG,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,EAAE,CAAC,OAAO,CAAC,mHAAmH,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3J,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { ApiContext } from "../api.js";
|
|
3
|
+
/** `api/uptime` and `api/uptime/<id>`: list, add, change, remove, and run a check now. */
|
|
4
|
+
export declare function handleUptime(c: ApiContext, sub: string, req: IncomingMessage, res: ServerResponse, url: URL): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/uptime/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAuD5C,0FAA0F;AAC1F,wBAAsB,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAajI"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { parseCheckInput, shownHeaders, UPTIME_LIMITS, uptimeList } from "@wizeworks/lens-core";
|
|
2
|
+
import { sendJson } from "@wizeworks/lens-node/kit";
|
|
3
|
+
import { parseJson, readBody } from "../body.js";
|
|
4
|
+
import { runHubCheck } from "./schedule.js";
|
|
5
|
+
import { checkById, countChecks, createCheck, deleteCheck, listChecks, listIncidents, updateCheck } from "./store.js";
|
|
6
|
+
/** A change must come from a page on this hub (or a script, which sends no Origin): other sites may not add checks here. */
|
|
7
|
+
function fromThisHub(req) {
|
|
8
|
+
const origin = req.headers.origin;
|
|
9
|
+
if (!origin)
|
|
10
|
+
return true;
|
|
11
|
+
return URL.canParse(origin) && new URL(origin).host === req.headers.host;
|
|
12
|
+
}
|
|
13
|
+
function list(c, p, res) {
|
|
14
|
+
const db = c.data.store.db;
|
|
15
|
+
const checks = listChecks(db, p.get("project") ?? undefined);
|
|
16
|
+
const now = c.o.now();
|
|
17
|
+
sendJson(res, 200, uptimeList(checks, listIncidents(db, checks.map((x) => x.id), now), now));
|
|
18
|
+
}
|
|
19
|
+
/** A check as the API shows it: secret-looking header values hidden. */
|
|
20
|
+
const shown = (c) => c && { ...c, headers: shownHeaders(c.headers) };
|
|
21
|
+
async function bodyOf(req) {
|
|
22
|
+
const raw = parseJson(await readBody(req));
|
|
23
|
+
return raw && typeof raw === "object" ? raw : {};
|
|
24
|
+
}
|
|
25
|
+
async function create(c, req, res) {
|
|
26
|
+
const db = c.data.store.db;
|
|
27
|
+
if (countChecks(db) >= UPTIME_LIMITS.maxChecks)
|
|
28
|
+
return sendJson(res, 400, { error: `A hub runs at most ${UPTIME_LIMITS.maxChecks} checks.` });
|
|
29
|
+
const body = await bodyOf(req);
|
|
30
|
+
const parsed = parseCheckInput(body);
|
|
31
|
+
if (!parsed.ok)
|
|
32
|
+
return sendJson(res, 400, { error: parsed.error });
|
|
33
|
+
const project = typeof body.project === "string" ? body.project.slice(0, 100) : "";
|
|
34
|
+
const id = createCheck(db, project, parsed.input, c.o.now());
|
|
35
|
+
sendJson(res, 201, shown(checkById(db, id)));
|
|
36
|
+
}
|
|
37
|
+
async function change(c, id, req, res) {
|
|
38
|
+
const db = c.data.store.db;
|
|
39
|
+
const current = checkById(db, id);
|
|
40
|
+
if (!current)
|
|
41
|
+
return sendJson(res, 404, { error: "Check not found." });
|
|
42
|
+
const parsed = parseCheckInput(await bodyOf(req), current);
|
|
43
|
+
if (!parsed.ok)
|
|
44
|
+
return sendJson(res, 400, { error: parsed.error });
|
|
45
|
+
updateCheck(db, current, parsed.input, c.o.now());
|
|
46
|
+
sendJson(res, 200, shown(checkById(db, id)));
|
|
47
|
+
}
|
|
48
|
+
async function runNow(c, id, res) {
|
|
49
|
+
const check = checkById(c.data.store.db, id);
|
|
50
|
+
if (!check)
|
|
51
|
+
return sendJson(res, 404, { error: "Check not found." });
|
|
52
|
+
await runHubCheck(c.data, check, { allowPrivate: true, now: c.o.now });
|
|
53
|
+
sendJson(res, 200, shown(checkById(c.data.store.db, id)));
|
|
54
|
+
}
|
|
55
|
+
/** `api/uptime` and `api/uptime/<id>`: list, add, change, remove, and run a check now. */
|
|
56
|
+
export async function handleUptime(c, sub, req, res, url) {
|
|
57
|
+
if (!c.o.uptime)
|
|
58
|
+
return sendJson(res, 404, { error: "Uptime checks are off on this hub (--no-uptime)." });
|
|
59
|
+
const method = req.method ?? "GET";
|
|
60
|
+
if (method !== "GET" && !fromThisHub(req))
|
|
61
|
+
return sendJson(res, 403, { error: "Changes must come from this hub's dashboard." });
|
|
62
|
+
const m = /^api\/uptime(?:\/([0-9a-f-]{36}))?(\/run)?$/.exec(sub);
|
|
63
|
+
if (!m)
|
|
64
|
+
return sendJson(res, 404, { error: "not found" });
|
|
65
|
+
const [, id, run] = m;
|
|
66
|
+
if (!id && method === "GET")
|
|
67
|
+
return list(c, url.searchParams, res);
|
|
68
|
+
if (!id && method === "POST")
|
|
69
|
+
return create(c, req, res);
|
|
70
|
+
if (id && run && method === "POST")
|
|
71
|
+
return runNow(c, id, res);
|
|
72
|
+
if (id && !run && method === "PATCH")
|
|
73
|
+
return change(c, id, req, res);
|
|
74
|
+
if (id && !run && method === "DELETE")
|
|
75
|
+
return sendJson(res, deleteCheck(c.data.store.db, id) ? 200 : 404, { ok: true });
|
|
76
|
+
sendJson(res, 405, { error: "method not allowed" });
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/uptime/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** True for errors about the server's certificate (expired, self-signed, wrong name), not the network. */
|
|
2
|
+
export declare const isCertError: (err: unknown) => boolean;
|
|
3
|
+
/** A bare TLS handshake that sends nothing, to read when a certificate the request refused ends. Null when it cannot tell. */
|
|
4
|
+
export declare function probeCertEnd(raw: string, allowPrivate: boolean, timeoutMs: number): Promise<number | null>;
|
|
5
|
+
//# sourceMappingURL=cert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cert.d.ts","sourceRoot":"","sources":["../../src/uptime/cert.ts"],"names":[],"mappings":"AAIA,0GAA0G;AAC1G,eAAO,MAAM,WAAW,QAAS,OAAO,KAAG,OAA4G,CAAC;AAExJ,8HAA8H;AAC9H,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiB1G"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { connect } from "node:tls";
|
|
3
|
+
import { bareHost, checkLiteral, guardedLookup } from "./guard.js";
|
|
4
|
+
/** True for errors about the server's certificate (expired, self-signed, wrong name), not the network. */
|
|
5
|
+
export const isCertError = (err) => /CERT|SELF_SIGNED|UNABLE_TO_VERIFY|ALTNAME/i.test(String(err?.code ?? ""));
|
|
6
|
+
/** A bare TLS handshake that sends nothing, to read when a certificate the request refused ends. Null when it cannot tell. */
|
|
7
|
+
export function probeCertEnd(raw, allowPrivate, timeoutMs) {
|
|
8
|
+
const url = new URL(raw);
|
|
9
|
+
try {
|
|
10
|
+
checkLiteral(url, allowPrivate);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return Promise.resolve(null);
|
|
14
|
+
}
|
|
15
|
+
const host = bareHost(url);
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const socket = connect({ host, port: Number(url.port) || 443, ...(isIP(host) ? {} : { servername: host }), rejectUnauthorized: false, lookup: guardedLookup(allowPrivate), timeout: timeoutMs }, () => {
|
|
18
|
+
const end = Date.parse(socket.getPeerCertificate()?.valid_to ?? "");
|
|
19
|
+
socket.destroy();
|
|
20
|
+
resolve(Number.isFinite(end) ? end : null);
|
|
21
|
+
});
|
|
22
|
+
socket.on("error", () => resolve(null));
|
|
23
|
+
socket.on("timeout", () => (socket.destroy(), resolve(null)));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=cert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cert.js","sourceRoot":"","sources":["../../src/uptime/cert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEnE,0GAA0G;AAC1G,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAY,EAAW,EAAE,CAAC,4CAA4C,CAAC,IAAI,CAAC,MAAM,CAAE,GAAyB,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;AAExJ,8HAA8H;AAC9H,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,YAAqB,EAAE,SAAiB;IAChF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC;QACH,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE;YACpM,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;YACpE,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type LookupFunction } from "node:net";
|
|
2
|
+
/** Loopback, private, link-local (cloud metadata), carrier-grade NAT, multicast, and reserved addresses. */
|
|
3
|
+
export declare const isPrivateAddress: (ip: string) => boolean;
|
|
4
|
+
export declare class BlockedAddressError extends Error {
|
|
5
|
+
constructor(host: string);
|
|
6
|
+
}
|
|
7
|
+
/** The host of a URL without IPv6 brackets. */
|
|
8
|
+
export declare const bareHost: (u: URL) => string;
|
|
9
|
+
/** A DNS lookup that refuses private addresses unless they are allowed, so a check cannot reach the host's own network. */
|
|
10
|
+
export declare function guardedLookup(allowPrivate: boolean): LookupFunction;
|
|
11
|
+
/** Refuse a literal private address up front: connections to an IP skip the lookup. */
|
|
12
|
+
export declare function checkLiteral(u: URL, allowPrivate: boolean): void;
|
|
13
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/uptime/guard.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAQrD,4GAA4G;AAC5G,eAAO,MAAM,gBAAgB,OAAQ,MAAM,KAAG,OAAsF,CAAC;AAErI,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,IAAI,EAAE,MAAM,EAEvB;CACF;AAED,+CAA+C;AAC/C,eAAO,MAAM,QAAQ,MAAO,GAAG,KAAG,MAA4C,CAAC;AAE/E,2HAA2H;AAC3H,wBAAgB,aAAa,CAAC,YAAY,EAAE,OAAO,GAAG,cAAc,CAUnE;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,GAAG,IAAI,CAGhE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { lookup } from "node:dns";
|
|
2
|
+
import { isIP } from "node:net";
|
|
3
|
+
const PRIVATE_V4 = [
|
|
4
|
+
/^0\./, /^10\./, /^127\./, /^169\.254\./, /^172\.(1[6-9]|2\d|3[01])\./, /^192\.168\./, /^192\.0\.0\./, /^198\.1[89]\./,
|
|
5
|
+
/^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./, /^(22[4-9]|2[3-5]\d)\./,
|
|
6
|
+
];
|
|
7
|
+
const PRIVATE_V6 = /^(::1?$|fc|fd|fe[89ab]|::ffff:(0|10|127|169\.254|172\.(1[6-9]|2\d|3[01])|192\.168|100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7]))\.)/i;
|
|
8
|
+
/** Loopback, private, link-local (cloud metadata), carrier-grade NAT, multicast, and reserved addresses. */
|
|
9
|
+
export const isPrivateAddress = (ip) => (isIP(ip) === 6 ? PRIVATE_V6.test(ip) : PRIVATE_V4.some((r) => r.test(ip)));
|
|
10
|
+
export class BlockedAddressError extends Error {
|
|
11
|
+
constructor(host) {
|
|
12
|
+
super(`${host} is a private or local address, which checks from here cannot reach.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** The host of a URL without IPv6 brackets. */
|
|
16
|
+
export const bareHost = (u) => u.hostname.replace(/^\[|\]$/g, "");
|
|
17
|
+
/** A DNS lookup that refuses private addresses unless they are allowed, so a check cannot reach the host's own network. */
|
|
18
|
+
export function guardedLookup(allowPrivate) {
|
|
19
|
+
return (host, options, callback) => {
|
|
20
|
+
lookup(host, { ...options, all: true }, (err, addresses) => {
|
|
21
|
+
if (err)
|
|
22
|
+
return callback(err, "", 4);
|
|
23
|
+
const list = addresses;
|
|
24
|
+
if (!allowPrivate && list.some((a) => isPrivateAddress(a.address)))
|
|
25
|
+
return callback(new BlockedAddressError(host), "", 4);
|
|
26
|
+
if (options.all)
|
|
27
|
+
return callback(null, list);
|
|
28
|
+
callback(null, list[0].address, list[0].family);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Refuse a literal private address up front: connections to an IP skip the lookup. */
|
|
33
|
+
export function checkLiteral(u, allowPrivate) {
|
|
34
|
+
const host = bareHost(u);
|
|
35
|
+
if (!allowPrivate && isIP(host) && isPrivateAddress(host))
|
|
36
|
+
throw new BlockedAddressError(host);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/uptime/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,IAAI,EAAuB,MAAM,UAAU,CAAC;AAErD,MAAM,UAAU,GAAG;IACjB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,4BAA4B,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe;IACtH,0CAA0C,EAAE,uBAAuB;CACpE,CAAC;AACF,MAAM,UAAU,GAAG,8HAA8H,CAAC;AAElJ,4GAA4G;AAC5G,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAErI,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,IAAY;QACtB,KAAK,CAAC,GAAG,IAAI,sEAAsE,CAAC,CAAC;IACvF,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAM,EAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAE/E,2HAA2H;AAC3H,MAAM,UAAU,aAAa,CAAC,YAAqB;IACjD,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;QACjC,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE;YACzD,IAAI,GAAG;gBAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,SAA6D,CAAC;YAC3E,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBAAE,OAAO,QAAQ,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC1H,IAAK,OAA6B,CAAC,GAAG;gBAAE,OAAQ,QAAyD,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACtH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,YAAY,CAAC,CAAM,EAAE,YAAqB;IACxD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;AACjG,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type UptimeCheckInput, type UptimeResult } from "@wizeworks/lens-core";
|
|
2
|
+
export interface RunOptions {
|
|
3
|
+
/** Let checks reach private and local addresses (hubs: yes; the cloud: only when self-hosted with --allow-private-webhooks). */
|
|
4
|
+
allowPrivate: boolean;
|
|
5
|
+
now?: () => number;
|
|
6
|
+
/** Extra trusted certificates, for tests. */
|
|
7
|
+
ca?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Run one check: follow redirects, time it, match status and body, and read the certificate's end. */
|
|
10
|
+
export declare function runCheck(check: UptimeCheckInput, o: RunOptions): Promise<UptimeResult>;
|
|
11
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/uptime/run.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIlH,MAAM,WAAW,UAAU;IACzB,gIAAgI;IAChI,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,6CAA6C;IAC7C,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAmFD,uGAAuG;AACvG,wBAAsB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAgB5F"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { request as httpRequest } from "node:http";
|
|
2
|
+
import { request as httpsRequest } from "node:https";
|
|
3
|
+
import { parseExpectStatus, statusMatches } from "@wizeworks/lens-core";
|
|
4
|
+
import { isCertError, probeCertEnd } from "./cert.js";
|
|
5
|
+
import { checkLiteral, guardedLookup } from "./guard.js";
|
|
6
|
+
const MAX_REDIRECTS = 5;
|
|
7
|
+
const MAX_BODY = 1_000_000;
|
|
8
|
+
const USER_AGENT = "WizeLens-Uptime/1 (+https://wizelens.com/docs/uptime)";
|
|
9
|
+
/** When the peer certificate ends, from an https response. */
|
|
10
|
+
function certEndOf(res) {
|
|
11
|
+
const socket = res.socket;
|
|
12
|
+
if (typeof socket.getPeerCertificate !== "function")
|
|
13
|
+
return null;
|
|
14
|
+
const end = Date.parse(socket.getPeerCertificate()?.valid_to ?? "");
|
|
15
|
+
return Number.isFinite(end) ? end : null;
|
|
16
|
+
}
|
|
17
|
+
/** Read up to MAX_BODY characters of the body; past that, stop reading. */
|
|
18
|
+
function readBody(res, keep) {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
let text = "";
|
|
21
|
+
let size = 0;
|
|
22
|
+
res.setEncoding("utf8");
|
|
23
|
+
res.on("data", (chunk) => {
|
|
24
|
+
if (keep)
|
|
25
|
+
text += chunk;
|
|
26
|
+
size += chunk.length;
|
|
27
|
+
if (size > MAX_BODY)
|
|
28
|
+
(res.destroy(), resolve(text.slice(0, MAX_BODY)));
|
|
29
|
+
});
|
|
30
|
+
res.on("end", () => resolve(text));
|
|
31
|
+
res.on("error", reject);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** One request, no redirects followed. */
|
|
35
|
+
function hop(url, check, o, signal) {
|
|
36
|
+
checkLiteral(url, o.allowPrivate);
|
|
37
|
+
const send = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
38
|
+
const headers = { "user-agent": USER_AGENT, accept: "*/*", ...check.headers };
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
const req = send(url, { method: check.method, headers, signal, agent: false, lookup: guardedLookup(o.allowPrivate), ...(o.ca ? { ca: o.ca } : {}) }, (res) => {
|
|
41
|
+
const tlsExpiresMs = certEndOf(res);
|
|
42
|
+
readBody(res, check.expectBody !== "").then((body) => resolve({ status: res.statusCode ?? 0, location: res.headers.location ?? null, body, tlsExpiresMs }), reject);
|
|
43
|
+
});
|
|
44
|
+
req.on("error", reject);
|
|
45
|
+
req.end();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Redirects are followed unless the check expects a 3xx status itself. */
|
|
49
|
+
const followsRedirects = (check) => !(parseExpectStatus(check.expectStatus) ?? []).some(([lo, hi]) => lo < 400 && hi >= 300);
|
|
50
|
+
async function follow(check, o, signal) {
|
|
51
|
+
let url = new URL(check.url);
|
|
52
|
+
let tls = null;
|
|
53
|
+
for (let i = 0;; i++) {
|
|
54
|
+
const h = await hop(url, check, o, signal);
|
|
55
|
+
tls ??= h.tlsExpiresMs;
|
|
56
|
+
if (!followsRedirects(check) || h.status < 300 || h.status >= 400 || !h.location || i >= MAX_REDIRECTS)
|
|
57
|
+
return { ...h, url: url.toString(), tls };
|
|
58
|
+
url = new URL(h.location, url);
|
|
59
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
60
|
+
return { ...h, url: url.toString(), tls };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Why a response fails the check, or null when it passes. */
|
|
64
|
+
function verdict(check, h) {
|
|
65
|
+
if (!statusMatches(check.expectStatus, h.status))
|
|
66
|
+
return `Expected status ${check.expectStatus}, got ${h.status}`;
|
|
67
|
+
if (check.expectBody && !h.body.includes(check.expectBody))
|
|
68
|
+
return `The response does not contain "${check.expectBody.slice(0, 80)}"`;
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const errorText = (err, timeoutMs) => {
|
|
72
|
+
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError"))
|
|
73
|
+
return `Timed out after ${timeoutMs / 1000} s`;
|
|
74
|
+
const e = err;
|
|
75
|
+
return (e.message || e.code || "The request failed").slice(0, 300);
|
|
76
|
+
};
|
|
77
|
+
/** Run one check: follow redirects, time it, match status and body, and read the certificate's end. */
|
|
78
|
+
export async function runCheck(check, o) {
|
|
79
|
+
const now = o.now ?? Date.now;
|
|
80
|
+
const startMs = now();
|
|
81
|
+
const t0 = performance.now();
|
|
82
|
+
const took = () => Math.max(0, Math.round((performance.now() - t0) * 10) / 10);
|
|
83
|
+
try {
|
|
84
|
+
const h = await follow(check, o, AbortSignal.timeout(check.timeoutMs));
|
|
85
|
+
const error = verdict(check, h);
|
|
86
|
+
return { startMs, durationMs: took(), ok: error === null, status: h.status, error, tlsExpiresMs: h.tls, finalUrl: h.url };
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const durationMs = took();
|
|
90
|
+
const cert = isCertError(err);
|
|
91
|
+
const tlsExpiresMs = cert ? await probeCertEnd(check.url, o.allowPrivate, check.timeoutMs) : null;
|
|
92
|
+
const error = `${cert ? "The TLS certificate is not valid: " : ""}${errorText(err, check.timeoutMs)}`;
|
|
93
|
+
return { startMs, durationMs, ok: false, status: null, error, tlsExpiresMs, finalUrl: check.url };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/uptime/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { HubData } from "../data.js";
|
|
2
|
+
import type { HubWrite } from "../store.js";
|
|
3
|
+
import { type RunOptions } from "./run.js";
|
|
4
|
+
import { type HubCheck } from "./store.js";
|
|
5
|
+
/** The write a run makes: a trace of the wizelens-uptime service, in the check's project and environment. */
|
|
6
|
+
export declare function uptimeWrite(c: HubCheck, telemetry: Pick<HubWrite, "spans" | "logs">, runtime: string): HubWrite;
|
|
7
|
+
/** Run one check now: keep its result, and write it as a trace. */
|
|
8
|
+
export declare function runHubCheck(data: HubData, c: HubCheck, o: RunOptions & {
|
|
9
|
+
now: () => number;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
/** Run every check that is due. Each run is claimed first, so a slow one is not started again by the next tick. */
|
|
12
|
+
export declare function runDueChecks(data: HubData, o: RunOptions & {
|
|
13
|
+
now: () => number;
|
|
14
|
+
}): Promise<number>;
|
|
15
|
+
//# sourceMappingURL=schedule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/uptime/schedule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAY,MAAM,UAAU,CAAC;AACrD,OAAO,EAAuB,KAAK,QAAQ,EAA2B,MAAM,YAAY,CAAC;AAEzF,6GAA6G;AAC7G,wBAAgB,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAG/G;AAED,mEAAmE;AACnE,wBAAsB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlH;AAED,mHAAmH;AACnH,wBAAsB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAQxG"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { UPTIME_SERVICE, uptimeTelemetry } from "@wizeworks/lens-core";
|
|
2
|
+
import { runCheck } from "./run.js";
|
|
3
|
+
import { claimRun, dueChecks, pruneIncidents, saveRun } from "./store.js";
|
|
4
|
+
/** The write a run makes: a trace of the wizelens-uptime service, in the check's project and environment. */
|
|
5
|
+
export function uptimeWrite(c, telemetry, runtime) {
|
|
6
|
+
const sender = { service: UPTIME_SERVICE, project: c.project || undefined, environment: c.env || undefined, runtime };
|
|
7
|
+
return { sender, via: "uptime", ...telemetry, remotes: [] };
|
|
8
|
+
}
|
|
9
|
+
/** Run one check now: keep its result, and write it as a trace. */
|
|
10
|
+
export async function runHubCheck(data, c, o) {
|
|
11
|
+
const r = await runCheck(c, o);
|
|
12
|
+
saveRun(data.store.db, c, r);
|
|
13
|
+
data.write(uptimeWrite(c, uptimeTelemetry(c, r), "wizelens-hub"));
|
|
14
|
+
}
|
|
15
|
+
/** Run every check that is due. Each run is claimed first, so a slow one is not started again by the next tick. */
|
|
16
|
+
export async function runDueChecks(data, o) {
|
|
17
|
+
const db = data.store.db;
|
|
18
|
+
const now = o.now();
|
|
19
|
+
const due = dueChecks(db, now);
|
|
20
|
+
for (const c of due)
|
|
21
|
+
claimRun(db, c, now);
|
|
22
|
+
await Promise.all(due.map((c) => runHubCheck(data, c, o).catch((err) => console.error(`[wizelens-hub] uptime check ${c.id} failed:`, err))));
|
|
23
|
+
pruneIncidents(db, now);
|
|
24
|
+
return due.length;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/uptime/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,EAAmB,QAAQ,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAiB,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEzF,6GAA6G;AAC7G,MAAM,UAAU,WAAW,CAAC,CAAW,EAAE,SAA2C,EAAE,OAAe;IACnG,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,OAAO,EAAE,CAAC;IACtH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC9D,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAa,EAAE,CAAW,EAAE,CAAqC;IACjG,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,mHAAmH;AACnH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAa,EAAE,CAAqC;IACrF,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACpB,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtJ,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACxB,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import { type UptimeCheck, type UptimeCheckInput, type UptimeIncident, type UptimeResult } from "@wizeworks/lens-core";
|
|
3
|
+
export declare const HUB_UPTIME_SCHEMA = "\nCREATE TABLE IF NOT EXISTS uptime_checks (\n id TEXT PRIMARY KEY, project TEXT NOT NULL DEFAULT '', name TEXT NOT NULL, url TEXT NOT NULL, method TEXT NOT NULL, headers TEXT NOT NULL,\n expect_status TEXT NOT NULL, expect_body TEXT NOT NULL, interval_min INTEGER NOT NULL, timeout_ms INTEGER NOT NULL, env TEXT NOT NULL DEFAULT '',\n enabled INTEGER NOT NULL, created_ms REAL NOT NULL, state TEXT NOT NULL DEFAULT 'pending', last_run_ms REAL, last_duration_ms REAL,\n last_status INTEGER, last_error TEXT, tls_expires_ms REAL, next_ms REAL NOT NULL\n);\nCREATE INDEX IF NOT EXISTS ix_uptime_checks_next ON uptime_checks (next_ms);\nCREATE TABLE IF NOT EXISTS uptime_incidents (\n id TEXT PRIMARY KEY, check_id TEXT NOT NULL, start_ms REAL NOT NULL, end_ms REAL, reason TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS ix_uptime_incidents_check ON uptime_incidents (check_id, start_ms);\n";
|
|
4
|
+
export type HubCheck = UptimeCheck & {
|
|
5
|
+
project: string;
|
|
6
|
+
};
|
|
7
|
+
/** Checks of one project, or of every project when none is given. */
|
|
8
|
+
export declare const listChecks: (db: DatabaseSync, project?: string) => HubCheck[];
|
|
9
|
+
export declare const checkById: (db: DatabaseSync, id: string) => HubCheck | undefined;
|
|
10
|
+
export declare const countChecks: (db: DatabaseSync) => number;
|
|
11
|
+
export declare function createCheck(db: DatabaseSync, project: string, c: UptimeCheckInput, now: number): string;
|
|
12
|
+
/** Save a change. A new interval moves the next run; turning a check off leaves its incidents as they are. */
|
|
13
|
+
export declare function updateCheck(db: DatabaseSync, current: HubCheck, c: UptimeCheckInput, now: number): void;
|
|
14
|
+
export declare function deleteCheck(db: DatabaseSync, id: string): boolean;
|
|
15
|
+
/** Enabled checks whose next run is due. */
|
|
16
|
+
export declare const dueChecks: (db: DatabaseSync, now: number) => HubCheck[];
|
|
17
|
+
/** Push a check's next run out before it runs, so a slow run is not started twice. */
|
|
18
|
+
export declare const claimRun: (db: DatabaseSync, c: HubCheck, now: number) => void;
|
|
19
|
+
/** Keep a run's result on its check, and open or close an incident. */
|
|
20
|
+
export declare function saveRun(db: DatabaseSync, c: HubCheck, r: UptimeResult): void;
|
|
21
|
+
/** Incidents of the given checks still open or ended in the last 90 days. */
|
|
22
|
+
export declare function listIncidents(db: DatabaseSync, checkIds: readonly string[], now: number): UptimeIncident[];
|
|
23
|
+
/** Drop incidents that ended more than 90 days ago. */
|
|
24
|
+
export declare const pruneIncidents: (db: DatabaseSync, now: number) => void;
|
|
25
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/uptime/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAkD,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGvK,eAAO,MAAM,iBAAiB,g4BAY7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAUzD,qEAAqE;AACrE,eAAO,MAAM,UAAU,OAAQ,YAAY,YAAY,MAAM,KAAG,QAAQ,EAC4G,CAAC;AAErL,eAAO,MAAM,SAAS,OAAQ,YAAY,MAAM,MAAM,KAAG,QAAQ,GAAG,SAAiF,CAAC;AAEtJ,eAAO,MAAM,WAAW,OAAQ,YAAY,KAAG,MAA0F,CAAC;AAE1I,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOvG;AAED,8GAA8G;AAC9G,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAUvG;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAGjE;AAED,4CAA4C;AAC5C,eAAO,MAAM,SAAS,OAAQ,YAAY,OAAO,MAAM,KAAG,QAAQ,EAAwH,CAAC;AAE3L,sFAAsF;AACtF,eAAO,MAAM,QAAQ,OAAQ,YAAY,KAAK,QAAQ,OAAO,MAAM,KAAG,IAAoH,CAAC;AAE3L,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,GAAG,IAAI,CAe5E;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAM1G;AAED,uDAAuD;AACvD,eAAO,MAAM,cAAc,OAAQ,YAAY,OAAO,MAAM,KAAG,IAAyH,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { changeOf, lastRunOf, nextRunMs, UPTIME_KEEP_MS } from "@wizeworks/lens-core";
|
|
3
|
+
// Uptime checks and incidents in the hub file (docs/CONTRACT.md, "Hub storage"). Results themselves are traces.
|
|
4
|
+
export const HUB_UPTIME_SCHEMA = `
|
|
5
|
+
CREATE TABLE IF NOT EXISTS uptime_checks (
|
|
6
|
+
id TEXT PRIMARY KEY, project TEXT NOT NULL DEFAULT '', name TEXT NOT NULL, url TEXT NOT NULL, method TEXT NOT NULL, headers TEXT NOT NULL,
|
|
7
|
+
expect_status TEXT NOT NULL, expect_body TEXT NOT NULL, interval_min INTEGER NOT NULL, timeout_ms INTEGER NOT NULL, env TEXT NOT NULL DEFAULT '',
|
|
8
|
+
enabled INTEGER NOT NULL, created_ms REAL NOT NULL, state TEXT NOT NULL DEFAULT 'pending', last_run_ms REAL, last_duration_ms REAL,
|
|
9
|
+
last_status INTEGER, last_error TEXT, tls_expires_ms REAL, next_ms REAL NOT NULL
|
|
10
|
+
);
|
|
11
|
+
CREATE INDEX IF NOT EXISTS ix_uptime_checks_next ON uptime_checks (next_ms);
|
|
12
|
+
CREATE TABLE IF NOT EXISTS uptime_incidents (
|
|
13
|
+
id TEXT PRIMARY KEY, check_id TEXT NOT NULL, start_ms REAL NOT NULL, end_ms REAL, reason TEXT NOT NULL
|
|
14
|
+
);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS ix_uptime_incidents_check ON uptime_incidents (check_id, start_ms);
|
|
16
|
+
`;
|
|
17
|
+
const COLUMNS = `id, project, name, url, method, headers, expect_status AS expectStatus, expect_body AS expectBody, interval_min AS intervalMin,
|
|
18
|
+
timeout_ms AS timeoutMs, env, enabled, created_ms AS createdMs, state, last_run_ms AS lastRunMs, last_duration_ms AS lastDurationMs,
|
|
19
|
+
last_status AS lastStatus, last_error AS lastError, tls_expires_ms AS tlsExpiresMs`;
|
|
20
|
+
const toCheck = (r) => ({ ...r, headers: JSON.parse(r.headers), enabled: r.enabled === 1 });
|
|
21
|
+
const rows = (db, sql, ...params) => db.prepare(sql).all(...params).map(toCheck);
|
|
22
|
+
/** Checks of one project, or of every project when none is given. */
|
|
23
|
+
export const listChecks = (db, project) => project === undefined ? rows(db, `SELECT ${COLUMNS} FROM uptime_checks ORDER BY name`) : rows(db, `SELECT ${COLUMNS} FROM uptime_checks WHERE project = ? ORDER BY name`, project);
|
|
24
|
+
export const checkById = (db, id) => rows(db, `SELECT ${COLUMNS} FROM uptime_checks WHERE id = ?`, id)[0];
|
|
25
|
+
export const countChecks = (db) => db.prepare("SELECT count(*) AS n FROM uptime_checks").get().n;
|
|
26
|
+
export function createCheck(db, project, c, now) {
|
|
27
|
+
const id = randomUUID();
|
|
28
|
+
db.prepare(`INSERT INTO uptime_checks (id, project, name, url, method, headers, expect_status, expect_body, interval_min, timeout_ms, env, enabled, created_ms, next_ms)
|
|
29
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, project, c.name, c.url, c.method, JSON.stringify(c.headers), c.expectStatus, c.expectBody, c.intervalMin, c.timeoutMs, c.env, c.enabled ? 1 : 0, now, now);
|
|
30
|
+
return id;
|
|
31
|
+
}
|
|
32
|
+
/** Save a change. A new interval moves the next run; turning a check off leaves its incidents as they are. */
|
|
33
|
+
export function updateCheck(db, current, c, now) {
|
|
34
|
+
const next = Math.min(nextRunMs({ lastRunMs: current.lastRunMs, intervalMin: c.intervalMin }, now), now + c.intervalMin * 60_000);
|
|
35
|
+
db.prepare(`UPDATE uptime_checks SET name = ?, url = ?, method = ?, headers = ?, expect_status = ?, expect_body = ?, interval_min = ?, timeout_ms = ?, env = ?,
|
|
36
|
+
enabled = ?, next_ms = ? WHERE id = ?`).run(c.name, c.url, c.method, JSON.stringify(c.headers), c.expectStatus, c.expectBody, c.intervalMin, c.timeoutMs, c.env, c.enabled ? 1 : 0, next, current.id);
|
|
37
|
+
if (c.enabled)
|
|
38
|
+
return;
|
|
39
|
+
// A check turned off is not down: its open incident ends now, and it starts over as pending.
|
|
40
|
+
db.prepare("UPDATE uptime_incidents SET end_ms = ? WHERE check_id = ? AND end_ms IS NULL").run(now, current.id);
|
|
41
|
+
db.prepare("UPDATE uptime_checks SET state = 'pending' WHERE id = ?").run(current.id);
|
|
42
|
+
}
|
|
43
|
+
export function deleteCheck(db, id) {
|
|
44
|
+
db.prepare("DELETE FROM uptime_incidents WHERE check_id = ?").run(id);
|
|
45
|
+
return Number(db.prepare("DELETE FROM uptime_checks WHERE id = ?").run(id).changes) > 0;
|
|
46
|
+
}
|
|
47
|
+
/** Enabled checks whose next run is due. */
|
|
48
|
+
export const dueChecks = (db, now) => rows(db, `SELECT ${COLUMNS} FROM uptime_checks WHERE enabled = 1 AND next_ms <= ? ORDER BY next_ms LIMIT 50`, now);
|
|
49
|
+
/** Push a check's next run out before it runs, so a slow run is not started twice. */
|
|
50
|
+
export const claimRun = (db, c, now) => void db.prepare("UPDATE uptime_checks SET next_ms = ? WHERE id = ?").run(now + c.intervalMin * 60_000, c.id);
|
|
51
|
+
/** Keep a run's result on its check, and open or close an incident. */
|
|
52
|
+
export function saveRun(db, c, r) {
|
|
53
|
+
const change = changeOf(c, r);
|
|
54
|
+
const last = lastRunOf(r);
|
|
55
|
+
db.exec("BEGIN");
|
|
56
|
+
try {
|
|
57
|
+
db.prepare("UPDATE uptime_checks SET state = ?, last_run_ms = ?, last_duration_ms = ?, last_status = ?, last_error = ?, tls_expires_ms = ? WHERE id = ?").run(last.state, last.lastRunMs, last.lastDurationMs, last.lastStatus, last.lastError, last.tlsExpiresMs, c.id);
|
|
58
|
+
if (change.open !== null)
|
|
59
|
+
db.prepare("INSERT INTO uptime_incidents (id, check_id, start_ms, end_ms, reason) VALUES (?, ?, ?, NULL, ?)").run(randomUUID(), c.id, r.startMs, change.open);
|
|
60
|
+
if (change.closeAtMs !== null)
|
|
61
|
+
db.prepare("UPDATE uptime_incidents SET end_ms = ? WHERE check_id = ? AND end_ms IS NULL").run(change.closeAtMs, c.id);
|
|
62
|
+
db.exec("COMMIT");
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
db.exec("ROLLBACK");
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Incidents of the given checks still open or ended in the last 90 days. */
|
|
70
|
+
export function listIncidents(db, checkIds, now) {
|
|
71
|
+
if (checkIds.length === 0)
|
|
72
|
+
return [];
|
|
73
|
+
const marks = checkIds.map(() => "?").join(", ");
|
|
74
|
+
return db
|
|
75
|
+
.prepare(`SELECT id, check_id AS checkId, start_ms AS startMs, end_ms AS endMs, reason FROM uptime_incidents WHERE check_id IN (${marks}) AND (end_ms IS NULL OR end_ms >= ?)`)
|
|
76
|
+
.all(...checkIds, now - UPTIME_KEEP_MS);
|
|
77
|
+
}
|
|
78
|
+
/** Drop incidents that ended more than 90 days ago. */
|
|
79
|
+
export const pruneIncidents = (db, now) => void db.prepare("DELETE FROM uptime_incidents WHERE end_ms IS NOT NULL AND end_ms < ?").run(now - UPTIME_KEEP_MS);
|
|
80
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/uptime/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAmF,MAAM,sBAAsB,CAAC;AAEvK,gHAAgH;AAChH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;CAYhC,CAAC;AAIF,MAAM,OAAO,GAAG;;qFAEqE,CAAC;AAGtF,MAAM,OAAO,GAAG,CAAC,CAAM,EAAY,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAA2B,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC;AACrI,MAAM,IAAI,GAAG,CAAC,EAAgB,EAAE,GAAW,EAAE,GAAG,MAAuB,EAAE,EAAE,CAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAE9I,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAgB,EAAE,OAAgB,EAAc,EAAE,CAC3E,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,OAAO,mCAAmC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,OAAO,qDAAqD,EAAE,OAAO,CAAC,CAAC;AAErL,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAgB,EAAE,EAAU,EAAwB,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,OAAO,kCAAkC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtJ,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAgB,EAAU,EAAE,CAAE,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAC;AAE1I,MAAM,UAAU,WAAW,CAAC,EAAgB,EAAE,OAAe,EAAE,CAAmB,EAAE,GAAW;IAC7F,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,EAAE,CAAC,OAAO,CACR;uDACmD,CACpD,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACrK,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,WAAW,CAAC,EAAgB,EAAE,OAAiB,EAAE,CAAmB,EAAE,GAAW;IAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,WAAW,GAAG,MAAM,CAAC,CAAC;IAClI,EAAE,CAAC,OAAO,CACR;2CACuC,CACxC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAChK,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO;IACtB,6FAA6F;IAC7F,EAAE,CAAC,OAAO,CAAC,8EAA8E,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAChH,EAAE,CAAC,OAAO,CAAC,yDAAyD,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAgB,EAAE,EAAU;IACtD,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC1F,CAAC;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAgB,EAAE,GAAW,EAAc,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,OAAO,kFAAkF,EAAE,GAAG,CAAC,CAAC;AAE3L,sFAAsF;AACtF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAgB,EAAE,CAAW,EAAE,GAAW,EAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,WAAW,GAAG,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAE3L,uEAAuE;AACvE,MAAM,UAAU,OAAO,CAAC,EAAgB,EAAE,CAAW,EAAE,CAAe;IACpE,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjB,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CAAC,6IAA6I,CAAC,CAAC,GAAG,CAC3J,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAC1G,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;YAAE,EAAE,CAAC,OAAO,CAAC,iGAAiG,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACxL,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI;YAAE,EAAE,CAAC,OAAO,CAAC,8EAA8E,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACtJ,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpB,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,EAAgB,EAAE,QAA2B,EAAE,GAAW;IACtF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,EAAE;SACN,OAAO,CAAC,yHAAyH,KAAK,uCAAuC,CAAC;SAC9K,GAAG,CAAC,GAAG,QAAQ,EAAE,GAAG,GAAG,cAAc,CAAgC,CAAC;AAC3E,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAgB,EAAE,GAAW,EAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,sEAAsE,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,cAAc,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wizeworks/lens-hub",
|
|
3
|
-
"version": "0.3.0-alpha.
|
|
3
|
+
"version": "0.3.0-alpha.4",
|
|
4
4
|
"description": "The WizeLens local hub: one place for the traces of every service on your machine or network, with the full dashboard and MCP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "WizeWorks LLC",
|
|
@@ -47,11 +47,12 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"protobufjs": "^7.6.6",
|
|
50
|
-
"@wizeworks/lens-ui": "^0.3.0-alpha.
|
|
51
|
-
"@wizeworks/lens-
|
|
52
|
-
"@wizeworks/lens-
|
|
50
|
+
"@wizeworks/lens-ui": "^0.3.0-alpha.4",
|
|
51
|
+
"@wizeworks/lens-core": "^0.3.0-alpha.4",
|
|
52
|
+
"@wizeworks/lens-node": "^0.3.0-alpha.4"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
55
56
|
"@types/node": "^24.19.2",
|
|
56
57
|
"typescript": "^7.0.2",
|
|
57
58
|
"vitest": "^5.0.5"
|