@unhingged/logit 0.0.0-stage → 0.1.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/dist/next.js ADDED
@@ -0,0 +1,212 @@
1
+ import {
2
+ REQUEST_COMPLETION_TEMPLATE,
3
+ runRequestScope
4
+ } from "./chunk-7J27DQIR.js";
5
+ import {
6
+ CLEF_MEDIA_TYPE,
7
+ DEFAULT_DESTRUCTURING,
8
+ DEFAULT_OUTPUT_TEMPLATE,
9
+ LEVELS,
10
+ LEVEL_CODES,
11
+ LEVEL_NUMBERS,
12
+ LEVEL_ORDER,
13
+ LevelSwitch,
14
+ LogContext,
15
+ LogEvent,
16
+ Logger,
17
+ LoggerConfiguration,
18
+ Matching,
19
+ Operation,
20
+ SERILOG_LEVEL_NAMES,
21
+ ansi,
22
+ audit,
23
+ batchingSink,
24
+ byExcluding,
25
+ byIncludingOnly,
26
+ byTransforming,
27
+ callbackSink,
28
+ captureError,
29
+ captureProperty,
30
+ captureValue,
31
+ clefFormatter,
32
+ closeAndFlush,
33
+ conditional,
34
+ configure,
35
+ consoleSink,
36
+ createLogger,
37
+ detectColors,
38
+ diagnosticContext,
39
+ formatDate,
40
+ formatError,
41
+ formatLevel,
42
+ formatNumber,
43
+ fromLogContext,
44
+ httpSink,
45
+ isLevel,
46
+ isoTimestamp,
47
+ jsonFormatter,
48
+ jsonReplacer,
49
+ levelAtLeast,
50
+ log,
51
+ mapSink,
52
+ memorySink,
53
+ parseLevel,
54
+ parseTemplate,
55
+ prettyFormatter,
56
+ rateLimited,
57
+ renderTemplate,
58
+ renderValue,
59
+ resolveFormatter,
60
+ resolveLevel,
61
+ resolveStyles,
62
+ restricted,
63
+ sampled,
64
+ selfLog,
65
+ seqSink,
66
+ streamSink,
67
+ templateHash,
68
+ textFormatter,
69
+ toJson,
70
+ withComputed,
71
+ withEnvironment,
72
+ withProperties,
73
+ withProperty,
74
+ withTraceContext
75
+ } from "./chunk-GW7WQELF.js";
76
+
77
+ // src/next.ts
78
+ import { AsyncLocalStorage } from "async_hooks";
79
+ if (!LogContext.isAsync) LogContext.use(new AsyncLocalStorage());
80
+ function withLogging(handler, options = {}) {
81
+ const logger = options.logger ?? log;
82
+ const wrapped = async (request, ...args) => {
83
+ const url = safeUrl(request.url);
84
+ const info = { method: request.method, path: url?.pathname ?? request.url, url: request.url, headers: request.headers };
85
+ if (options.ignore?.(info)) return handler(request, ...args);
86
+ return runRequestScope(info, options, logger, async (scope) => {
87
+ try {
88
+ const response = await handler(request, ...args);
89
+ scope.complete(response instanceof Response ? response.status : 200);
90
+ return response;
91
+ } catch (error) {
92
+ scope.complete(statusOf(error), error);
93
+ throw error;
94
+ }
95
+ });
96
+ };
97
+ return wrapped;
98
+ }
99
+ function safeUrl(url) {
100
+ try {
101
+ return new URL(url);
102
+ } catch {
103
+ return void 0;
104
+ }
105
+ }
106
+ function statusOf(error) {
107
+ const digest = error?.digest;
108
+ if (typeof digest === "string") {
109
+ if (digest.startsWith("NEXT_REDIRECT")) {
110
+ const parts = digest.split(";");
111
+ const code = Number(parts[3]);
112
+ return Number.isFinite(code) ? code : 307;
113
+ }
114
+ if (digest === "NEXT_NOT_FOUND") return 404;
115
+ }
116
+ return 500;
117
+ }
118
+ function createOnRequestError(options = {}) {
119
+ const logger = (options.logger ?? log).forSource(options.source ?? "next");
120
+ const level = options.level ?? "error";
121
+ return async (error, request, context) => {
122
+ const err = error instanceof Error ? error : new Error(String(error));
123
+ const digest = error?.digest;
124
+ const target = logger.forContext({
125
+ RequestMethod: request.method,
126
+ RequestPath: request.path,
127
+ RouterKind: context.routerKind,
128
+ RouteType: context.routeType,
129
+ ...context.renderSource ? { RenderSource: context.renderSource } : {},
130
+ ...typeof digest === "string" ? { Digest: digest } : {}
131
+ });
132
+ target.write(level, err, "{RouteType:l} {RoutePath:l} failed", context.routeType, context.routePath);
133
+ if (options.flush ?? true) await logger.flush();
134
+ };
135
+ }
136
+ var requestDiagnostics = diagnosticContext;
137
+ export {
138
+ CLEF_MEDIA_TYPE,
139
+ DEFAULT_DESTRUCTURING,
140
+ DEFAULT_OUTPUT_TEMPLATE,
141
+ LEVELS,
142
+ LEVEL_CODES,
143
+ LEVEL_NUMBERS,
144
+ LEVEL_ORDER,
145
+ LevelSwitch,
146
+ LogContext,
147
+ LogEvent,
148
+ Logger,
149
+ LoggerConfiguration,
150
+ Matching,
151
+ Operation,
152
+ REQUEST_COMPLETION_TEMPLATE,
153
+ SERILOG_LEVEL_NAMES,
154
+ ansi,
155
+ audit,
156
+ batchingSink,
157
+ byExcluding,
158
+ byIncludingOnly,
159
+ byTransforming,
160
+ callbackSink,
161
+ captureError,
162
+ captureProperty,
163
+ captureValue,
164
+ clefFormatter,
165
+ closeAndFlush,
166
+ conditional,
167
+ configure,
168
+ consoleSink,
169
+ createLogger,
170
+ createOnRequestError,
171
+ detectColors,
172
+ diagnosticContext,
173
+ formatDate,
174
+ formatError,
175
+ formatLevel,
176
+ formatNumber,
177
+ fromLogContext,
178
+ httpSink,
179
+ isLevel,
180
+ isoTimestamp,
181
+ jsonFormatter,
182
+ jsonReplacer,
183
+ levelAtLeast,
184
+ log,
185
+ mapSink,
186
+ memorySink,
187
+ parseLevel,
188
+ parseTemplate,
189
+ prettyFormatter,
190
+ rateLimited,
191
+ renderTemplate,
192
+ renderValue,
193
+ requestDiagnostics,
194
+ resolveFormatter,
195
+ resolveLevel,
196
+ resolveStyles,
197
+ restricted,
198
+ sampled,
199
+ selfLog,
200
+ seqSink,
201
+ streamSink,
202
+ templateHash,
203
+ textFormatter,
204
+ toJson,
205
+ withComputed,
206
+ withEnvironment,
207
+ withLogging,
208
+ withProperties,
209
+ withProperty,
210
+ withTraceContext
211
+ };
212
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next.ts"],"sourcesContent":["/**\n * `@unhingged/logit/next` — Next.js in three places:\n *\n * instrumentation.ts `register()` configures the logger once per server\n * (behind a literal `process.env.NEXT_RUNTIME === 'nodejs'`\n * check, which Next inlines at build time so the Node-only\n * import is dropped from the edge bundle);\n * `onRequestError` logs every error Next catches.\n * middleware.ts `withLogging(middleware)` — ambient request context\n * and a completion event, on the edge runtime too.\n * route handlers `withLogging(handler)` — the same for `GET` / `POST`.\n * server actions `log.timed('Action createOrder', () => …)`.\n *\n * This entry imports only `node:async_hooks`, which Next.js provides in the\n * edge runtime as well, so it is safe in `middleware.ts`.\n */\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { LogContext, diagnosticContext } from './context';\nimport type { LogLevel } from './levels';\nimport { type Logger, log } from './logger';\nimport { type RequestLoggingOptions, runRequestScope } from './request';\n\nexport * from './index';\nexport { REQUEST_COMPLETION_TEMPLATE, type RequestLoggingOptions, type RequestInfo } from './request';\n\nif (!LogContext.isAsync) LogContext.use(new AsyncLocalStorage());\n\ntype HandlerResult = Response | void | Promise<Response | void>;\n\n/**\n * Wraps a route handler or `middleware` so that every request gets\n * `RequestId`, `RequestMethod` and `RequestPath` in the ambient context and\n * one completion event when it finishes. Errors are logged at `error` with\n * the request's facts and rethrown.\n *\n * export const GET = withLogging(async (request) => { … });\n */\nexport function withLogging<A extends unknown[], R extends HandlerResult>(\n handler: (request: Request, ...args: A) => R,\n options: RequestLoggingOptions = {},\n): (request: Request, ...args: A) => Promise<Awaited<R>> {\n const logger = options.logger ?? log;\n const wrapped = async (request: Request, ...args: A): Promise<unknown> => {\n const url = safeUrl(request.url);\n const info = { method: request.method, path: url?.pathname ?? request.url, url: request.url, headers: request.headers };\n if (options.ignore?.(info)) return handler(request, ...args);\n return runRequestScope(info, options, logger, async (scope) => {\n try {\n const response = await handler(request, ...args);\n scope.complete(response instanceof Response ? response.status : 200);\n return response;\n } catch (error) {\n scope.complete(statusOf(error), error);\n throw error;\n }\n });\n };\n return wrapped as (request: Request, ...args: A) => Promise<Awaited<R>>;\n}\n\nfunction safeUrl(url: string): URL | undefined {\n try {\n return new URL(url);\n } catch {\n return undefined;\n }\n}\n\n/** Next's `redirect()` / `notFound()` throw; they are not failures. */\nfunction statusOf(error: unknown): number {\n const digest = (error as { digest?: unknown })?.digest;\n if (typeof digest === 'string') {\n if (digest.startsWith('NEXT_REDIRECT')) {\n const parts = digest.split(';');\n const code = Number(parts[3]);\n return Number.isFinite(code) ? code : 307;\n }\n if (digest === 'NEXT_NOT_FOUND') return 404;\n }\n return 500;\n}\n\n/** The shape Next.js passes to `onRequestError` (kept structural so this package does not depend on `next`). */\nexport interface NextRequestErrorContext {\n routerKind: 'Pages Router' | 'App Router';\n routePath: string;\n routeType: 'render' | 'route' | 'action' | 'middleware';\n renderSource?: string;\n revalidateReason?: string;\n renderType?: string;\n}\n\nexport interface NextErrorRequest {\n path: string;\n method: string;\n headers: Record<string, string | string[] | undefined> | { get(name: string): string | null };\n}\n\nexport interface OnRequestErrorOptions {\n logger?: Logger;\n level?: LogLevel;\n source?: string;\n /** Flush the logger after each error (recommended on serverless, where the instance may freeze right after). Default true. */\n flush?: boolean;\n}\n\n/**\n * Builds the `onRequestError` export for `instrumentation.ts`:\n *\n * export const onRequestError = createOnRequestError();\n *\n * Logs the error with the route, the router kind and the request's facts.\n * Next may hand over a wrapped error during RSC rendering — the `digest` is\n * logged too, which is what identifies the original.\n */\nexport function createOnRequestError(options: OnRequestErrorOptions = {}) {\n const logger = (options.logger ?? log).forSource(options.source ?? 'next');\n const level = options.level ?? 'error';\n return async (error: unknown, request: NextErrorRequest, context: NextRequestErrorContext): Promise<void> => {\n const err = error instanceof Error ? error : new Error(String(error));\n const digest = (error as { digest?: unknown })?.digest;\n const target = logger.forContext({\n RequestMethod: request.method,\n RequestPath: request.path,\n RouterKind: context.routerKind,\n RouteType: context.routeType,\n ...(context.renderSource ? { RenderSource: context.renderSource } : {}),\n ...(typeof digest === 'string' ? { Digest: digest } : {}),\n });\n target.write(level, err, '{RouteType:l} {RoutePath:l} failed', context.routeType, context.routePath);\n if (options.flush ?? true) await logger.flush();\n };\n}\n\n/** `diagnosticContext.set()` re-exported under the name the Next docs use. */\nexport const requestDiagnostics = diagnosticContext;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,SAAS,yBAAyB;AASlC,IAAI,CAAC,WAAW,QAAS,YAAW,IAAI,IAAI,kBAAkB,CAAC;AAYxD,SAAS,YACd,SACA,UAAiC,CAAC,GACqB;AACvD,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,UAAU,OAAO,YAAqB,SAA8B;AACxE,UAAM,MAAM,QAAQ,QAAQ,GAAG;AAC/B,UAAM,OAAO,EAAE,QAAQ,QAAQ,QAAQ,MAAM,KAAK,YAAY,QAAQ,KAAK,KAAK,QAAQ,KAAK,SAAS,QAAQ,QAAQ;AACtH,QAAI,QAAQ,SAAS,IAAI,EAAG,QAAO,QAAQ,SAAS,GAAG,IAAI;AAC3D,WAAO,gBAAgB,MAAM,SAAS,QAAQ,OAAO,UAAU;AAC7D,UAAI;AACF,cAAM,WAAW,MAAM,QAAQ,SAAS,GAAG,IAAI;AAC/C,cAAM,SAAS,oBAAoB,WAAW,SAAS,SAAS,GAAG;AACnE,eAAO;AAAA,MACT,SAAS,OAAO;AACd,cAAM,SAAS,SAAS,KAAK,GAAG,KAAK;AACrC,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,KAA8B;AAC7C,MAAI;AACF,WAAO,IAAI,IAAI,GAAG;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,SAAS,OAAwB;AACxC,QAAM,SAAU,OAAgC;AAChD,MAAI,OAAO,WAAW,UAAU;AAC9B,QAAI,OAAO,WAAW,eAAe,GAAG;AACtC,YAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,YAAM,OAAO,OAAO,MAAM,CAAC,CAAC;AAC5B,aAAO,OAAO,SAAS,IAAI,IAAI,OAAO;AAAA,IACxC;AACA,QAAI,WAAW,iBAAkB,QAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAmCO,SAAS,qBAAqB,UAAiC,CAAC,GAAG;AACxE,QAAM,UAAU,QAAQ,UAAU,KAAK,UAAU,QAAQ,UAAU,MAAM;AACzE,QAAM,QAAQ,QAAQ,SAAS;AAC/B,SAAO,OAAO,OAAgB,SAA2B,YAAoD;AAC3G,UAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACpE,UAAM,SAAU,OAAgC;AAChD,UAAM,SAAS,OAAO,WAAW;AAAA,MAC/B,eAAe,QAAQ;AAAA,MACvB,aAAa,QAAQ;AAAA,MACrB,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,MACnB,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;AAAA,MACrE,GAAI,OAAO,WAAW,WAAW,EAAE,QAAQ,OAAO,IAAI,CAAC;AAAA,IACzD,CAAC;AACD,WAAO,MAAM,OAAO,KAAK,sCAAsC,QAAQ,WAAW,QAAQ,SAAS;AACnG,QAAI,QAAQ,SAAS,KAAM,OAAM,OAAO,MAAM;AAAA,EAChD;AACF;AAGO,IAAM,qBAAqB;","names":[]}
package/dist/node.cjs ADDED
@@ -0,0 +1,341 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+ var _chunk3FU7DTQEcjs = require('./chunk-3FU7DTQE.cjs');
72
+
73
+ // src/node.ts
74
+ var _async_hooks = require('async_hooks');
75
+ var _fs = require('fs');
76
+ var _os = require('os');
77
+ var _path = require('path');
78
+ var _util = require('util');
79
+ if (!_chunk3FU7DTQEcjs.LogContext.isAsync) _chunk3FU7DTQEcjs.LogContext.use(new (0, _async_hooks.AsyncLocalStorage)());
80
+ function withMachineName() {
81
+ const name = _os.hostname.call(void 0, );
82
+ return (event) => event.addPropertyIfAbsent("MachineName", name);
83
+ }
84
+ function withProcessId() {
85
+ const pid = process.pid;
86
+ return (event) => event.addPropertyIfAbsent("ProcessId", pid);
87
+ }
88
+ function withProcessInfo() {
89
+ const name = _os.hostname.call(void 0, );
90
+ const pid = process.pid;
91
+ const env = process.env.NODE_ENV;
92
+ return (event) => {
93
+ event.addPropertyIfAbsent("MachineName", name);
94
+ event.addPropertyIfAbsent("ProcessId", pid);
95
+ if (env) event.addPropertyIfAbsent("Environment", env);
96
+ };
97
+ }
98
+ function fileSink(options) {
99
+ const formatter = _chunk3FU7DTQEcjs.resolveFormatter.call(void 0, options.format, { outputTemplate: options.outputTemplate, colors: false, utc: options.utc }, "json");
100
+ const target = _path.resolve.call(void 0, options.path);
101
+ const dir = _path.dirname.call(void 0, target);
102
+ const ext = _path.extname.call(void 0, target);
103
+ const stem = _path.basename.call(void 0, target, ext);
104
+ const rolling = _nullishCoalesce(options.rolling, () => ( "none"));
105
+ const maxBytes = _nullishCoalesce(options.maxBytes, () => ( Infinity));
106
+ const retained = _nullishCoalesce(options.retainedFileCount, () => ( Infinity));
107
+ const utc = _nullishCoalesce(options.utc, () => ( false));
108
+ let fd = null;
109
+ let currentPeriod = "";
110
+ let currentPath = "";
111
+ let size = 0;
112
+ let sequence = 0;
113
+ const period = (date) => {
114
+ if (rolling === "none") return "";
115
+ const p = (n) => String(n).padStart(2, "0");
116
+ const y = utc ? date.getUTCFullYear() : date.getFullYear();
117
+ const mo = p((utc ? date.getUTCMonth() : date.getMonth()) + 1);
118
+ const d = p(utc ? date.getUTCDate() : date.getDate());
119
+ const h = p(utc ? date.getUTCHours() : date.getHours());
120
+ const mi = p(utc ? date.getUTCMinutes() : date.getMinutes());
121
+ switch (rolling) {
122
+ case "month":
123
+ return `${y}${mo}`;
124
+ case "day":
125
+ return `${y}${mo}${d}`;
126
+ case "hour":
127
+ return `${y}${mo}${d}${h}`;
128
+ case "minute":
129
+ return `${y}${mo}${d}${h}${mi}`;
130
+ default:
131
+ return "";
132
+ }
133
+ };
134
+ const fileName = (p, seq) => `${stem}${p ? `-${p}` : ""}${seq ? `_${String(seq).padStart(3, "0")}` : ""}${ext}`;
135
+ const isOurs = (name) => name.startsWith(stem) && name.endsWith(ext) && /^[-_0-9]*$/.test(name.slice(stem.length, name.length - ext.length));
136
+ const open = (p) => {
137
+ if (fd !== null) {
138
+ _fs.closeSync.call(void 0, fd);
139
+ fd = null;
140
+ }
141
+ if (_nullishCoalesce(options.mkdir, () => ( true))) _fs.mkdirSync.call(void 0, dir, { recursive: true });
142
+ sequence = 0;
143
+ if (Number.isFinite(maxBytes)) {
144
+ while (_fs.existsSync.call(void 0, _path.join.call(void 0, dir, fileName(p, sequence))) && _fs.statSync.call(void 0, _path.join.call(void 0, dir, fileName(p, sequence))).size >= maxBytes) sequence++;
145
+ }
146
+ currentPath = _path.join.call(void 0, dir, fileName(p, sequence));
147
+ fd = _fs.openSync.call(void 0, currentPath, "a");
148
+ size = _fs.fstatSync.call(void 0, fd).size;
149
+ currentPeriod = p;
150
+ prune();
151
+ };
152
+ const prune = () => {
153
+ if (!Number.isFinite(retained)) return;
154
+ try {
155
+ const files = _fs.readdirSync.call(void 0, dir).filter(isOurs).map((name) => ({ name, mtime: _fs.statSync.call(void 0, _path.join.call(void 0, dir, name)).mtimeMs })).sort((a, b) => b.mtime - a.mtime || b.name.localeCompare(a.name));
156
+ for (const file of files.slice(retained)) {
157
+ if (_path.join.call(void 0, dir, file.name) === currentPath) continue;
158
+ _fs.unlinkSync.call(void 0, _path.join.call(void 0, dir, file.name));
159
+ }
160
+ } catch (error) {
161
+ _chunk3FU7DTQEcjs.selfLog.write(`fileSink: pruning ${dir} failed`, error);
162
+ }
163
+ };
164
+ return {
165
+ name: `file(${options.path})`,
166
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
167
+ audit: options.audit,
168
+ emit(event) {
169
+ const line = `${formatter(event)}
170
+ `;
171
+ const p = period(event.timestamp);
172
+ if (fd === null || p !== currentPeriod) open(p);
173
+ else if (size + line.length > maxBytes && size > 0) {
174
+ _fs.closeSync.call(void 0, fd);
175
+ fd = null;
176
+ sequence++;
177
+ const next = _path.join.call(void 0, dir, fileName(p, sequence));
178
+ if (_fs.existsSync.call(void 0, next)) {
179
+ while (_fs.existsSync.call(void 0, _path.join.call(void 0, dir, fileName(p, sequence)))) sequence++;
180
+ }
181
+ currentPath = _path.join.call(void 0, dir, fileName(p, sequence));
182
+ fd = _fs.openSync.call(void 0, currentPath, "a");
183
+ size = 0;
184
+ prune();
185
+ }
186
+ const bytes = Buffer.byteLength(line);
187
+ _fs.writeSync.call(void 0, fd, line);
188
+ size += bytes;
189
+ },
190
+ close() {
191
+ if (fd !== null) {
192
+ _fs.closeSync.call(void 0, fd);
193
+ fd = null;
194
+ }
195
+ },
196
+ /** @internal for tests */
197
+ get currentPath() {
198
+ return currentPath;
199
+ }
200
+ };
201
+ }
202
+ function interceptConsole(logger, options = {}) {
203
+ const map = {
204
+ log: "info",
205
+ info: "info",
206
+ debug: "debug",
207
+ warn: "warn",
208
+ error: "error",
209
+ trace: "error",
210
+ ...options.levels
211
+ };
212
+ const source = logger.forSource(_nullishCoalesce(options.source, () => ( "console")));
213
+ const original = {};
214
+ for (const method of Object.keys(map)) {
215
+ original[method] = console[method];
216
+ const level = _chunk3FU7DTQEcjs.parseLevel.call(void 0, map[method]);
217
+ console[method] = ((...args) => {
218
+ const error = args.find((a) => a instanceof Error);
219
+ const rest = error ? args.filter((a) => a !== error) : args;
220
+ const text = rest.length ? _util.format.call(void 0, ...rest) : error ? error.message : "";
221
+ if (error) source.write(level, error, "{Message:l}", text);
222
+ else source.write(level, "{Message:l}", text);
223
+ });
224
+ }
225
+ return () => {
226
+ for (const method of Object.keys(original)) console[method] = original[method];
227
+ };
228
+ }
229
+ var SIGNAL_NUMBERS = { SIGINT: 2, SIGTERM: 15, SIGHUP: 1, SIGQUIT: 3 };
230
+ function closeOnExit(logger, options = {}) {
231
+ const signals = _nullishCoalesce(options.signals, () => ( ["SIGINT", "SIGTERM"]));
232
+ const exit = _nullishCoalesce(options.exit, () => ( true));
233
+ let closing = null;
234
+ const close = () => closing ??= logger.close().catch((error) => _chunk3FU7DTQEcjs.selfLog.write("close on exit failed", error));
235
+ const onBeforeExit = () => {
236
+ void close();
237
+ };
238
+ const onSignal = (signal) => {
239
+ void close().then(() => {
240
+ if (exit) process.exit(128 + (_nullishCoalesce(SIGNAL_NUMBERS[signal], () => ( 0))));
241
+ });
242
+ };
243
+ const onCrash = (error, kind) => {
244
+ logger.fatal(error instanceof Error ? error : new Error(String(error)), `{Kind:l} \u2014 the process will exit`, kind);
245
+ void close().then(() => {
246
+ if (exit) process.exit(1);
247
+ });
248
+ };
249
+ const onUncaught = (error) => onCrash(error, "Uncaught exception");
250
+ const onUnhandled = (reason) => onCrash(reason, "Unhandled rejection");
251
+ process.on("beforeExit", onBeforeExit);
252
+ for (const signal of signals) process.on(signal, onSignal);
253
+ if (_nullishCoalesce(options.crashes, () => ( true))) {
254
+ process.on("uncaughtException", onUncaught);
255
+ process.on("unhandledRejection", onUnhandled);
256
+ }
257
+ return () => {
258
+ process.off("beforeExit", onBeforeExit);
259
+ for (const signal of signals) process.off(signal, onSignal);
260
+ process.off("uncaughtException", onUncaught);
261
+ process.off("unhandledRejection", onUnhandled);
262
+ };
263
+ }
264
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+
275
+
276
+
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334
+
335
+
336
+
337
+
338
+
339
+
340
+ exports.CLEF_MEDIA_TYPE = _chunk3FU7DTQEcjs.CLEF_MEDIA_TYPE; exports.DEFAULT_DESTRUCTURING = _chunk3FU7DTQEcjs.DEFAULT_DESTRUCTURING; exports.DEFAULT_OUTPUT_TEMPLATE = _chunk3FU7DTQEcjs.DEFAULT_OUTPUT_TEMPLATE; exports.LEVELS = _chunk3FU7DTQEcjs.LEVELS; exports.LEVEL_CODES = _chunk3FU7DTQEcjs.LEVEL_CODES; exports.LEVEL_NUMBERS = _chunk3FU7DTQEcjs.LEVEL_NUMBERS; exports.LEVEL_ORDER = _chunk3FU7DTQEcjs.LEVEL_ORDER; exports.LevelSwitch = _chunk3FU7DTQEcjs.LevelSwitch; exports.LogContext = _chunk3FU7DTQEcjs.LogContext; exports.LogEvent = _chunk3FU7DTQEcjs.LogEvent; exports.Logger = _chunk3FU7DTQEcjs.Logger; exports.LoggerConfiguration = _chunk3FU7DTQEcjs.LoggerConfiguration; exports.Matching = _chunk3FU7DTQEcjs.Matching; exports.Operation = _chunk3FU7DTQEcjs.Operation; exports.SERILOG_LEVEL_NAMES = _chunk3FU7DTQEcjs.SERILOG_LEVEL_NAMES; exports.ansi = _chunk3FU7DTQEcjs.ansi; exports.audit = _chunk3FU7DTQEcjs.audit; exports.batchingSink = _chunk3FU7DTQEcjs.batchingSink; exports.byExcluding = _chunk3FU7DTQEcjs.byExcluding; exports.byIncludingOnly = _chunk3FU7DTQEcjs.byIncludingOnly; exports.byTransforming = _chunk3FU7DTQEcjs.byTransforming; exports.callbackSink = _chunk3FU7DTQEcjs.callbackSink; exports.captureError = _chunk3FU7DTQEcjs.captureError; exports.captureProperty = _chunk3FU7DTQEcjs.captureProperty; exports.captureValue = _chunk3FU7DTQEcjs.captureValue; exports.clefFormatter = _chunk3FU7DTQEcjs.clefFormatter; exports.closeAndFlush = _chunk3FU7DTQEcjs.closeAndFlush; exports.closeOnExit = closeOnExit; exports.conditional = _chunk3FU7DTQEcjs.conditional; exports.configure = _chunk3FU7DTQEcjs.configure; exports.consoleSink = _chunk3FU7DTQEcjs.consoleSink; exports.createLogger = _chunk3FU7DTQEcjs.createLogger; exports.detectColors = _chunk3FU7DTQEcjs.detectColors; exports.diagnosticContext = _chunk3FU7DTQEcjs.diagnosticContext; exports.fileSink = fileSink; exports.formatDate = _chunk3FU7DTQEcjs.formatDate; exports.formatError = _chunk3FU7DTQEcjs.formatError; exports.formatLevel = _chunk3FU7DTQEcjs.formatLevel; exports.formatNumber = _chunk3FU7DTQEcjs.formatNumber; exports.fromLogContext = _chunk3FU7DTQEcjs.fromLogContext; exports.httpSink = _chunk3FU7DTQEcjs.httpSink; exports.interceptConsole = interceptConsole; exports.isLevel = _chunk3FU7DTQEcjs.isLevel; exports.isoTimestamp = _chunk3FU7DTQEcjs.isoTimestamp; exports.jsonFormatter = _chunk3FU7DTQEcjs.jsonFormatter; exports.jsonReplacer = _chunk3FU7DTQEcjs.jsonReplacer; exports.levelAtLeast = _chunk3FU7DTQEcjs.levelAtLeast; exports.log = _chunk3FU7DTQEcjs.log; exports.mapSink = _chunk3FU7DTQEcjs.mapSink; exports.memorySink = _chunk3FU7DTQEcjs.memorySink; exports.parseLevel = _chunk3FU7DTQEcjs.parseLevel; exports.parseTemplate = _chunk3FU7DTQEcjs.parseTemplate; exports.prettyFormatter = _chunk3FU7DTQEcjs.prettyFormatter; exports.rateLimited = _chunk3FU7DTQEcjs.rateLimited; exports.renderTemplate = _chunk3FU7DTQEcjs.renderTemplate; exports.renderValue = _chunk3FU7DTQEcjs.renderValue; exports.resolveFormatter = _chunk3FU7DTQEcjs.resolveFormatter; exports.resolveLevel = _chunk3FU7DTQEcjs.resolveLevel; exports.resolveStyles = _chunk3FU7DTQEcjs.resolveStyles; exports.restricted = _chunk3FU7DTQEcjs.restricted; exports.sampled = _chunk3FU7DTQEcjs.sampled; exports.selfLog = _chunk3FU7DTQEcjs.selfLog; exports.seqSink = _chunk3FU7DTQEcjs.seqSink; exports.streamSink = _chunk3FU7DTQEcjs.streamSink; exports.templateHash = _chunk3FU7DTQEcjs.templateHash; exports.textFormatter = _chunk3FU7DTQEcjs.textFormatter; exports.toJson = _chunk3FU7DTQEcjs.toJson; exports.withComputed = _chunk3FU7DTQEcjs.withComputed; exports.withEnvironment = _chunk3FU7DTQEcjs.withEnvironment; exports.withMachineName = withMachineName; exports.withProcessId = withProcessId; exports.withProcessInfo = withProcessInfo; exports.withProperties = _chunk3FU7DTQEcjs.withProperties; exports.withProperty = _chunk3FU7DTQEcjs.withProperty; exports.withTraceContext = _chunk3FU7DTQEcjs.withTraceContext;
341
+ //# sourceMappingURL=node.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/logit/logit/packages/logit/dist/node.cjs","../src/node.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACA;ACnEA,0CAAkC;AAClC,wBAAgI;AAChI,wBAAyB;AACzB,4BAA0D;AAC1D,4BAAqC;AAcrC,GAAA,CAAI,CAAC,4BAAA,CAAW,OAAA,EAAS,4BAAA,CAAW,GAAA,CAAI,IAAI,mCAAA,CAAkB,CAAC,CAAA;AAExD,SAAS,eAAA,CAAA,EAA4B;AAC1C,EAAA,MAAM,KAAA,EAAO,0BAAA,CAAS;AACtB,EAAA,OAAO,CAAC,KAAA,EAAA,GAAU,KAAA,CAAM,mBAAA,CAAoB,aAAA,EAAe,IAAI,CAAA;AACjE;AAEO,SAAS,aAAA,CAAA,EAA0B;AACxC,EAAA,MAAM,IAAA,EAAM,OAAA,CAAQ,GAAA;AACpB,EAAA,OAAO,CAAC,KAAA,EAAA,GAAU,KAAA,CAAM,mBAAA,CAAoB,WAAA,EAAa,GAAG,CAAA;AAC9D;AAGO,SAAS,eAAA,CAAA,EAA4B;AAC1C,EAAA,MAAM,KAAA,EAAO,0BAAA,CAAS;AACtB,EAAA,MAAM,IAAA,EAAM,OAAA,CAAQ,GAAA;AACpB,EAAA,MAAM,IAAA,EAAM,OAAA,CAAQ,GAAA,CAAI,QAAA;AACxB,EAAA,OAAO,CAAC,KAAA,EAAA,GAAU;AAChB,IAAA,KAAA,CAAM,mBAAA,CAAoB,aAAA,EAAe,IAAI,CAAA;AAC7C,IAAA,KAAA,CAAM,mBAAA,CAAoB,WAAA,EAAa,GAAG,CAAA;AAC1C,IAAA,GAAA,CAAI,GAAA,EAAK,KAAA,CAAM,mBAAA,CAAoB,aAAA,EAAe,GAAG,CAAA;AAAA,EACvD,CAAA;AACF;AA0BO,SAAS,QAAA,CAAS,OAAA,EAAgC;AACvD,EAAA,MAAM,UAAA,EAAY,gDAAA,OAAiB,CAAQ,MAAA,EAAQ,EAAE,cAAA,EAAgB,OAAA,CAAQ,cAAA,EAAgB,MAAA,EAAQ,KAAA,EAAO,GAAA,EAAK,OAAA,CAAQ,IAAI,CAAA,EAAG,MAAM,CAAA;AACtI,EAAA,MAAM,OAAA,EAAS,2BAAA,OAAQ,CAAQ,IAAI,CAAA;AACnC,EAAA,MAAM,IAAA,EAAM,2BAAA,MAAc,CAAA;AAC1B,EAAA,MAAM,IAAA,EAAM,2BAAA,MAAc,CAAA;AAC1B,EAAA,MAAM,KAAA,EAAO,4BAAA,MAAS,EAAQ,GAAG,CAAA;AACjC,EAAA,MAAM,QAAA,mBAAU,OAAA,CAAQ,OAAA,UAAW,QAAA;AACnC,EAAA,MAAM,SAAA,mBAAW,OAAA,CAAQ,QAAA,UAAY,UAAA;AACrC,EAAA,MAAM,SAAA,mBAAW,OAAA,CAAQ,iBAAA,UAAqB,UAAA;AAC9C,EAAA,MAAM,IAAA,mBAAM,OAAA,CAAQ,GAAA,UAAO,OAAA;AAE3B,EAAA,IAAI,GAAA,EAAoB,IAAA;AACxB,EAAA,IAAI,cAAA,EAAgB,EAAA;AACpB,EAAA,IAAI,YAAA,EAAc,EAAA;AAClB,EAAA,IAAI,KAAA,EAAO,CAAA;AACX,EAAA,IAAI,SAAA,EAAW,CAAA;AAEf,EAAA,MAAM,OAAA,EAAS,CAAC,IAAA,EAAA,GAAuB;AACrC,IAAA,GAAA,CAAI,QAAA,IAAY,MAAA,EAAQ,OAAO,EAAA;AAC/B,IAAA,MAAM,EAAA,EAAI,CAAC,CAAA,EAAA,GAAc,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AAClD,IAAA,MAAM,EAAA,EAAI,IAAA,EAAM,IAAA,CAAK,cAAA,CAAe,EAAA,EAAI,IAAA,CAAK,WAAA,CAAY,CAAA;AACzD,IAAA,MAAM,GAAA,EAAK,CAAA,CAAA,CAAG,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,EAAA,EAAI,IAAA,CAAK,QAAA,CAAS,CAAA,EAAA,EAAK,CAAC,CAAA;AAC7D,IAAA,MAAM,EAAA,EAAI,CAAA,CAAE,IAAA,EAAM,IAAA,CAAK,UAAA,CAAW,EAAA,EAAI,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AACpD,IAAA,MAAM,EAAA,EAAI,CAAA,CAAE,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,EAAA,EAAI,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA;AACtD,IAAA,MAAM,GAAA,EAAK,CAAA,CAAE,IAAA,EAAM,IAAA,CAAK,aAAA,CAAc,EAAA,EAAI,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA;AAC3D,IAAA,OAAA,CAAQ,OAAA,EAAS;AAAA,MACf,KAAK,OAAA;AACH,QAAA,OAAO,CAAA,EAAA;AACJ,MAAA;AACI,QAAA;AACJ,MAAA;AACI,QAAA;AACJ,MAAA;AACI,QAAA;AACT,MAAA;AACS,QAAA;AACX,IAAA;AACF,EAAA;AAEM,EAAA;AAEA,EAAA;AAEQ,EAAA;AACD,IAAA;AACC,MAAA;AACL,MAAA;AACP,IAAA;AACY,IAAA;AAED,IAAA;AACA,IAAA;AACF,MAAA;AACT,IAAA;AACA,IAAA;AACK,IAAA;AACE,IAAA;AACP,IAAA;AACM,IAAA;AACR,EAAA;AAEc,EAAA;AACA,IAAA;AACR,IAAA;AACI,MAAA;AAIN,MAAA;AACM,QAAA;AACJ,QAAA;AACF,MAAA;AACO,IAAA;AACC,MAAA;AACV,IAAA;AACF,EAAA;AAEO,EAAA;AACC,IAAA;AACN,IAAA;AACO,IAAA;AACe,IAAA;AACd,MAAA;AAA0B;AACtB,MAAA;AACN,MAAA;AACK,MAAA;AACP,QAAA;AACK,QAAA;AACL,QAAA;AACM,QAAA;AACF,QAAA;AAEF,UAAA;AACF,QAAA;AACA,QAAA;AACK,QAAA;AACE,QAAA;AACD,QAAA;AACR,MAAA;AACM,MAAA;AACI,MAAA;AACF,MAAA;AACV,IAAA;AACQ,IAAA;AACF,MAAA;AACF,QAAA;AACK,QAAA;AACP,MAAA;AACF,IAAA;AAAA;AAEI,IAAA;AACK,MAAA;AACT,IAAA;AACF,EAAA;AACF;AAiBgB;AACF,EAAA;AACL,IAAA;AACC,IAAA;AACC,IAAA;AACD,IAAA;AACC,IAAA;AACA,IAAA;AACI,IAAA;AACb,EAAA;AACM,EAAA;AACA,EAAA;AACK,EAAA;AACA,IAAA;AACH,IAAA;AACE,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACK,MAAA;AACN,MAAA;AACP,IAAA;AACF,EAAA;AACa,EAAA;AACA,IAAA;AACb,EAAA;AACF;AAWM;AAOU;AACR,EAAA;AACO,EAAA;AACuB,EAAA;AACtB,EAAA;AAER,EAAA;AACO,IAAA;AACb,EAAA;AACM,EAAA;AACO,IAAA;AACC,MAAA;AACX,IAAA;AACH,EAAA;AACM,EAAA;AACG,IAAA;AACI,IAAA;AACC,MAAA;AACX,IAAA;AACH,EAAA;AACM,EAAA;AACA,EAAA;AAEK,EAAA;AACA,EAAA;AACC,EAAA;AACC,IAAA;AACA,IAAA;AACb,EAAA;AACa,EAAA;AACC,IAAA;AACD,IAAA;AACC,IAAA;AACA,IAAA;AACd,EAAA;AACF;ADlBgB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/logit/logit/packages/logit/dist/node.cjs","sourcesContent":[null,"/**\n * `@unhingged/logit/node` — the parts that need Node's built-ins: a rolling\n * file sink, host / process enrichers, capturing `console.*`, and\n * flush-on-exit. Everything isomorphic is re-exported, so one import does.\n */\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { closeSync, existsSync, fstatSync, mkdirSync, openSync, readdirSync, renameSync, statSync, unlinkSync, writeSync } from 'node:fs';\nimport { hostname } from 'node:os';\nimport { basename, dirname, extname, join, resolve } from 'node:path';\nimport { format as utilFormat } from 'node:util';\nimport { LogContext } from './context';\nimport type { Enricher } from './enrichers';\nimport type { LogEvent } from './event';\nimport { type FormatName, resolveFormatter } from './format';\nimport type { Formatter } from './format/types';\nimport { type LogLevel, parseLevel } from './levels';\nimport type { Logger } from './logger';\nimport { selfLog } from './selflog';\nimport type { Sink, SinkOptions } from './sinks/types';\n\nexport * from './index';\n\n// Make sure ambient context follows async execution even where detection failed.\nif (!LogContext.isAsync) LogContext.use(new AsyncLocalStorage());\n\nexport function withMachineName(): Enricher {\n const name = hostname();\n return (event) => event.addPropertyIfAbsent('MachineName', name);\n}\n\nexport function withProcessId(): Enricher {\n const pid = process.pid;\n return (event) => event.addPropertyIfAbsent('ProcessId', pid);\n}\n\n/** `MachineName`, `ProcessId` and `Environment` in one go. */\nexport function withProcessInfo(): Enricher {\n const name = hostname();\n const pid = process.pid;\n const env = process.env.NODE_ENV;\n return (event) => {\n event.addPropertyIfAbsent('MachineName', name);\n event.addPropertyIfAbsent('ProcessId', pid);\n if (env) event.addPropertyIfAbsent('Environment', env);\n };\n}\n\nexport type RollingInterval = 'none' | 'minute' | 'hour' | 'day' | 'month';\n\nexport interface FileSinkOptions extends SinkOptions {\n /** `logs/app.log`. With a rolling interval the date goes before the extension: `logs/app-20261008.log`. */\n path: string;\n format?: FormatName | Formatter;\n outputTemplate?: string;\n utc?: boolean;\n /** Start a new file every minute / hour / day / month. Default `'none'`. */\n rolling?: RollingInterval;\n /** Start a new file when the current one exceeds this many bytes (`_001`, `_002`… suffixes). */\n maxBytes?: number;\n /** Keep only this many files for the path; older ones are deleted on roll. */\n retainedFileCount?: number;\n /** Also create the directory. Default true. */\n mkdir?: boolean;\n}\n\n/**\n * Appends one line per event to a file with synchronous writes — nothing is\n * lost when the process dies, at the cost of a syscall per event (fine for\n * the usual thousands of events a second; put a batching sink in front for\n * more). Rolls by time, by size, or both, and prunes old files.\n */\nexport function fileSink(options: FileSinkOptions): Sink {\n const formatter = resolveFormatter(options.format, { outputTemplate: options.outputTemplate, colors: false, utc: options.utc }, 'json');\n const target = resolve(options.path);\n const dir = dirname(target);\n const ext = extname(target);\n const stem = basename(target, ext);\n const rolling = options.rolling ?? 'none';\n const maxBytes = options.maxBytes ?? Infinity;\n const retained = options.retainedFileCount ?? Infinity;\n const utc = options.utc ?? false;\n\n let fd: number | null = null;\n let currentPeriod = '';\n let currentPath = '';\n let size = 0;\n let sequence = 0;\n\n const period = (date: Date): string => {\n if (rolling === 'none') return '';\n const p = (n: number) => String(n).padStart(2, '0');\n const y = utc ? date.getUTCFullYear() : date.getFullYear();\n const mo = p((utc ? date.getUTCMonth() : date.getMonth()) + 1);\n const d = p(utc ? date.getUTCDate() : date.getDate());\n const h = p(utc ? date.getUTCHours() : date.getHours());\n const mi = p(utc ? date.getUTCMinutes() : date.getMinutes());\n switch (rolling) {\n case 'month':\n return `${y}${mo}`;\n case 'day':\n return `${y}${mo}${d}`;\n case 'hour':\n return `${y}${mo}${d}${h}`;\n case 'minute':\n return `${y}${mo}${d}${h}${mi}`;\n default:\n return '';\n }\n };\n\n const fileName = (p: string, seq: number): string => `${stem}${p ? `-${p}` : ''}${seq ? `_${String(seq).padStart(3, '0')}` : ''}${ext}`;\n\n const isOurs = (name: string): boolean => name.startsWith(stem) && name.endsWith(ext) && /^[-_0-9]*$/.test(name.slice(stem.length, name.length - ext.length));\n\n const open = (p: string): void => {\n if (fd !== null) {\n closeSync(fd);\n fd = null;\n }\n if (options.mkdir ?? true) mkdirSync(dir, { recursive: true });\n // Find the first free sequence number for the period, continuing where a previous run left off.\n sequence = 0;\n if (Number.isFinite(maxBytes)) {\n while (existsSync(join(dir, fileName(p, sequence))) && statSync(join(dir, fileName(p, sequence))).size >= maxBytes) sequence++;\n }\n currentPath = join(dir, fileName(p, sequence));\n fd = openSync(currentPath, 'a');\n size = fstatSync(fd).size;\n currentPeriod = p;\n prune();\n };\n\n const prune = (): void => {\n if (!Number.isFinite(retained)) return;\n try {\n const files = readdirSync(dir)\n .filter(isOurs)\n .map((name) => ({ name, mtime: statSync(join(dir, name)).mtimeMs }))\n .sort((a, b) => b.mtime - a.mtime || b.name.localeCompare(a.name));\n for (const file of files.slice(retained)) {\n if (join(dir, file.name) === currentPath) continue;\n unlinkSync(join(dir, file.name));\n }\n } catch (error) {\n selfLog.write(`fileSink: pruning ${dir} failed`, error);\n }\n };\n\n return {\n name: `file(${options.path})`,\n restrictedToMinimumLevel: options.restrictedToMinimumLevel,\n audit: options.audit,\n emit(event: LogEvent) {\n const line = `${formatter(event)}\\n`;\n const p = period(event.timestamp);\n if (fd === null || p !== currentPeriod) open(p);\n else if (size + line.length > maxBytes && size > 0) {\n closeSync(fd!);\n fd = null;\n sequence++;\n const next = join(dir, fileName(p, sequence));\n if (existsSync(next)) {\n // A previous run filled this number too: keep going until a free one.\n while (existsSync(join(dir, fileName(p, sequence)))) sequence++;\n }\n currentPath = join(dir, fileName(p, sequence));\n fd = openSync(currentPath, 'a');\n size = 0;\n prune();\n }\n const bytes = Buffer.byteLength(line);\n writeSync(fd!, line);\n size += bytes;\n },\n close() {\n if (fd !== null) {\n closeSync(fd);\n fd = null;\n }\n },\n /** @internal for tests */\n get currentPath() {\n return currentPath;\n },\n } as Sink & { readonly currentPath: string };\n}\n\n/** Renames `a.log` to `a.log.1`… — kept simple on purpose; `renameSync` is here for size rolling of a fixed name if ever needed. */\nvoid renameSync;\n\nexport interface InterceptConsoleOptions {\n /** Map console methods to levels. Default: log/info → info, debug → debug, warn → warn, error/trace → error. */\n levels?: Partial<Record<'log' | 'info' | 'debug' | 'warn' | 'error' | 'trace', LogLevel | string>>;\n /** `SourceContext` for the captured lines. Default `'console'`. */\n source?: string;\n}\n\n/**\n * Routes `console.log` and friends through a logger, so a framework's own\n * output (Next.js, a dependency's warnings) comes out in the same format and\n * goes to the same sinks. Returns a function that restores the console.\n */\nexport function interceptConsole(logger: Logger, options: InterceptConsoleOptions = {}): () => void {\n const map = {\n log: 'info',\n info: 'info',\n debug: 'debug',\n warn: 'warn',\n error: 'error',\n trace: 'error',\n ...options.levels,\n } as const;\n const source = logger.forSource(options.source ?? 'console');\n const original: Partial<Record<keyof typeof map, (...args: unknown[]) => void>> = {};\n for (const method of Object.keys(map) as Array<keyof typeof map>) {\n original[method] = console[method] as (...args: unknown[]) => void;\n const level = parseLevel(map[method]);\n console[method] = ((...args: unknown[]) => {\n const error = args.find((a): a is Error => a instanceof Error);\n const rest = error ? args.filter((a) => a !== error) : args;\n const text = rest.length ? utilFormat(...rest) : error ? error.message : '';\n if (error) source.write(level, error, '{Message:l}', text);\n else source.write(level, '{Message:l}', text);\n }) as typeof console.log;\n }\n return () => {\n for (const method of Object.keys(original) as Array<keyof typeof map>) console[method] = original[method] as never;\n };\n}\n\nexport interface CloseOnExitOptions {\n /** Signals to handle. Default `['SIGINT', 'SIGTERM']`. Pass `[]` to only hook `beforeExit`. */\n signals?: NodeJS.Signals[];\n /** Exit the process after closing, with 128 + the signal number. Default true. */\n exit?: boolean;\n /** Also log uncaught exceptions and unhandled rejections at `fatal` before exiting. Default true. */\n crashes?: boolean;\n}\n\nconst SIGNAL_NUMBERS: Record<string, number> = { SIGINT: 2, SIGTERM: 15, SIGHUP: 1, SIGQUIT: 3 };\n\n/**\n * Flushes and closes the logger when the process is about to end — on\n * `beforeExit`, on SIGINT / SIGTERM, and (by default) after logging a crash.\n * Register once, at startup. Returns a function that removes the handlers.\n */\nexport function closeOnExit(logger: Logger, options: CloseOnExitOptions = {}): () => void {\n const signals = options.signals ?? ['SIGINT', 'SIGTERM'];\n const exit = options.exit ?? true;\n let closing: Promise<void> | null = null;\n const close = () => (closing ??= logger.close().catch((error) => selfLog.write('close on exit failed', error)));\n\n const onBeforeExit = () => {\n void close();\n };\n const onSignal = (signal: NodeJS.Signals) => {\n void close().then(() => {\n if (exit) process.exit(128 + (SIGNAL_NUMBERS[signal] ?? 0));\n });\n };\n const onCrash = (error: unknown, kind: string) => {\n logger.fatal(error instanceof Error ? error : new Error(String(error)), `{Kind:l} — the process will exit`, kind);\n void close().then(() => {\n if (exit) process.exit(1);\n });\n };\n const onUncaught = (error: unknown) => onCrash(error, 'Uncaught exception');\n const onUnhandled = (reason: unknown) => onCrash(reason, 'Unhandled rejection');\n\n process.on('beforeExit', onBeforeExit);\n for (const signal of signals) process.on(signal, onSignal);\n if (options.crashes ?? true) {\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onUnhandled);\n }\n return () => {\n process.off('beforeExit', onBeforeExit);\n for (const signal of signals) process.off(signal, onSignal);\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onUnhandled);\n };\n}\n"]}
@@ -0,0 +1,58 @@
1
+ import { SinkOptions, FormatName, Formatter, LogLevel, Logger, Sink, Enricher } from './index.cjs';
2
+ export { BatchingOptions, BatchingSink, CLEF_MEDIA_TYPE, CapturedError, ClefFormatterOptions, ConsoleSinkOptions, ContextFrame, ContextHandle, ContextStore, DEFAULT_DESTRUCTURING, DEFAULT_OUTPUT_TEMPLATE, DestructuringOptions, DestructuringPolicy, FetchLike, Filter, HoleToken, HttpSinkOptions, JsonFormatterOptions, LEVELS, LEVEL_CODES, LEVEL_NUMBERS, LEVEL_ORDER, LevelOrSwitch, LevelSwitch, LogContext, LogEvent, LogEventInit, LogMethod, LoggerConfiguration, LoggerOptions, MapSinkOptions, Matching, MemorySink, MessageTemplate, Operation, OperationOptions, PrettyFormatterOptions, RenderOptions, SERILOG_LEVEL_NAMES, SeqSinkOptions, StreamLike, StreamSinkOptions, TemplateToken, TextFormatterOptions, TextToken, TraceContext, ValueStyles, ansi, audit, batchingSink, byExcluding, byIncludingOnly, byTransforming, callbackSink, captureError, captureProperty, captureValue, clefFormatter, closeAndFlush, conditional, configure, consoleSink, createLogger, detectColors, diagnosticContext, formatDate, formatError, formatLevel, formatNumber, fromLogContext, httpSink, isLevel, isoTimestamp, jsonFormatter, jsonReplacer, levelAtLeast, log, mapSink, memorySink, parseLevel, parseTemplate, prettyFormatter, rateLimited, renderTemplate, renderValue, resolveFormatter, resolveLevel, resolveStyles, restricted, sampled, selfLog, seqSink, streamSink, templateHash, textFormatter, toJson, withComputed, withEnvironment, withProperties, withProperty, withTraceContext } from './index.cjs';
3
+
4
+ declare function withMachineName(): Enricher;
5
+ declare function withProcessId(): Enricher;
6
+ /** `MachineName`, `ProcessId` and `Environment` in one go. */
7
+ declare function withProcessInfo(): Enricher;
8
+ type RollingInterval = 'none' | 'minute' | 'hour' | 'day' | 'month';
9
+ interface FileSinkOptions extends SinkOptions {
10
+ /** `logs/app.log`. With a rolling interval the date goes before the extension: `logs/app-20261008.log`. */
11
+ path: string;
12
+ format?: FormatName | Formatter;
13
+ outputTemplate?: string;
14
+ utc?: boolean;
15
+ /** Start a new file every minute / hour / day / month. Default `'none'`. */
16
+ rolling?: RollingInterval;
17
+ /** Start a new file when the current one exceeds this many bytes (`_001`, `_002`… suffixes). */
18
+ maxBytes?: number;
19
+ /** Keep only this many files for the path; older ones are deleted on roll. */
20
+ retainedFileCount?: number;
21
+ /** Also create the directory. Default true. */
22
+ mkdir?: boolean;
23
+ }
24
+ /**
25
+ * Appends one line per event to a file with synchronous writes — nothing is
26
+ * lost when the process dies, at the cost of a syscall per event (fine for
27
+ * the usual thousands of events a second; put a batching sink in front for
28
+ * more). Rolls by time, by size, or both, and prunes old files.
29
+ */
30
+ declare function fileSink(options: FileSinkOptions): Sink;
31
+ interface InterceptConsoleOptions {
32
+ /** Map console methods to levels. Default: log/info → info, debug → debug, warn → warn, error/trace → error. */
33
+ levels?: Partial<Record<'log' | 'info' | 'debug' | 'warn' | 'error' | 'trace', LogLevel | string>>;
34
+ /** `SourceContext` for the captured lines. Default `'console'`. */
35
+ source?: string;
36
+ }
37
+ /**
38
+ * Routes `console.log` and friends through a logger, so a framework's own
39
+ * output (Next.js, a dependency's warnings) comes out in the same format and
40
+ * goes to the same sinks. Returns a function that restores the console.
41
+ */
42
+ declare function interceptConsole(logger: Logger, options?: InterceptConsoleOptions): () => void;
43
+ interface CloseOnExitOptions {
44
+ /** Signals to handle. Default `['SIGINT', 'SIGTERM']`. Pass `[]` to only hook `beforeExit`. */
45
+ signals?: NodeJS.Signals[];
46
+ /** Exit the process after closing, with 128 + the signal number. Default true. */
47
+ exit?: boolean;
48
+ /** Also log uncaught exceptions and unhandled rejections at `fatal` before exiting. Default true. */
49
+ crashes?: boolean;
50
+ }
51
+ /**
52
+ * Flushes and closes the logger when the process is about to end — on
53
+ * `beforeExit`, on SIGINT / SIGTERM, and (by default) after logging a crash.
54
+ * Register once, at startup. Returns a function that removes the handlers.
55
+ */
56
+ declare function closeOnExit(logger: Logger, options?: CloseOnExitOptions): () => void;
57
+
58
+ export { type CloseOnExitOptions, Enricher, type FileSinkOptions, FormatName, Formatter, type InterceptConsoleOptions, LogLevel, Logger, type RollingInterval, Sink, SinkOptions, closeOnExit, fileSink, interceptConsole, withMachineName, withProcessId, withProcessInfo };