@hasna/logs 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -10
- package/dashboard/dist/assets/index-C0wZYq1m.js +53 -0
- package/dashboard/dist/assets/index-DGNrK5qb.css +1 -0
- package/dashboard/dist/index.html +14 -0
- package/dist/cli/index.js +8511 -177
- package/dist/count-bmj4r2zb.js +10 -0
- package/dist/{diagnose-e0w5rwbc.js → diagnose-3q5cy9ra.js} +2 -2
- package/dist/{export-c3eqjste.js → export-cngdb9fh.js} +1 -1
- package/dist/{http-zm3ph78w.js → http-r0xc3d2s.js} +79 -8
- package/dist/index-931pbyn5.js +141 -0
- package/dist/index-b5c72f1p.js +7 -0
- package/dist/{index-gc0zvs88.js → index-bnr19y0h.js} +596 -37
- package/dist/{index-7w7v7hnr.js → index-by1pdzbr.js} +14 -5
- package/dist/{index-3dr7d80h.js → index-e1930v9b.js} +12 -8
- package/dist/{index-eh9bkbpa.js → index-e72k53yq.js} +10 -2
- package/dist/{index-edn08m6f.js → index-gcd14q2f.js} +9 -6
- package/dist/index-hq6kzaah.js +26 -0
- package/dist/index-j34f36wy.js +5672 -0
- package/dist/index-p4dbdzx4.js +1849 -0
- package/dist/{index-5qznfyah.js → index-q27bgpr1.js} +1086 -1646
- package/dist/index-t3x838zw.js +2583 -0
- package/dist/{index-ww5ggfv3.js → index-zkb3z95a.js} +12 -9
- package/dist/index.js +2982 -22
- package/dist/{jobs-ypmmc2ma.js → jobs-hsgyhfvm.js} +2 -1
- package/dist/mcp/index.js +1473 -4286
- package/dist/{query-7jwj05er.js → query-c5a43zx3.js} +3 -2
- package/dist/server/index.js +2944 -417
- package/dist/storage.js +50 -0
- package/package.json +27 -8
- package/biome.json +0 -13
- package/bun.lock +0 -376
- package/dashboard/README.md +0 -73
- package/dashboard/bun.lock +0 -526
- package/dashboard/eslint.config.js +0 -23
- package/dashboard/index.html +0 -13
- package/dashboard/package.json +0 -32
- package/dashboard/src/App.css +0 -184
- package/dashboard/src/App.tsx +0 -49
- package/dashboard/src/api.ts +0 -33
- package/dashboard/src/assets/hero.png +0 -0
- package/dashboard/src/assets/react.svg +0 -1
- package/dashboard/src/assets/vite.svg +0 -1
- package/dashboard/src/index.css +0 -111
- package/dashboard/src/main.tsx +0 -10
- package/dashboard/src/pages/Alerts.tsx +0 -69
- package/dashboard/src/pages/Issues.tsx +0 -50
- package/dashboard/src/pages/Perf.tsx +0 -75
- package/dashboard/src/pages/Projects.tsx +0 -67
- package/dashboard/src/pages/Summary.tsx +0 -67
- package/dashboard/src/pages/Tail.tsx +0 -65
- package/dashboard/tsconfig.app.json +0 -28
- package/dashboard/tsconfig.json +0 -7
- package/dashboard/tsconfig.node.json +0 -26
- package/dashboard/vite.config.ts +0 -14
- package/dist/count-x3n7qg3c.js +0 -9
- package/dist/index-997bkzr2.js +0 -15
- package/dist/index-pen6t0yc.js +0 -10794
- package/sdk/package.json +0 -27
- package/sdk/src/index.ts +0 -143
- package/sdk/src/types.ts +0 -56
- package/src/cli/entrypoints.test.ts +0 -63
- package/src/cli/index.ts +0 -471
- package/src/db/index.test.ts +0 -33
- package/src/db/index.ts +0 -189
- package/src/db/migrations/001_alert_rules.ts +0 -21
- package/src/db/migrations/002_issues.ts +0 -21
- package/src/db/migrations/003_retention.ts +0 -15
- package/src/db/migrations/004_page_auth.ts +0 -13
- package/src/db/pg-migrations.ts +0 -167
- package/src/index.ts +0 -1
- package/src/lib/alerts.test.ts +0 -67
- package/src/lib/alerts.ts +0 -117
- package/src/lib/browser-script.test.ts +0 -35
- package/src/lib/browser-script.ts +0 -31
- package/src/lib/compare.test.ts +0 -52
- package/src/lib/compare.ts +0 -85
- package/src/lib/count.test.ts +0 -44
- package/src/lib/count.ts +0 -55
- package/src/lib/diagnose.test.ts +0 -55
- package/src/lib/diagnose.ts +0 -91
- package/src/lib/export.test.ts +0 -66
- package/src/lib/export.ts +0 -65
- package/src/lib/github.ts +0 -38
- package/src/lib/health.test.ts +0 -48
- package/src/lib/health.ts +0 -51
- package/src/lib/ingest.test.ts +0 -57
- package/src/lib/ingest.ts +0 -78
- package/src/lib/issues.test.ts +0 -79
- package/src/lib/issues.ts +0 -70
- package/src/lib/jobs.test.ts +0 -69
- package/src/lib/jobs.ts +0 -63
- package/src/lib/lighthouse.ts +0 -65
- package/src/lib/package-meta.test.ts +0 -43
- package/src/lib/package-meta.ts +0 -80
- package/src/lib/page-auth.test.ts +0 -54
- package/src/lib/page-auth.ts +0 -48
- package/src/lib/parse-time.test.ts +0 -37
- package/src/lib/parse-time.ts +0 -14
- package/src/lib/perf.test.ts +0 -45
- package/src/lib/perf.ts +0 -46
- package/src/lib/projects.test.ts +0 -73
- package/src/lib/projects.ts +0 -69
- package/src/lib/query.test.ts +0 -104
- package/src/lib/query.ts +0 -84
- package/src/lib/retention.test.ts +0 -42
- package/src/lib/retention.ts +0 -62
- package/src/lib/rotate.test.ts +0 -37
- package/src/lib/rotate.ts +0 -27
- package/src/lib/scanner.ts +0 -131
- package/src/lib/scheduler.ts +0 -63
- package/src/lib/session-context.ts +0 -28
- package/src/lib/summarize.test.ts +0 -38
- package/src/lib/summarize.ts +0 -23
- package/src/mcp/http.test.ts +0 -92
- package/src/mcp/http.ts +0 -135
- package/src/mcp/index.test.ts +0 -27
- package/src/mcp/index.ts +0 -444
- package/src/server/index.ts +0 -61
- package/src/server/routes/alerts.ts +0 -32
- package/src/server/routes/issues.ts +0 -43
- package/src/server/routes/jobs.ts +0 -32
- package/src/server/routes/logs.ts +0 -113
- package/src/server/routes/perf.ts +0 -23
- package/src/server/routes/projects.ts +0 -67
- package/src/server/routes/stream.ts +0 -43
- package/src/server/server.test.ts +0 -194
- package/src/types/index.ts +0 -119
- package/tsconfig.json +0 -22
- /package/dashboard/{public → dist}/favicon.svg +0 -0
- /package/dashboard/{public → dist}/icons.svg +0 -0
|
@@ -7,14 +7,16 @@ import {
|
|
|
7
7
|
isJSONRPCErrorResponse,
|
|
8
8
|
isJSONRPCRequest,
|
|
9
9
|
isJSONRPCResultResponse
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-q27bgpr1.js";
|
|
11
11
|
import"./index-re3ntm60.js";
|
|
12
12
|
|
|
13
13
|
// src/mcp/http.ts
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createServer
|
|
16
|
+
} from "http";
|
|
15
17
|
|
|
16
18
|
// node_modules/@hono/node-server/dist/index.mjs
|
|
17
|
-
import { Http2ServerRequest as Http2ServerRequest2 } from "http2";
|
|
19
|
+
import { Http2ServerRequest as Http2ServerRequest2, constants as h2constants } from "http2";
|
|
18
20
|
import { Http2ServerRequest } from "http2";
|
|
19
21
|
import { Readable } from "stream";
|
|
20
22
|
import crypto2 from "crypto";
|
|
@@ -154,6 +156,17 @@ var requestPrototype = {
|
|
|
154
156
|
}
|
|
155
157
|
});
|
|
156
158
|
});
|
|
159
|
+
Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom"), {
|
|
160
|
+
value: function(depth, options, inspectFn) {
|
|
161
|
+
const props = {
|
|
162
|
+
method: this.method,
|
|
163
|
+
url: this.url,
|
|
164
|
+
headers: this.headers,
|
|
165
|
+
nativeRequest: this[requestCache]
|
|
166
|
+
};
|
|
167
|
+
return `Request (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
157
170
|
Object.setPrototypeOf(requestPrototype, Request.prototype);
|
|
158
171
|
var newRequest = (incoming, defaultHostname) => {
|
|
159
172
|
const req = Object.create(requestPrototype);
|
|
@@ -254,6 +267,17 @@ var Response2 = class _Response {
|
|
|
254
267
|
}
|
|
255
268
|
});
|
|
256
269
|
});
|
|
270
|
+
Object.defineProperty(Response2.prototype, Symbol.for("nodejs.util.inspect.custom"), {
|
|
271
|
+
value: function(depth, options, inspectFn) {
|
|
272
|
+
const props = {
|
|
273
|
+
status: this.status,
|
|
274
|
+
headers: this.headers,
|
|
275
|
+
ok: this.ok,
|
|
276
|
+
nativeResponse: this[responseCache]
|
|
277
|
+
};
|
|
278
|
+
return `Response (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
257
281
|
Object.setPrototypeOf(Response2, GlobalResponse);
|
|
258
282
|
Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
|
|
259
283
|
async function readWithoutBlocking(readPromise) {
|
|
@@ -324,6 +348,48 @@ if (typeof global.crypto === "undefined") {
|
|
|
324
348
|
global.crypto = crypto2;
|
|
325
349
|
}
|
|
326
350
|
var outgoingEnded = Symbol("outgoingEnded");
|
|
351
|
+
var incomingDraining = Symbol("incomingDraining");
|
|
352
|
+
var DRAIN_TIMEOUT_MS = 500;
|
|
353
|
+
var MAX_DRAIN_BYTES = 64 * 1024 * 1024;
|
|
354
|
+
var drainIncoming = (incoming) => {
|
|
355
|
+
const incomingWithDrainState = incoming;
|
|
356
|
+
if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
incomingWithDrainState[incomingDraining] = true;
|
|
360
|
+
if (incoming instanceof Http2ServerRequest2) {
|
|
361
|
+
try {
|
|
362
|
+
incoming.stream?.close?.(h2constants.NGHTTP2_NO_ERROR);
|
|
363
|
+
} catch {}
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
let bytesRead = 0;
|
|
367
|
+
const cleanup = () => {
|
|
368
|
+
clearTimeout(timer);
|
|
369
|
+
incoming.off("data", onData);
|
|
370
|
+
incoming.off("end", cleanup);
|
|
371
|
+
incoming.off("error", cleanup);
|
|
372
|
+
};
|
|
373
|
+
const forceClose = () => {
|
|
374
|
+
cleanup();
|
|
375
|
+
const socket = incoming.socket;
|
|
376
|
+
if (socket && !socket.destroyed) {
|
|
377
|
+
socket.destroySoon();
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
|
|
381
|
+
timer.unref?.();
|
|
382
|
+
const onData = (chunk) => {
|
|
383
|
+
bytesRead += chunk.length;
|
|
384
|
+
if (bytesRead > MAX_DRAIN_BYTES) {
|
|
385
|
+
forceClose();
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
incoming.on("data", onData);
|
|
389
|
+
incoming.on("end", cleanup);
|
|
390
|
+
incoming.on("error", cleanup);
|
|
391
|
+
incoming.resume();
|
|
392
|
+
};
|
|
327
393
|
var handleRequestError = () => new Response(null, {
|
|
328
394
|
status: 400
|
|
329
395
|
});
|
|
@@ -487,14 +553,18 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
487
553
|
setTimeout(() => {
|
|
488
554
|
if (!incomingEnded) {
|
|
489
555
|
setTimeout(() => {
|
|
490
|
-
incoming
|
|
491
|
-
outgoing.destroy();
|
|
556
|
+
drainIncoming(incoming);
|
|
492
557
|
});
|
|
493
558
|
}
|
|
494
559
|
});
|
|
495
560
|
}
|
|
496
561
|
};
|
|
497
562
|
}
|
|
563
|
+
outgoing.on("finish", () => {
|
|
564
|
+
if (!incomingEnded) {
|
|
565
|
+
drainIncoming(incoming);
|
|
566
|
+
}
|
|
567
|
+
});
|
|
498
568
|
}
|
|
499
569
|
outgoing.on("close", () => {
|
|
500
570
|
const abortController = req[abortControllerKey];
|
|
@@ -509,7 +579,7 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
509
579
|
setTimeout(() => {
|
|
510
580
|
if (!incomingEnded) {
|
|
511
581
|
setTimeout(() => {
|
|
512
|
-
incoming
|
|
582
|
+
drainIncoming(incoming);
|
|
513
583
|
});
|
|
514
584
|
}
|
|
515
585
|
});
|
|
@@ -1147,8 +1217,9 @@ function isStdioMode(argv = process.argv, env = process.env) {
|
|
|
1147
1217
|
}
|
|
1148
1218
|
function resolveMcpHttpPort(argv = process.argv, env = process.env) {
|
|
1149
1219
|
const portIdx = argv.indexOf("--port");
|
|
1150
|
-
|
|
1151
|
-
|
|
1220
|
+
const portValue = argv[portIdx + 1];
|
|
1221
|
+
if (portIdx !== -1 && portValue) {
|
|
1222
|
+
return parsePort(portValue, "--port");
|
|
1152
1223
|
}
|
|
1153
1224
|
if (env.MCP_HTTP_PORT) {
|
|
1154
1225
|
return parsePort(env.MCP_HTTP_PORT, "MCP_HTTP_PORT");
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/lib/identity.ts
|
|
3
|
+
import { execFileSync } from "child_process";
|
|
4
|
+
import { createHash } from "crypto";
|
|
5
|
+
import { existsSync, readFileSync } from "fs";
|
|
6
|
+
import { arch, hostname, platform, release } from "os";
|
|
7
|
+
import { dirname, join, resolve } from "path";
|
|
8
|
+
function detectRuntimeIdentity(db, cwd, opts = {}) {
|
|
9
|
+
const environment = opts.environment ?? "development" ?? "development";
|
|
10
|
+
const machine = upsertMachine(db);
|
|
11
|
+
const repo = detectRepo(cwd);
|
|
12
|
+
if (repo)
|
|
13
|
+
upsertRepo(db, repo);
|
|
14
|
+
const app = detectApp(cwd, repo?.id ?? null, opts.project_id ?? null, environment);
|
|
15
|
+
if (app)
|
|
16
|
+
upsertApp(db, app);
|
|
17
|
+
return {
|
|
18
|
+
machine_id: machine,
|
|
19
|
+
repo_id: repo?.id ?? null,
|
|
20
|
+
app_id: app?.id ?? null,
|
|
21
|
+
environment
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function upsertMachine(db) {
|
|
25
|
+
const info = {
|
|
26
|
+
hostname: hostname(),
|
|
27
|
+
platform: platform(),
|
|
28
|
+
arch: arch(),
|
|
29
|
+
os_release: release()
|
|
30
|
+
};
|
|
31
|
+
const id = `machine_${sha256(`${info.hostname}:${info.platform}:${info.arch}`).slice(0, 16)}`;
|
|
32
|
+
db.prepare(`
|
|
33
|
+
INSERT INTO machines (id, hostname, platform, arch, os_release, metadata, last_seen_at)
|
|
34
|
+
VALUES (?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
35
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
36
|
+
hostname = excluded.hostname,
|
|
37
|
+
platform = excluded.platform,
|
|
38
|
+
arch = excluded.arch,
|
|
39
|
+
os_release = excluded.os_release,
|
|
40
|
+
metadata = excluded.metadata,
|
|
41
|
+
last_seen_at = excluded.last_seen_at
|
|
42
|
+
`).run(id, info.hostname, info.platform, info.arch, info.os_release, JSON.stringify(info));
|
|
43
|
+
return id;
|
|
44
|
+
}
|
|
45
|
+
function detectRepo(cwd) {
|
|
46
|
+
const root = git(cwd, ["rev-parse", "--show-toplevel"]);
|
|
47
|
+
if (!root)
|
|
48
|
+
return null;
|
|
49
|
+
const remote = git(root, ["config", "--get", "remote.origin.url"]);
|
|
50
|
+
const branch = git(root, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
51
|
+
const sha = git(root, ["rev-parse", "HEAD"]);
|
|
52
|
+
const dirty = git(root, ["status", "--porcelain"]) ? 1 : 0;
|
|
53
|
+
return {
|
|
54
|
+
id: `repo_${sha256(root).slice(0, 16)}`,
|
|
55
|
+
root_path: root,
|
|
56
|
+
remote_url: remote,
|
|
57
|
+
branch,
|
|
58
|
+
commit_sha: sha,
|
|
59
|
+
dirty
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function upsertRepo(db, repo) {
|
|
63
|
+
db.prepare(`
|
|
64
|
+
INSERT INTO repositories (id, root_path, remote_url, branch, commit_sha, dirty, metadata, last_seen_at)
|
|
65
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
66
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
67
|
+
root_path = excluded.root_path,
|
|
68
|
+
remote_url = excluded.remote_url,
|
|
69
|
+
branch = excluded.branch,
|
|
70
|
+
commit_sha = excluded.commit_sha,
|
|
71
|
+
dirty = excluded.dirty,
|
|
72
|
+
metadata = excluded.metadata,
|
|
73
|
+
last_seen_at = excluded.last_seen_at
|
|
74
|
+
`).run(repo.id, repo.root_path, repo.remote_url, repo.branch, repo.commit_sha, repo.dirty, JSON.stringify(repo));
|
|
75
|
+
}
|
|
76
|
+
function detectApp(cwd, repoId, projectId, environment) {
|
|
77
|
+
const packageJsonPath = findNearestPackageJson(cwd);
|
|
78
|
+
if (!packageJsonPath)
|
|
79
|
+
return null;
|
|
80
|
+
try {
|
|
81
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
82
|
+
const name = packageJson.name ?? dirname(packageJsonPath).split(/[\\/]/).pop() ?? "app";
|
|
83
|
+
return {
|
|
84
|
+
id: `app_${sha256(packageJsonPath).slice(0, 16)}`,
|
|
85
|
+
repo_id: repoId,
|
|
86
|
+
project_id: projectId,
|
|
87
|
+
name,
|
|
88
|
+
runtime: "cli",
|
|
89
|
+
environment,
|
|
90
|
+
version: packageJson.version ?? null,
|
|
91
|
+
metadata: { package_json_path: packageJsonPath }
|
|
92
|
+
};
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function upsertApp(db, app) {
|
|
98
|
+
db.prepare(`
|
|
99
|
+
INSERT INTO apps (id, repo_id, project_id, name, runtime, environment, version, metadata, last_seen_at)
|
|
100
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
101
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
102
|
+
repo_id = excluded.repo_id,
|
|
103
|
+
project_id = excluded.project_id,
|
|
104
|
+
name = excluded.name,
|
|
105
|
+
runtime = excluded.runtime,
|
|
106
|
+
environment = excluded.environment,
|
|
107
|
+
version = excluded.version,
|
|
108
|
+
metadata = excluded.metadata,
|
|
109
|
+
last_seen_at = excluded.last_seen_at
|
|
110
|
+
`).run(app.id, app.repo_id, app.project_id, app.name, app.runtime, app.environment, app.version, JSON.stringify(app.metadata));
|
|
111
|
+
}
|
|
112
|
+
function findNearestPackageJson(cwd) {
|
|
113
|
+
let dir = resolve(cwd);
|
|
114
|
+
while (true) {
|
|
115
|
+
const candidate = join(dir, "package.json");
|
|
116
|
+
if (existsSync(candidate))
|
|
117
|
+
return candidate;
|
|
118
|
+
const parent = dirname(dir);
|
|
119
|
+
if (parent === dir)
|
|
120
|
+
return null;
|
|
121
|
+
dir = parent;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function git(cwd, args) {
|
|
125
|
+
try {
|
|
126
|
+
const output = execFileSync("git", args, {
|
|
127
|
+
cwd,
|
|
128
|
+
encoding: "utf8",
|
|
129
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
130
|
+
timeout: 1000
|
|
131
|
+
}).trim();
|
|
132
|
+
return output || null;
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function sha256(input) {
|
|
138
|
+
return createHash("sha256").update(input).digest("hex");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { detectRuntimeIdentity };
|