@holz/json-backend 0.8.3-rc.169 → 0.8.3-rc.171

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
@@ -1,66 +1,27 @@
1
1
  # `@holz/json-backend`
2
2
 
3
- Serializes structured logs to a writable stream in [NDJSON](https://github.com/ndjson/ndjson-spec) format.
3
+ Prints structured logs to a writable stream in NDJSON form.
4
4
 
5
5
  ## Usage
6
6
 
7
- This backend serializes logs into a [`WritableStream<Uint8Array>`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream). Each chunk is UTF-8 encoded. Ideal for append-only log files.
8
-
9
- Target environments are servers, host endpoints, and browsers (via [OPFS](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createWritable)).
10
-
11
7
  ```typescript
12
8
  import { createJsonBackend } from '@holz/json-backend';
13
9
  import { createLogger } from '@holz/core';
10
+ import { createWriteStream } from 'node:fs';
14
11
 
15
12
  const logger = createLogger(
16
13
  createJsonBackend({
17
- stream: new WritableStream<Uint8Array>(
18
- {
19
- // ...
20
- },
21
- new CountQueuingStrategy({
22
- highWaterMark: 1024,
23
- }),
24
- ),
14
+ stream: createWriteStream('my-logs.ndjson', { flags: 'a' }),
25
15
  }),
26
16
  );
27
17
  ```
28
18
 
29
- ### Node Streams
30
-
31
- Node's streams shipped long before the web standard and need to be wrapped with [Writable.toWeb](https://nodejs.org/api/stream.html#streamwritabletowebstreamwritable):
32
-
33
- ```typescript
34
- import { createWriteStream } from 'node:fs';
35
- import { Writable } from 'node:stream';
36
-
37
- createJsonBackend({
38
- stream: Writable.toWeb(createWriteStream('logs.ndjson', { flags: 'a' })),
39
- }),
40
- ```
41
-
42
- The same adapter works for any Node writable, including `process.stderr`.
43
-
44
- ### Closing the Stream
45
-
46
- By default, the stream remains open forever. Pass an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to control the shutdown.
19
+ Logs are output in [NDJSON](https://github.com/ndjson/ndjson-spec) format. The output is optimized for log files, following the order of typical log statements. The output includes the log level, timestamp, message, and context, if provided.
47
20
 
48
- ```typescript
49
- const controller = new AbortController();
50
-
51
- createJsonBackend({
52
- stream: writableStream,
53
- signal: controller.signal,
54
- });
55
-
56
- // Permanently close the writable stream.
57
- controller.abort();
58
- ```
21
+ The `stream` option specifies where the logs will be written to. You can use any writable stream, such as a file or `process.stdout`.
59
22
 
60
- Tap the stream's [close](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream/WritableStream#closecontroller) handler or node's [finish](https://nodejs.org/api/fs.html#event-finish) event for a clean shutdown.
23
+ ## Log Rotation
61
24
 
62
- ## Caveats
25
+ Long-lived processes or noisy services can fill up the disk, given enough time.
63
26
 
64
- - Writes are fire-and-forget. Stream backpressure from an overwhelmed sink will cause logs to be dropped. Use [CountQueuingStrategy](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) to adjust the log buffer.
65
- - Long-running processes and noisy services create giant files. Lean on your environment's tools (`journalctl`) or use a package like [rotating-file-stream](https://github.com/iccicci/rotating-file-stream).
66
- - OPFS streams in browser environments have poor durability. You may need synchronous access to periodically flush writes, an API only available in workers.
27
+ Lean on your environment's tools (`journalctl`) or use a package like [rotating-file-stream](https://github.com/iccicci/rotating-file-stream) to prevent files from growing unbounded.
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={fatal:60,error:50,warn:40,info:30,debug:20,trace:10},t=(n,r)=>{let i=(e,t,i={})=>{n({timestamp:Date.now(),message:t,level:e,origin:r,context:i})},a={owner:r,trace:i.bind(null,e.trace),debug:i.bind(null,e.debug),info:i.bind(null,e.info),warn:i.bind(null,e.warn),error:i.bind(null,e.error),fatal:i.bind(null,e.fatal),namespace:e=>t(n,r.concat(e)),withMiddleware:e=>t(e(n),r)},o={configurable:!1,enumerable:!1};return Object.defineProperties(a,{withMiddleware:o,namespace:o,trace:o,debug:o,info:o,warn:o,error:o,fatal:o})},n=new TextEncoder,r=({stream:e,signal:t})=>{let r=e.getWriter();return t?.aborted?r.close().catch(i):t?.addEventListener(`abort`,()=>void r.close().catch(i),{once:!0}),e=>{if(r.desiredSize===null||r.desiredSize<=0)return;let t=JSON.stringify({level:o[e.level],time:new Date(e.timestamp).toISOString(),msg:e.message,origin:e.origin,ctx:Object.keys(e.context).length>0?e.context:void 0},a);r.write(n.encode(`${t}\n`)).catch(i)}},i=()=>{},a=(e,t)=>t instanceof Error?{...t,name:t.name,message:t.message,cause:t.cause,...t instanceof AggregateError&&{errors:t.errors}}:t,o=Object.fromEntries(Object.entries(e).map(([e,t])=>[t,e]));exports.createJsonBackend=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={fatal:60,error:50,warn:40,info:30,debug:20,trace:10},t=(n,r)=>{let i=(e,t,i={})=>{n({timestamp:Date.now(),message:t,level:e,origin:r,context:i})},a={owner:r,trace:i.bind(null,e.trace),debug:i.bind(null,e.debug),info:i.bind(null,e.info),warn:i.bind(null,e.warn),error:i.bind(null,e.error),fatal:i.bind(null,e.fatal),namespace:e=>t(n,r.concat(e)),withMiddleware:e=>t(e(n),r)},o={configurable:!1,enumerable:!1};return Object.defineProperties(a,{withMiddleware:o,namespace:o,trace:o,debug:o,info:o,warn:o,error:o,fatal:o})},n=({stream:e})=>t=>{let n=JSON.stringify({level:i[t.level],time:new Date(t.timestamp).toISOString(),msg:t.message,origin:t.origin,ctx:Object.keys(t.context).length>0?t.context:void 0},r);e.write(`${n}\n`)},r=(e,t)=>t instanceof Error?{...t,name:t.name,message:t.message,cause:t.cause,...t instanceof AggregateError&&{errors:t.errors}}:t,i=Object.fromEntries(Object.entries(e).map(([e,t])=>[t,e]));exports.createJsonBackend=n;
@@ -1,33 +1,22 @@
1
1
  import { LogProcessor } from '@holz/core';
2
+ import { Writable } from 'node:stream';
2
3
 
3
4
  declare interface Config {
4
- /** Where to print logs. Each log is written as a line of UTF-8 NDJSON. */
5
- stream: WritableStream<Uint8Array>;
6
- /**
7
- * Closes the stream on abort, flushing queued writes and committing
8
- * OPFS-style sinks. Fire-and-forget: to await the flush, observe your own
9
- * sink or resource completion. Logs are dropped once shutdown begins.
10
- */
11
- signal?: AbortSignal;
5
+ /** Where to print logs. */
6
+ stream: Writable;
12
7
  }
13
8
 
14
9
  /**
15
10
  * Prints structured logs to a writable stream in NDJSON form. Optimized for
16
11
  * log files.
17
12
  *
18
- * Writes to a Web Streams `WritableStream<Uint8Array>` so the same backend
19
- * runs across Node, Deno, Bun, and the browser (e.g. OPFS). See the readme
20
- * for a Node file-stream example.
21
- *
22
13
  * @example
23
14
  * createJsonBackend({
24
- * stream: new WritableStream({
25
- * write: (chunk) => void process.stdout.write(chunk),
26
- * }),
15
+ * stream: fs.createWriteStream('my-app.log', { flags: 'a' }),
27
16
  * })
28
17
  *
29
18
  * @see https://github.com/ndjson/ndjson-spec
30
19
  */
31
- export declare const createJsonBackend: ({ stream, signal }: Config) => LogProcessor;
20
+ export declare const createJsonBackend: ({ stream }: Config) => LogProcessor;
32
21
 
33
22
  export { }
@@ -39,25 +39,21 @@ var e = {
39
39
  error: o,
40
40
  fatal: o
41
41
  });
42
- }, n = new TextEncoder(), r = ({ stream: e, signal: t }) => {
43
- let r = e.getWriter();
44
- return t?.aborted ? r.close().catch(i) : t?.addEventListener("abort", () => void r.close().catch(i), { once: !0 }), (e) => {
45
- if (r.desiredSize === null || r.desiredSize <= 0) return;
46
- let t = JSON.stringify({
47
- level: o[e.level],
48
- time: new Date(e.timestamp).toISOString(),
49
- msg: e.message,
50
- origin: e.origin,
51
- ctx: Object.keys(e.context).length > 0 ? e.context : void 0
52
- }, a);
53
- r.write(n.encode(`${t}\n`)).catch(i);
54
- };
55
- }, i = () => {}, a = (e, t) => t instanceof Error ? {
42
+ }, n = ({ stream: e }) => (t) => {
43
+ let n = JSON.stringify({
44
+ level: i[t.level],
45
+ time: new Date(t.timestamp).toISOString(),
46
+ msg: t.message,
47
+ origin: t.origin,
48
+ ctx: Object.keys(t.context).length > 0 ? t.context : void 0
49
+ }, r);
50
+ e.write(`${n}\n`);
51
+ }, r = (e, t) => t instanceof Error ? {
56
52
  ...t,
57
53
  name: t.name,
58
54
  message: t.message,
59
55
  cause: t.cause,
60
56
  ...t instanceof AggregateError && { errors: t.errors }
61
- } : t, o = Object.fromEntries(Object.entries(e).map(([e, t]) => [t, e]));
57
+ } : t, i = Object.fromEntries(Object.entries(e).map(([e, t]) => [t, e]));
62
58
  //#endregion
63
- export { r as createJsonBackend };
59
+ export { n as createJsonBackend };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holz/json-backend",
3
- "version": "0.8.3-rc.169+b0bea47",
3
+ "version": "0.8.3-rc.171+909c4b9",
4
4
  "description": "Print logs as newline-delimited JSON.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  "test:types": "tsc"
38
38
  },
39
39
  "devDependencies": {
40
- "@holz/core": "^0.8.3-rc.169+b0bea47",
40
+ "@holz/core": "^0.8.3-rc.171+909c4b9",
41
41
  "@microsoft/api-extractor": "^7.58.8",
42
42
  "@types/node": "^24.0.0",
43
43
  "@vitest/coverage-v8": "^4.0.0",
@@ -47,5 +47,5 @@
47
47
  "vite-tsconfig-paths": "^6.0.0",
48
48
  "vitest": "^4.0.0"
49
49
  },
50
- "gitHead": "b0bea47da1b33d1e7c1d681a19b2cbe6e0cfea7a"
50
+ "gitHead": "909c4b99657f1f67fc7124fc8fad767acad32708"
51
51
  }