@glassops/scribe 1.0.1 → 1.0.3

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
@@ -20,35 +20,42 @@ This ensures production, staging, and development never collide, and that multi
20
20
  ### Structured, operationally meaningful logs
21
21
 
22
22
  - JSON‑structured entries with timestamps.
23
- - Dailyrotated files with configurable retention.
24
- - Semantic log levels (critical, change, http, etc.) mapped to dedicated transports.
25
- - Requestscoped metadata (tenant, service, environment, user, correlationId, requestId).
23
+ - Daily-rotated files with configurable retention (default: 14 days).
24
+ - Semantic log levels (`critical`, `change`, `http`, etc.) mapped to dedicated transports.
25
+ - Request-scoped metadata (`tenant`, `service`, `environment`, `user`, `correlationId`, `requestId`).
26
26
 
27
27
  ### Deep, case‑insensitive redaction
28
28
 
29
29
  Sensitive keys are removed at any depth, regardless of casing:
30
30
 
31
- - password, Password, PASSWORD.
32
- - authorization, Authorization, etc.
31
+ - `password`, `Password`, `PASSWORD`
32
+ - `authorization`, `Authorization`, etc.
33
33
 
34
- Circular references become "[Circular]". Buffers become "[Binary]".
34
+ Other behaviors:
35
+
36
+ - Circular references → `"[Circular]"`
37
+ - Buffers → `"[Binary]"`
35
38
 
36
39
  ### Transport‑agnostic architecture
37
40
 
38
41
  File transports are enabled by default, but Scribe supports:
39
42
 
40
- - Console‑only mode.
41
- - Cloud‑only mode.
42
- - Hybrid mode.
43
+ - Console‑only mode
44
+ - Cloud‑only mode
45
+ - Hybrid mode
43
46
 
44
- Using:
47
+ Configurable through:
45
48
 
46
49
  - `disableFileTransports`
47
50
  - `extraTransports`
48
51
 
49
52
  ### Pure, re‑entrant API
50
53
 
51
- No global state, no shared mutable configuration, no hidden defaults. Every logger instance is fully deterministic and scoped.
54
+ - No global state
55
+ - No shared mutable configuration
56
+ - No hidden defaults
57
+
58
+ Every logger instance is fully deterministic and scoped.
52
59
 
53
60
  ## Installation
54
61
 
@@ -60,18 +67,16 @@ npm install @glassops/scribe
60
67
 
61
68
  Scribe is built around three principles:
62
69
 
63
- - Identity is explicit every log entry carries a complete scope describing tenant, environment, service, and correlation identifiers.
64
- - Streams are semantic — incidents, changes, HTTP traffic, and application logs are treated as distinct operational categories.
65
- - Safety is mandatory — redaction, sanitization, and directory grammar are enforced before logs reach any transport.
70
+ - **Identity is explicit**: Every log entry carries a complete scope describing tenant, environment, service, and correlation identifiers.
71
+ - **Streams are semantic**: Incidents, changes, HTTP traffic, and application logs are treated as distinct operational categories.
72
+ - **Safety is mandatory**: Redaction, sanitization, and directory grammar are enforced before logs reach any transport.
66
73
 
67
74
  ## Directory structure
68
75
 
69
- Scribe derives the log directory from the LoggerScope:
76
+ All segments of the directory path are sanitized to prevent traversal or invalid characters.
70
77
 
71
- With service: `<target>/<service>/<tenant>`
72
- Without service: `<target>/<tenant>/<environment>`
73
-
74
- All segments are sanitized to prevent traversal or invalid characters.
78
+ - With service: `<target>/<service>/<tenant>`
79
+ - Without service: `<target>/<tenant>/<environment>`
75
80
 
76
81
  ## Usage
77
82
 
@@ -92,20 +97,24 @@ const directory = createDirectory("/var/logs", {
92
97
  ```ts
93
98
  import { createLogger } from "@glassops/scribe";
94
99
 
95
- const logger = createLogger(directory, {
96
- tenant: "acme",
97
- environment: "production",
98
- service: "billing",
99
- correlationId: "abc123",
100
- }, {
101
- level: "info",
102
- requestLog: "requests-%DATE%.log",
103
- appLog: "app-%DATE%.log",
104
- incidentLog: "incident-%DATE%.log",
105
- changeLog: "change-%DATE%.log",
106
- logToConsole: true,
107
- sensitiveKeys: ["password", "token"],
108
- });
100
+ const logger = createLogger(
101
+ directory,
102
+ {
103
+ tenant: "acme",
104
+ environment: "production",
105
+ service: "billing",
106
+ correlationId: "abc123",
107
+ },
108
+ {
109
+ level: "info",
110
+ requestLog: "requests-%DATE%.log",
111
+ appLog: "app-%DATE%.log",
112
+ incidentLog: "incident-%DATE%.log",
113
+ changeLog: "change-%DATE%.log",
114
+ logToConsole: true,
115
+ sensitiveKeys: ["password", "token"],
116
+ }
117
+ );
109
118
  ```
110
119
 
111
120
  ## Logging methods
@@ -124,47 +133,62 @@ Example:
124
133
  ```ts
125
134
  logger.logInfo("User updated profile", {
126
135
  userId: "123",
127
- password: "secret", // redacted
136
+ password: "secret", // redacted automatically
128
137
  });
129
138
  ```
130
139
 
131
140
  ## HTTP logging (Morgan integration)
132
141
 
142
+ Scribe supports direct integration with Morgan. ANSI sequences are stripped before writing to ensure clean JSON logs:
143
+
133
144
  ```ts
134
145
  app.use(morgan("combined", { stream: logger.createLoggerStream() }));
135
146
  ```
136
147
 
137
- ANSI sequences are stripped before writing, ensuring clean machine‑readable logs.
138
-
139
148
  ## Redaction behavior
140
149
 
141
- Scribe removes sensitive keys at any depth:
150
+ - Case-insensitive key matching
151
+ - Nested sensitive fields are recursively redacted
152
+ - **Circular references**: `"[Circular]"`
153
+ - **Buffers**: `"[Binary]"`
154
+
155
+ ## Scoping
156
+
157
+ You can derive a new logger with additional metadata:
142
158
 
143
159
  ```ts
144
- {
145
- password: "[REDACTED]",
146
- nested: {
147
- token: "[REDACTED]"
148
- }
149
- }
160
+ const userLogger = await logger.scope({ user: "steven" });
161
+ userLogger.logInfo("User action");
150
162
  ```
151
163
 
152
- - Case‑insensitive matching
153
- - Circular references → "[Circular]"
154
- - Buffers → "[Binary]"
164
+ Produces a new logger instance with merged scope. Logger directory may change if scope affects service or environment.
155
165
 
156
- ## Scoping
166
+ Existing transports are closed and rebuilt automatically if necessary.
157
167
 
158
- You can derive a new logger with additional metadata:
159
- const userLogger = logger.scope({ user: "steven" });
160
- userLogger.logInfo("User action");
168
+ ## Logger API
169
+
170
+ ```ts
171
+ interface ScribeLogger {
172
+ logError(error: string | Error, context?: Record<string, unknown>): void;
173
+ logWarn(message: string, context?: Record<string, unknown>): void;
174
+ logInfo(message: string, context?: Record<string, unknown>): void;
175
+ logDebug(message: string, context?: Record<string, unknown>): void;
176
+ logIncident(message: string, context?: Record<string, unknown>): void;
177
+ logChange(message: string, context?: Record<string, unknown>): void;
178
+ createLoggerStream(): { write: (message: string) => void };
179
+ scope(partial: Partial<LoggerScope>): Promise<void>;
180
+ close(): Promise<void>;
181
+ logger: Logger;
182
+ }
183
+ ```
161
184
 
162
- This produces a new logger instance with merged scope.
185
+ - `createLoggerStream()`: Returns a Morgan-compatible writable stream.
186
+ - `scope()`: Returns a `Promise<void>`; merges partial metadata into current logger.
187
+ - `close()`: Gracefully shuts down transports.
188
+ - `logger`: Exposes underlying Winston Logger instance.
163
189
 
164
190
  ## Transport configuration
165
191
 
166
- Scribe supports file‑based, console‑only, cloud‑only, and hybrid modes.
167
-
168
192
  ```ts
169
193
  interface LoggerOptions {
170
194
  level: LogLevel;
@@ -175,7 +199,6 @@ interface LoggerOptions {
175
199
  logToConsole?: boolean;
176
200
  sensitiveKeys?: string[];
177
201
  retention?: string;
178
-
179
202
  disableFileTransports?: boolean;
180
203
  extraTransports?: Transport[];
181
204
  }
@@ -191,11 +214,13 @@ interface LoggerOptions {
191
214
  - `change`
192
215
  - `debug`
193
216
 
217
+ Each level is treated as a separate operational stream rather than a severity threshold.
218
+
194
219
  ## Build and publish
195
220
 
196
- Scribe uses a strict file whitelist and a deterministic build pipeline.
221
+ Scribe uses a strict file whitelist and deterministic build pipeline.
197
222
 
198
- ## Scripts
223
+ ### Scripts
199
224
 
200
225
  ```json
201
226
  {
@@ -207,13 +232,13 @@ Scribe uses a strict file whitelist and a deterministic build pipeline.
207
232
  }
208
233
  ```
209
234
 
210
- Prepack ensures `dist/` is always built before:
235
+ Prepack ensures dist/ is always built before:
211
236
 
212
237
  - `npm publish`
213
238
  - `npm publish --dry-run`
214
239
  - `npm pack`
215
240
 
216
- Files included in the package
241
+ Files included in the package:
217
242
 
218
243
  ```json
219
244
  {
@@ -221,29 +246,21 @@ Files included in the package
221
246
  }
222
247
  ```
223
248
 
224
- This guarantees only compiled output and documentation are published.
249
+ Guarantees only compiled output and documentation are published.
225
250
 
226
251
  ## Design rationale
227
252
 
228
- - Directory grammar prevents crossenvironment and crosstenant collisions.
253
+ - Directory grammar prevents cross-environment and cross-tenant collisions.
229
254
  - Semantic log levels allow operational tooling to treat incidents, changes, and HTTP traffic as distinct streams.
230
- - Deep, caseinsensitive redaction prevents credential leakage.
231
- - Pure, reentrant API ensures deterministic behavior across multitenant and multiservice deployments.
255
+ - Deep, case-insensitive redaction prevents credential leakage.
256
+ - Pure, re-entrant API ensures deterministic behavior across multi-tenant and multi-service deployments.
232
257
  - Daily rotation keeps log files predictable for ingestion pipelines.
233
- - Transportagnostic design supports file, console, cloud, and hybrid logging.
258
+ - Transport-agnostic design supports file, console, cloud, and hybrid logging.
234
259
 
235
260
  ## License
236
261
 
237
262
  Copyright [2026] [GlassOps Limited]
238
263
 
239
- Licensed under the Apache License, Version 2.0 (the ["License"](LICENSE));
240
- you may not use this file except in compliance with the License.
241
- You may obtain a copy of the License at
242
-
243
- <http://www.apache.org/licenses/LICENSE-2.0>
264
+ Licensed under the Apache License, Version 2.0 (["License"](LICENSE)).
244
265
 
245
- Unless required by applicable law or agreed to in writing, software
246
- distributed under the License is distributed on an "AS IS" BASIS,
247
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
248
- See the License for the specific language governing permissions and
249
- limitations under the License.
266
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
@@ -4,7 +4,7 @@
4
4
  |* provided LoggerScope. This is the only step containing
5
5
  |* side-effects in Scribe's initialization flow.
6
6
  \* -------------------------------------------------------------------------- */
7
- import type { LoggerScope } from "./types.js";
7
+ import type { LoggerScope } from './types.js';
8
8
  /**
9
9
  * Resolves and creates the directory where log files will be written.
10
10
  *
@@ -1 +1 @@
1
- {"version":3,"file":"create-directory.d.ts","sourceRoot":"","sources":["../src/create-directory.ts"],"names":[],"mappings":"AAAA;;;;;gFAKgF;AAWhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,OAAO,WAAW,WAoBjE,CAAC"}
1
+ {"version":3,"file":"create-directory.d.ts","sourceRoot":"","sources":["../src/create-directory.ts"],"names":[],"mappings":"AAAA;;;;;gFAKgF;AAWhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,OAAO,WAAW,WA2BjE,CAAC"}
@@ -7,9 +7,9 @@
7
7
  /* --------------------------------------------------------------------------
8
8
  |* NPM Dependencies
9
9
  \* -------------------------------------------------------------------------- */
10
- import fs from "fs";
11
- import path from "path";
12
- import { safe } from "./utilities.js";
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ import { safe } from './utilities.js';
13
13
  /* -------------------------------------------------------------------------- *\
14
14
  |* Create Directory
15
15
  \* -------------------------------------------------------------------------- */
@@ -25,14 +25,18 @@ import { safe } from "./utilities.js";
25
25
  */
26
26
  export const createDirectory = (target, scope) => {
27
27
  if (!target)
28
- throw new Error("Invalid log directory");
28
+ throw new Error('Invalid log directory');
29
29
  const { tenant, environment, service } = scope;
30
30
  if (!tenant || !environment) {
31
- throw new Error("LoggerScope must include tenant and environment");
31
+ throw new Error('LoggerScope must include tenant and environment');
32
32
  }
33
- const directory = service
34
- ? path.join(target, safe(service), safe(tenant))
35
- : path.join(target, safe(tenant), safe(environment));
33
+ const base = path.resolve(target);
34
+ const segmentA = service ? safe(service) : safe(tenant);
35
+ const segmentB = service ? safe(tenant) : safe(environment);
36
+ if (!segmentA || !segmentB) {
37
+ throw new Error('Invalid directory segment after sanitization');
38
+ }
39
+ const directory = path.join(base, segmentA, segmentB);
36
40
  try {
37
41
  fs.mkdirSync(directory, { recursive: true });
38
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create-directory.js","sourceRoot":"","sources":["../src/create-directory.ts"],"names":[],"mappings":"AAAA;;;;;gFAKgF;AAEhF;;gFAEgF;AAChF,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAMxB,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC;;gFAEgF;AAChF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,KAAkB,EAAE,EAAE;IAClE,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEtD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAE/C,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,SAAS,GAAG,OAAO;QACrB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAEzD,IAAI,CAAC;QACD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,IAAI,KAAK,CAAC,mCAAmC,SAAS,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC"}
1
+ {"version":3,"file":"create-directory.js","sourceRoot":"","sources":["../src/create-directory.ts"],"names":[],"mappings":"AAAA;;;;;gFAKgF;AAEhF;;gFAEgF;AAChF,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAMxB,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC;;gFAEgF;AAChF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,KAAkB,EAAE,EAAE;IAClE,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEtD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAE/C,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAElC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAE5D,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEtD,IAAI,CAAC;QACD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,IAAI,KAAK,CAAC,mCAAmC,SAAS,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC"}
@@ -1,5 +1,5 @@
1
- import winston from "winston";
2
- import type { LoggerOptions, LoggerScope } from "./types.js";
1
+ import winston from 'winston';
2
+ import type { LoggerOptions, LoggerScope } from './types.js';
3
3
  /**
4
4
  * Creates a fully configured Winston logger with:
5
5
  *
@@ -14,7 +14,7 @@ import type { LoggerOptions, LoggerScope } from "./types.js";
14
14
  * `logError`, `logIncident`, etc.), a Morgan-compatible HTTP stream, and a
15
15
  * `scope()` method for deriving new loggers with extended metadata.
16
16
  */
17
- export declare const createLogger: (directory: string, scope: LoggerScope, options: LoggerOptions) => {
17
+ export declare const createLogger: (targetDirectory: string, scope: LoggerScope, options: LoggerOptions) => {
18
18
  logError: (error: string | Error, context?: Record<string, unknown>) => void;
19
19
  logWarn: (message: string, context?: Record<string, unknown>) => void;
20
20
  logInfo: (message: string, context?: Record<string, unknown>) => void;
@@ -24,7 +24,8 @@ export declare const createLogger: (directory: string, scope: LoggerScope, optio
24
24
  createLoggerStream: () => {
25
25
  write: (message: string) => void;
26
26
  };
27
- scope: (partial: Partial<LoggerScope>) => /*elided*/ any;
27
+ scope: (partial: Partial<LoggerScope>) => Promise<void>;
28
+ close: () => Promise<void>;
28
29
  logger: winston.Logger;
29
30
  };
30
31
  //# sourceMappingURL=create-logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-logger.d.ts","sourceRoot":"","sources":["../src/create-logger.ts"],"names":[],"mappings":"AAUA,OAAO,OAAO,MAAM,SAAS,CAAC;AAO9B,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAmCvE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GACrB,WAAW,MAAM,EACjB,OAAO,WAAW,EAClB,SAAS,aAAa;sBAkJP,MAAM,GAAG,KAAK,YACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;uBAGjB,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;uBAGxC,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;wBAGvC,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;2BAGrC,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;yBAG1C,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;yBAIxC,MAAM;;qBAaV,OAAO,CAAC,WAAW,CAAC;;CAK5C,CAAC"}
1
+ {"version":3,"file":"create-logger.d.ts","sourceRoot":"","sources":["../src/create-logger.ts"],"names":[],"mappings":"AAUA,OAAO,OAAO,MAAM,SAAS,CAAC;AAO9B,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAoCvE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GACrB,iBAAiB,MAAM,EACvB,OAAO,WAAW,EAClB,SAAS,aAAa;sBAwKA,MAAM,GAAG,KAAK,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;uBAG/C,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;uBAGxC,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;wBAGvC,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;2BAGrC,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;yBAG1C,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;yBAIxC,MAAM;;qBA1CK,OAAO,CAAC,WAAW,CAAC;;;CAsD3D,CAAC"}
@@ -1,7 +1,8 @@
1
- import DailyRotateFile from "winston-daily-rotate-file";
2
- import winston from "winston";
1
+ import DailyRotateFile from 'winston-daily-rotate-file';
2
+ import winston from 'winston';
3
3
  const { combine, timestamp, errors, colorize, json } = winston.format;
4
- import { redact, stripAnsi } from "./utilities.js";
4
+ import { redact, stripAnsi } from './utilities.js';
5
+ import { createDirectory } from './create-directory.js';
5
6
  /* -------------------------------------------------------------------------- *\
6
7
  |* Initialize Variables
7
8
  \* -------------------------------------------------------------------------- */
@@ -21,13 +22,13 @@ const customLevels = Object.freeze({
21
22
  debug: 6,
22
23
  });
23
24
  const customColors = Object.freeze({
24
- critical: "magenta",
25
- error: "red",
26
- warn: "yellow",
27
- info: "green",
28
- http: "blue",
29
- change: "cyan",
30
- debug: "gray",
25
+ critical: 'magenta',
26
+ error: 'red',
27
+ warn: 'yellow',
28
+ info: 'green',
29
+ http: 'blue',
30
+ change: 'cyan',
31
+ debug: 'gray',
31
32
  });
32
33
  winston.addColors(customColors);
33
34
  /* -------------------------------------------------------------------------- *\
@@ -47,84 +48,84 @@ winston.addColors(customColors);
47
48
  * `logError`, `logIncident`, etc.), a Morgan-compatible HTTP stream, and a
48
49
  * `scope()` method for deriving new loggers with extended metadata.
49
50
  */
50
- export const createLogger = (directory, scope, options) => {
51
- const { tenant, service, environment, user, correlationId, requestId } = scope;
51
+ export const createLogger = (targetDirectory, scope, options) => {
52
+ let currentScope = { ...scope };
53
+ let currentDirectory = createDirectory(targetDirectory, currentScope);
54
+ let closed = false;
52
55
  const sensitiveKeys = [
53
- "password",
54
- "token",
55
- "secret",
56
- "authorization",
56
+ 'password',
57
+ 'token',
58
+ 'secret',
59
+ 'authorization',
57
60
  ...(options.sensitiveKeys ?? []),
58
61
  ];
59
- const retention = options.retention ?? "14d";
60
- const transports = [];
61
- if (!options.disableFileTransports) {
62
- transports.push(new DailyRotateFile({
63
- dirname: directory,
64
- filename: options.requestLog,
65
- datePattern: "YYYY-MM-DD",
66
- level: "http",
67
- zippedArchive: true,
68
- maxFiles: retention,
69
- format: combine(winston.format((log) => log.level === "http" ? log : false)(), timestamp(), json()),
70
- }));
71
- transports.push(new DailyRotateFile({
72
- dirname: directory,
73
- filename: options.appLog,
74
- datePattern: "YYYY-MM-DD",
75
- level: options.level,
76
- zippedArchive: true,
77
- maxFiles: retention,
78
- format: combine(errors({ stack: environment !== "production" }), timestamp(), json()),
79
- }));
80
- if (options.incidentLog) {
62
+ const retention = options.retention ?? '14d';
63
+ const buildTransports = (dir) => {
64
+ const transports = [];
65
+ if (!options.disableFileTransports) {
81
66
  transports.push(new DailyRotateFile({
82
- dirname: directory,
83
- filename: options.incidentLog,
84
- datePattern: "YYYY-MM-DD",
85
- level: "critical",
67
+ dirname: dir,
68
+ filename: options.requestLog,
69
+ datePattern: 'YYYY-MM-DD',
70
+ level: 'http',
86
71
  zippedArchive: true,
87
72
  maxFiles: retention,
88
- format: combine(winston.format((log) => log.level === "critical" ? log : false)(), timestamp(), json()),
73
+ format: combine(winston.format((log) => (log.level === 'http' ? log : false))(), timestamp(), json()),
89
74
  }));
90
- }
91
- if (options.changeLog) {
92
75
  transports.push(new DailyRotateFile({
93
- dirname: directory,
94
- filename: options.changeLog,
95
- datePattern: "YYYY-MM-DD",
96
- level: "change",
76
+ dirname: dir,
77
+ filename: options.appLog,
78
+ datePattern: 'YYYY-MM-DD',
79
+ level: options.level,
97
80
  zippedArchive: true,
98
81
  maxFiles: retention,
99
- format: combine(winston.format((log) => log.level === "change" ? log : false)(), timestamp(), json()),
82
+ format: combine(errors({ stack: scope.environment !== 'production' }), timestamp(), json()),
83
+ }));
84
+ if (options.incidentLog) {
85
+ transports.push(new DailyRotateFile({
86
+ dirname: dir,
87
+ filename: options.incidentLog,
88
+ datePattern: 'YYYY-MM-DD',
89
+ level: 'critical',
90
+ zippedArchive: true,
91
+ maxFiles: retention,
92
+ format: combine(winston.format((log) => (log.level === 'critical' ? log : false))(), timestamp(), json()),
93
+ }));
94
+ }
95
+ if (options.changeLog) {
96
+ transports.push(new DailyRotateFile({
97
+ dirname: dir,
98
+ filename: options.changeLog,
99
+ datePattern: 'YYYY-MM-DD',
100
+ level: 'change',
101
+ zippedArchive: true,
102
+ maxFiles: retention,
103
+ format: combine(winston.format((log) => (log.level === 'change' ? log : false))(), timestamp(), json()),
104
+ }));
105
+ }
106
+ }
107
+ if (options.logToConsole) {
108
+ transports.push(new winston.transports.Console({
109
+ format: combine(colorize(), timestamp()),
100
110
  }));
101
111
  }
102
- }
103
- if (options.logToConsole) {
104
- transports.push(new winston.transports.Console({
105
- format: combine(colorize(), timestamp()),
106
- }));
107
- }
108
- if (options.extraTransports?.length) {
109
- transports.push(...options.extraTransports);
110
- }
112
+ if (options.extraTransports?.length) {
113
+ transports.push(...options.extraTransports);
114
+ }
115
+ return transports;
116
+ };
111
117
  const loggerInstance = winston.createLogger({
112
118
  levels: customLevels,
113
119
  level: options.level,
114
- transports,
120
+ transports: buildTransports(currentDirectory),
115
121
  defaultMeta: {
116
- tenant,
117
- service,
118
- environment,
119
- user,
120
- correlationId,
121
- requestId,
122
+ ...currentScope,
122
123
  pid: process.pid,
123
124
  },
124
125
  });
125
126
  const log = (level, message, context = {}) => {
126
127
  const safeContext = redact(context, sensitiveKeys);
127
- const includeStack = environment !== "production";
128
+ const includeStack = currentScope.environment !== 'production';
128
129
  loggerInstance.log(level, message instanceof Error
129
130
  ? {
130
131
  message: message.message,
@@ -133,27 +134,47 @@ export const createLogger = (directory, scope, options) => {
133
134
  }
134
135
  : { message, ...safeContext });
135
136
  };
137
+ const close = async () => {
138
+ if (closed)
139
+ return;
140
+ closed = true;
141
+ await Promise.all(loggerInstance.transports.map((t) => new Promise((resolve) => {
142
+ t.on('finish', resolve);
143
+ t.end();
144
+ })));
145
+ loggerInstance.clear();
146
+ };
147
+ const scopeRebind = async (partial) => {
148
+ const newScope = { ...currentScope, ...partial };
149
+ const newDirectory = createDirectory(targetDirectory, newScope);
150
+ if (newDirectory !== currentDirectory) {
151
+ await close();
152
+ closed = false;
153
+ const newTransports = buildTransports(newDirectory);
154
+ newTransports.forEach((t) => loggerInstance.add(t));
155
+ currentDirectory = newDirectory;
156
+ }
157
+ currentScope = newScope;
158
+ loggerInstance.defaultMeta = { ...currentScope, pid: process.pid };
159
+ };
160
+ /* ----------------------------------------------------------------------
161
+ |* Return Public API
162
+ ---------------------------------------------------------------------- */
136
163
  return {
137
- logError: (error, context = {}) => log("error", error, context),
138
- logWarn: (message, context = {}) => log("warn", message, context),
139
- logInfo: (message, context = {}) => log("info", message, context),
140
- logDebug: (message, context = {}) => log("debug", message, context),
141
- logIncident: (message, context = {}) => log("critical", message, { category: "incident", ...context }),
142
- logChange: (message, context = {}) => log("change", message, { category: "change", ...context }),
164
+ logError: (error, context = {}) => log('error', error, context),
165
+ logWarn: (message, context = {}) => log('warn', message, context),
166
+ logInfo: (message, context = {}) => log('info', message, context),
167
+ logDebug: (message, context = {}) => log('debug', message, context),
168
+ logIncident: (message, context = {}) => log('critical', message, { category: 'incident', ...context }),
169
+ logChange: (message, context = {}) => log('change', message, { category: 'change', ...context }),
143
170
  createLoggerStream: () => ({
144
171
  write: (message) => {
145
- const clean = stripAnsi(message).replace(/\n$/, "");
146
- log("http", clean, {
147
- source: "morgan",
148
- service,
149
- tenant,
150
- environment,
151
- correlationId,
152
- requestId,
153
- });
172
+ const clean = stripAnsi(message).replace(/\n$/, '');
173
+ log('http', clean, { source: 'morgan', ...currentScope });
154
174
  },
155
175
  }),
156
- scope: (partial) => createLogger(directory, { ...scope, ...partial }, options),
176
+ scope: scopeRebind,
177
+ close,
157
178
  logger: loggerInstance,
158
179
  };
159
180
  };
@@ -1 +1 @@
1
- {"version":3,"file":"create-logger.js","sourceRoot":"","sources":["../src/create-logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-logger.js","sourceRoot":"","sources":["../src/create-logger.ts"],"names":[],"mappings":"AASA,OAAO,eAAe,MAAM,2BAA2B,CAAC;AACxD,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;AAMtE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;gFAEgF;AAChF;;;;;GAKG;AACH,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;CACX,CAAC,CAAC;AACH,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,QAAQ,EAAE,SAAS;IACnB,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,MAAM;CAChB,CAAC,CAAC;AACH,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AAEhC;;gFAEgF;AAChF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CACxB,eAAuB,EACvB,KAAkB,EAClB,OAAsB,EACxB,EAAE;IACA,IAAI,YAAY,GAAgB,EAAE,GAAG,KAAK,EAAE,CAAC;IAC7C,IAAI,gBAAgB,GAAG,eAAe,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IACtE,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,aAAa,GAAG;QAClB,UAAU;QACV,OAAO;QACP,QAAQ;QACR,eAAe;QACf,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;KACnC,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAE7C,MAAM,eAAe,GAAG,CAAC,GAAW,EAAe,EAAE;QACjD,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;YACjC,UAAU,CAAC,IAAI,CACX,IAAI,eAAe,CAAC;gBAChB,OAAO,EAAE,GAAG;gBACZ,QAAQ,EAAE,OAAO,CAAC,UAAU;gBAC5B,WAAW,EAAE,YAAY;gBACzB,KAAK,EAAE,MAAM;gBACb,aAAa,EAAE,IAAI;gBACnB,QAAQ,EAAE,SAAS;gBACnB,MAAM,EAAE,OAAO,CACX,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAC/D,SAAS,EAAE,EACX,IAAI,EAAE,CACT;aACJ,CAAC,CACL,CAAC;YAEF,UAAU,CAAC,IAAI,CACX,IAAI,eAAe,CAAC;gBAChB,OAAO,EAAE,GAAG;gBACZ,QAAQ,EAAE,OAAO,CAAC,MAAM;gBACxB,WAAW,EAAE,YAAY;gBACzB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,aAAa,EAAE,IAAI;gBACnB,QAAQ,EAAE,SAAS;gBACnB,MAAM,EAAE,OAAO,CACX,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,KAAK,YAAY,EAAE,CAAC,EACrD,SAAS,EAAE,EACX,IAAI,EAAE,CACT;aACJ,CAAC,CACL,CAAC;YAEF,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACtB,UAAU,CAAC,IAAI,CACX,IAAI,eAAe,CAAC;oBAChB,OAAO,EAAE,GAAG;oBACZ,QAAQ,EAAE,OAAO,CAAC,WAAW;oBAC7B,WAAW,EAAE,YAAY;oBACzB,KAAK,EAAE,UAAU;oBACjB,aAAa,EAAE,IAAI;oBACnB,QAAQ,EAAE,SAAS;oBACnB,MAAM,EAAE,OAAO,CACX,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EACnE,SAAS,EAAE,EACX,IAAI,EAAE,CACT;iBACJ,CAAC,CACL,CAAC;YACN,CAAC;YAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACpB,UAAU,CAAC,IAAI,CACX,IAAI,eAAe,CAAC;oBAChB,OAAO,EAAE,GAAG;oBACZ,QAAQ,EAAE,OAAO,CAAC,SAAS;oBAC3B,WAAW,EAAE,YAAY;oBACzB,KAAK,EAAE,QAAQ;oBACf,aAAa,EAAE,IAAI;oBACnB,QAAQ,EAAE,SAAS;oBACnB,MAAM,EAAE,OAAO,CACX,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EACjE,SAAS,EAAE,EACX,IAAI,EAAE,CACT;iBACJ,CAAC,CACL,CAAC;YACN,CAAC;QACL,CAAC;QAED,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACvB,UAAU,CAAC,IAAI,CACX,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC3B,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC;aAC3C,CAAC,CACL,CAAC;QACN,CAAC;QAED,IAAI,OAAO,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;QACxC,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,UAAU,EAAE,eAAe,CAAC,gBAAgB,CAAC;QAC7C,WAAW,EAAE;YACT,GAAG,YAAY;YACf,GAAG,EAAE,OAAO,CAAC,GAAG;SACnB;KACJ,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,CAAC,KAAe,EAAE,OAAgB,EAAE,UAAmC,EAAE,EAAE,EAAE;QACrF,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAE,aAAa,CAA4B,CAAC;QAC9E,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,KAAK,YAAY,CAAC;QAE/D,cAAc,CAAC,GAAG,CACd,KAAK,EACL,OAAO,YAAY,KAAK;YACpB,CAAC,CAAC;gBACI,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,GAAG,CAAC,YAAY,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC7C,GAAG,WAAW;aACjB;YACH,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CACpC,CAAC;IACN,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE;QACrB,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,MAAM,OAAO,CAAC,GAAG,CACb,cAAc,CAAC,UAAU,CAAC,GAAG,CACzB,CAAC,CAAC,EAAE,EAAE,CACF,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC1B,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACxB,CAAC,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CACT,CACJ,CAAC;QACF,cAAc,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,EAAE,OAA6B,EAAE,EAAE;QACxD,MAAM,QAAQ,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC;QACjD,MAAM,YAAY,GAAG,eAAe,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAEhE,IAAI,YAAY,KAAK,gBAAgB,EAAE,CAAC;YACpC,MAAM,KAAK,EAAE,CAAC;YAEd,MAAM,GAAG,KAAK,CAAC;YAEf,MAAM,aAAa,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;YACpD,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAEpD,gBAAgB,GAAG,YAAY,CAAC;QACpC,CAAC;QAED,YAAY,GAAG,QAAQ,CAAC;QACxB,cAAc,CAAC,WAAW,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IACvE,CAAC,CAAC;IAEF;;6EAEyE;IACzE,OAAO;QACH,QAAQ,EAAE,CAAC,KAAqB,EAAE,UAAmC,EAAE,EAAE,EAAE,CACvE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC;QAEhC,OAAO,EAAE,CAAC,OAAe,EAAE,UAAmC,EAAE,EAAE,EAAE,CAChE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAEjC,OAAO,EAAE,CAAC,OAAe,EAAE,UAAmC,EAAE,EAAE,EAAE,CAChE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAEjC,QAAQ,EAAE,CAAC,OAAe,EAAE,UAAmC,EAAE,EAAE,EAAE,CACjE,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;QAElC,WAAW,EAAE,CAAC,OAAe,EAAE,UAAmC,EAAE,EAAE,EAAE,CACpE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAAC;QAElE,SAAS,EAAE,CAAC,OAAe,EAAE,UAAmC,EAAE,EAAE,EAAE,CAClE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;QAE9D,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;YACvB,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE;gBACvB,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACpD,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC,CAAC;YAC9D,CAAC;SACJ,CAAC;QAEF,KAAK,EAAE,WAAW;QAElB,KAAK;QAEL,MAAM,EAAE,cAAc;KACzB,CAAC;AACN,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /** ------------------------------------------------------------------------
2
2
  |* @package @glassops/scribe
3
- |* @version 1.0.0
3
+ |* @version 1.0.2
4
4
  |* @see https://www.jane-io.com
5
5
  |* @license Apache-2.0
6
6
  |* -------------------------------------------------------------------------
@@ -13,16 +13,16 @@
13
13
  /**
14
14
  * Public authoring contracts for configuring logger scope and behavior.
15
15
  */
16
- export type { LoggerScope, LoggerOptions, LogLevel } from "./types.js";
16
+ export type { LoggerScope, LoggerOptions, LogLevel } from './types.js';
17
17
  /**
18
18
  * Pure, deterministic entrypoints for initializing the log directory and
19
19
  * constructing a scoped logger instance. These are the primary runtime APIs.
20
20
  */
21
- export { createDirectory } from "./create-directory.js";
22
- export { createLogger } from "./create-logger.js";
21
+ export { createDirectory } from './create-directory.js';
22
+ export { createLogger } from './create-logger.js';
23
23
  /**
24
24
  * Internal helpers exposed for advanced use cases. These functions are pure
25
25
  * and side‑effect‑free, but not required for normal operation.
26
26
  */
27
- export { redact, safe, stripAnsi } from "./utilities.js";
27
+ export { redact, safe, stripAnsi } from './utilities.js';
28
28
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /** ------------------------------------------------------------------------
2
2
  |* @package @glassops/scribe
3
- |* @version 1.0.0
3
+ |* @version 1.0.2
4
4
  |* @see https://www.jane-io.com
5
5
  |* @license Apache-2.0
6
6
  |* -------------------------------------------------------------------------
@@ -17,8 +17,8 @@
17
17
  * Pure, deterministic entrypoints for initializing the log directory and
18
18
  * constructing a scoped logger instance. These are the primary runtime APIs.
19
19
  */
20
- export { createDirectory } from "./create-directory.js";
21
- export { createLogger } from "./create-logger.js";
20
+ export { createDirectory } from './create-directory.js';
21
+ export { createLogger } from './create-logger.js';
22
22
  /* --------------------------------------------------------------------------
23
23
  |* Utilities
24
24
  \* -------------------------------------------------------------------------- */
@@ -26,5 +26,5 @@ export { createLogger } from "./create-logger.js";
26
26
  * Internal helpers exposed for advanced use cases. These functions are pure
27
27
  * and side‑effect‑free, but not required for normal operation.
28
28
  */
29
- export { redact, safe, stripAnsi } from "./utilities.js";
29
+ export { redact, safe, stripAnsi } from './utilities.js';
30
30
  //# sourceMappingURL=index.js.map
package/dist/types.d.ts CHANGED
@@ -6,7 +6,22 @@
6
6
  /* --------------------------------------------------------------------------
7
7
  |* NPM Dependencies
8
8
  \* -------------------------------------------------------------------------- */
9
- import type Transport from "winston-transport";
9
+ import type { Logger } from 'winston';
10
+ import type Transport from 'winston-transport';
11
+ export interface ScribeLogger {
12
+ logError: (error: string | Error, context?: Record<string, unknown>) => void;
13
+ logWarn: (message: string, context?: Record<string, unknown>) => void;
14
+ logInfo: (message: string, context?: Record<string, unknown>) => void;
15
+ logDebug: (message: string, context?: Record<string, unknown>) => void;
16
+ logIncident: (message: string, context?: Record<string, unknown>) => void;
17
+ logChange: (message: string, context?: Record<string, unknown>) => void;
18
+ createLoggerStream: () => {
19
+ write: (message: string) => void;
20
+ };
21
+ scope: (partial: Partial<LoggerScope>) => Promise<void>;
22
+ close: () => Promise<void>;
23
+ logger: Logger;
24
+ }
10
25
  /**
11
26
  * Describes the identity of the log stream. Every log entry is tagged with
12
27
  * these fields to ensure deterministic partitioning across tenants,
@@ -62,5 +77,5 @@ export interface LoggerOptions {
62
77
  * Supported semantic log levels. These map directly to Scribe's custom
63
78
  * level hierarchy and determine which transport receives each log entry.
64
79
  */
65
- export type LogLevel = "critical" | "error" | "warn" | "info" | "http" | "change" | "debug";
80
+ export type LogLevel = 'critical' | 'error' | 'warn' | 'info' | 'http' | 'change' | 'debug';
66
81
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;gFAOgF;AAChF,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAK/C;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,QAAQ,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAKD;;;GAGG;AACH,MAAM,MAAM,QAAQ,GACd,UAAU,GACV,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,QAAQ,GACR,OAAO,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;gFAOgF;AAChF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAK/C,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7E,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACvE,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC1E,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACxE,kBAAkB,EAAE,MAAM;QAAE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC/D,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAClB;AAKD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,QAAQ,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAKD;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC"}
@@ -23,13 +23,5 @@ export declare const safe: (value: string) => string;
23
23
  * control characters.
24
24
  */
25
25
  export declare const stripAnsi: (log: string) => string;
26
- /**
27
- * Recursively removes sensitive fields from an input object. Supports nested
28
- * objects, arrays, and circular references. Sensitive keys are replaced with
29
- * "[REDACTED]". Buffers are replaced with "[Binary]" to avoid dumping raw
30
- * binary data into logs. All other values are preserved as‑is.
31
- *
32
- * This function never mutates the input and guarantees deterministic output.
33
- */
34
- export declare const redact: (input: unknown, sensitiveKeys: string[], seen?: WeakSet<object>) => unknown;
26
+ export declare const redact: (value: unknown, sensitiveKeys: string[], depth?: number, seen?: WeakSet<object>) => unknown;
35
27
  //# sourceMappingURL=utilities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;gFAUgF;AAChF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,WACqB,CAAC;AAKxD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,WAEY,CAAC;AAKlD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,GACf,OAAO,OAAO,EACd,eAAe,MAAM,EAAE,EACvB,sBAAoB,KACrB,OA2BF,CAAC"}
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;gFAUgF;AAChF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,WAajC,CAAC;AAKF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,WAEY,CAAC;AAiBlD,eAAO,MAAM,MAAM,GACf,OAAO,OAAO,EACd,eAAe,MAAM,EAAE,EACvB,cAAS,EACT,sBAA4B,KAC7B,OA4CF,CAAC"}
package/dist/utilities.js CHANGED
@@ -15,7 +15,18 @@
15
15
  * deterministic, cross‑platform directory names and prevents path traversal
16
16
  * or invalid characters from entering the log directory grammar.
17
17
  */
18
- export const safe = (value) => value.toLowerCase().replace(/[^a-zA-Z0-9-_]/g, "-");
18
+ export const safe = (value) => {
19
+ const result = value
20
+ .toLowerCase()
21
+ .replace(/[^a-zA-Z0-9-_]/g, '-')
22
+ .trim()
23
+ .replace(/-+/g, '-')
24
+ .replace(/^-|-$/g, '');
25
+ if (!result) {
26
+ throw new Error('Invalid directory segment');
27
+ }
28
+ return result;
29
+ };
19
30
  /* -------------------------------------------------------------------------- *\
20
31
  |* Strip ANSI
21
32
  \* -------------------------------------------------------------------------- */
@@ -27,7 +38,7 @@ export const safe = (value) => value.toLowerCase().replace(/[^a-zA-Z0-9-_]/g, "-
27
38
  */
28
39
  export const stripAnsi = (log) =>
29
40
  // eslint-disable-next-line no-control-regex
30
- log.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, "");
41
+ log.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, '');
31
42
  /* -------------------------------------------------------------------------- *\
32
43
  |* Redact
33
44
  \* -------------------------------------------------------------------------- */
@@ -39,29 +50,44 @@ log.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, "");
39
50
  *
40
51
  * This function never mutates the input and guarantees deterministic output.
41
52
  */
42
- export const redact = (input, sensitiveKeys, seen = new WeakSet()) => {
43
- if (Array.isArray(input)) {
44
- return input.map((value) => redact(value, sensitiveKeys, seen));
53
+ const MAX_DEPTH = 6;
54
+ const MAX_KEYS = 100;
55
+ const MAX_STRING_LENGTH = 10_000;
56
+ export const redact = (value, sensitiveKeys, depth = 0, seen = new WeakSet()) => {
57
+ if (value === null || value === undefined) {
58
+ return value;
59
+ }
60
+ if (typeof value === 'object') {
61
+ if (seen.has(value)) {
62
+ return '[Circular]';
63
+ }
64
+ seen.add(value);
65
+ }
66
+ if (depth > MAX_DEPTH) {
67
+ return '[MaxDepthExceeded]';
45
68
  }
46
- if (input && typeof input === "object") {
47
- if (seen.has(input))
48
- return "[Circular]";
49
- seen.add(input);
50
- const clone = {};
51
- for (const [key, value] of Object.entries(input)) {
52
- const normalized = sensitiveKeys.map((k) => k.toLowerCase());
53
- if (normalized.includes(key.toLowerCase())) {
54
- clone[key] = "[REDACTED]";
55
- }
56
- else if (value instanceof Buffer) {
57
- clone[key] = "[Binary]";
58
- }
59
- else {
60
- clone[key] = redact(value, sensitiveKeys, seen);
61
- }
69
+ if (typeof value === 'string') {
70
+ return value.length > MAX_STRING_LENGTH
71
+ ? value.slice(0, MAX_STRING_LENGTH) + '...[Truncated]'
72
+ : value;
73
+ }
74
+ if (typeof value !== 'object') {
75
+ return value;
76
+ }
77
+ if (Array.isArray(value)) {
78
+ return value.slice(0, MAX_KEYS).map((item) => redact(item, sensitiveKeys, depth + 1, seen));
79
+ }
80
+ const output = {};
81
+ const entries = Object.entries(value).slice(0, MAX_KEYS);
82
+ const normalizedKeys = new Set(sensitiveKeys.map((k) => k.toLowerCase()));
83
+ for (const [key, val] of entries) {
84
+ if (normalizedKeys.has(key.toLowerCase())) {
85
+ output[key] = '[REDACTED]';
86
+ }
87
+ else {
88
+ output[key] = redact(val, sensitiveKeys, depth + 1, seen);
62
89
  }
63
- return clone;
64
90
  }
65
- return input;
91
+ return output;
66
92
  };
67
93
  //# sourceMappingURL=utilities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;gFAUgF;AAChF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CAClC,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAExD;;gFAEgF;AAChF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE;AACrC,4CAA4C;AAC5C,GAAG,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;AAElD;;gFAEgF;AAChF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAClB,KAAc,EACd,aAAuB,EACvB,IAAI,GAAG,IAAI,OAAO,EAAE,EACb,EAAE;IACT,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAe,CAAC;YAAE,OAAO,YAAY,CAAC;QACnD,IAAI,CAAC,GAAG,CAAC,KAAe,CAAC,CAAC;QAE1B,MAAM,KAAK,GAA4B,EAAE,CAAC;QAE1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAE7D,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBACzC,KAAK,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;YAC9B,CAAC;iBAAM,IAAI,KAAK,YAAY,MAAM,EAAE,CAAC;gBACjC,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACJ,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;YACpD,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC"}
1
+ {"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassops/scribe",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Deterministic, multi-tenant logging subsystem for GlassOps services.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "GlassOps Limited",