@decohere/scribe 0.0.1-dev.13 → 0.0.1-dev.130
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/LICENSE +15 -0
- package/commonjs/src/console.adapter.js +21 -14
- package/commonjs/src/env.js +2 -3
- package/commonjs/src/errors.js +0 -2
- package/commonjs/src/index.js +3 -2
- package/commonjs/src/log-entry.adapter.js +55 -0
- package/commonjs/src/log-entry.js +89 -0
- package/commonjs/src/logger.adapter.js +58 -6
- package/commonjs/src/logger.factory.js +112 -11
- package/commonjs/src/logger.type.js +0 -2
- package/commonjs/src/redact.js +67 -0
- package/commonjs/src/testing/capture.adapter.js +23 -0
- package/commonjs/src/testing/index.js +14 -2
- package/commonjs/src/types.js +19 -6
- package/es6/src/console.adapter.js +22 -15
- package/es6/src/env.js +3 -4
- package/es6/src/errors.js +0 -2
- package/es6/src/index.js +3 -2
- package/es6/src/log-entry.adapter.js +49 -0
- package/es6/src/log-entry.js +79 -0
- package/es6/src/logger.adapter.js +45 -3
- package/es6/src/logger.factory.js +112 -11
- package/es6/src/logger.type.js +0 -2
- package/es6/src/redact.js +57 -0
- package/es6/src/testing/capture.adapter.js +17 -0
- package/es6/src/testing/index.js +1 -3
- package/es6/src/types.js +16 -6
- package/package.json +15 -1
- package/types/src/console.adapter.d.ts +1 -0
- package/types/src/env.d.ts +1 -1
- package/types/src/index.d.ts +3 -0
- package/types/src/log-entry.adapter.d.ts +20 -0
- package/types/src/log-entry.d.ts +38 -0
- package/types/src/logger.adapter.d.ts +32 -1
- package/types/src/logger.factory.d.ts +31 -2
- package/types/src/logger.type.d.ts +5 -0
- package/types/src/redact.d.ts +10 -0
- package/types/src/testing/capture.adapter.d.ts +14 -0
- package/types/src/testing/index.d.ts +1 -1
- package/types/src/types.d.ts +7 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { DefaultCensor, DefaultRedactions } from "./types.js";
|
|
2
|
+
function keysFromPaths(paths) {
|
|
3
|
+
const keys = new Set();
|
|
4
|
+
for (const path of paths){
|
|
5
|
+
const segments = path.split(".").filter((segment)=>segment.length > 0 && segment !== "*");
|
|
6
|
+
const key = segments.at(-1);
|
|
7
|
+
if (key != null) {
|
|
8
|
+
keys.add(key);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return keys;
|
|
12
|
+
}
|
|
13
|
+
function isPlainObject(value) {
|
|
14
|
+
if (value == null || typeof value !== "object" || Array.isArray(value) || value instanceof Error) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const proto = Object.getPrototypeOf(value);
|
|
18
|
+
return proto === Object.prototype || proto === null;
|
|
19
|
+
}
|
|
20
|
+
function object(value, keys, censor = DefaultCensor, copies = new WeakMap()) {
|
|
21
|
+
if (value == null || typeof value !== "object") {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
if (value instanceof Error) {
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
// A cycle in the input stays a cycle in the copy.
|
|
28
|
+
const copied = copies.get(value);
|
|
29
|
+
if (copied !== undefined) {
|
|
30
|
+
return copied;
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
const out = [];
|
|
34
|
+
copies.set(value, out);
|
|
35
|
+
for (const item of value){
|
|
36
|
+
out.push(object(item, keys, censor, copies));
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
if (!isPlainObject(value)) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
const out = {};
|
|
44
|
+
copies.set(value, out);
|
|
45
|
+
for (const [key, nested] of Object.entries(value)){
|
|
46
|
+
out[key] = keys.has(key) ? censor : object(nested, keys, censor, copies);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
function fromOptions(options) {
|
|
51
|
+
return keysFromPaths(options?.paths ?? DefaultRedactions.paths);
|
|
52
|
+
}
|
|
53
|
+
export const redact = {
|
|
54
|
+
object,
|
|
55
|
+
keysFromPaths,
|
|
56
|
+
fromOptions
|
|
57
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LogEntryAdapter } from "../log-entry.adapter.js";
|
|
2
|
+
/**
|
|
3
|
+
* Test double: keeps every entry that passes the level threshold, prints
|
|
4
|
+
* nothing. `scribe.configure({ adapter: capture })`, run the code, then assert
|
|
5
|
+
* on `capture.entries`.
|
|
6
|
+
*/ export class CaptureAdapter extends LogEntryAdapter {
|
|
7
|
+
entries = [];
|
|
8
|
+
/** Entries at `level`. */ at(level) {
|
|
9
|
+
return this.entries.filter((entry)=>entry.level === level);
|
|
10
|
+
}
|
|
11
|
+
clear() {
|
|
12
|
+
this.entries.length = 0;
|
|
13
|
+
}
|
|
14
|
+
write(entry) {
|
|
15
|
+
this.entries.push(entry);
|
|
16
|
+
}
|
|
17
|
+
}
|
package/es6/src/testing/index.js
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUvc3JjL3Rlc3RpbmcvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHt9O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFdBQVUifQ==
|
|
1
|
+
export * from "./capture.adapter.js";
|
package/es6/src/types.js
CHANGED
|
@@ -15,11 +15,21 @@ export const LogLevels = {
|
|
|
15
15
|
trace: 10
|
|
16
16
|
};
|
|
17
17
|
export const DefaultLogLevel = "info";
|
|
18
|
+
/** Pino's default censor. ConsoleAdapter uses the same placeholder. */ export const DefaultCensor = "[Redacted]";
|
|
19
|
+
/**
|
|
20
|
+
* Object keys Scribe redacts. Adapters apply this list — Pino via `redact.paths`
|
|
21
|
+
* (top-level and one nest), ConsoleAdapter via `redact.object`.
|
|
22
|
+
*/ export const DefaultRedactionKeys = [
|
|
23
|
+
"password",
|
|
24
|
+
"secret",
|
|
25
|
+
"token",
|
|
26
|
+
"otp",
|
|
27
|
+
"pw",
|
|
28
|
+
"userconfig"
|
|
29
|
+
];
|
|
18
30
|
export const DefaultRedactions = {
|
|
19
|
-
paths: [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
paths: DefaultRedactionKeys.flatMap((key)=>[
|
|
32
|
+
key,
|
|
33
|
+
`*.${key}`
|
|
34
|
+
])
|
|
23
35
|
};
|
|
24
|
-
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUvc3JjL3R5cGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IExPR19MRVZFTFMgPSBbXCJmYXRhbFwiLCBcImVycm9yXCIsIFwid2FyblwiLCBcImluZm9cIiwgXCJkZWJ1Z1wiLCBcInRyYWNlXCJdIGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBMb2dMZXZlbCA9IHR5cGVvZiBMT0dfTEVWRUxTO1xuXG5leHBvcnQgdHlwZSBEZWZhdWx0TGV2ZWxzID0gTG9nTGV2ZWxbbnVtYmVyXTtcblxuZXhwb3J0IGNvbnN0IExvZ0xldmVscyA9IHtcblx0ZmF0YWw6IDYwLFxuXHRlcnJvcjogNTAsXG5cdHdhcm46IDQwLFxuXHRpbmZvOiAzMCxcblx0ZGVidWc6IDIwLFxuXHR0cmFjZTogMTAsXG59IHNhdGlzZmllcyBSZWNvcmQ8RGVmYXVsdExldmVscywgbnVtYmVyPjtcblxuZXhwb3J0IGNvbnN0IERlZmF1bHRMb2dMZXZlbDogRGVmYXVsdExldmVscyA9IFwiaW5mb1wiO1xuXG5leHBvcnQgdHlwZSBSZWRhY3Rpb25PcHRpb25zID0ge1xuXHRwYXRoczogc3RyaW5nW107XG59O1xuXG5leHBvcnQgY29uc3QgRGVmYXVsdFJlZGFjdGlvbnM6IFJlZGFjdGlvbk9wdGlvbnMgPSB7IHBhdGhzOiBbXCIqLnBhc3N3b3JkXCIsIFwiKi5zZWNyZXRcIl0gfTtcblxuZXhwb3J0IGludGVyZmFjZSBTY3JpYmVPcHRpb25zPFxuXHRUIGV4dGVuZHMgc3RyaW5nID0gbmV2ZXIsXG5cdEN1c3RvbU9ubHkgZXh0ZW5kcyB0cnVlIHwgZmFsc2UgPSB1bmRlZmluZWQsXG4+IHtcblx0bG9nTGV2ZWw/OiBEZWZhdWx0TGV2ZWxzIHwgc3RyaW5nO1xuXHRjdXN0b21MZXZlbHM/OiB7XG5cdFx0W2xldmVsIGluIFRdOiBudW1iZXI7XG5cdH07XG5cdGN1c3RvbU9ubHk/OiBDdXN0b21Pbmx5O1xuXHRyZWRhY3Rpb25zPzogUmVkYWN0aW9uT3B0aW9ucztcbn1cblxuZXhwb3J0IHR5cGUgTG9nQWRhcHRlck9wdGlvbnMgPSBSZWNvcmQ8c3RyaW5nLCBuZXZlcj47XG4iXSwibmFtZXMiOlsiTE9HX0xFVkVMUyIsIkxvZ0xldmVscyIsImZhdGFsIiwiZXJyb3IiLCJ3YXJuIiwiaW5mbyIsImRlYnVnIiwidHJhY2UiLCJEZWZhdWx0TG9nTGV2ZWwiLCJEZWZhdWx0UmVkYWN0aW9ucyIsInBhdGhzIl0sIm1hcHBpbmdzIjoiQUFBQSxNQUFNQSxhQUFhO0lBQUM7SUFBUztJQUFTO0lBQVE7SUFBUTtJQUFTO0NBQVE7QUFNdkUsT0FBTyxNQUFNQyxZQUFZO0lBQ3hCQyxPQUFPO0lBQ1BDLE9BQU87SUFDUEMsTUFBTTtJQUNOQyxNQUFNO0lBQ05DLE9BQU87SUFDUEMsT0FBTztBQUNSLEVBQTBDO0FBRTFDLE9BQU8sTUFBTUMsa0JBQWlDLE9BQU87QUFNckQsT0FBTyxNQUFNQyxvQkFBc0M7SUFBRUMsT0FBTztRQUFDO1FBQWM7S0FBVztBQUFDLEVBQUUifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decohere/scribe",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.130",
|
|
4
4
|
"description": "Structured logging interface with pluggable adapters",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
"structured-logging",
|
|
9
9
|
"decohere"
|
|
10
10
|
],
|
|
11
|
+
"homepage": "https://github.com/typesmiths/decohere/tree/main/projects/scribe/scribe#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/typesmiths/decohere/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/typesmiths/decohere.git",
|
|
18
|
+
"directory": "projects/scribe/scribe"
|
|
19
|
+
},
|
|
11
20
|
"license": "ISC",
|
|
12
21
|
"author": "Typesmiths",
|
|
13
22
|
"type": "module",
|
|
@@ -17,6 +26,11 @@
|
|
|
17
26
|
"types": "./types/src/index.d.ts",
|
|
18
27
|
"import": "./es6/src/index.js",
|
|
19
28
|
"require": "./commonjs/src/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./testing": {
|
|
31
|
+
"types": "./types/src/testing/index.d.ts",
|
|
32
|
+
"import": "./es6/src/testing/index.js",
|
|
33
|
+
"require": "./commonjs/src/testing/index.js"
|
|
20
34
|
}
|
|
21
35
|
},
|
|
22
36
|
"scripts": {
|
|
@@ -6,6 +6,7 @@ export declare class ConsoleAdapter extends LogAdapter {
|
|
|
6
6
|
private configuredLevels;
|
|
7
7
|
private configuredLogLevel;
|
|
8
8
|
private configuredLogLevelValue;
|
|
9
|
+
private redactionKeys;
|
|
9
10
|
constructor(_options?: ConsoleAdapterOptions);
|
|
10
11
|
configure<T extends string = never, CustomOnly extends true | false = false>(scribeOptions: ScribeOptions<T, CustomOnly>): void;
|
|
11
12
|
getLogger<T extends string = never, CustomOnly extends true | false = false>(name?: string): Logger<T, CustomOnly>;
|
package/types/src/env.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { DefaultLevels } from "./types.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Reads the log level from environment variables.
|
|
4
4
|
* Checks LOG_LEVEL, SCRIBE_LOG_LEVEL, and LOGGING_LEVEL in order.
|
|
5
|
-
* Returns null if none are set.
|
|
5
|
+
* Returns null if none are set, or if the runtime has no `process` (browsers).
|
|
6
6
|
*/
|
|
7
7
|
export declare function getLogLevelFromEnv(): string | null;
|
|
8
8
|
/**
|
package/types/src/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export * from "./console.adapter.js";
|
|
2
2
|
export * from "./env.js";
|
|
3
3
|
export * from "./errors.js";
|
|
4
|
+
export * from "./log-entry.adapter.js";
|
|
5
|
+
export * from "./log-entry.js";
|
|
4
6
|
export * from "./logger.adapter.js";
|
|
5
7
|
export * from "./logger.factory.js";
|
|
6
8
|
export * from "./logger.type.js";
|
|
9
|
+
export * from "./redact.js";
|
|
7
10
|
export * from "./types.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type LogEntry } from "./log-entry.js";
|
|
2
|
+
import { LogAdapter } from "./logger.adapter.js";
|
|
3
|
+
import type { Logger } from "./logger.type.js";
|
|
4
|
+
import { type ScribeOptions } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Base for adapters that write structured entries. It owns levels, the level
|
|
7
|
+
* threshold, `child`, and censoring the `redactions` keys; a subclass only
|
|
8
|
+
* writes each `LogEntry`.
|
|
9
|
+
*/
|
|
10
|
+
export declare abstract class LogEntryAdapter extends LogAdapter {
|
|
11
|
+
protected levels: Record<string, number>;
|
|
12
|
+
private level;
|
|
13
|
+
private threshold;
|
|
14
|
+
private redactionKeys;
|
|
15
|
+
configure<T extends string = never, CustomOnly extends true | false = false>(scribeOptions: ScribeOptions<T, CustomOnly>): void;
|
|
16
|
+
getLogger<T extends string = never, CustomOnly extends true | false = false>(name?: string): Logger<T, CustomOnly>;
|
|
17
|
+
/** Write one entry that passed the level threshold. */
|
|
18
|
+
protected abstract write(entry: LogEntry): void;
|
|
19
|
+
private createLogger;
|
|
20
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type SerializedError } from "./logger.adapter.js";
|
|
2
|
+
/**
|
|
3
|
+
* One logged call. Adapters that write structured lines build it with
|
|
4
|
+
* `logEntry.from`, and taps receive it.
|
|
5
|
+
*/
|
|
6
|
+
export type LogEntry = {
|
|
7
|
+
level: string;
|
|
8
|
+
name: string;
|
|
9
|
+
msg?: string;
|
|
10
|
+
err?: SerializedError;
|
|
11
|
+
/** Bound fields (`child`), then the call's own fields. */
|
|
12
|
+
fields: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export type LogEntryOptions = {
|
|
15
|
+
bindings?: Record<string, unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* Keys the adapter censors (`redact.fromOptions`). Redaction is the
|
|
18
|
+
* adapter's job, so the facade's tap passes none.
|
|
19
|
+
*/
|
|
20
|
+
redactionKeys?: ReadonlySet<string>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Builds an entry from a log call's arguments:
|
|
24
|
+
*
|
|
25
|
+
* - `log.info("text")`, `log.info(42)` → `msg`
|
|
26
|
+
* - `log.error(err)` → `msg` is `err.message`, `err` the serialized error
|
|
27
|
+
* - `log.info({ fields })`, `log.info({ fields }, "text")` → `fields` (a string
|
|
28
|
+
* `msg` field becomes the message)
|
|
29
|
+
* - `log.info("text", { fields })` → `msg` + `fields`
|
|
30
|
+
* - `log.error("text", err)` → `msg` + `err`
|
|
31
|
+
* - `log.info("text", value)` → `msg` + `fields.data`; any further arguments go
|
|
32
|
+
* in `fields.args`
|
|
33
|
+
*/
|
|
34
|
+
declare function from(level: string, name: string, [first, ...rest]: readonly unknown[], { bindings, redactionKeys }: LogEntryOptions): LogEntry;
|
|
35
|
+
export declare const logEntry: {
|
|
36
|
+
from: typeof from;
|
|
37
|
+
};
|
|
38
|
+
export {};
|
|
@@ -1,14 +1,45 @@
|
|
|
1
1
|
import type { Logger } from "./logger.type.js";
|
|
2
2
|
import { type ScribeOptions } from "./types.js";
|
|
3
|
-
export
|
|
3
|
+
export declare function formatError(err: Error): string;
|
|
4
|
+
export type SerializedError = {
|
|
5
|
+
name: string;
|
|
6
|
+
message: string;
|
|
7
|
+
stack?: string;
|
|
8
|
+
cause?: unknown;
|
|
9
|
+
/** Own enumerable properties such as `code` or `statusCode`. */
|
|
10
|
+
[property: string]: unknown;
|
|
11
|
+
};
|
|
12
|
+
/** How many causes deep `serializeError` follows by default. */
|
|
13
|
+
export declare const DefaultErrorCauseDepth = 3;
|
|
14
|
+
/**
|
|
15
|
+
* Plain-object form of an error for structured logs. An `Error` cause, or an
|
|
16
|
+
* `Error` in another own property, is serialized the same way, up to
|
|
17
|
+
* `causeDepth` levels; any other value is kept as it is.
|
|
18
|
+
*/
|
|
19
|
+
export declare function serializeError(err: Error, causeDepth?: number): SerializedError;
|
|
20
|
+
export interface LoggerAdapter extends AsyncDisposable {
|
|
4
21
|
configure<T extends string = never, CustomOnly extends true | false = false>(options: ScribeOptions<T, CustomOnly>): any;
|
|
5
22
|
getLogger<T extends string = never, CustomOnly extends true | false = false>(name: string): Logger<T, CustomOnly>;
|
|
6
23
|
flush(cb?: () => void): void;
|
|
24
|
+
/**
|
|
25
|
+
* Synchronously stop accepting writes (kill ThreadStream / close fds).
|
|
26
|
+
* Call before swapping adapters so a dead worker cannot spam on further logs.
|
|
27
|
+
* Idempotent — safe to call more than once.
|
|
28
|
+
*/
|
|
29
|
+
retire(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Drain buffered output and release unmanaged handles (workers, fds).
|
|
32
|
+
* Idempotent — safe to call more than once.
|
|
33
|
+
*/
|
|
34
|
+
stop(): Promise<void>;
|
|
7
35
|
}
|
|
8
36
|
export declare abstract class LogAdapter implements LoggerAdapter {
|
|
9
37
|
abstract configure<T extends string = never, CustomOnly extends true | false = false>(options: ScribeOptions<T, CustomOnly>): any;
|
|
10
38
|
abstract getLogger<T extends string = never, CustomOnly extends true | false = false>(name: string): Logger<T, CustomOnly>;
|
|
11
39
|
flush(cb?: () => void): void;
|
|
40
|
+
retire(): void;
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
12
43
|
protected getLogLevels(options: ScribeOptions<any, any>): Record<string, number>;
|
|
13
44
|
protected getUniqueLevels(defaultLevels: Record<string, number>, customLevels: Record<string, number>): [string, number][];
|
|
14
45
|
}
|
|
@@ -1,24 +1,53 @@
|
|
|
1
|
+
import { type LogEntry } from "./log-entry.js";
|
|
1
2
|
import type { LoggerAdapter } from "./logger.adapter.js";
|
|
2
3
|
import type { Logger } from "./logger.type.js";
|
|
3
4
|
import { type ScribeOptions } from "./types.js";
|
|
4
5
|
type LoggerFactoryOptions<T extends string = never, CustomOnly extends true | false = false> = {
|
|
5
6
|
options?: ScribeOptions<T, CustomOnly>;
|
|
6
7
|
adapter: LoggerAdapter;
|
|
8
|
+
/**
|
|
9
|
+
* Called with every entry a `scribe.logger(...)` handle writes (levels the
|
|
10
|
+
* adapter has enabled). For error reporters such as Sentry. Scribe does not
|
|
11
|
+
* redact what it hands the tap; the tap, or the service behind it, does.
|
|
12
|
+
* A tap that throws does not break the call that logged: the error is
|
|
13
|
+
* rethrown on a microtask, where the runtime reports it as uncaught.
|
|
14
|
+
*/
|
|
15
|
+
tap?: LogTap;
|
|
7
16
|
};
|
|
8
|
-
export
|
|
17
|
+
export type LogTap = (entry: LogEntry) => void;
|
|
18
|
+
export declare class scribe implements AsyncDisposable {
|
|
9
19
|
private loggerProvider;
|
|
20
|
+
/** True after `configure({ adapter })` — the constructor’s ConsoleAdapter is only a fallback. */
|
|
21
|
+
private adapterConfigured;
|
|
22
|
+
private defaultAdapterWarned;
|
|
23
|
+
private tap;
|
|
10
24
|
private static instance;
|
|
11
25
|
static logger<T extends string = never, CustomOnly extends true | false = false>(name?: string, customLevels?: {
|
|
12
26
|
[level in T]: number;
|
|
13
27
|
}): Logger<T, CustomOnly>;
|
|
14
28
|
static configure<T extends string = never, CustomOnly extends true | false = false>(configOptions: LoggerFactoryOptions<T, CustomOnly>): (name?: string) => Logger<T, CustomOnly>;
|
|
15
|
-
static get extend(): scribe;
|
|
16
29
|
static flush(cb?: () => void): void;
|
|
30
|
+
/** Synchronously stop accepting writes on the active adapter. */
|
|
31
|
+
static retire(): void;
|
|
32
|
+
/** Drain the active adapter and release workers / destinations. */
|
|
33
|
+
static stop(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Module-level `const log = scribe.logger(...)` must follow a later
|
|
36
|
+
* `scribe.configure()` (CLI / Flux / HotReloadServer). Forward every use to
|
|
37
|
+
* the active adapter logger for `name`, and `child(fields)` to a live handle
|
|
38
|
+
* that adds `bindings`, so children follow a reconfigure too.
|
|
39
|
+
*/
|
|
40
|
+
private static createLiveLogger;
|
|
17
41
|
constructor();
|
|
18
42
|
configure<T extends string = never, CustomOnly extends true | false = false>(configOptions: LoggerFactoryOptions<T, CustomOnly>): (name?: string) => Logger<T, CustomOnly>;
|
|
43
|
+
retire(): void;
|
|
44
|
+
stop(): Promise<void>;
|
|
45
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
19
46
|
getLogger<T extends string = never, CustomOnly extends true | false = false>(name?: string, customLevels?: {
|
|
20
47
|
[level in T]: number;
|
|
21
48
|
}): Logger<T, CustomOnly>;
|
|
49
|
+
private notifyTap;
|
|
50
|
+
private warnIfDefaultAdapter;
|
|
22
51
|
private supportsLevels;
|
|
23
52
|
private mergeDefaults;
|
|
24
53
|
}
|
|
@@ -10,4 +10,9 @@ export type Logger<CustomLevels extends string = never, CustomOnly extends true
|
|
|
10
10
|
[Property in CustomLevels]: LogFn;
|
|
11
11
|
} & {
|
|
12
12
|
isLevelEnabled(level: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* A logger with the same name and levels that adds `fields` (a request id, a
|
|
15
|
+
* job name) to every entry. Children of children merge their fields.
|
|
16
|
+
*/
|
|
17
|
+
child(fields: Record<string, unknown>): Logger<CustomLevels, CustomOnly>;
|
|
13
18
|
} & BaseLogger;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type RedactionOptions } from "./types.js";
|
|
2
|
+
declare function keysFromPaths(paths: string[]): Set<string>;
|
|
3
|
+
declare function object(value: unknown, keys: ReadonlySet<string>, censor?: string, copies?: WeakMap<object, unknown>): unknown;
|
|
4
|
+
declare function fromOptions(options?: RedactionOptions): Set<string>;
|
|
5
|
+
export declare const redact: {
|
|
6
|
+
object: typeof object;
|
|
7
|
+
keysFromPaths: typeof keysFromPaths;
|
|
8
|
+
fromOptions: typeof fromOptions;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LogEntryAdapter } from "../log-entry.adapter.js";
|
|
2
|
+
import type { LogEntry } from "../log-entry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Test double: keeps every entry that passes the level threshold, prints
|
|
5
|
+
* nothing. `scribe.configure({ adapter: capture })`, run the code, then assert
|
|
6
|
+
* on `capture.entries`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CaptureAdapter extends LogEntryAdapter {
|
|
9
|
+
readonly entries: LogEntry[];
|
|
10
|
+
/** Entries at `level`. */
|
|
11
|
+
at(level: string): LogEntry[];
|
|
12
|
+
clear(): void;
|
|
13
|
+
protected write(entry: LogEntry): void;
|
|
14
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from "./capture.adapter.js";
|
package/types/src/types.d.ts
CHANGED
|
@@ -13,6 +13,13 @@ export declare const DefaultLogLevel: DefaultLevels;
|
|
|
13
13
|
export type RedactionOptions = {
|
|
14
14
|
paths: string[];
|
|
15
15
|
};
|
|
16
|
+
/** Pino's default censor. ConsoleAdapter uses the same placeholder. */
|
|
17
|
+
export declare const DefaultCensor = "[Redacted]";
|
|
18
|
+
/**
|
|
19
|
+
* Object keys Scribe redacts. Adapters apply this list — Pino via `redact.paths`
|
|
20
|
+
* (top-level and one nest), ConsoleAdapter via `redact.object`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const DefaultRedactionKeys: readonly ["password", "secret", "token", "otp", "pw", "userconfig"];
|
|
16
23
|
export declare const DefaultRedactions: RedactionOptions;
|
|
17
24
|
export interface ScribeOptions<T extends string = never, CustomOnly extends true | false = undefined> {
|
|
18
25
|
logLevel?: DefaultLevels | string;
|