@hasna/logs 0.3.3 → 0.3.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/cli/index.js CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  ingestLog,
11
11
  listPages,
12
12
  listProjects,
13
+ resolveProjectId,
13
14
  summarizeLogs
14
15
  } from "../index-5tvnhvgr.js";
15
16
  import {
@@ -2136,12 +2137,17 @@ var {
2136
2137
  } = import__.default;
2137
2138
 
2138
2139
  // src/cli/index.ts
2140
+ function resolveProject(nameOrId) {
2141
+ if (!nameOrId)
2142
+ return;
2143
+ return resolveProjectId(getDb(), nameOrId) ?? nameOrId;
2144
+ }
2139
2145
  var program2 = new Command().name("logs").description("@hasna/logs \u2014 log aggregation and monitoring").version("0.0.1");
2140
- program2.command("list").description("Search and list logs").option("--project <id>", "Filter by project ID").option("--page <id>", "Filter by page ID").option("--level <levels>", "Comma-separated levels (error,warn,info,debug,fatal)").option("--service <name>", "Filter by service").option("--since <iso>", "Since timestamp or relative (1h, 24h, 7d)").option("--text <query>", "Full-text search").option("--limit <n>", "Max results", "100").option("--format <fmt>", "Output format: table|json|compact", "table").action((opts) => {
2146
+ program2.command("list").description("Search and list logs").option("--project <name|id>", "Filter by project name or ID").option("--page <id>", "Filter by page ID").option("--level <levels>", "Comma-separated levels (error,warn,info,debug,fatal)").option("--service <name>", "Filter by service").option("--since <iso>", "Since timestamp or relative (1h, 24h, 7d)").option("--text <query>", "Full-text search").option("--limit <n>", "Max results", "100").option("--format <fmt>", "Output format: table|json|compact", "table").action((opts) => {
2141
2147
  const db = getDb();
2142
2148
  const since = parseRelativeTime(opts.since);
2143
2149
  const rows = searchLogs(db, {
2144
- project_id: opts.project,
2150
+ project_id: resolveProject(opts.project),
2145
2151
  page_id: opts.page,
2146
2152
  level: opts.level ? opts.level.split(",") : undefined,
2147
2153
  service: opts.service,
@@ -2165,13 +2171,13 @@ program2.command("list").description("Search and list logs").option("--project <
2165
2171
  console.log(`
2166
2172
  ${rows.length} log(s)`);
2167
2173
  });
2168
- program2.command("tail").description("Show most recent logs").option("--project <id>").option("--n <count>", "Number of logs", "50").action((opts) => {
2169
- const rows = tailLogs(getDb(), opts.project, Number(opts.n));
2174
+ program2.command("tail").description("Show most recent logs").option("--project <name|id>", "Project name or ID").option("--n <count>", "Number of logs", "50").action((opts) => {
2175
+ const rows = tailLogs(getDb(), resolveProject(opts.project), Number(opts.n));
2170
2176
  for (const r of rows)
2171
2177
  console.log(`${r.timestamp} ${pad(r.level.toUpperCase(), 5)} ${r.message}`);
2172
2178
  });
2173
- program2.command("summary").description("Error/warn summary by service").option("--project <id>").option("--since <time>", "Relative time (1h, 24h, 7d)", "24h").action((opts) => {
2174
- const summary = summarizeLogs(getDb(), opts.project, parseRelativeTime(opts.since));
2179
+ program2.command("summary").description("Error/warn summary by service").option("--project <name|id>", "Project name or ID").option("--since <time>", "Relative time (1h, 24h, 7d)", "24h").action((opts) => {
2180
+ const summary = summarizeLogs(getDb(), resolveProject(opts.project), parseRelativeTime(opts.since));
2175
2181
  if (!summary.length) {
2176
2182
  console.log("No errors/warnings in this window.");
2177
2183
  return;
@@ -2179,8 +2185,8 @@ program2.command("summary").description("Error/warn summary by service").option(
2179
2185
  for (const s of summary)
2180
2186
  console.log(`${pad(s.level.toUpperCase(), 5)} ${pad(s.service ?? "-", 15)} count=${s.count} latest=${s.latest}`);
2181
2187
  });
2182
- program2.command("push <message>").description("Push a log entry").option("--level <level>", "Log level", "info").option("--service <name>").option("--project <id>").option("--trace <id>", "Trace ID").action((message, opts) => {
2183
- const row = ingestLog(getDb(), { level: opts.level, message, service: opts.service, project_id: opts.project, trace_id: opts.trace });
2188
+ program2.command("push <message>").description("Push a log entry").option("--level <level>", "Log level", "info").option("--service <name>").option("--project <name|id>", "Project name or ID").option("--trace <id>", "Trace ID").action((message, opts) => {
2189
+ const row = ingestLog(getDb(), { level: opts.level, message, service: opts.service, project_id: resolveProject(opts.project), trace_id: opts.trace });
2184
2190
  console.log(`Logged: ${row.id}`);
2185
2191
  });
2186
2192
  var projectCmd = program2.command("project").description("Manage projects");
@@ -2198,38 +2204,38 @@ projectCmd.command("list").action(() => {
2198
2204
  console.log(`${p.id} ${p.name} ${p.base_url ?? ""} ${p.github_repo ?? ""}`);
2199
2205
  });
2200
2206
  var pageCmd = program2.command("page").description("Manage pages");
2201
- pageCmd.command("add").option("--project <id>").option("--url <url>").option("--name <name>").action((opts) => {
2207
+ pageCmd.command("add").option("--project <name|id>", "Project name or ID").option("--url <url>").option("--name <name>").action((opts) => {
2202
2208
  if (!opts.project || !opts.url) {
2203
2209
  console.error("--project and --url required");
2204
2210
  process.exit(1);
2205
2211
  }
2206
- const p = createPage(getDb(), { project_id: opts.project, url: opts.url, name: opts.name });
2212
+ const p = createPage(getDb(), { project_id: resolveProject(opts.project), url: opts.url, name: opts.name });
2207
2213
  console.log(`Page registered: ${p.id} \u2014 ${p.url}`);
2208
2214
  });
2209
- pageCmd.command("list").option("--project <id>").action((opts) => {
2215
+ pageCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
2210
2216
  if (!opts.project) {
2211
2217
  console.error("--project required");
2212
2218
  process.exit(1);
2213
2219
  }
2214
- const pages = listPages(getDb(), opts.project);
2220
+ const pages = listPages(getDb(), resolveProject(opts.project));
2215
2221
  for (const p of pages)
2216
2222
  console.log(`${p.id} ${p.url} last=${p.last_scanned_at ?? "never"}`);
2217
2223
  });
2218
2224
  var jobCmd = program2.command("job").description("Manage scan jobs");
2219
- jobCmd.command("create").option("--project <id>").option("--schedule <cron>", "Cron expression", "*/30 * * * *").action((opts) => {
2225
+ jobCmd.command("create").option("--project <name|id>", "Project name or ID").option("--schedule <cron>", "Cron expression", "*/30 * * * *").action((opts) => {
2220
2226
  if (!opts.project) {
2221
2227
  console.error("--project required");
2222
2228
  process.exit(1);
2223
2229
  }
2224
- const j = createJob(getDb(), { project_id: opts.project, schedule: opts.schedule });
2230
+ const j = createJob(getDb(), { project_id: resolveProject(opts.project), schedule: opts.schedule });
2225
2231
  console.log(`Job created: ${j.id} \u2014 ${j.schedule}`);
2226
2232
  });
2227
- jobCmd.command("list").option("--project <id>").action((opts) => {
2228
- const jobs = listJobs(getDb(), opts.project);
2233
+ jobCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
2234
+ const jobs = listJobs(getDb(), resolveProject(opts.project));
2229
2235
  for (const j of jobs)
2230
2236
  console.log(`${j.id} ${j.schedule} enabled=${j.enabled} last=${j.last_run_at ?? "never"}`);
2231
2237
  });
2232
- program2.command("scan").description("Run an immediate scan for a job").option("--job <id>").option("--project <id>").action(async (opts) => {
2238
+ program2.command("scan").description("Run an immediate scan for a job").option("--job <id>").option("--project <name|id>", "Project name or ID").action(async (opts) => {
2233
2239
  if (!opts.job) {
2234
2240
  console.error("--job required");
2235
2241
  process.exit(1);
@@ -2302,12 +2308,12 @@ Errors: ${errorCount} Warnings: ${warnCount}`);
2302
2308
  process.exit(0);
2303
2309
  });
2304
2310
  });
2305
- program2.command("export").description("Export logs to JSON or CSV").option("--project <id>").option("--since <time>", "Relative time or ISO").option("--level <level>").option("--service <name>").option("--format <fmt>", "json or csv", "json").option("--output <file>", "Output file (default: stdout)").option("--limit <n>", "Max rows", "100000").action(async (opts) => {
2311
+ program2.command("export").description("Export logs to JSON or CSV").option("--project <name|id>", "Project name or ID").option("--since <time>", "Relative time or ISO").option("--level <level>").option("--service <name>").option("--format <fmt>", "json or csv", "json").option("--output <file>", "Output file (default: stdout)").option("--limit <n>", "Max rows", "100000").action(async (opts) => {
2306
2312
  const { exportToCsv, exportToJson } = await import("../export-c3eqjste.js");
2307
2313
  const { createWriteStream } = await import("fs");
2308
2314
  const db = getDb();
2309
2315
  const options = {
2310
- project_id: opts.project,
2316
+ project_id: resolveProject(opts.project),
2311
2317
  since: parseRelativeTime(opts.since),
2312
2318
  level: opts.level,
2313
2319
  service: opts.service,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/logs",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Log aggregation + browser script + headless page scanner + performance monitoring for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/cli/index.ts CHANGED
@@ -5,10 +5,16 @@ import { ingestLog } from "../lib/ingest.ts"
5
5
  import { searchLogs, tailLogs } from "../lib/query.ts"
6
6
  import { summarizeLogs } from "../lib/summarize.ts"
7
7
  import { createJob, listJobs } from "../lib/jobs.ts"
8
- import { createPage, createProject, listPages, listProjects } from "../lib/projects.ts"
8
+ import { createPage, createProject, listPages, listProjects, resolveProjectId } from "../lib/projects.ts"
9
9
  import { runJob } from "../lib/scheduler.ts"
10
10
  import type { LogLevel } from "../types/index.ts"
11
11
 
12
+ /** Resolve a project name or ID from CLI --project flag */
13
+ function resolveProject(nameOrId: string | undefined): string | undefined {
14
+ if (!nameOrId) return undefined;
15
+ return resolveProjectId(getDb(), nameOrId) ?? nameOrId;
16
+ }
17
+
12
18
  const program = new Command()
13
19
  .name("logs")
14
20
  .description("@hasna/logs — log aggregation and monitoring")
@@ -17,7 +23,7 @@ const program = new Command()
17
23
  // ── logs list ──────────────────────────────────────────────
18
24
  program.command("list")
19
25
  .description("Search and list logs")
20
- .option("--project <id>", "Filter by project ID")
26
+ .option("--project <name|id>", "Filter by project name or ID")
21
27
  .option("--page <id>", "Filter by page ID")
22
28
  .option("--level <levels>", "Comma-separated levels (error,warn,info,debug,fatal)")
23
29
  .option("--service <name>", "Filter by service")
@@ -29,7 +35,7 @@ program.command("list")
29
35
  const db = getDb()
30
36
  const since = parseRelativeTime(opts.since)
31
37
  const rows = searchLogs(db, {
32
- project_id: opts.project,
38
+ project_id: resolveProject(opts.project),
33
39
  page_id: opts.page,
34
40
  level: opts.level ? (opts.level.split(",") as LogLevel[]) : undefined,
35
41
  service: opts.service,
@@ -52,20 +58,20 @@ program.command("list")
52
58
  // ── logs tail ──────────────────────────────────────────────
53
59
  program.command("tail")
54
60
  .description("Show most recent logs")
55
- .option("--project <id>")
61
+ .option("--project <name|id>", "Project name or ID")
56
62
  .option("--n <count>", "Number of logs", "50")
57
63
  .action((opts) => {
58
- const rows = tailLogs(getDb(), opts.project, Number(opts.n))
64
+ const rows = tailLogs(getDb(), resolveProject(opts.project), Number(opts.n))
59
65
  for (const r of rows) console.log(`${r.timestamp} ${pad(r.level.toUpperCase(), 5)} ${r.message}`)
60
66
  })
61
67
 
62
68
  // ── logs summary ──────────────────────────────────────────
63
69
  program.command("summary")
64
70
  .description("Error/warn summary by service")
65
- .option("--project <id>")
71
+ .option("--project <name|id>", "Project name or ID")
66
72
  .option("--since <time>", "Relative time (1h, 24h, 7d)", "24h")
67
73
  .action((opts) => {
68
- const summary = summarizeLogs(getDb(), opts.project, parseRelativeTime(opts.since))
74
+ const summary = summarizeLogs(getDb(), resolveProject(opts.project), parseRelativeTime(opts.since))
69
75
  if (!summary.length) { console.log("No errors/warnings in this window."); return }
70
76
  for (const s of summary) console.log(`${pad(s.level.toUpperCase(), 5)} ${pad(s.service ?? "-", 15)} count=${s.count} latest=${s.latest}`)
71
77
  })
@@ -75,10 +81,10 @@ program.command("push <message>")
75
81
  .description("Push a log entry")
76
82
  .option("--level <level>", "Log level", "info")
77
83
  .option("--service <name>")
78
- .option("--project <id>")
84
+ .option("--project <name|id>", "Project name or ID")
79
85
  .option("--trace <id>", "Trace ID")
80
86
  .action((message, opts) => {
81
- const row = ingestLog(getDb(), { level: opts.level as LogLevel, message, service: opts.service, project_id: opts.project, trace_id: opts.trace })
87
+ const row = ingestLog(getDb(), { level: opts.level as LogLevel, message, service: opts.service, project_id: resolveProject(opts.project), trace_id: opts.trace })
82
88
  console.log(`Logged: ${row.id}`)
83
89
  })
84
90
 
@@ -104,18 +110,18 @@ projectCmd.command("list").action(() => {
104
110
  const pageCmd = program.command("page").description("Manage pages")
105
111
 
106
112
  pageCmd.command("add")
107
- .option("--project <id>")
113
+ .option("--project <name|id>", "Project name or ID")
108
114
  .option("--url <url>")
109
115
  .option("--name <name>")
110
116
  .action((opts) => {
111
117
  if (!opts.project || !opts.url) { console.error("--project and --url required"); process.exit(1) }
112
- const p = createPage(getDb(), { project_id: opts.project, url: opts.url, name: opts.name })
118
+ const p = createPage(getDb(), { project_id: resolveProject(opts.project), url: opts.url, name: opts.name })
113
119
  console.log(`Page registered: ${p.id} — ${p.url}`)
114
120
  })
115
121
 
116
- pageCmd.command("list").option("--project <id>").action((opts) => {
122
+ pageCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
117
123
  if (!opts.project) { console.error("--project required"); process.exit(1) }
118
- const pages = listPages(getDb(), opts.project)
124
+ const pages = listPages(getDb(), resolveProject(opts.project))
119
125
  for (const p of pages) console.log(`${p.id} ${p.url} last=${p.last_scanned_at ?? "never"}`)
120
126
  })
121
127
 
@@ -123,16 +129,16 @@ pageCmd.command("list").option("--project <id>").action((opts) => {
123
129
  const jobCmd = program.command("job").description("Manage scan jobs")
124
130
 
125
131
  jobCmd.command("create")
126
- .option("--project <id>")
132
+ .option("--project <name|id>", "Project name or ID")
127
133
  .option("--schedule <cron>", "Cron expression", "*/30 * * * *")
128
134
  .action((opts) => {
129
135
  if (!opts.project) { console.error("--project required"); process.exit(1) }
130
- const j = createJob(getDb(), { project_id: opts.project, schedule: opts.schedule })
136
+ const j = createJob(getDb(), { project_id: resolveProject(opts.project), schedule: opts.schedule })
131
137
  console.log(`Job created: ${j.id} — ${j.schedule}`)
132
138
  })
133
139
 
134
- jobCmd.command("list").option("--project <id>").action((opts) => {
135
- const jobs = listJobs(getDb(), opts.project)
140
+ jobCmd.command("list").option("--project <name|id>", "Project name or ID").action((opts) => {
141
+ const jobs = listJobs(getDb(), resolveProject(opts.project))
136
142
  for (const j of jobs) console.log(`${j.id} ${j.schedule} enabled=${j.enabled} last=${j.last_run_at ?? "never"}`)
137
143
  })
138
144
 
@@ -140,7 +146,7 @@ jobCmd.command("list").option("--project <id>").action((opts) => {
140
146
  program.command("scan")
141
147
  .description("Run an immediate scan for a job")
142
148
  .option("--job <id>")
143
- .option("--project <id>")
149
+ .option("--project <name|id>", "Project name or ID")
144
150
  .action(async (opts) => {
145
151
  if (!opts.job) { console.error("--job required"); process.exit(1) }
146
152
  const db = getDb()
@@ -216,7 +222,7 @@ program.command("watch")
216
222
  // ── logs export ───────────────────────────────────────────
217
223
  program.command("export")
218
224
  .description("Export logs to JSON or CSV")
219
- .option("--project <id>")
225
+ .option("--project <name|id>", "Project name or ID")
220
226
  .option("--since <time>", "Relative time or ISO")
221
227
  .option("--level <level>")
222
228
  .option("--service <name>")
@@ -228,7 +234,7 @@ program.command("export")
228
234
  const { createWriteStream } = await import("node:fs")
229
235
  const db = getDb()
230
236
  const options = {
231
- project_id: opts.project,
237
+ project_id: resolveProject(opts.project),
232
238
  since: parseRelativeTime(opts.since),
233
239
  level: opts.level,
234
240
  service: opts.service,