@ontrails/logging 1.0.0-beta.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/.turbo/turbo-build.log +1 -0
- package/.turbo/turbo-lint.log +3 -0
- package/.turbo/turbo-typecheck.log +1 -0
- package/CHANGELOG.md +20 -0
- package/README.md +160 -0
- package/dist/env.d.ts +13 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +38 -0
- package/dist/env.js.map +1 -0
- package/dist/formatters.d.ts +8 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +72 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/levels.d.ts +9 -0
- package/dist/levels.d.ts.map +1 -0
- package/dist/levels.js +52 -0
- package/dist/levels.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +80 -0
- package/dist/logger.js.map +1 -0
- package/dist/logtape/index.d.ts +24 -0
- package/dist/logtape/index.d.ts.map +1 -0
- package/dist/logtape/index.js +31 -0
- package/dist/logtape/index.js.map +1 -0
- package/dist/sinks.d.ts +13 -0
- package/dist/sinks.d.ts.map +1 -0
- package/dist/sinks.js +58 -0
- package/dist/sinks.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +25 -0
- package/src/__tests__/env.test.ts +54 -0
- package/src/__tests__/formatters.test.ts +119 -0
- package/src/__tests__/levels.test.ts +82 -0
- package/src/__tests__/logger.test.ts +279 -0
- package/src/__tests__/sinks.test.ts +181 -0
- package/src/env.ts +49 -0
- package/src/formatters.ts +101 -0
- package/src/index.ts +28 -0
- package/src/levels.ts +69 -0
- package/src/logger.ts +135 -0
- package/src/logtape/index.ts +68 -0
- package/src/sinks.ts +71 -0
- package/src/types.ts +99 -0
- package/tsconfig.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ tsc -b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ tsc --noEmit
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @ontrails/logging
|
|
2
|
+
|
|
3
|
+
## 1.0.0-beta.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Initial v1 beta release of the Trails framework.
|
|
8
|
+
|
|
9
|
+
- **@ontrails/core** — Result type, error taxonomy, trail/hike/event/topo, validateTopo, validateInput/Output, deriveFields, patterns, redaction, branded types, resilience
|
|
10
|
+
- **@ontrails/cli** — CLI surface adapter, Commander integration, flag derivation, layers
|
|
11
|
+
- **@ontrails/mcp** — MCP surface adapter, tool generation, annotations, progress bridge
|
|
12
|
+
- **@ontrails/logging** — Structured logging, sinks, formatters, LogTape adapter
|
|
13
|
+
- **@ontrails/testing** — testAll, testExamples, testTrail, testHike, testContracts, testDetours, surface harnesses
|
|
14
|
+
- **@ontrails/warden** — AST-based code convention rules via oxc-parser, drift detection, CI formatters
|
|
15
|
+
- **@ontrails/schema** — Surface map generation, hashing, semantic diffing
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @ontrails/core@1.0.0-beta.0
|
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# @ontrails/logging
|
|
2
|
+
|
|
3
|
+
Structured logging for Trails. One API: `createLogger(config)`. Built-in sinks and formatters, hierarchical category filtering, automatic redaction, and an optional LogTape adapter.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @ontrails/logging @ontrails/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For LogTape integration:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun add @logtape/logtape
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { createLogger } from '@ontrails/logging';
|
|
21
|
+
|
|
22
|
+
const logger = createLogger({
|
|
23
|
+
name: 'app.entity',
|
|
24
|
+
level: 'info',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
logger.info('Entity created', { entityId: 'e1', name: 'Alpha' });
|
|
28
|
+
// 10:00:00 INFO [app.entity] Entity created entityId=e1 name=Alpha
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API Overview
|
|
32
|
+
|
|
33
|
+
### `createLogger(config)`
|
|
34
|
+
|
|
35
|
+
The single entry point. Returns a `Logger` (from `@ontrails/core`) that plugs directly into `TrailContext.logger`.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const logger = createLogger({
|
|
39
|
+
name: 'app.db.queries',
|
|
40
|
+
level: 'info',
|
|
41
|
+
levels: {
|
|
42
|
+
app: 'info',
|
|
43
|
+
'app.db': 'debug',
|
|
44
|
+
'app.http': 'warn',
|
|
45
|
+
},
|
|
46
|
+
sinks: [createConsoleSink(), createFileSink({ path: './app.log' })],
|
|
47
|
+
redaction: { sensitiveKeys: ['password', 'token'] },
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Sinks
|
|
52
|
+
|
|
53
|
+
A `LogSink` receives formatted log records and writes them somewhere.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { createConsoleSink, createFileSink } from '@ontrails/logging';
|
|
57
|
+
|
|
58
|
+
// Console output (default sink)
|
|
59
|
+
createConsoleSink({ formatter: createPrettyFormatter() });
|
|
60
|
+
|
|
61
|
+
// File output
|
|
62
|
+
createFileSink({ path: './logs/app.log', formatter: createJsonFormatter() });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Formatters
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { createJsonFormatter, createPrettyFormatter } from '@ontrails/logging';
|
|
69
|
+
|
|
70
|
+
// Structured JSON -- one object per line, ISO 8601 timestamps
|
|
71
|
+
createJsonFormatter();
|
|
72
|
+
// {"level":"info","message":"Entity created","category":"app.entity","timestamp":"2026-03-25T10:00:00.000Z"}
|
|
73
|
+
|
|
74
|
+
// Human-readable -- optional ANSI colors, compact metadata
|
|
75
|
+
createPrettyFormatter();
|
|
76
|
+
// 10:00:00 INFO [app.entity] Entity created entityId=e1
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Hierarchical Category Filtering
|
|
80
|
+
|
|
81
|
+
Categories are dot-separated. Level resolution walks up the hierarchy until a match is found:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const logger = createLogger({
|
|
85
|
+
name: 'app.db.queries',
|
|
86
|
+
level: 'info', // global fallback
|
|
87
|
+
levels: {
|
|
88
|
+
app: 'info',
|
|
89
|
+
'app.db': 'debug', // matches "app.db.queries"
|
|
90
|
+
'app.http': 'warn',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Resolution for `"app.db.queries"`: check exact match, then `"app.db"` (found: `"debug"`), then `"app"`, then `config.level`, then `TRAILS_LOG_LEVEL` env var, then `"info"`.
|
|
96
|
+
|
|
97
|
+
### Child Loggers
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const child = logger.child({ requestId: 'abc-123', trail: 'entity.show' });
|
|
101
|
+
child.info('Processing');
|
|
102
|
+
// Every log record from this child includes requestId and trail metadata
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Children inherit the parent's sinks, level config, and redaction. They share the parent's sink pipeline.
|
|
106
|
+
|
|
107
|
+
### Redaction
|
|
108
|
+
|
|
109
|
+
Sensitive data is automatically stripped before any sink dispatch. Uses `@ontrails/core/redaction` under the hood.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const logger = createLogger({
|
|
113
|
+
name: 'app',
|
|
114
|
+
redaction: {
|
|
115
|
+
patterns: [/custom-secret-\w+/g],
|
|
116
|
+
sensitiveKeys: ['password', 'internalToken'],
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
logger.info('Auth', { user: 'admin', password: 'hunter2' });
|
|
121
|
+
// password is redacted: "[REDACTED]"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Environment Configuration
|
|
125
|
+
|
|
126
|
+
Log level can be set via environment:
|
|
127
|
+
|
|
128
|
+
1. Explicit `config.level` (highest priority)
|
|
129
|
+
2. `config.levels` hierarchy
|
|
130
|
+
3. `TRAILS_LOG_LEVEL` env var
|
|
131
|
+
4. `TRAILS_ENV` profile defaults (`development` = `"debug"`, `test` = silent)
|
|
132
|
+
5. Fallback: `"info"`
|
|
133
|
+
|
|
134
|
+
### LogTape Adapter (`@ontrails/logging/logtape`)
|
|
135
|
+
|
|
136
|
+
Bridge Trails logging to an existing LogTape infrastructure:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { logtapeSink } from '@ontrails/logging/logtape';
|
|
140
|
+
import { getLogger } from '@logtape/logtape';
|
|
141
|
+
|
|
142
|
+
const logger = createLogger({
|
|
143
|
+
name: 'app',
|
|
144
|
+
sinks: [logtapeSink({ logger: getLogger('app') })],
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`@logtape/logtape` is an optional peer dependency. The main package does not depend on it.
|
|
149
|
+
|
|
150
|
+
## Subpath Exports
|
|
151
|
+
|
|
152
|
+
| Export | Contents |
|
|
153
|
+
| --- | --- |
|
|
154
|
+
| `@ontrails/logging` | `createLogger`, `createConsoleSink`, `createFileSink`, `createJsonFormatter`, `createPrettyFormatter`, level resolution |
|
|
155
|
+
| `@ontrails/logging/logtape` | `logtapeSink` adapter (requires `@logtape/logtape` peer) |
|
|
156
|
+
|
|
157
|
+
## Further Reading
|
|
158
|
+
|
|
159
|
+
- [Getting Started](../../docs/getting-started.md)
|
|
160
|
+
- [Architecture](../../docs/architecture.md)
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LogLevel } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve log level from environment variables.
|
|
4
|
+
*
|
|
5
|
+
* 1. `TRAILS_LOG_LEVEL` -- explicit override (if valid).
|
|
6
|
+
* 2. `TRAILS_ENV` profile defaults:
|
|
7
|
+
* - `development` -> `"debug"`
|
|
8
|
+
* - `test` -> `undefined` (no logging by default)
|
|
9
|
+
* - `production` -> `undefined` (caller falls through to `"info"`)
|
|
10
|
+
* 3. `undefined` -- no env-based level configured.
|
|
11
|
+
*/
|
|
12
|
+
export declare const resolveLogLevel: (env?: Record<string, string | undefined>) => LogLevel | undefined;
|
|
13
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAe3C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACvC,QAAQ,GAAG,SAoBb,CAAC"}
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { LEVEL_PRIORITY } from './levels.js';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Valid log level set (for validation)
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
const VALID_LEVELS = new Set(Object.keys(LEVEL_PRIORITY));
|
|
6
|
+
const isValidLogLevel = (value) => VALID_LEVELS.has(value);
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// resolveLogLevel
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
/**
|
|
11
|
+
* Resolve log level from environment variables.
|
|
12
|
+
*
|
|
13
|
+
* 1. `TRAILS_LOG_LEVEL` -- explicit override (if valid).
|
|
14
|
+
* 2. `TRAILS_ENV` profile defaults:
|
|
15
|
+
* - `development` -> `"debug"`
|
|
16
|
+
* - `test` -> `undefined` (no logging by default)
|
|
17
|
+
* - `production` -> `undefined` (caller falls through to `"info"`)
|
|
18
|
+
* 3. `undefined` -- no env-based level configured.
|
|
19
|
+
*/
|
|
20
|
+
export const resolveLogLevel = (env) => {
|
|
21
|
+
const source = env ?? process.env;
|
|
22
|
+
// 1. Explicit override
|
|
23
|
+
const explicit = source['TRAILS_LOG_LEVEL'];
|
|
24
|
+
if (explicit !== undefined && isValidLogLevel(explicit)) {
|
|
25
|
+
return explicit;
|
|
26
|
+
}
|
|
27
|
+
// 2. Profile defaults
|
|
28
|
+
const profile = source['TRAILS_ENV'];
|
|
29
|
+
if (profile === 'development') {
|
|
30
|
+
return 'debug';
|
|
31
|
+
}
|
|
32
|
+
if (profile === 'test') {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
// production and everything else -- no opinion
|
|
36
|
+
return undefined;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=env.js.map
|
package/dist/env.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;AAElE,MAAM,eAAe,GAAG,CAAC,KAAa,EAAqB,EAAE,CAC3D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAE1B,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAwC,EAClB,EAAE;IACxB,MAAM,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAElC,uBAAuB;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,QAAQ,KAAK,SAAS,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,sBAAsB;IACtB,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+CAA+C;IAC/C,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LogFormatter, PrettyFormatterOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* One JSON object per log record, newline-delimited.
|
|
4
|
+
* Metadata fields are flattened into the top-level object.
|
|
5
|
+
*/
|
|
6
|
+
export declare const createJsonFormatter: () => LogFormatter;
|
|
7
|
+
export declare const createPrettyFormatter: (options?: PrettyFormatterOptions) => LogFormatter;
|
|
8
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEZ,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAO,YAYrC,CAAC;AAoDH,eAAO,MAAM,qBAAqB,GAChC,UAAU,sBAAsB,KAC/B,YAoBF,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// JSON Formatter
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* One JSON object per log record, newline-delimited.
|
|
6
|
+
* Metadata fields are flattened into the top-level object.
|
|
7
|
+
*/
|
|
8
|
+
export const createJsonFormatter = () => ({
|
|
9
|
+
format(record) {
|
|
10
|
+
const { level, message, category, timestamp, metadata } = record;
|
|
11
|
+
const obj = {
|
|
12
|
+
category,
|
|
13
|
+
level,
|
|
14
|
+
message,
|
|
15
|
+
timestamp: timestamp.toISOString(),
|
|
16
|
+
...metadata,
|
|
17
|
+
};
|
|
18
|
+
return JSON.stringify(obj);
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Pretty Formatter
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
const LEVEL_COLORS = {
|
|
25
|
+
debug: '\u001B[36m',
|
|
26
|
+
error: '\u001B[31m',
|
|
27
|
+
fatal: '\u001B[35m',
|
|
28
|
+
info: '\u001B[32m',
|
|
29
|
+
trace: '\u001B[90m',
|
|
30
|
+
warn: '\u001B[33m',
|
|
31
|
+
};
|
|
32
|
+
const RESET = '\u001B[0m';
|
|
33
|
+
const formatMetadata = (metadata) => {
|
|
34
|
+
const entries = Object.entries(metadata);
|
|
35
|
+
if (entries.length === 0) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
return ` ${entries
|
|
39
|
+
.map(([k, v]) => {
|
|
40
|
+
const display = typeof v === 'string' ? v : JSON.stringify(v);
|
|
41
|
+
return `${k}=${display}`;
|
|
42
|
+
})
|
|
43
|
+
.join(' ')}`;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Human-readable formatter.
|
|
47
|
+
*
|
|
48
|
+
* Output: `10:00:00 INFO [app.entity] Entity created requestId=abc-123`
|
|
49
|
+
*/
|
|
50
|
+
const formatTimestamp = (timestamp) => `${timestamp.toISOString().slice(11, 19)} `;
|
|
51
|
+
const formatLevelAndMessage = (level, levelLabel, category, message, useColors) => {
|
|
52
|
+
if (useColors) {
|
|
53
|
+
const color = LEVEL_COLORS[level] ?? '';
|
|
54
|
+
return `${color}${levelLabel}${RESET} [${category}] ${message}`;
|
|
55
|
+
}
|
|
56
|
+
return `${levelLabel} [${category}] ${message}`;
|
|
57
|
+
};
|
|
58
|
+
export const createPrettyFormatter = (options) => {
|
|
59
|
+
const showTimestamps = options?.timestamps !== false;
|
|
60
|
+
const useColors = options?.colors ?? process.stdout?.isTTY === true;
|
|
61
|
+
return {
|
|
62
|
+
format(record) {
|
|
63
|
+
const { level, message, category, timestamp, metadata } = record;
|
|
64
|
+
const levelLabel = level.toUpperCase().padEnd(5);
|
|
65
|
+
const meta = formatMetadata(metadata);
|
|
66
|
+
const prefix = showTimestamps ? formatTimestamp(timestamp) : '';
|
|
67
|
+
const body = formatLevelAndMessage(level, levelLabel, category, message, useColors);
|
|
68
|
+
return meta.length > 0 ? `${prefix}${body}${meta}` : `${prefix}${body}`;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createLogger } from './logger.js';
|
|
2
|
+
export type { Logger } from '@ontrails/core';
|
|
3
|
+
export { createConsoleSink, createFileSink } from './sinks.js';
|
|
4
|
+
export { createJsonFormatter, createPrettyFormatter } from './formatters.js';
|
|
5
|
+
export { resolveLogLevel } from './env.js';
|
|
6
|
+
export { LEVEL_PRIORITY, shouldLog, resolveCategory } from './levels.js';
|
|
7
|
+
export type { LogLevel, LogMetadata, LogRecord, LoggerConfig, LogSink, LogFormatter, ConsoleSinkOptions, FileSinkOptions, PrettyFormatterOptions, } from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGzE,YAAY,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Logger
|
|
2
|
+
export { createLogger } from './logger.js';
|
|
3
|
+
// Sinks and formatters
|
|
4
|
+
export { createConsoleSink, createFileSink } from './sinks.js';
|
|
5
|
+
export { createJsonFormatter, createPrettyFormatter } from './formatters.js';
|
|
6
|
+
// Level resolution
|
|
7
|
+
export { resolveLogLevel } from './env.js';
|
|
8
|
+
// Levels
|
|
9
|
+
export { LEVEL_PRIORITY, shouldLog, resolveCategory } from './levels.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,uBAAuB;AACvB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,mBAAmB;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/levels.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LogLevel } from './types.js';
|
|
2
|
+
export declare const LEVEL_PRIORITY: Record<LogLevel, number>;
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if a message at `messageLevel` should be emitted given the
|
|
5
|
+
* configured threshold `configuredLevel`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const shouldLog: (messageLevel: LogLevel, configuredLevel: LogLevel) => boolean;
|
|
8
|
+
export declare const resolveCategory: (name: string, levels: Record<string, LogLevel> | undefined, fallback: LogLevel) => LogLevel;
|
|
9
|
+
//# sourceMappingURL=levels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"levels.d.ts","sourceRoot":"","sources":["../src/levels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAM3C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAQnD,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS,GACpB,cAAc,QAAQ,EACtB,iBAAiB,QAAQ,KACxB,OAA0E,CAAC;AAgC9E,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,EAC5C,UAAU,QAAQ,KACjB,QAKF,CAAC"}
|
package/dist/levels.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Level Priority
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
export const LEVEL_PRIORITY = {
|
|
5
|
+
debug: 1,
|
|
6
|
+
error: 4,
|
|
7
|
+
fatal: 5,
|
|
8
|
+
info: 2,
|
|
9
|
+
silent: 6,
|
|
10
|
+
trace: 0,
|
|
11
|
+
warn: 3,
|
|
12
|
+
};
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// shouldLog
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/**
|
|
17
|
+
* Returns true if a message at `messageLevel` should be emitted given the
|
|
18
|
+
* configured threshold `configuredLevel`.
|
|
19
|
+
*/
|
|
20
|
+
export const shouldLog = (messageLevel, configuredLevel) => LEVEL_PRIORITY[messageLevel] >= LEVEL_PRIORITY[configuredLevel];
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// resolveCategory
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Walk up the dot-separated category hierarchy to find the most specific
|
|
26
|
+
* configured level.
|
|
27
|
+
*
|
|
28
|
+
* Example: "app.db.queries" -> "app.db" -> "app" -> fallback
|
|
29
|
+
*/
|
|
30
|
+
/** Walk up the dot-separated hierarchy looking for a configured level. */
|
|
31
|
+
const findLevel = (name, levels) => {
|
|
32
|
+
let prefix = name;
|
|
33
|
+
while (prefix.length > 0) {
|
|
34
|
+
const level = levels[prefix];
|
|
35
|
+
if (level !== undefined) {
|
|
36
|
+
return level;
|
|
37
|
+
}
|
|
38
|
+
const lastDot = prefix.lastIndexOf('.');
|
|
39
|
+
if (lastDot === -1) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
prefix = prefix.slice(0, lastDot);
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
};
|
|
46
|
+
export const resolveCategory = (name, levels, fallback) => {
|
|
47
|
+
if (!levels) {
|
|
48
|
+
return fallback;
|
|
49
|
+
}
|
|
50
|
+
return findLevel(name, levels) ?? fallback;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=levels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"levels.js","sourceRoot":"","sources":["../src/levels.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,YAAsB,EACtB,eAAyB,EAChB,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC,IAAI,cAAc,CAAC,eAAe,CAAC,CAAC;AAE9E,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;GAKG;AACH,0EAA0E;AAC1E,MAAM,SAAS,GAAG,CAChB,IAAY,EACZ,MAAgC,EACV,EAAE;IACxB,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM;QACR,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,IAAY,EACZ,MAA4C,EAC5C,QAAkB,EACR,EAAE;IACZ,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ,CAAC;AAC7C,CAAC,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Logger } from '@ontrails/core';
|
|
2
|
+
import type { LoggerConfig } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create a structured logger with hierarchical category filtering,
|
|
5
|
+
* automatic redaction, and pluggable sinks.
|
|
6
|
+
*
|
|
7
|
+
* This is the **only** API for creating loggers in `@ontrails/logging`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const createLogger: (config: LoggerConfig) => Logger;
|
|
10
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAK7C,OAAO,KAAK,EAGV,YAAY,EAGb,MAAM,YAAY,CAAC;AAwFpB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,KAAG,MAuBnD,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createRedactor, DEFAULT_PATTERNS, DEFAULT_SENSITIVE_KEYS, } from '@ontrails/core/redaction';
|
|
2
|
+
import { resolveLogLevel } from './env.js';
|
|
3
|
+
import { resolveCategory, shouldLog } from './levels.js';
|
|
4
|
+
import { createConsoleSink } from './sinks.js';
|
|
5
|
+
const buildInstance = (name, effectiveLevel, redactor, sinks,
|
|
6
|
+
// oxlint-disable-next-line only-used-in-recursion
|
|
7
|
+
config, baseMetadata) => {
|
|
8
|
+
const log = (level, message, metadata) => {
|
|
9
|
+
if (!shouldLog(level, effectiveLevel)) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const mergedMeta = {
|
|
13
|
+
...baseMetadata,
|
|
14
|
+
...metadata,
|
|
15
|
+
};
|
|
16
|
+
const record = {
|
|
17
|
+
category: name,
|
|
18
|
+
level,
|
|
19
|
+
message: redactor.redact(message),
|
|
20
|
+
metadata: Object.keys(mergedMeta).length > 0
|
|
21
|
+
? redactor.redactObject(mergedMeta)
|
|
22
|
+
: {},
|
|
23
|
+
timestamp: new Date(),
|
|
24
|
+
};
|
|
25
|
+
for (const sink of sinks) {
|
|
26
|
+
sink.write(record);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
child(metadata) {
|
|
31
|
+
return buildInstance(name, effectiveLevel, redactor, sinks, config, {
|
|
32
|
+
...baseMetadata,
|
|
33
|
+
...metadata,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
debug(message, metadata) {
|
|
37
|
+
log('debug', message, metadata);
|
|
38
|
+
},
|
|
39
|
+
error(message, metadata) {
|
|
40
|
+
log('error', message, metadata);
|
|
41
|
+
},
|
|
42
|
+
fatal(message, metadata) {
|
|
43
|
+
log('fatal', message, metadata);
|
|
44
|
+
},
|
|
45
|
+
info(message, metadata) {
|
|
46
|
+
log('info', message, metadata);
|
|
47
|
+
},
|
|
48
|
+
name,
|
|
49
|
+
trace(message, metadata) {
|
|
50
|
+
log('trace', message, metadata);
|
|
51
|
+
},
|
|
52
|
+
warn(message, metadata) {
|
|
53
|
+
log('warn', message, metadata);
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// createLogger
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
/**
|
|
61
|
+
* Create a structured logger with hierarchical category filtering,
|
|
62
|
+
* automatic redaction, and pluggable sinks.
|
|
63
|
+
*
|
|
64
|
+
* This is the **only** API for creating loggers in `@ontrails/logging`.
|
|
65
|
+
*/
|
|
66
|
+
export const createLogger = (config) => {
|
|
67
|
+
const envLevel = resolveLogLevel();
|
|
68
|
+
const baseLevel = config.level ?? envLevel ?? 'info';
|
|
69
|
+
const effectiveLevel = resolveCategory(config.name, config.levels, baseLevel);
|
|
70
|
+
const redactor = createRedactor({
|
|
71
|
+
patterns: [...DEFAULT_PATTERNS, ...(config.redaction?.patterns ?? [])],
|
|
72
|
+
sensitiveKeys: [
|
|
73
|
+
...DEFAULT_SENSITIVE_KEYS,
|
|
74
|
+
...(config.redaction?.sensitiveKeys ?? []),
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
const sinks = config.sinks ?? [createConsoleSink()];
|
|
78
|
+
return buildInstance(config.name, effectiveLevel, redactor, sinks, { baseLevel, levels: config.levels }, {});
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LogSink } from '../types.js';
|
|
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 adapter 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/logtape/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,OAAO,EAAE,MAAM,aAAa,CAAC;AAMtD;;;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"}
|
|
@@ -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 adapter 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/logtape/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/dist/sinks.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConsoleSinkOptions, FileSinkOptions, LogSink } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Sink that writes to `console.*` methods.
|
|
4
|
+
*
|
|
5
|
+
* By default, uses `createPrettyFormatter()` when `TRAILS_ENV` is
|
|
6
|
+
* `"development"` and `createJsonFormatter()` otherwise.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createConsoleSink: (options?: ConsoleSinkOptions) => LogSink;
|
|
9
|
+
/**
|
|
10
|
+
* Sink that appends log records to a file using `Bun.file()`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const createFileSink: (options: FileSinkOptions) => LogSink;
|
|
13
|
+
//# sourceMappingURL=sinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinks.d.ts","sourceRoot":"","sources":["../src/sinks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EAEf,OAAO,EACR,MAAM,YAAY,CAAC;AAepB;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,kBAAkB,KAAG,OAoBhE,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,eAAe,KAAG,OAczD,CAAC"}
|