@ontrails/logtape 1.0.0-beta.15

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.
@@ -0,0 +1 @@
1
+ $ tsc -b
@@ -0,0 +1,3 @@
1
+ $ oxlint ./src
2
+ Found 0 warnings and 0 errors.
3
+ Finished in 60ms on 2 files with 93 rules using 24 threads.
@@ -0,0 +1 @@
1
+ $ tsc --noEmit
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @ontrails/logtape
2
+
3
+ ## 1.0.0-beta.15
4
+
5
+ ### Patch Changes
6
+
7
+ - @ontrails/logging@1.0.0-beta.15
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @ontrails/logtape
2
+
3
+ The logtape sink for `@ontrails/logging`. See `@ontrails/logging` for the logger API; this package only provides the optional logtape forwarding sink.
@@ -0,0 +1,24 @@
1
+ import type { LogSink } from '@ontrails/logging';
2
+ /**
3
+ * Subset of the logtape Logger interface that we forward records to.
4
+ * Accepts any object that provides the standard log-level methods.
5
+ */
6
+ export interface LogtapeLoggerLike {
7
+ trace(message: string, props?: Record<string, unknown>): void;
8
+ debug(message: string, props?: Record<string, unknown>): void;
9
+ info(message: string, props?: Record<string, unknown>): void;
10
+ warn(message: string, props?: Record<string, unknown>): void;
11
+ error(message: string, props?: Record<string, unknown>): void;
12
+ fatal(message: string, props?: Record<string, unknown>): void;
13
+ }
14
+ export interface LogtapeSinkOptions {
15
+ /** An existing logtape logger (or compatible object) to forward records to. */
16
+ readonly logger: LogtapeLoggerLike;
17
+ }
18
+ /**
19
+ * Sink connector that forwards `LogRecord` instances to an existing logtape
20
+ * logger. Redaction runs _before_ the sink receives records, so sensitive
21
+ * data is scrubbed regardless of the backend.
22
+ */
23
+ export declare const logtapeSink: (options: LogtapeSinkOptions) => LogSink;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAM5D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC/D;AAMD,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACpC;AAiBD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,kBAAkB,KAAG,OAmBzD,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ const LEVEL_MAP = {
2
+ debug: 'debug',
3
+ error: 'error',
4
+ fatal: 'fatal',
5
+ info: 'info',
6
+ trace: 'trace',
7
+ warn: 'warn',
8
+ };
9
+ /**
10
+ * Sink connector that forwards `LogRecord` instances to an existing logtape
11
+ * logger. Redaction runs _before_ the sink receives records, so sensitive
12
+ * data is scrubbed regardless of the backend.
13
+ */
14
+ export const logtapeSink = (options) => {
15
+ const { logger } = options;
16
+ return {
17
+ name: 'logtape',
18
+ write(record) {
19
+ const method = LEVEL_MAP[record.level];
20
+ if (method === undefined) {
21
+ return;
22
+ }
23
+ const props = {
24
+ category: record.category,
25
+ ...record.metadata,
26
+ };
27
+ logger[method](record.message, props);
28
+ },
29
+ };
30
+ };
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkCA,MAAM,SAAS,GAAkC;IAC/C,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;CACb,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAA2B,EAAW,EAAE;IAClE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,MAAiB;YACrB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAA4B;gBACrC,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,GAAG,MAAM,CAAC,QAAQ;aACnB,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@ontrails/logtape",
3
+ "version": "1.0.0-beta.15",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./src/index.ts",
7
+ "./package.json": "./package.json"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc -b",
11
+ "test": "bun test",
12
+ "typecheck": "tsc --noEmit",
13
+ "lint": "oxlint ./src",
14
+ "clean": "rm -rf dist *.tsbuildinfo"
15
+ },
16
+ "peerDependencies": {
17
+ "@ontrails/logging": "^1.0.0-beta.14"
18
+ }
19
+ }
@@ -0,0 +1,74 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+
3
+ import { logtapeSink } from '../index.js';
4
+ import type { LogtapeLoggerLike } from '../index.js';
5
+
6
+ const createRecordingLogger = () => {
7
+ const calls: {
8
+ level: string;
9
+ message: string;
10
+ props?: Record<string, unknown>;
11
+ }[] = [];
12
+
13
+ const logger: LogtapeLoggerLike = {
14
+ debug(message, props) {
15
+ calls.push({ level: 'debug', message, props });
16
+ },
17
+ error(message, props) {
18
+ calls.push({ level: 'error', message, props });
19
+ },
20
+ fatal(message, props) {
21
+ calls.push({ level: 'fatal', message, props });
22
+ },
23
+ info(message, props) {
24
+ calls.push({ level: 'info', message, props });
25
+ },
26
+ trace(message, props) {
27
+ calls.push({ level: 'trace', message, props });
28
+ },
29
+ warn(message, props) {
30
+ calls.push({ level: 'warn', message, props });
31
+ },
32
+ };
33
+
34
+ return { calls, logger };
35
+ };
36
+
37
+ describe('logtapeSink', () => {
38
+ test('forwards records to the underlying logtape logger by level', () => {
39
+ const { calls, logger } = createRecordingLogger();
40
+ const sink = logtapeSink({ logger });
41
+
42
+ sink.write({
43
+ category: 'app.http',
44
+ level: 'info',
45
+ message: 'request received',
46
+ metadata: { path: '/greet' },
47
+ timestamp: new Date(),
48
+ });
49
+
50
+ expect(calls).toEqual([
51
+ {
52
+ level: 'info',
53
+ message: 'request received',
54
+ props: { category: 'app.http', path: '/greet' },
55
+ },
56
+ ]);
57
+ });
58
+
59
+ test('ignores records whose level does not map to a logtape method', () => {
60
+ const { calls, logger } = createRecordingLogger();
61
+ const sink = logtapeSink({ logger });
62
+
63
+ sink.write({
64
+ category: 'app',
65
+ // @ts-expect-error -- exercising unexpected level handling
66
+ level: 'unknown',
67
+ message: 'should not forward',
68
+ metadata: {},
69
+ timestamp: new Date(),
70
+ });
71
+
72
+ expect(calls).toEqual([]);
73
+ });
74
+ });
package/src/index.ts ADDED
@@ -0,0 +1,68 @@
1
+ import type { LogRecord, LogSink } from '@ontrails/logging';
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Minimal logtape logger interface (avoids importing @logtape/logtape)
5
+ // ---------------------------------------------------------------------------
6
+
7
+ /**
8
+ * Subset of the logtape Logger interface that we forward records to.
9
+ * Accepts any object that provides the standard log-level methods.
10
+ */
11
+ export interface LogtapeLoggerLike {
12
+ trace(message: string, props?: Record<string, unknown>): void;
13
+ debug(message: string, props?: Record<string, unknown>): void;
14
+ info(message: string, props?: Record<string, unknown>): void;
15
+ warn(message: string, props?: Record<string, unknown>): void;
16
+ error(message: string, props?: Record<string, unknown>): void;
17
+ fatal(message: string, props?: Record<string, unknown>): void;
18
+ }
19
+
20
+ // ---------------------------------------------------------------------------
21
+ // Options
22
+ // ---------------------------------------------------------------------------
23
+
24
+ export interface LogtapeSinkOptions {
25
+ /** An existing logtape logger (or compatible object) to forward records to. */
26
+ readonly logger: LogtapeLoggerLike;
27
+ }
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // logtapeSink
31
+ // ---------------------------------------------------------------------------
32
+
33
+ type ForwardMethod = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
34
+
35
+ const LEVEL_MAP: Record<string, ForwardMethod> = {
36
+ debug: 'debug',
37
+ error: 'error',
38
+ fatal: 'fatal',
39
+ info: 'info',
40
+ trace: 'trace',
41
+ warn: 'warn',
42
+ };
43
+
44
+ /**
45
+ * Sink connector that forwards `LogRecord` instances to an existing logtape
46
+ * logger. Redaction runs _before_ the sink receives records, so sensitive
47
+ * data is scrubbed regardless of the backend.
48
+ */
49
+ export const logtapeSink = (options: LogtapeSinkOptions): LogSink => {
50
+ const { logger } = options;
51
+
52
+ return {
53
+ name: 'logtape',
54
+ write(record: LogRecord): void {
55
+ const method = LEVEL_MAP[record.level];
56
+ if (method === undefined) {
57
+ return;
58
+ }
59
+
60
+ const props: Record<string, unknown> = {
61
+ category: record.category,
62
+ ...record.metadata,
63
+ };
64
+
65
+ logger[method](record.message, props);
66
+ },
67
+ };
68
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": ["src"],
8
+ "exclude": ["**/__tests__/**", "**/*.test.ts", "dist"]
9
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "rootDir": "./src",
6
+ "types": ["bun"]
7
+ },
8
+ "include": ["src/**/*.test.ts", "src/__tests__/**/*.ts"],
9
+ "exclude": []
10
+ }
@@ -0,0 +1 @@
1
+ {"root":["./src/index.ts"],"version":"5.9.3"}