@hasna/logs 0.3.23 → 0.3.24

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.
Files changed (47) hide show
  1. package/LICENSE +1 -2
  2. package/README.md +3 -22
  3. package/bun.lock +7 -14
  4. package/dist/cli/index.js +2 -2
  5. package/dist/{index-t97ttm0a.js → index-75dwghvv.js} +88 -6
  6. package/dist/{index-1f2ghyhm.js → index-g8f8kep6.js} +93 -8
  7. package/dist/{index-zmayq5kj.js → index-pf8hpweg.js} +2 -2
  8. package/dist/{index-2sbhn1ye.js → index-w24zm361.js} +2 -2
  9. package/dist/mcp/index.js +23801 -8266
  10. package/dist/server/index.js +2 -2
  11. package/package.json +4 -3
  12. package/sdk/package.json +4 -9
  13. package/src/cli/entrypoints.test.ts +1 -1
  14. package/src/db/index.ts +1 -1
  15. package/src/lib/cloud-sync.ts +167 -0
  16. package/src/lib/ingest.ts +3 -3
  17. package/src/lib/remote-storage.ts +45 -0
  18. package/src/mcp/index.ts +30 -34
  19. package/dist/export-yjaar93b.js +0 -10
  20. package/dist/health-9792c1rc.js +0 -8
  21. package/dist/health-egdb00st.js +0 -8
  22. package/dist/http-0wsh40x1.js +0 -1240
  23. package/dist/index-14dvwcf1.js +0 -45
  24. package/dist/index-4ba0sabv.js +0 -1241
  25. package/dist/index-4hj4sakk.js +0 -1241
  26. package/dist/index-5cj74qka.js +0 -10803
  27. package/dist/index-5qwba140.js +0 -1241
  28. package/dist/index-5tvnhvgr.js +0 -536
  29. package/dist/index-6y8pmes4.js +0 -45
  30. package/dist/index-6zrkek5y.js +0 -9454
  31. package/dist/index-7qhh666n.js +0 -1241
  32. package/dist/index-86j0hn03.js +0 -540
  33. package/dist/index-exeq2gs6.js +0 -79
  34. package/dist/index-fzmz9aqs.js +0 -1241
  35. package/dist/index-g8dczzvv.js +0 -30
  36. package/dist/index-hjzbctgt.js +0 -5868
  37. package/dist/index-rbrsvsyh.js +0 -88
  38. package/dist/index-vmr85wa1.js +0 -9579
  39. package/dist/index-wbsq8qjd.js +0 -1241
  40. package/dist/index-xjn8gam3.js +0 -39
  41. package/dist/index-yb8yd4j6.js +0 -39
  42. package/dist/jobs-02z4fzsn.js +0 -22
  43. package/dist/query-6s5gqkck.js +0 -15
  44. package/dist/query-shjjj67k.js +0 -14
  45. package/dist/query-tcg3bm9s.js +0 -14
  46. package/src/mcp/http.test.ts +0 -92
  47. package/src/mcp/http.ts +0 -135
@@ -1,39 +0,0 @@
1
- // @bun
2
- import {
3
- __require
4
- } from "./index-re3ntm60.js";
5
-
6
- // src/lib/health.ts
7
- var startTime = Date.now();
8
- function getHealth(db) {
9
- const projects = db.prepare("SELECT COUNT(*) as c FROM projects").get().c;
10
- const total_logs = db.prepare("SELECT COUNT(*) as c FROM logs").get().c;
11
- const scheduler_jobs = db.prepare("SELECT COUNT(*) as c FROM scan_jobs WHERE enabled = 1").get().c;
12
- const open_issues = db.prepare("SELECT COUNT(*) as c FROM issues WHERE status = 'open'").get().c;
13
- const levelRows = db.prepare("SELECT level, COUNT(*) as c FROM logs GROUP BY level").all();
14
- const logs_by_level = Object.fromEntries(levelRows.map((r) => [r.level, r.c]));
15
- const oldest = db.prepare("SELECT MIN(timestamp) as t FROM logs").get();
16
- const newest = db.prepare("SELECT MAX(timestamp) as t FROM logs").get();
17
- let db_size_bytes = null;
18
- try {
19
- const dbPath = process.env.LOGS_DB_PATH;
20
- if (dbPath) {
21
- const { statSync } = __require("fs");
22
- db_size_bytes = statSync(dbPath).size;
23
- }
24
- } catch {}
25
- return {
26
- status: "ok",
27
- uptime_seconds: Math.floor((Date.now() - startTime) / 1000),
28
- db_size_bytes,
29
- projects,
30
- total_logs,
31
- logs_by_level,
32
- oldest_log: oldest.t,
33
- newest_log: newest.t,
34
- scheduler_jobs,
35
- open_issues
36
- };
37
- }
38
-
39
- export { getHealth };
@@ -1,39 +0,0 @@
1
- // @bun
2
- import {
3
- __require
4
- } from "./index-g8dczzvv.js";
5
-
6
- // src/lib/health.ts
7
- var startTime = Date.now();
8
- function getHealth(db) {
9
- const projects = db.prepare("SELECT COUNT(*) as c FROM projects").get().c;
10
- const total_logs = db.prepare("SELECT COUNT(*) as c FROM logs").get().c;
11
- const scheduler_jobs = db.prepare("SELECT COUNT(*) as c FROM scan_jobs WHERE enabled = 1").get().c;
12
- const open_issues = db.prepare("SELECT COUNT(*) as c FROM issues WHERE status = 'open'").get().c;
13
- const levelRows = db.prepare("SELECT level, COUNT(*) as c FROM logs GROUP BY level").all();
14
- const logs_by_level = Object.fromEntries(levelRows.map((r) => [r.level, r.c]));
15
- const oldest = db.prepare("SELECT MIN(timestamp) as t FROM logs").get();
16
- const newest = db.prepare("SELECT MAX(timestamp) as t FROM logs").get();
17
- let db_size_bytes = null;
18
- try {
19
- const dbPath = process.env.LOGS_DB_PATH;
20
- if (dbPath) {
21
- const { statSync } = __require("fs");
22
- db_size_bytes = statSync(dbPath).size;
23
- }
24
- } catch {}
25
- return {
26
- status: "ok",
27
- uptime_seconds: Math.floor((Date.now() - startTime) / 1000),
28
- db_size_bytes,
29
- projects,
30
- total_logs,
31
- logs_by_level,
32
- oldest_log: oldest.t,
33
- newest_log: newest.t,
34
- scheduler_jobs,
35
- open_issues
36
- };
37
- }
38
-
39
- export { getHealth };
@@ -1,22 +0,0 @@
1
- // @bun
2
- import {
3
- createJob,
4
- createScanRun,
5
- deleteJob,
6
- finishScanRun,
7
- getJob,
8
- listJobs,
9
- listScanRuns,
10
- updateJob
11
- } from "./index-3dr7d80h.js";
12
- import"./index-g8dczzvv.js";
13
- export {
14
- updateJob,
15
- listScanRuns,
16
- listJobs,
17
- getJob,
18
- finishScanRun,
19
- deleteJob,
20
- createScanRun,
21
- createJob
22
- };
@@ -1,15 +0,0 @@
1
- // @bun
2
- import {
3
- getLogContext,
4
- getLogContextFromId,
5
- searchLogs,
6
- tailLogs
7
- } from "./index-exeq2gs6.js";
8
- import"./index-997bkzr2.js";
9
- import"./index-re3ntm60.js";
10
- export {
11
- tailLogs,
12
- searchLogs,
13
- getLogContextFromId,
14
- getLogContext
15
- };
@@ -1,14 +0,0 @@
1
- // @bun
2
- import {
3
- getLogContext,
4
- getLogContextFromId,
5
- searchLogs,
6
- tailLogs
7
- } from "./index-rbrsvsyh.js";
8
- import"./index-re3ntm60.js";
9
- export {
10
- tailLogs,
11
- searchLogs,
12
- getLogContextFromId,
13
- getLogContext
14
- };
@@ -1,14 +0,0 @@
1
- // @bun
2
- import {
3
- getLogContext,
4
- getLogContextFromId,
5
- searchLogs,
6
- tailLogs
7
- } from "./index-rbrsvsyh.js";
8
- import"./index-g8dczzvv.js";
9
- export {
10
- tailLogs,
11
- searchLogs,
12
- getLogContextFromId,
13
- getLogContext
14
- };
@@ -1,92 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
- import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
5
- import { buildServer } from "./index.ts";
6
- import {
7
- DEFAULT_MCP_HTTP_PORT,
8
- isHttpMode,
9
- resolveMcpHttpPort,
10
- startMcpHttpServer,
11
- } from "./http.ts";
12
-
13
- describe("logs MCP HTTP transport", () => {
14
- test("defaults port to 8864", () => {
15
- expect(DEFAULT_MCP_HTTP_PORT).toBe(8864);
16
- expect(resolveMcpHttpPort(["node"], {})).toBe(8864);
17
- expect(resolveMcpHttpPort(["node", "--port", "9001"], {})).toBe(9001);
18
- expect(resolveMcpHttpPort(["node"], { MCP_HTTP_PORT: "9002" })).toBe(9002);
19
- });
20
-
21
- test("isHttpMode detects flag and env", () => {
22
- expect(isHttpMode(["node"], {})).toBe(false);
23
- expect(isHttpMode(["node", "--http"], {})).toBe(true);
24
- expect(isHttpMode(["node"], { MCP_HTTP: "1" })).toBe(true);
25
- });
26
- });
27
-
28
- describe("logs buildServer stdio registration", () => {
29
- test("registers tools over in-memory transport", async () => {
30
- const server = buildServer();
31
- const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
32
- await server.connect(serverTransport);
33
-
34
- const client = new Client({ name: "test", version: "0.0.0" });
35
- await client.connect(clientTransport);
36
-
37
- const tools = await client.listTools();
38
- expect(tools.tools.some((tool) => tool.name === "get_health")).toBe(true);
39
-
40
- await client.close();
41
- await server.close();
42
- });
43
- });
44
-
45
- describe("logs streamable HTTP server", () => {
46
- let handle: Awaited<ReturnType<typeof startMcpHttpServer>>;
47
-
48
- beforeAll(async () => {
49
- handle = await startMcpHttpServer(buildServer, { port: 0 });
50
- });
51
-
52
- afterAll(async () => {
53
- await handle.close();
54
- });
55
-
56
- test("GET /health returns ok", async () => {
57
- const res = await fetch(`http://${handle.host}:${handle.port}/health`);
58
- expect(res.status).toBe(200);
59
- expect(await res.json()).toEqual({ status: "ok", name: "logs" });
60
- });
61
-
62
- test("initialize and call get_health over streamable HTTP", async () => {
63
- const transport = new StreamableHTTPClientTransport(
64
- new URL(`http://${handle.host}:${handle.port}/mcp`),
65
- );
66
- const client = new Client({ name: "test", version: "0.0.0" });
67
- await client.connect(transport);
68
-
69
- const result = await client.callTool({ name: "get_health", arguments: {} });
70
- expect(result.content).toBeDefined();
71
- expect(Array.isArray(result.content)).toBe(true);
72
-
73
- await client.close();
74
- });
75
-
76
- test("serves three concurrent clients from one process", async () => {
77
- const clients = await Promise.all(
78
- Array.from({ length: 3 }, async () => {
79
- const transport = new StreamableHTTPClientTransport(
80
- new URL(`http://${handle.host}:${handle.port}/mcp`),
81
- );
82
- const client = new Client({ name: "test", version: "0.0.0" });
83
- await client.connect(transport);
84
- const tools = await client.listTools();
85
- return { client, count: tools.tools.length };
86
- }),
87
- );
88
-
89
- expect(clients.every((entry) => entry.count > 0)).toBe(true);
90
- await Promise.all(clients.map((entry) => entry.client.close()));
91
- });
92
- });
package/src/mcp/http.ts DELETED
@@ -1,135 +0,0 @@
1
- import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
2
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
-
5
- export const MCP_HTTP_SERVICE_NAME = "logs";
6
- export const DEFAULT_MCP_HTTP_PORT = 8864;
7
-
8
- export function isHttpMode(
9
- argv: string[] = process.argv,
10
- env: NodeJS.ProcessEnv = process.env,
11
- ): boolean {
12
- return argv.includes("--http") || env.MCP_HTTP === "1";
13
- }
14
-
15
- export function isStdioMode(
16
- argv: string[] = process.argv,
17
- env: NodeJS.ProcessEnv = process.env,
18
- ): boolean {
19
- return argv.includes("--stdio") || env.MCP_STDIO === "1";
20
- }
21
-
22
- export function resolveMcpHttpPort(
23
- argv: string[] = process.argv,
24
- env: NodeJS.ProcessEnv = process.env,
25
- ): number {
26
- const portIdx = argv.indexOf("--port");
27
- if (portIdx !== -1 && argv[portIdx + 1]) {
28
- return parsePort(argv[portIdx + 1]!, "--port");
29
- }
30
- if (env.MCP_HTTP_PORT) {
31
- return parsePort(env.MCP_HTTP_PORT, "MCP_HTTP_PORT");
32
- }
33
- return DEFAULT_MCP_HTTP_PORT;
34
- }
35
-
36
- function parsePort(raw: string, source: string): number {
37
- const parsed = Number(raw);
38
- if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
39
- throw new Error(`Invalid ${source} value "${raw}". Expected 0-65535.`);
40
- }
41
- return parsed;
42
- }
43
-
44
- async function readJsonBody(req: IncomingMessage): Promise<unknown> {
45
- const chunks: Buffer[] = [];
46
- for await (const chunk of req) {
47
- chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
48
- }
49
- const text = Buffer.concat(chunks).toString("utf8");
50
- if (!text) return undefined;
51
- return JSON.parse(text) as unknown;
52
- }
53
-
54
- export type McpHttpServerHandle = {
55
- port: number;
56
- host: string;
57
- close: () => Promise<void>;
58
- };
59
-
60
- export async function startMcpHttpServer(
61
- buildServer: () => McpServer,
62
- options?: { port?: number; host?: string; serviceName?: string },
63
- ): Promise<McpHttpServerHandle> {
64
- const host = options?.host ?? "127.0.0.1";
65
- const requestedPort = options?.port ?? resolveMcpHttpPort();
66
- const serviceName = options?.serviceName ?? MCP_HTTP_SERVICE_NAME;
67
-
68
- const httpServer = createServer(async (req: IncomingMessage, res: ServerResponse) => {
69
- try {
70
- const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
71
-
72
- if (req.method === "GET" && url.pathname === "/health") {
73
- res.writeHead(200, { "Content-Type": "application/json" });
74
- res.end(JSON.stringify({ status: "ok", name: serviceName }));
75
- return;
76
- }
77
-
78
- if (url.pathname !== "/mcp") {
79
- res.writeHead(404, { "Content-Type": "text/plain" });
80
- res.end("Not Found");
81
- return;
82
- }
83
-
84
- const server = buildServer();
85
- const transport = new StreamableHTTPServerTransport({
86
- sessionIdGenerator: undefined,
87
- });
88
-
89
- await server.connect(transport);
90
-
91
- let parsedBody: unknown;
92
- if (req.method === "POST") {
93
- parsedBody = await readJsonBody(req);
94
- }
95
-
96
- await transport.handleRequest(req, res, parsedBody);
97
-
98
- res.on("close", () => {
99
- void transport.close();
100
- void server.close();
101
- });
102
- } catch (error) {
103
- console.error(`[${serviceName}-mcp] HTTP error:`, error);
104
- if (!res.headersSent) {
105
- res.writeHead(500, { "Content-Type": "application/json" });
106
- res.end(
107
- JSON.stringify({
108
- jsonrpc: "2.0",
109
- error: { code: -32603, message: "Internal server error" },
110
- id: null,
111
- }),
112
- );
113
- }
114
- }
115
- });
116
-
117
- await new Promise<void>((resolve, reject) => {
118
- httpServer.once("error", reject);
119
- httpServer.listen(requestedPort, host, () => resolve());
120
- });
121
-
122
- const addr = httpServer.address();
123
- const port = typeof addr === "object" && addr ? addr.port : requestedPort;
124
-
125
- console.error(`[${serviceName}-mcp] Streamable HTTP listening on http://${host}:${port}/mcp`);
126
-
127
- return {
128
- port,
129
- host,
130
- close: () =>
131
- new Promise<void>((resolve, reject) => {
132
- httpServer.close((err) => (err ? reject(err) : resolve()));
133
- }),
134
- };
135
- }