hazo_logs 1.0.14 → 1.1.0

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 CHANGED
@@ -562,6 +562,31 @@ const authHandler = withLogAuth(handler, async (request) => {
562
562
  });
563
563
  ```
564
564
 
565
+ ## Live tail (v1.1+)
566
+
567
+ `tailLogs` watches the active rotating log file and emits new entries as they are written. Filters mirror `readLogs`. Use it directly for in-process consumers:
568
+
569
+ ```ts
570
+ import { tailLogs } from "hazo_logs/server";
571
+
572
+ const ctrl = new AbortController();
573
+ for await (const entry of tailLogs({ reference: ["job-123"], signal: ctrl.signal })) {
574
+ console.log(entry.message);
575
+ }
576
+ // later: ctrl.abort();
577
+ ```
578
+
579
+ For SSE-over-HTTP (admin UIs, dashboards), use `createLogStreamApiHandler`:
580
+
581
+ ```ts
582
+ import { createLogStreamApiHandler } from "hazo_logs/ui/server";
583
+
584
+ // Next.js app router
585
+ export const GET = createLogStreamApiHandler({ reference: ["job-123"] });
586
+ ```
587
+
588
+ Clients consume via the standard `EventSource` API. The stream closes when the client disconnects.
589
+
565
590
  ## Log File Format
566
591
 
567
592
  Logs are stored as newline-delimited JSON:
@@ -0,0 +1,11 @@
1
+ import type { LogEntry, LogLevel } from "./types.js";
2
+ export interface TailOptions {
3
+ reference?: string[];
4
+ sessionId?: string[];
5
+ level?: LogLevel[];
6
+ package?: string[];
7
+ signal?: AbortSignal;
8
+ logDirectory?: string;
9
+ }
10
+ export declare function tailLogs(opts?: TailOptions): AsyncIterable<LogEntry>;
11
+ //# sourceMappingURL=log-tail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-tail.d.ts","sourceRoot":"","sources":["../../src/lib/log-tail.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGrD,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAWD,wBAAgB,QAAQ,CAAC,IAAI,GAAE,WAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC,CAoIxE"}
@@ -0,0 +1,161 @@
1
+ import { promises as fsp, watch, statSync } from "fs";
2
+ import { join } from "path";
3
+ import { loadConfig } from "./config_loader.js";
4
+ function todayDateString() {
5
+ const d = new Date();
6
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
7
+ }
8
+ function activeLogFile(logDir) {
9
+ return join(logDir, `hazo-${todayDateString()}.log`);
10
+ }
11
+ export function tailLogs(opts = {}) {
12
+ const logDir = opts.logDirectory ?? loadConfig().log_directory;
13
+ return {
14
+ [Symbol.asyncIterator]() {
15
+ const buffer = [];
16
+ const wakers = [];
17
+ let done = false;
18
+ let position = 0;
19
+ let watcher;
20
+ let pollInterval;
21
+ let rolloverInterval;
22
+ let leftover = "";
23
+ let readChain = Promise.resolve();
24
+ let filePath = activeLogFile(logDir);
25
+ // Start at end-of-file: tail only NEW lines, not history.
26
+ try {
27
+ position = statSync(filePath).size;
28
+ }
29
+ catch {
30
+ position = 0;
31
+ }
32
+ function matches(e) {
33
+ if (opts.reference?.length && !opts.reference.includes(e.reference))
34
+ return false;
35
+ if (opts.sessionId?.length && !opts.sessionId.includes(e.sessionId))
36
+ return false;
37
+ if (opts.level?.length && !opts.level.includes(e.level))
38
+ return false;
39
+ if (opts.package?.length && !opts.package.includes(e.package))
40
+ return false;
41
+ return true;
42
+ }
43
+ function deliver(entry) {
44
+ const w = wakers.shift();
45
+ if (w)
46
+ w({ value: entry, done: false });
47
+ else
48
+ buffer.push(entry);
49
+ }
50
+ function finish() {
51
+ if (done)
52
+ return;
53
+ done = true;
54
+ if (rolloverInterval) {
55
+ clearInterval(rolloverInterval);
56
+ rolloverInterval = undefined;
57
+ }
58
+ if (pollInterval) {
59
+ clearInterval(pollInterval);
60
+ pollInterval = undefined;
61
+ }
62
+ watcher?.close();
63
+ while (wakers.length)
64
+ wakers.shift()({ value: undefined, done: true });
65
+ }
66
+ function scheduleRead() {
67
+ readChain = readChain.then(readDelta).catch(() => { });
68
+ }
69
+ async function readDelta() {
70
+ try {
71
+ const st = await fsp.stat(filePath);
72
+ if (st.size < position) {
73
+ // truncation / rotation — restart from current end
74
+ position = st.size;
75
+ leftover = "";
76
+ return;
77
+ }
78
+ if (st.size === position)
79
+ return;
80
+ const fh = await fsp.open(filePath, "r");
81
+ const len = st.size - position;
82
+ const buf = Buffer.alloc(len);
83
+ await fh.read(buf, 0, len, position);
84
+ await fh.close();
85
+ position = st.size;
86
+ const text = leftover + buf.toString("utf8");
87
+ const lines = text.split("\n");
88
+ leftover = lines.pop() ?? "";
89
+ for (const line of lines) {
90
+ const trimmed = line.trim();
91
+ if (!trimmed)
92
+ continue;
93
+ try {
94
+ const parsed = JSON.parse(trimmed);
95
+ if (matches(parsed))
96
+ deliver(parsed);
97
+ }
98
+ catch {
99
+ // skip malformed lines
100
+ }
101
+ }
102
+ }
103
+ catch {
104
+ // file may not exist yet; ignore
105
+ }
106
+ }
107
+ function startWatcher() {
108
+ try {
109
+ watcher = watch(filePath, scheduleRead);
110
+ }
111
+ catch {
112
+ // file doesn't exist yet — poll until it appears
113
+ pollInterval = setInterval(async () => {
114
+ try {
115
+ await fsp.stat(filePath);
116
+ if (pollInterval)
117
+ clearInterval(pollInterval);
118
+ pollInterval = undefined;
119
+ startWatcher();
120
+ await readDelta();
121
+ }
122
+ catch { /* keep polling */ }
123
+ }, 200);
124
+ pollInterval?.unref?.();
125
+ }
126
+ }
127
+ startWatcher();
128
+ let currentPath = filePath;
129
+ rolloverInterval = setInterval(() => {
130
+ const newPath = activeLogFile(logDir);
131
+ if (newPath !== currentPath) {
132
+ watcher?.close();
133
+ currentPath = newPath;
134
+ filePath = newPath;
135
+ position = 0;
136
+ leftover = "";
137
+ startWatcher();
138
+ void scheduleRead();
139
+ }
140
+ }, 60_000);
141
+ rolloverInterval?.unref?.();
142
+ opts.signal?.addEventListener("abort", finish);
143
+ if (opts.signal?.aborted)
144
+ finish();
145
+ return {
146
+ async next() {
147
+ if (buffer.length)
148
+ return { value: buffer.shift(), done: false };
149
+ if (done)
150
+ return { value: undefined, done: true };
151
+ return new Promise((resolve) => { wakers.push(resolve); });
152
+ },
153
+ async return() {
154
+ finish();
155
+ return { value: undefined, done: true };
156
+ },
157
+ };
158
+ },
159
+ };
160
+ }
161
+ //# sourceMappingURL=log-tail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-tail.js","sourceRoot":"","sources":["../../src/lib/log-tail.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -21,4 +21,6 @@ export { generateSessionId, startSession, startSessionAsync, runWithLogContext,
21
21
  export { readLogs, getAvailableLogDates, getUniquePackages, getUniqueExecutionIds, getUniqueSessionIds, getUniqueReferences, } from './lib/log-reader.js';
22
22
  export type { Logger, LogLevel, LogData, LogEntry, LogContext, HazoLogConfig, PackageLoggerOptions, LogOrigin, } from './lib/types.js';
23
23
  export type { ReadLogsOptions, LogQueryResult } from './lib/log-reader.js';
24
+ export { tailLogs } from "./lib/log-tail.js";
25
+ export type { TailOptions } from "./lib/log-tail.js";
24
26
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,MAAM,EACN,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,UAAU,EACV,aAAa,EACb,oBAAoB,EACpB,SAAS,GACV,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,MAAM,EACN,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,UAAU,EACV,aAAa,EACb,oBAAoB,EACpB,SAAS,GACV,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/server.js CHANGED
@@ -22,4 +22,5 @@ export { loadConfig } from './lib/config_loader.js';
22
22
  export { generateSessionId, startSession, startSessionAsync, runWithLogContext, runWithLogContextAsync, getLogContext, withSession, withContext, } from './lib/context/log-context.js';
23
23
  // Log reader (uses fs, readline)
24
24
  export { readLogs, getAvailableLogDates, getUniquePackages, getUniqueExecutionIds, getUniqueSessionIds, getUniqueReferences, } from './lib/log-reader.js';
25
+ export { tailLogs } from "./lib/log-tail.js";
25
26
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,8BAA8B,CAAC;AAEtC,iCAAiC;AACjC,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,uCAAuC;AACvC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,8BAA8B,CAAC;AAEtC,iCAAiC;AACjC,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAgB7B,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { LogLevel } from "../../lib/types.js";
2
+ export interface LogStreamApiOptions {
3
+ reference?: string[];
4
+ sessionId?: string[];
5
+ level?: LogLevel[];
6
+ package?: string[];
7
+ logDirectory?: string;
8
+ }
9
+ /**
10
+ * Returns a Web-API handler that streams tailLogs() output as Server-Sent Events.
11
+ * Honours the request's AbortSignal (closes the underlying watcher when the client disconnects).
12
+ */
13
+ export declare function createLogStreamApiHandler(opts?: LogStreamApiOptions): (req: Request) => Promise<Response>;
14
+ //# sourceMappingURL=log-stream-api-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-stream-api-handler.d.ts","sourceRoot":"","sources":["../../../src/ui/api/log-stream-api-handler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,GAAE,mBAAwB,IACxC,KAAK,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CA4C/D"}
@@ -0,0 +1,53 @@
1
+ // NOTE: Intentionally NOT importing 'server-only' here, matching sibling
2
+ // handlers (log-api-handler.ts, client-log-handler.ts). The server-only
3
+ // guard lives at the aggregator (src/ui/server.ts) so this file can be
4
+ // unit-tested directly under vitest.
5
+ import { tailLogs } from "../../lib/log-tail.js";
6
+ /**
7
+ * Returns a Web-API handler that streams tailLogs() output as Server-Sent Events.
8
+ * Honours the request's AbortSignal (closes the underlying watcher when the client disconnects).
9
+ */
10
+ export function createLogStreamApiHandler(opts = {}) {
11
+ return async function handler(req) {
12
+ const ctrl = new AbortController();
13
+ req.signal.addEventListener("abort", () => ctrl.abort());
14
+ // Allow per-request overrides via query string.
15
+ const url = new URL(req.url);
16
+ const ref = url.searchParams.getAll("reference");
17
+ const sess = url.searchParams.getAll("sessionId");
18
+ const lvl = url.searchParams.getAll("level");
19
+ const pkg = url.searchParams.getAll("package");
20
+ const tailOpts = {
21
+ reference: ref.length ? ref : opts.reference,
22
+ sessionId: sess.length ? sess : opts.sessionId,
23
+ level: lvl.length ? lvl : opts.level,
24
+ package: pkg.length ? pkg : opts.package,
25
+ logDirectory: opts.logDirectory,
26
+ signal: ctrl.signal,
27
+ };
28
+ const encoder = new TextEncoder();
29
+ const stream = new ReadableStream({
30
+ async start(controller) {
31
+ try {
32
+ for await (const entry of tailLogs(tailOpts)) {
33
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(entry)}\n\n`));
34
+ }
35
+ }
36
+ catch (err) {
37
+ controller.enqueue(encoder.encode(`event: error\ndata: ${JSON.stringify({ error: String(err) })}\n\n`));
38
+ }
39
+ controller.close();
40
+ },
41
+ cancel() { ctrl.abort(); },
42
+ });
43
+ return new Response(stream, {
44
+ status: 200,
45
+ headers: {
46
+ "content-type": "text/event-stream",
47
+ "cache-control": "no-cache",
48
+ "connection": "keep-alive",
49
+ },
50
+ });
51
+ };
52
+ }
53
+ //# sourceMappingURL=log-stream-api-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-stream-api-handler.js","sourceRoot":"","sources":["../../../src/ui/api/log-stream-api-handler.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wEAAwE;AACxE,uEAAuE;AACvE,qCAAqC;AACrC,OAAO,EAAE,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AAWnE;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAA4B,EAAE;IACtE,OAAO,KAAK,UAAU,OAAO,CAAC,GAAY;QACxC,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAEzD,gDAAgD;QAChD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAe,CAAC;QAC3D,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE/C,MAAM,QAAQ,GAAgB;YAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS;YAC5C,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS;YAC9C,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;YACpC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;YACxC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,cAAc,CAAa;YAC5C,KAAK,CAAC,KAAK,CAAC,UAAU;gBACpB,IAAI,CAAC;oBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAC7C,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;oBAC3E,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,uBAAuB,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC1G,CAAC;gBACD,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;YACD,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;SAC3B,CAAC,CAAC;QAEH,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE;YAC1B,MAAM,EAAE,GAAG;YACX,OAAO,EAAE;gBACP,cAAc,EAAE,mBAAmB;gBACnC,eAAe,EAAE,UAAU;gBAC3B,YAAY,EAAE,YAAY;aAC3B;SACF,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -9,6 +9,8 @@
9
9
  import 'server-only';
10
10
  export { createLogApiHandler } from './api/log-api-handler.js';
11
11
  export { createClientLogHandler } from './api/client-log-handler.js';
12
+ export { createLogStreamApiHandler } from './api/log-stream-api-handler.js';
13
+ export type { LogStreamApiOptions } from './api/log-stream-api-handler.js';
12
14
  export { withLogAuth } from './middleware/with-log-auth.js';
13
15
  export type { LogApiConfig, LogApiHandler, AuthCheckFn, } from './types.js';
14
16
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAG5D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,aAAa,CAAC;AAGrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAG5D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/ui/server.js CHANGED
@@ -10,6 +10,7 @@ import 'server-only';
10
10
  // API Handlers
11
11
  export { createLogApiHandler } from './api/log-api-handler.js';
12
12
  export { createClientLogHandler } from './api/client-log-handler.js';
13
+ export { createLogStreamApiHandler } from './api/log-stream-api-handler.js';
13
14
  // Middleware
14
15
  export { withLogAuth } from './middleware/with-log-auth.js';
15
16
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,aAAa;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAG5E,aAAa;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_logs",
3
- "version": "1.0.14",
3
+ "version": "1.1.0",
4
4
  "description": "Logger for hazo packages - Winston wrapper with singleton pattern",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",