@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.
@@ -0,0 +1,2117 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/levels.ts
9
+ var LEVELS = ["verbose", "debug", "info", "warn", "error", "fatal"];
10
+ var LEVEL_ORDER = {
11
+ verbose: 0,
12
+ debug: 1,
13
+ info: 2,
14
+ warn: 3,
15
+ error: 4,
16
+ fatal: 5
17
+ };
18
+ var SERILOG_LEVEL_NAMES = {
19
+ verbose: "Verbose",
20
+ debug: "Debug",
21
+ info: "Information",
22
+ warn: "Warning",
23
+ error: "Error",
24
+ fatal: "Fatal"
25
+ };
26
+ var LEVEL_CODES = {
27
+ verbose: "VRB",
28
+ debug: "DBG",
29
+ info: "INF",
30
+ warn: "WRN",
31
+ error: "ERR",
32
+ fatal: "FTL"
33
+ };
34
+ var LEVEL_NUMBERS = {
35
+ verbose: 10,
36
+ debug: 20,
37
+ info: 30,
38
+ warn: 40,
39
+ error: 50,
40
+ fatal: 60
41
+ };
42
+ var ALIASES = {
43
+ verbose: "verbose",
44
+ trace: "verbose",
45
+ vrb: "verbose",
46
+ debug: "debug",
47
+ dbg: "debug",
48
+ info: "info",
49
+ information: "info",
50
+ informational: "info",
51
+ inf: "info",
52
+ warn: "warn",
53
+ warning: "warn",
54
+ wrn: "warn",
55
+ error: "error",
56
+ err: "error",
57
+ fatal: "fatal",
58
+ critical: "fatal",
59
+ crit: "fatal",
60
+ ftl: "fatal",
61
+ silent: "fatal"
62
+ };
63
+ function parseLevel(input) {
64
+ if (typeof input === "number") {
65
+ if (input <= 10) return "verbose";
66
+ if (input <= 20) return "debug";
67
+ if (input <= 30) return "info";
68
+ if (input <= 40) return "warn";
69
+ if (input <= 50) return "error";
70
+ return "fatal";
71
+ }
72
+ const level = ALIASES[String(input).trim().toLowerCase()];
73
+ if (!level) throw new Error(`logit: unknown log level "${input}" (expected one of ${LEVELS.join(", ")})`);
74
+ return level;
75
+ }
76
+ function isLevel(input) {
77
+ return typeof input === "string" && Object.prototype.hasOwnProperty.call(LEVEL_ORDER, input);
78
+ }
79
+ function levelAtLeast(level, minimum) {
80
+ return LEVEL_ORDER[level] >= LEVEL_ORDER[minimum];
81
+ }
82
+ var LevelSwitch = class {
83
+ #level;
84
+ #listeners = /* @__PURE__ */ new Set();
85
+ constructor(initial = "info") {
86
+ this.#level = parseLevel(initial);
87
+ }
88
+ get level() {
89
+ return this.#level;
90
+ }
91
+ set level(next) {
92
+ const parsed = parseLevel(next);
93
+ if (parsed === this.#level) return;
94
+ this.#level = parsed;
95
+ for (const listener of this.#listeners) listener(parsed);
96
+ }
97
+ /** Called with the new level on every change; returns an unsubscribe function. */
98
+ onChange(listener) {
99
+ this.#listeners.add(listener);
100
+ return () => this.#listeners.delete(listener);
101
+ }
102
+ };
103
+ function resolveLevel(value) {
104
+ return value instanceof LevelSwitch ? value.level : parseLevel(value);
105
+ }
106
+
107
+ // src/template.ts
108
+ var HOLE = /^([@$])?([0-9A-Za-z_]+)(?:,(-?\d+))?(?::([^}]+))?$/;
109
+ var CACHE_LIMIT = 2e3;
110
+ var cache = /* @__PURE__ */ new Map();
111
+ function parseTemplate(raw) {
112
+ const cached = cache.get(raw);
113
+ if (cached) return cached;
114
+ const parsed = parse(raw);
115
+ if (cache.size >= CACHE_LIMIT) cache.clear();
116
+ cache.set(raw, parsed);
117
+ return parsed;
118
+ }
119
+ function parse(raw) {
120
+ const tokens = [];
121
+ const holes = [];
122
+ let text = "";
123
+ let i = 0;
124
+ const n = raw.length;
125
+ while (i < n) {
126
+ const ch = raw[i];
127
+ if (ch === "{") {
128
+ if (raw[i + 1] === "{") {
129
+ text += "{";
130
+ i += 2;
131
+ continue;
132
+ }
133
+ const close = raw.indexOf("}", i + 1);
134
+ if (close !== -1) {
135
+ const body = raw.slice(i + 1, close);
136
+ const m = HOLE.exec(body);
137
+ if (m) {
138
+ if (text) {
139
+ tokens.push({ kind: "text", text });
140
+ text = "";
141
+ }
142
+ const name = m[2];
143
+ const isIndex = /^\d+$/.test(name);
144
+ const hole = {
145
+ kind: "hole",
146
+ raw: raw.slice(i, close + 1),
147
+ name,
148
+ ...isIndex ? { index: Number(name) } : {},
149
+ ...m[1] ? { operator: m[1] } : {},
150
+ ...m[3] !== void 0 ? { alignment: Number(m[3]) } : {},
151
+ ...m[4] !== void 0 ? { format: m[4] } : {}
152
+ };
153
+ tokens.push(hole);
154
+ holes.push(hole);
155
+ i = close + 1;
156
+ continue;
157
+ }
158
+ }
159
+ text += "{";
160
+ i += 1;
161
+ continue;
162
+ }
163
+ if (ch === "}" && raw[i + 1] === "}") {
164
+ text += "}";
165
+ i += 2;
166
+ continue;
167
+ }
168
+ text += ch;
169
+ i += 1;
170
+ }
171
+ if (text) tokens.push({ kind: "text", text });
172
+ const positional = holes.length > 0 && holes.every((h) => h.index !== void 0);
173
+ return { raw, tokens, holes, positional };
174
+ }
175
+ function templateHash(raw) {
176
+ let hash = 0;
177
+ for (let i = 0; i < raw.length; i++) {
178
+ hash = hash + raw.charCodeAt(i) >>> 0;
179
+ hash = hash + (hash << 10) >>> 0;
180
+ hash = (hash ^ hash >>> 6) >>> 0;
181
+ }
182
+ hash = hash + (hash << 3) >>> 0;
183
+ hash = (hash ^ hash >>> 11) >>> 0;
184
+ hash = hash + (hash << 15) >>> 0;
185
+ return hash.toString(16).padStart(8, "0");
186
+ }
187
+ function align(text, alignment) {
188
+ if (!alignment) return text;
189
+ const width = Math.abs(alignment);
190
+ if (text.length >= width) return text;
191
+ return alignment > 0 ? text.padStart(width) : text.padEnd(width);
192
+ }
193
+
194
+ // src/capture.ts
195
+ var DEFAULT_DESTRUCTURING = {
196
+ maxDepth: 10,
197
+ maxStringLength: Infinity,
198
+ maxCollectionCount: Infinity,
199
+ redact: [],
200
+ redactedValue: "[Redacted]",
201
+ policies: [],
202
+ typeTag: true
203
+ };
204
+ function resolveDestructuring(partial) {
205
+ return { ...DEFAULT_DESTRUCTURING, ...partial };
206
+ }
207
+ function byTransforming(type, transform) {
208
+ return (value) => value instanceof type ? { value: transform(value) } : void 0;
209
+ }
210
+ var PLAIN_PROTOS = /* @__PURE__ */ new Set([Object.prototype, null]);
211
+ function isPlainObject(value) {
212
+ return PLAIN_PROTOS.has(Object.getPrototypeOf(value));
213
+ }
214
+ function className(value) {
215
+ const name = value.constructor?.name;
216
+ return typeof name === "string" && name.length > 0 && name !== "Object" ? name : void 0;
217
+ }
218
+ function truncate(text, max) {
219
+ return text.length > max ? `${text.slice(0, max)}\u2026` : text;
220
+ }
221
+ function compileRedact(rules) {
222
+ return rules.map((rule) => rule.includes(".") ? { path: rule.toLowerCase().split(".") } : { key: rule.toLowerCase() });
223
+ }
224
+ var redactCache = /* @__PURE__ */ new WeakMap();
225
+ function redactRules(options) {
226
+ let rules = redactCache.get(options.redact);
227
+ if (!rules) {
228
+ rules = compileRedact(options.redact);
229
+ redactCache.set(options.redact, rules);
230
+ }
231
+ return rules;
232
+ }
233
+ function isRedacted(rules, path) {
234
+ if (rules.length === 0) return false;
235
+ const last = path[path.length - 1];
236
+ for (const rule of rules) {
237
+ if (rule.key !== void 0) {
238
+ if (rule.key === last) return true;
239
+ continue;
240
+ }
241
+ const segs = rule.path;
242
+ if (segs.length !== path.length) continue;
243
+ let ok = true;
244
+ for (let i = 0; i < segs.length; i++) {
245
+ if (segs[i] !== "*" && segs[i] !== path[i]) {
246
+ ok = false;
247
+ break;
248
+ }
249
+ }
250
+ if (ok) return true;
251
+ }
252
+ return false;
253
+ }
254
+ function captureValue(value, operator, options, path = [], seen = /* @__PURE__ */ new Set(), depth = 0) {
255
+ switch (typeof value) {
256
+ case "string":
257
+ return truncate(value, options.maxStringLength);
258
+ case "number":
259
+ return Number.isFinite(value) ? value : String(value);
260
+ case "boolean":
261
+ return value;
262
+ case "undefined":
263
+ return null;
264
+ case "bigint":
265
+ return Number.isSafeInteger(Number(value)) ? Number(value) : value.toString();
266
+ case "symbol":
267
+ return value.toString();
268
+ case "function":
269
+ return `[Function${value.name ? ` ${value.name}` : ""}]`;
270
+ case "object":
271
+ if (value === null) return null;
272
+ return captureObject(value, operator, options, path, seen, depth);
273
+ default:
274
+ return String(value);
275
+ }
276
+ }
277
+ function captureProperty(name, value, operator, options) {
278
+ const path = [name.toLowerCase()];
279
+ if (isRedacted(redactRules(options), path)) return options.redactedValue;
280
+ return captureValue(value, operator, options, path);
281
+ }
282
+ function captureObject(value, operator, options, path, seen, depth) {
283
+ if (operator === "$") return stringify(value, options);
284
+ for (const policy of options.policies) {
285
+ let answer;
286
+ try {
287
+ answer = policy(value);
288
+ } catch {
289
+ answer = void 0;
290
+ }
291
+ if (answer) return captureValue(answer.value, void 0, options, path, seen, depth);
292
+ }
293
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
294
+ if (value instanceof Error) return captureError(value, options, path, seen, depth);
295
+ if (seen.has(value)) return "[Circular]";
296
+ if (depth >= options.maxDepth) return Array.isArray(value) ? "[Array]" : "[Object]";
297
+ if (Array.isArray(value)) return captureArray(value, options, path, seen, depth);
298
+ if (value instanceof Set) return captureArray(Array.from(value), options, path, seen, depth);
299
+ if (value instanceof Map) return captureMap(value, options, path, seen, depth);
300
+ if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
301
+ return captureArray(Array.from(value), options, path, seen, depth);
302
+ }
303
+ const plain = isPlainObject(value);
304
+ if (!plain && operator !== "@") return stringify(value, options);
305
+ return captureStructure(value, plain, options, path, seen, depth);
306
+ }
307
+ function stringify(value, options) {
308
+ const asString = value.toString;
309
+ if (typeof asString === "function" && asString !== Object.prototype.toString && asString !== Error.prototype.toString) {
310
+ try {
311
+ return truncate(String(value), options.maxStringLength);
312
+ } catch {
313
+ }
314
+ }
315
+ const toJSON = value.toJSON;
316
+ if (typeof toJSON === "function") {
317
+ try {
318
+ const json = toJSON.call(value);
319
+ if (typeof json === "string") return truncate(json, options.maxStringLength);
320
+ if (json !== null && typeof json === "object") return captureValue(json, "@", options);
321
+ return json;
322
+ } catch {
323
+ }
324
+ }
325
+ if (Array.isArray(value)) return `[Array(${value.length})]`;
326
+ return className(value) ?? "[object Object]";
327
+ }
328
+ function captureArray(items, options, path, seen, depth) {
329
+ seen.add(items);
330
+ const limit = Math.min(items.length, options.maxCollectionCount);
331
+ const out = new Array(limit);
332
+ for (let i = 0; i < limit; i++) out[i] = captureValue(items[i], "@", options, path, seen, depth + 1);
333
+ seen.delete(items);
334
+ return out;
335
+ }
336
+ function captureMap(map, options, path, seen, depth) {
337
+ seen.add(map);
338
+ const rules = redactRules(options);
339
+ let count = 0;
340
+ let allScalarKeys = true;
341
+ for (const key of map.keys()) {
342
+ if (typeof key !== "string" && typeof key !== "number") {
343
+ allScalarKeys = false;
344
+ break;
345
+ }
346
+ }
347
+ let result;
348
+ if (allScalarKeys) {
349
+ const out = {};
350
+ for (const [key, item] of map) {
351
+ if (count++ >= options.maxCollectionCount) break;
352
+ const name = String(key);
353
+ const next = [...path, name.toLowerCase()];
354
+ out[name] = isRedacted(rules, next) ? options.redactedValue : captureValue(item, "@", options, next, seen, depth + 1);
355
+ }
356
+ result = out;
357
+ } else {
358
+ const out = [];
359
+ for (const [key, item] of map) {
360
+ if (count++ >= options.maxCollectionCount) break;
361
+ out.push([captureValue(key, "@", options, path, seen, depth + 1), captureValue(item, "@", options, path, seen, depth + 1)]);
362
+ }
363
+ result = out;
364
+ }
365
+ seen.delete(map);
366
+ return result;
367
+ }
368
+ function captureStructure(value, plain, options, path, seen, depth) {
369
+ seen.add(value);
370
+ const rules = redactRules(options);
371
+ const out = {};
372
+ if (!plain && options.typeTag) {
373
+ const name = className(value);
374
+ if (name) out.$type = name;
375
+ }
376
+ for (const key of Object.keys(value)) {
377
+ const next = [...path, key.toLowerCase()];
378
+ if (isRedacted(rules, next)) {
379
+ out[key] = options.redactedValue;
380
+ continue;
381
+ }
382
+ let item;
383
+ try {
384
+ item = value[key];
385
+ } catch (error) {
386
+ item = `[Throws: ${error instanceof Error ? error.message : String(error)}]`;
387
+ }
388
+ out[key] = captureValue(item, "@", options, next, seen, depth + 1);
389
+ }
390
+ seen.delete(value);
391
+ return out;
392
+ }
393
+ function captureError(error, options = DEFAULT_DESTRUCTURING, path = [], seen = /* @__PURE__ */ new Set(), depth = 0) {
394
+ const out = {
395
+ $type: "Error",
396
+ name: error.name || "Error",
397
+ message: truncate(String(error.message ?? ""), options.maxStringLength)
398
+ };
399
+ if (typeof error.stack === "string" && error.stack) out.stack = error.stack;
400
+ if (seen.has(error) || depth >= options.maxDepth) return out;
401
+ seen.add(error);
402
+ const rules = redactRules(options);
403
+ for (const key of Object.keys(error)) {
404
+ if (key === "name" || key === "message" || key === "stack") continue;
405
+ const next = [...path, key.toLowerCase()];
406
+ out[key] = isRedacted(rules, next) ? options.redactedValue : captureValue(error[key], "@", options, next, seen, depth + 1);
407
+ }
408
+ if ("cause" in error && error.cause !== void 0 && !("cause" in out)) {
409
+ out.cause = captureValue(error.cause, "@", options, [...path, "cause"], seen, depth + 1);
410
+ }
411
+ if (error instanceof AggregateError && !("errors" in out)) {
412
+ out.errors = captureArray(error.errors, options, [...path, "errors"], seen, depth + 1);
413
+ }
414
+ seen.delete(error);
415
+ return out;
416
+ }
417
+ function captureArguments(holes, positional, args, options, into) {
418
+ if (positional) {
419
+ for (const hole of holes) {
420
+ const i = hole.index;
421
+ if (i < args.length) into[hole.name] = captureProperty(hole.name, args[i], hole.operator, options);
422
+ }
423
+ return;
424
+ }
425
+ const n = Math.min(holes.length, args.length);
426
+ for (let i = 0; i < n; i++) {
427
+ const hole = holes[i];
428
+ into[hole.name] = captureProperty(hole.name, args[i], hole.operator, options);
429
+ }
430
+ }
431
+
432
+ // src/format/render.ts
433
+ var NONE = (text) => text;
434
+ var NO_STYLES = Object.freeze({ string: NONE, number: NONE, boolean: NONE, null: NONE, name: NONE, punctuation: NONE, missing: NONE });
435
+ function resolveStyles(styles) {
436
+ return styles ? { ...NO_STYLES, ...styles } : NO_STYLES;
437
+ }
438
+ var EMPTY = {};
439
+ function renderValue(value, format, options = EMPTY) {
440
+ const S = options.styles ? resolveStyles(options.styles) : NO_STYLES;
441
+ const literal = options.literal || format !== void 0 && format.includes("l");
442
+ const json = options.json || format !== void 0 && format.includes("j");
443
+ if (value === null || value === void 0) return S.null("null");
444
+ switch (typeof value) {
445
+ case "string":
446
+ return S.string(literal ? value : JSON.stringify(value));
447
+ case "number":
448
+ return S.number(format === void 0 ? String(value) : formatNumber(value, format));
449
+ case "boolean":
450
+ return S.boolean(value ? "true" : "false");
451
+ case "bigint":
452
+ return S.number(value.toString());
453
+ default:
454
+ break;
455
+ }
456
+ if (value instanceof Date) {
457
+ const text = format && !/^[lj]+$/.test(format) ? formatDate(value, format, options.utc) : value.toISOString();
458
+ return S.string(literal || json ? text : JSON.stringify(text));
459
+ }
460
+ if (json) return S.string(toJson(value));
461
+ const nested = options.literal ? { ...options, literal: false } : options;
462
+ if (Array.isArray(value)) {
463
+ let out = S.punctuation("[");
464
+ for (let i = 0; i < value.length; i++) {
465
+ if (i) out += S.punctuation(", ");
466
+ out += renderValue(value[i], void 0, nested);
467
+ }
468
+ return out + S.punctuation("]");
469
+ }
470
+ if (typeof value === "object") return renderStructure(value, nested, S);
471
+ return String(value);
472
+ }
473
+ function renderStructure(value, options, S) {
474
+ const type = value.$type;
475
+ if (type === "Error" && typeof value.message === "string") {
476
+ const name = typeof value.name === "string" ? value.name : "Error";
477
+ return `${S.name(name)}${S.punctuation(":")} ${S.string(value.message)}`;
478
+ }
479
+ const tag = typeof type === "string" ? `${S.name(type)} ` : "";
480
+ let inner = "";
481
+ for (const key of Object.keys(value)) {
482
+ if (key === "$type") continue;
483
+ if (inner) inner += S.punctuation(", ");
484
+ inner += `${S.name(key)}${S.punctuation(":")} ${renderValue(value[key], void 0, options)}`;
485
+ }
486
+ if (!inner) return `${tag}${S.punctuation("{ }")}`;
487
+ return `${tag}${S.punctuation("{ ")}${inner}${S.punctuation(" }")}`;
488
+ }
489
+ function toJson(value) {
490
+ try {
491
+ return JSON.stringify(value) ?? "null";
492
+ } catch {
493
+ try {
494
+ return JSON.stringify(value, jsonReplacer) ?? "null";
495
+ } catch {
496
+ return '"[Unserializable]"';
497
+ }
498
+ }
499
+ }
500
+ function jsonReplacer(_key, value) {
501
+ if (typeof value === "bigint") return value.toString();
502
+ if (typeof value === "number" && !Number.isFinite(value)) return String(value);
503
+ return value;
504
+ }
505
+ var PLAIN = (value) => String(value);
506
+ var numberFormats = /* @__PURE__ */ new Map();
507
+ function formatNumber(value, format) {
508
+ if (!format) return String(value);
509
+ let formatter = numberFormats.get(format);
510
+ if (!formatter) {
511
+ formatter = compileNumberFormat(format);
512
+ if (numberFormats.size > 500) numberFormats.clear();
513
+ numberFormats.set(format, formatter);
514
+ }
515
+ return formatter(value);
516
+ }
517
+ function compileNumberFormat(format) {
518
+ const f = format.replace(/[lj]/g, "");
519
+ if (!f) return PLAIN;
520
+ const fixed = /^[Ff](\d*)$/.exec(f);
521
+ if (fixed) {
522
+ const digits = fixed[1] ? Number(fixed[1]) : 2;
523
+ return (value) => value.toFixed(digits);
524
+ }
525
+ const grouped = /^[Nn](\d*)$/.exec(f);
526
+ if (grouped) {
527
+ const digits = grouped[1] ? Number(grouped[1]) : 2;
528
+ const nf = new Intl.NumberFormat("en-US", { minimumFractionDigits: digits, maximumFractionDigits: digits });
529
+ return (value) => nf.format(value);
530
+ }
531
+ const percent = /^[Pp](\d*)$/.exec(f);
532
+ if (percent) {
533
+ const digits = percent[1] ? Number(percent[1]) : 2;
534
+ return (value) => `${(value * 100).toFixed(digits)} %`;
535
+ }
536
+ const padded = /^[Dd](\d+)$/.exec(f);
537
+ if (padded) {
538
+ const width = Number(padded[1]);
539
+ return (value) => String(Math.trunc(value)).padStart(width, "0");
540
+ }
541
+ if (/^[Xx]\d*$/.test(f)) {
542
+ const width = Number(f.slice(1) || 0);
543
+ const upper = f[0] === "X";
544
+ return (value) => {
545
+ const hex = Math.trunc(value).toString(16);
546
+ return (upper ? hex.toUpperCase() : hex).padStart(width, "0");
547
+ };
548
+ }
549
+ const pattern = /^0*(?:\.(0*)(#*))?$/.exec(f);
550
+ if (pattern) {
551
+ const min = pattern[1]?.length ?? 0;
552
+ const max = min + (pattern[2]?.length ?? 0);
553
+ const hasFraction = pattern[1] !== void 0 || pattern[2] !== void 0;
554
+ const intMin = f.split(".")[0].length;
555
+ const optional = max > min;
556
+ return (value) => {
557
+ let text = hasFraction ? optional ? trimFraction(value.toFixed(max), min) : value.toFixed(max) : String(Math.round(value));
558
+ if (intMin > 1) {
559
+ const [whole, frac] = text.replace("-", "").split(".");
560
+ text = `${value < 0 ? "-" : ""}${whole.padStart(intMin, "0")}${frac !== void 0 ? `.${frac}` : ""}`;
561
+ }
562
+ return text;
563
+ };
564
+ }
565
+ return PLAIN;
566
+ }
567
+ var cachedSecond = Number.NaN;
568
+ var cachedPrefix = "";
569
+ function isoTimestamp(date) {
570
+ const ms = date.getTime();
571
+ if (Number.isNaN(ms)) return "Invalid Date";
572
+ const second = Math.floor(ms / 1e3);
573
+ if (second !== cachedSecond) {
574
+ cachedSecond = second;
575
+ cachedPrefix = new Date(second * 1e3).toISOString().slice(0, 19);
576
+ }
577
+ const millis = ms - second * 1e3;
578
+ return `${cachedPrefix}.${millis < 10 ? "00" : millis < 100 ? "0" : ""}${millis}Z`;
579
+ }
580
+ function trimFraction(text, keep) {
581
+ if (!text.includes(".")) return text;
582
+ let [whole, frac] = text.split(".");
583
+ while (frac.length > keep && frac.endsWith("0")) frac = frac.slice(0, -1);
584
+ return frac.length ? `${whole}.${frac}` : whole;
585
+ }
586
+ var pad = (n, width = 2) => String(n).padStart(width, "0");
587
+ function formatDate(date, pattern, utc = false) {
588
+ if (pattern === "o" || pattern === "O") return date.toISOString();
589
+ const get = utc ? {
590
+ year: date.getUTCFullYear(),
591
+ month: date.getUTCMonth() + 1,
592
+ day: date.getUTCDate(),
593
+ hours: date.getUTCHours(),
594
+ minutes: date.getUTCMinutes(),
595
+ seconds: date.getUTCSeconds(),
596
+ ms: date.getUTCMilliseconds(),
597
+ offset: 0
598
+ } : {
599
+ year: date.getFullYear(),
600
+ month: date.getMonth() + 1,
601
+ day: date.getDate(),
602
+ hours: date.getHours(),
603
+ minutes: date.getMinutes(),
604
+ seconds: date.getSeconds(),
605
+ ms: date.getMilliseconds(),
606
+ offset: -date.getTimezoneOffset()
607
+ };
608
+ const offsetText = (short) => {
609
+ const sign = get.offset >= 0 ? "+" : "-";
610
+ const abs = Math.abs(get.offset);
611
+ const h = pad(Math.floor(abs / 60));
612
+ const m = pad(abs % 60);
613
+ return short ? `${sign}${h}` : `${sign}${h}:${m}`;
614
+ };
615
+ let out = "";
616
+ let i = 0;
617
+ while (i < pattern.length) {
618
+ const ch = pattern[i];
619
+ if (ch === "'" || ch === '"') {
620
+ const end = pattern.indexOf(ch, i + 1);
621
+ out += pattern.slice(i + 1, end === -1 ? pattern.length : end);
622
+ i = end === -1 ? pattern.length : end + 1;
623
+ continue;
624
+ }
625
+ if (ch === "\\") {
626
+ out += pattern[i + 1] ?? "";
627
+ i += 2;
628
+ continue;
629
+ }
630
+ let run = 1;
631
+ while (pattern[i + run] === ch) run++;
632
+ switch (ch) {
633
+ case "y":
634
+ out += run >= 4 ? String(get.year) : pad(get.year % 100);
635
+ break;
636
+ case "M":
637
+ out += run >= 2 ? pad(get.month) : String(get.month);
638
+ break;
639
+ case "d":
640
+ out += run >= 2 ? pad(get.day) : String(get.day);
641
+ break;
642
+ case "H":
643
+ out += run >= 2 ? pad(get.hours) : String(get.hours);
644
+ break;
645
+ case "h": {
646
+ const h = get.hours % 12 || 12;
647
+ out += run >= 2 ? pad(h) : String(h);
648
+ break;
649
+ }
650
+ case "m":
651
+ out += run >= 2 ? pad(get.minutes) : String(get.minutes);
652
+ break;
653
+ case "s":
654
+ out += run >= 2 ? pad(get.seconds) : String(get.seconds);
655
+ break;
656
+ case "f":
657
+ case "F": {
658
+ const frac = pad(get.ms, 3).padEnd(run, "0").slice(0, run);
659
+ out += ch === "F" ? frac.replace(/0+$/, "") : frac;
660
+ break;
661
+ }
662
+ case "t":
663
+ out += run >= 2 ? get.hours < 12 ? "AM" : "PM" : get.hours < 12 ? "A" : "P";
664
+ break;
665
+ case "z":
666
+ out += offsetText(run < 3);
667
+ break;
668
+ case "K":
669
+ out += utc || get.offset === 0 ? "Z" : offsetText(false);
670
+ break;
671
+ default:
672
+ out += ch.repeat(run);
673
+ }
674
+ i += run;
675
+ }
676
+ return out;
677
+ }
678
+ function renderTemplate(template, properties, options = {}, renderings) {
679
+ let out = "";
680
+ for (const token of template.tokens) {
681
+ if (token.kind === "text") {
682
+ out += token.text;
683
+ continue;
684
+ }
685
+ out += renderHole(token, properties, options, renderings);
686
+ }
687
+ return out;
688
+ }
689
+ var hasOwn = Object.prototype.hasOwnProperty;
690
+ function renderHole(hole, properties, options, renderings) {
691
+ if (!hasOwn.call(properties, hole.name)) {
692
+ return options.styles?.missing ? options.styles.missing(hole.raw) : hole.raw;
693
+ }
694
+ const text = renderValue(properties[hole.name], hole.format, options);
695
+ if (renderings && hole.format) renderings.push(text);
696
+ return align(text, hole.alignment);
697
+ }
698
+
699
+ // src/event.ts
700
+ var LogEvent = class {
701
+ timestamp;
702
+ level;
703
+ template;
704
+ properties;
705
+ error;
706
+ traceId;
707
+ spanId;
708
+ #destructuring;
709
+ #capturedError;
710
+ #eventId;
711
+ constructor(init, destructuring) {
712
+ this.timestamp = init.timestamp ?? /* @__PURE__ */ new Date();
713
+ this.level = init.level;
714
+ this.template = init.template;
715
+ this.properties = init.properties ?? {};
716
+ this.error = init.error;
717
+ this.traceId = init.traceId;
718
+ this.spanId = init.spanId;
719
+ this.#destructuring = destructuring;
720
+ }
721
+ /** The template text, e.g. `"User {UserId} logged in"`. */
722
+ get messageTemplate() {
723
+ return this.template.raw;
724
+ }
725
+ /** Serilog's `SourceContext` — set by `logger.forSource()`. */
726
+ get sourceContext() {
727
+ const value = this.properties.SourceContext;
728
+ return typeof value === "string" ? value : void 0;
729
+ }
730
+ /** Eight hex digits identifying the template (Seq's `@i`). */
731
+ get eventId() {
732
+ return this.#eventId ??= templateHash(this.template.raw);
733
+ }
734
+ /** The error as a structure (name, message, stack, own properties, cause chain), captured once. */
735
+ get errorProperties() {
736
+ if (!this.error) return void 0;
737
+ return this.#capturedError ??= captureError(this.error, this.#destructuring);
738
+ }
739
+ /** Captures and adds `value` under `name` unless the event already has it — the rule enrichers follow. */
740
+ addPropertyIfAbsent(name, value, destructure = false) {
741
+ if (Object.prototype.hasOwnProperty.call(this.properties, name)) return;
742
+ this.properties[name] = captureProperty(name, value, destructure ? "@" : void 0, this.#destructuring);
743
+ }
744
+ /** Captures and adds `value` under `name`, replacing any existing value. */
745
+ addOrUpdateProperty(name, value, destructure = false) {
746
+ this.properties[name] = captureProperty(name, value, destructure ? "@" : void 0, this.#destructuring);
747
+ }
748
+ removeProperty(name) {
749
+ delete this.properties[name];
750
+ }
751
+ hasProperty(name) {
752
+ return Object.prototype.hasOwnProperty.call(this.properties, name);
753
+ }
754
+ /** The template rendered with this event's properties. */
755
+ renderMessage(options) {
756
+ return renderTemplate(this.template, this.properties, options);
757
+ }
758
+ /** Properties that are not holes in the template — the "extra" context, in Serilog's `{Properties}` sense. */
759
+ extraProperties() {
760
+ const out = {};
761
+ const holes = this.template.holes;
762
+ for (const key of Object.keys(this.properties)) {
763
+ if (!holes.some((h) => h.name === key)) out[key] = this.properties[key];
764
+ }
765
+ return out;
766
+ }
767
+ };
768
+
769
+ // src/context.ts
770
+ var StackStore = class {
771
+ current;
772
+ getStore() {
773
+ return this.current;
774
+ }
775
+ run(frame, fn) {
776
+ const previous = this.current;
777
+ this.current = frame;
778
+ try {
779
+ return fn();
780
+ } finally {
781
+ this.current = previous;
782
+ }
783
+ }
784
+ enterWith(frame) {
785
+ this.current = frame;
786
+ }
787
+ };
788
+ function detectStore() {
789
+ try {
790
+ const proc = globalThis.process;
791
+ const hooks = proc?.getBuiltinModule?.("node:async_hooks");
792
+ if (hooks?.AsyncLocalStorage) return new hooks.AsyncLocalStorage();
793
+ } catch {
794
+ }
795
+ try {
796
+ const req = globalThis.require ?? (typeof __require === "function" ? __require : void 0);
797
+ const hooks = req?.("node:async_hooks");
798
+ if (hooks?.AsyncLocalStorage) return new hooks.AsyncLocalStorage();
799
+ } catch {
800
+ }
801
+ return new StackStore();
802
+ }
803
+ var store = detectStore();
804
+ var DISPOSE = Symbol.dispose ?? /* @__PURE__ */ Symbol.for("Symbol.dispose");
805
+ function makeFrame(properties, parent, diagnostics) {
806
+ return { properties, parent: parent ?? null, diagnostics: diagnostics ?? parent?.diagnostics };
807
+ }
808
+ var LogContext = {
809
+ /**
810
+ * Runs `fn` with `properties` added to the ambient context. Async
811
+ * functions are followed through every `await` when an
812
+ * AsyncLocalStorage-backed store is active.
813
+ */
814
+ run(properties, fn) {
815
+ return store.run(makeFrame(properties, store.getStore()), fn);
816
+ },
817
+ /**
818
+ * Pushes properties onto the ambient context until the handle is disposed.
819
+ * Prefer `run()` for async code; `push()` relies on `enterWith`, which
820
+ * binds the rest of the *current* async scope.
821
+ */
822
+ push(properties) {
823
+ const previous = store.getStore();
824
+ if (!store.enterWith) throw new Error("logit: this context store has no enterWith(); use LogContext.run() instead");
825
+ store.enterWith(makeFrame(properties, previous));
826
+ let disposed = false;
827
+ const dispose = () => {
828
+ if (disposed) return;
829
+ disposed = true;
830
+ store.enterWith(previous);
831
+ };
832
+ return { dispose, [DISPOSE]: dispose };
833
+ },
834
+ /** The merged ambient properties, innermost frame winning. */
835
+ current() {
836
+ const frame = store.getStore();
837
+ if (!frame) return {};
838
+ const frames = [];
839
+ for (let f = frame; f; f = f.parent) frames.push(f);
840
+ const out = {};
841
+ for (let i = frames.length - 1; i >= 0; i--) Object.assign(out, frames[i].properties);
842
+ return out;
843
+ },
844
+ /** The innermost frame, for enrichers that want to walk it themselves. */
845
+ frame() {
846
+ return store.getStore();
847
+ },
848
+ /**
849
+ * Starts a request scope: ambient `properties` plus a fresh diagnostic
850
+ * bag that `diagnosticContext.set()` writes to and the request-completion
851
+ * event reads. Used by the Next.js and Express integrations.
852
+ */
853
+ runScope(properties, fn) {
854
+ const diagnostics = /* @__PURE__ */ new Map();
855
+ return store.run(makeFrame(properties, store.getStore(), diagnostics), () => fn(diagnostics));
856
+ },
857
+ /** Replaces the backing store — `new AsyncLocalStorage()` on runtimes we cannot detect. */
858
+ use(next) {
859
+ store = next;
860
+ },
861
+ /** `true` when frames follow async execution (an AsyncLocalStorage-like store is active). */
862
+ get isAsync() {
863
+ return !(store instanceof StackStore);
864
+ }
865
+ };
866
+ var diagnosticContext = {
867
+ set(name, value) {
868
+ store.getStore()?.diagnostics?.set(name, value);
869
+ },
870
+ /** `true` inside a request scope (so a library can skip the work of computing a value nobody will collect). */
871
+ get active() {
872
+ return store.getStore()?.diagnostics !== void 0;
873
+ }
874
+ };
875
+
876
+ // src/enrichers.ts
877
+ function withProperty(name, value, destructure = false) {
878
+ return (event) => event.addPropertyIfAbsent(name, value, destructure);
879
+ }
880
+ function withProperties(properties, destructure = false) {
881
+ const entries = Object.entries(properties);
882
+ return (event) => {
883
+ for (const [name, value] of entries) event.addPropertyIfAbsent(name, value, destructure);
884
+ };
885
+ }
886
+ function withComputed(name, compute, destructure = false) {
887
+ return (event) => {
888
+ if (event.hasProperty(name)) return;
889
+ event.addPropertyIfAbsent(name, compute(event), destructure);
890
+ };
891
+ }
892
+ function fromLogContext() {
893
+ return (event) => {
894
+ const frame = LogContext.frame();
895
+ if (!frame) return;
896
+ for (let f = frame; f; f = f.parent) {
897
+ for (const name of Object.keys(f.properties)) {
898
+ const value = f.properties[name];
899
+ if (name === "traceId") {
900
+ if (event.traceId === void 0 && typeof value === "string") event.traceId = value;
901
+ continue;
902
+ }
903
+ if (name === "spanId") {
904
+ if (event.spanId === void 0 && typeof value === "string") event.spanId = value;
905
+ continue;
906
+ }
907
+ event.addPropertyIfAbsent(name, value, true);
908
+ }
909
+ if (!f.parent) break;
910
+ }
911
+ };
912
+ }
913
+ function withEnvironment(name) {
914
+ const env = name ?? globalThis.process?.env?.NODE_ENV;
915
+ return (event) => {
916
+ if (env) event.addPropertyIfAbsent("Environment", env);
917
+ };
918
+ }
919
+ function withTraceContext(get) {
920
+ return (event) => {
921
+ if (event.traceId !== void 0 && event.spanId !== void 0) return;
922
+ let ctx;
923
+ try {
924
+ ctx = get();
925
+ } catch {
926
+ return;
927
+ }
928
+ if (!ctx) return;
929
+ if (event.traceId === void 0 && ctx.traceId) event.traceId = ctx.traceId;
930
+ if (event.spanId === void 0 && ctx.spanId) event.spanId = ctx.spanId;
931
+ };
932
+ }
933
+
934
+ // src/filters.ts
935
+ function byExcluding(predicate) {
936
+ return (event) => !predicate(event);
937
+ }
938
+ function byIncludingOnly(predicate) {
939
+ return predicate;
940
+ }
941
+ var Matching = {
942
+ /** Events whose `SourceContext` is `source` or starts with `source.`. */
943
+ fromSource(source) {
944
+ const prefix = `${source}.`;
945
+ return (event) => {
946
+ const ctx = event.sourceContext;
947
+ return ctx !== void 0 && (ctx === source || ctx.startsWith(prefix));
948
+ };
949
+ },
950
+ /** Events that carry `name` — optionally with a value the predicate accepts. */
951
+ withProperty(name, predicate) {
952
+ return (event) => event.hasProperty(name) && (predicate ? predicate(event.properties[name]) : true);
953
+ },
954
+ /** Events written with exactly this template text. */
955
+ withTemplate(template) {
956
+ return (event) => event.messageTemplate === template;
957
+ },
958
+ /** Events whose rendered message matches the pattern. */
959
+ messageMatches(pattern) {
960
+ return (event) => pattern.test(event.renderMessage({ literal: true }));
961
+ }
962
+ };
963
+ function sampled(rate, predicate = () => true, random = Math.random) {
964
+ return (event) => !predicate(event) || random() < rate;
965
+ }
966
+ function rateLimited(max, windowMs, predicate = () => true, now2 = Date.now) {
967
+ let windowStart = 0;
968
+ let count = 0;
969
+ return (event) => {
970
+ if (!predicate(event)) return true;
971
+ const t = now2();
972
+ if (t - windowStart >= windowMs) {
973
+ windowStart = t;
974
+ count = 0;
975
+ }
976
+ return ++count <= max;
977
+ };
978
+ }
979
+
980
+ // src/selflog.ts
981
+ var output = null;
982
+ var selfLog = {
983
+ /** `'stderr'` writes to `console.error`; a function receives each line. */
984
+ enable(target) {
985
+ output = target === "stderr" ? (line) => console.error(line) : target;
986
+ },
987
+ disable() {
988
+ output = null;
989
+ },
990
+ get enabled() {
991
+ return output !== null;
992
+ },
993
+ /** Writes one line (prefixed with the time) if enabled; swallows its own errors. */
994
+ write(message, error) {
995
+ if (!output) return;
996
+ try {
997
+ const detail = error instanceof Error ? ` \u2014 ${error.stack ?? error.message}` : error !== void 0 ? ` \u2014 ${String(error)}` : "";
998
+ output(`${(/* @__PURE__ */ new Date()).toISOString()} logit: ${message}${detail}`);
999
+ } catch {
1000
+ }
1001
+ }
1002
+ };
1003
+
1004
+ // src/format/text.ts
1005
+ var DEFAULT_OUTPUT_TEMPLATE = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}";
1006
+ function formatLevel(level, format) {
1007
+ const name = SERILOG_LEVEL_NAMES[level];
1008
+ if (!format) return name;
1009
+ const m = /^([uw])(\d*)$/.exec(format);
1010
+ if (!m) return name;
1011
+ const width = m[2] ? Number(m[2]) : 0;
1012
+ let text = width === 3 ? LEVEL_CODES[level] : width > 0 ? name.slice(0, width) : name;
1013
+ if (width > 0 && text.length < width) text = text.padEnd(width);
1014
+ return m[1] === "u" ? text.toUpperCase() : text.toLowerCase();
1015
+ }
1016
+ function formatError(error, indent = "") {
1017
+ if (!error) return "";
1018
+ const lines = [];
1019
+ let current = error;
1020
+ let depth = 0;
1021
+ const seen = /* @__PURE__ */ new Set();
1022
+ while (current !== void 0 && current !== null && depth < 10 && !seen.has(current)) {
1023
+ seen.add(current);
1024
+ const prefix = depth === 0 ? indent : `${indent}${" ".repeat(depth)}caused by: `;
1025
+ if (current instanceof Error) {
1026
+ const body = current.stack && current.stack.includes(current.message) ? current.stack : `${current.name}: ${current.message}${current.stack ? `
1027
+ ${current.stack}` : ""}`;
1028
+ lines.push(prefix + body.split("\n").join(`
1029
+ ${indent}${" ".repeat(depth)}`));
1030
+ if (current instanceof AggregateError && current.errors.length) {
1031
+ current.errors.forEach((inner, i) => {
1032
+ lines.push(`${indent}${" ".repeat(depth + 1)}[${i}] ${formatError(inner instanceof Error ? inner : new Error(String(inner)), `${indent}${" ".repeat(depth + 1)}`).trimStart()}`);
1033
+ });
1034
+ }
1035
+ current = current.cause;
1036
+ } else {
1037
+ lines.push(prefix + String(current));
1038
+ current = void 0;
1039
+ }
1040
+ depth++;
1041
+ }
1042
+ return lines.join("\n");
1043
+ }
1044
+ function textFormatter(options = {}) {
1045
+ const template = parseTemplate(options.outputTemplate ?? DEFAULT_OUTPUT_TEMPLATE);
1046
+ const utc = options.utc ?? false;
1047
+ const styles = options.styles;
1048
+ const tokenStyles = options.tokenStyles ?? {};
1049
+ const usedNames = new Set(template.holes.map((h) => h.name));
1050
+ return (event) => {
1051
+ let out = "";
1052
+ for (const token of template.tokens) {
1053
+ if (token.kind === "text") {
1054
+ out += token.text;
1055
+ continue;
1056
+ }
1057
+ out += align(renderToken(token, event), token.alignment);
1058
+ }
1059
+ return out;
1060
+ };
1061
+ function renderToken(hole, event) {
1062
+ switch (hole.name) {
1063
+ case "Timestamp": {
1064
+ const text = hole.format ? formatDate(event.timestamp, hole.format, utc) : event.timestamp.toISOString();
1065
+ return tokenStyles.Timestamp?.(text, event) ?? text;
1066
+ }
1067
+ case "Level": {
1068
+ const text = formatLevel(event.level, hole.format);
1069
+ return tokenStyles.Level?.(text, event) ?? text;
1070
+ }
1071
+ case "Message": {
1072
+ const renderOptions = { literal: hole.format?.includes("l"), json: hole.format?.includes("j"), utc, styles };
1073
+ const text = renderTemplate(event.template, event.properties, renderOptions);
1074
+ return tokenStyles.Message?.(text, event) ?? text;
1075
+ }
1076
+ case "NewLine":
1077
+ return "\n";
1078
+ case "Exception": {
1079
+ if (!event.error) return "";
1080
+ const text = formatError(event.error);
1081
+ return tokenStyles.Exception?.(text, event) ?? text;
1082
+ }
1083
+ case "Properties": {
1084
+ const extra = {};
1085
+ for (const key of Object.keys(event.properties)) {
1086
+ if (usedNames.has(key) || event.template.holes.some((h) => h.name === key)) continue;
1087
+ extra[key] = event.properties[key];
1088
+ }
1089
+ if (Object.keys(extra).length === 0) return "";
1090
+ const text = hole.format?.includes("j") ? toJson(extra) : renderValue(extra, void 0, { styles });
1091
+ return tokenStyles.Properties?.(text, event) ?? text;
1092
+ }
1093
+ case "TraceId":
1094
+ return event.traceId ?? "";
1095
+ case "SpanId":
1096
+ return event.spanId ?? "";
1097
+ case "EventId":
1098
+ return event.eventId;
1099
+ default: {
1100
+ if (!event.hasProperty(hole.name)) return "";
1101
+ const text = renderValue(event.properties[hole.name], hole.format ?? "l", { utc, styles });
1102
+ return hole.name === "SourceContext" ? tokenStyles.SourceContext?.(text, event) ?? text : text;
1103
+ }
1104
+ }
1105
+ }
1106
+ }
1107
+
1108
+ // src/format/clef.ts
1109
+ var CLEF_MEDIA_TYPE = "application/vnd.serilog.clef";
1110
+ function clefFormatter(options = {}) {
1111
+ return (event) => {
1112
+ const out = { "@t": isoTimestamp(event.timestamp) };
1113
+ if (options.renderMessage) out["@m"] = event.renderMessage({ literal: true });
1114
+ out["@mt"] = event.messageTemplate;
1115
+ if (event.level !== "info") out["@l"] = SERILOG_LEVEL_NAMES[event.level];
1116
+ if (event.error) out["@x"] = formatError(event.error);
1117
+ out["@i"] = event.eventId;
1118
+ const renderings = [];
1119
+ renderTemplate(event.template, event.properties, {}, renderings);
1120
+ if (renderings.length) out["@r"] = renderings;
1121
+ if (event.traceId) out["@tr"] = event.traceId;
1122
+ if (event.spanId) out["@sp"] = event.spanId;
1123
+ for (const key of Object.keys(event.properties)) {
1124
+ out[key.startsWith("@") ? `@${key}` : key] = event.properties[key];
1125
+ }
1126
+ return toJson(out);
1127
+ };
1128
+ }
1129
+
1130
+ // src/format/json.ts
1131
+ var DEFAULT_KEYS = {
1132
+ timestamp: "timestamp",
1133
+ level: "level",
1134
+ message: "message",
1135
+ template: "template",
1136
+ source: "source",
1137
+ error: "error",
1138
+ traceId: "traceId",
1139
+ spanId: "spanId",
1140
+ eventId: "eventId"
1141
+ };
1142
+ var templateJson = /* @__PURE__ */ new WeakMap();
1143
+ function jsonFormatter(options = {}) {
1144
+ const keys = { ...DEFAULT_KEYS, ...options.keys };
1145
+ const reserved = Object.values(keys);
1146
+ const levelFormat = options.levelFormat ?? "name";
1147
+ const withMessage = options.message ?? true;
1148
+ const withTemplate = options.template ?? true;
1149
+ const withEventId = options.eventId ?? false;
1150
+ const epoch = options.timestampFormat === "epoch";
1151
+ const key = (name) => `,${JSON.stringify(name)}:`;
1152
+ const timestampKey = `{${JSON.stringify(keys.timestamp)}:`;
1153
+ const levelFragment = {};
1154
+ for (const level of LEVELS) {
1155
+ const value = levelFormat === "number" ? LEVEL_NUMBERS[level] : levelFormat === "serilog" ? SERILOG_LEVEL_NAMES[level] : levelFormat === "upper" ? level.toUpperCase() : level;
1156
+ levelFragment[level] = `${key(keys.level)}${JSON.stringify(value)}`;
1157
+ }
1158
+ const messageKey = key(keys.message);
1159
+ const templateKey = key(keys.template);
1160
+ const eventIdKey = key(keys.eventId);
1161
+ const sourceKey = key(keys.source);
1162
+ const traceKey = key(keys.traceId);
1163
+ const spanKey = key(keys.spanId);
1164
+ const errorKey = key(keys.error);
1165
+ return (event) => {
1166
+ let out = timestampKey + (epoch ? String(event.timestamp.getTime()) : `"${isoTimestamp(event.timestamp)}"`) + levelFragment[event.level];
1167
+ if (withMessage) out += messageKey + JSON.stringify(event.renderMessage({ literal: true }));
1168
+ if (withTemplate) {
1169
+ let cached = templateJson.get(event.template);
1170
+ if (cached === void 0) {
1171
+ cached = JSON.stringify(event.messageTemplate);
1172
+ templateJson.set(event.template, cached);
1173
+ }
1174
+ out += templateKey + cached;
1175
+ }
1176
+ if (withEventId) out += `${eventIdKey}"${event.eventId}"`;
1177
+ const properties = event.properties;
1178
+ const source = properties.SourceContext;
1179
+ if (typeof source === "string") out += sourceKey + JSON.stringify(source);
1180
+ if (event.traceId) out += traceKey + JSON.stringify(event.traceId);
1181
+ if (event.spanId) out += spanKey + JSON.stringify(event.spanId);
1182
+ let rest;
1183
+ let needsCopy = source !== void 0;
1184
+ if (!needsCopy) {
1185
+ for (let i = 0; i < reserved.length; i++) {
1186
+ if (Object.prototype.hasOwnProperty.call(properties, reserved[i])) {
1187
+ needsCopy = true;
1188
+ break;
1189
+ }
1190
+ }
1191
+ }
1192
+ if (needsCopy) {
1193
+ rest = {};
1194
+ for (const name of Object.keys(properties)) {
1195
+ if (name === "SourceContext") continue;
1196
+ rest[reserved.includes(name) ? `${name}_` : name] = properties[name];
1197
+ }
1198
+ } else {
1199
+ rest = properties;
1200
+ }
1201
+ const propsJson = toJson(rest);
1202
+ if (propsJson.length > 2) out += `,${propsJson.slice(1, -1)}`;
1203
+ if (event.error) out += errorKey + toJson(event.errorProperties);
1204
+ return `${out}}`;
1205
+ };
1206
+ }
1207
+
1208
+ // src/format/pretty.ts
1209
+ var ESC = "\x1B[";
1210
+ var code = (open, close) => (text) => `${ESC}${open}m${text}${ESC}${close}m`;
1211
+ var ansi = {
1212
+ bold: code(1, 22),
1213
+ dim: code(2, 22),
1214
+ italic: code(3, 23),
1215
+ underline: code(4, 24),
1216
+ red: code(31, 39),
1217
+ green: code(32, 39),
1218
+ yellow: code(33, 39),
1219
+ blue: code(34, 39),
1220
+ magenta: code(35, 39),
1221
+ cyan: code(36, 39),
1222
+ white: code(37, 39),
1223
+ gray: code(90, 39),
1224
+ bgRed: code(41, 49)
1225
+ };
1226
+ var LEVEL_STYLE = {
1227
+ verbose: ansi.gray,
1228
+ debug: ansi.blue,
1229
+ info: ansi.green,
1230
+ warn: ansi.yellow,
1231
+ error: ansi.red,
1232
+ fatal: (text) => ansi.bold(ansi.bgRed(ansi.white(text)))
1233
+ };
1234
+ function detectColors(stream) {
1235
+ const env = globalThis.process?.env;
1236
+ if (!env) return false;
1237
+ if (env.NO_COLOR !== void 0 && env.NO_COLOR !== "") return false;
1238
+ if (env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "0" && env.FORCE_COLOR !== "") return true;
1239
+ if (env.TERM === "dumb") return false;
1240
+ return stream?.isTTY === true;
1241
+ }
1242
+ function prettyFormatter(options = {}) {
1243
+ const colors = options.colors ?? false;
1244
+ const c = colors ? ansi : identityAnsi;
1245
+ const styles = colors ? {
1246
+ string: ansi.cyan,
1247
+ number: ansi.magenta,
1248
+ boolean: ansi.magenta,
1249
+ null: ansi.gray,
1250
+ name: ansi.white,
1251
+ punctuation: ansi.gray,
1252
+ missing: ansi.gray
1253
+ } : void 0;
1254
+ const timestamp = options.timestamp ?? "HH:mm:ss.fff";
1255
+ const showExtras = options.extras ?? true;
1256
+ const showSource = options.source ?? true;
1257
+ return (event) => {
1258
+ const parts = [];
1259
+ if (timestamp) parts.push(c.dim(formatDate(event.timestamp, timestamp, options.utc)));
1260
+ parts.push(LEVEL_STYLE[event.level] === void 0 || !colors ? formatLevel(event.level, "u3") : LEVEL_STYLE[event.level](formatLevel(event.level, "u3")));
1261
+ const source = showSource ? event.sourceContext : void 0;
1262
+ if (source) parts.push(c.dim(`[${source}]`));
1263
+ parts.push(renderTemplate(event.template, event.properties, { literal: true, styles }));
1264
+ if (showExtras) {
1265
+ const extras = event.extraProperties();
1266
+ const pairs = [];
1267
+ for (const key of Object.keys(extras)) {
1268
+ if (key === "SourceContext") continue;
1269
+ pairs.push(`${key}=${renderValue(extras[key], void 0, { literal: true, json: true })}`);
1270
+ }
1271
+ if (pairs.length) parts.push(c.dim(pairs.join(" ")));
1272
+ }
1273
+ let line = parts.join(" ");
1274
+ if (event.error) {
1275
+ const block = formatError(event.error, " ");
1276
+ line += `
1277
+ ${colors ? ansi.red(block) : block}`;
1278
+ }
1279
+ return line;
1280
+ };
1281
+ }
1282
+ var identityAnsi = Object.fromEntries(Object.keys(ansi).map((key) => [key, (text) => text]));
1283
+
1284
+ // src/format/index.ts
1285
+ function resolveFormatter(format, defaults = {}, fallback = "json") {
1286
+ if (typeof format === "function") return format;
1287
+ switch (format ?? fallback) {
1288
+ case "pretty":
1289
+ return prettyFormatter({ colors: defaults.colors, utc: defaults.utc });
1290
+ case "text":
1291
+ return textFormatter({ outputTemplate: defaults.outputTemplate, utc: defaults.utc });
1292
+ case "clef":
1293
+ return clefFormatter();
1294
+ case "json":
1295
+ default:
1296
+ return jsonFormatter();
1297
+ }
1298
+ }
1299
+
1300
+ // src/sinks/basic.ts
1301
+ function callbackSink(fn, options = {}) {
1302
+ return { name: "callback", emit: fn, ...options };
1303
+ }
1304
+ function memorySink(options = {}) {
1305
+ const events = [];
1306
+ const capacity = options.capacity ?? Infinity;
1307
+ return {
1308
+ name: "memory",
1309
+ events,
1310
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
1311
+ audit: options.audit,
1312
+ emit(event) {
1313
+ events.push(event);
1314
+ if (events.length > capacity) events.splice(0, events.length - capacity);
1315
+ },
1316
+ clear() {
1317
+ events.length = 0;
1318
+ },
1319
+ messages() {
1320
+ return events.map((e) => e.renderMessage({ literal: true }));
1321
+ }
1322
+ };
1323
+ }
1324
+ function streamSink(stream, options = {}) {
1325
+ const formatter = resolveFormatter(options.format, {
1326
+ outputTemplate: options.outputTemplate,
1327
+ colors: options.colors ?? detectColors(stream),
1328
+ utc: options.utc
1329
+ });
1330
+ let pendingDrain = null;
1331
+ return {
1332
+ name: "stream",
1333
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
1334
+ audit: options.audit,
1335
+ emit(event) {
1336
+ const ok = stream.write(`${formatter(event)}
1337
+ `);
1338
+ if (ok === false && stream.once && !pendingDrain) {
1339
+ pendingDrain = new Promise((resolve) => stream.once("drain", () => resolve())).then(() => {
1340
+ pendingDrain = null;
1341
+ });
1342
+ }
1343
+ },
1344
+ async flush() {
1345
+ if (pendingDrain) await pendingDrain;
1346
+ }
1347
+ };
1348
+ }
1349
+
1350
+ // src/sinks/console.ts
1351
+ function nodeProcess() {
1352
+ const proc = globalThis.process;
1353
+ return proc && typeof proc.stdout?.write === "function" ? proc : void 0;
1354
+ }
1355
+ function consoleSink(options = {}) {
1356
+ const proc = nodeProcess();
1357
+ if (proc?.stdout) {
1358
+ const colors = options.colors ?? detectColors(proc.stdout);
1359
+ const format = options.format ?? (colors || proc.stdout.isTTY ? "pretty" : "json");
1360
+ const out = streamSink(proc.stdout, { ...options, format, colors });
1361
+ if (!options.stderrFrom) return { ...out, name: "console" };
1362
+ const err = streamSink(proc.stderr ?? proc.stdout, { ...options, format, colors: options.colors ?? detectColors(proc.stderr) });
1363
+ const threshold = parseLevel(options.stderrFrom);
1364
+ return {
1365
+ name: "console",
1366
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
1367
+ audit: options.audit,
1368
+ emit(event) {
1369
+ (levelAtLeast(event.level, threshold) ? err : out).emit(event);
1370
+ },
1371
+ async flush() {
1372
+ await out.flush?.();
1373
+ await err.flush?.();
1374
+ }
1375
+ };
1376
+ }
1377
+ return browserConsoleSink(options);
1378
+ }
1379
+ var BROWSER_METHOD = {
1380
+ verbose: "debug",
1381
+ debug: "debug",
1382
+ info: "info",
1383
+ warn: "warn",
1384
+ error: "error",
1385
+ fatal: "error"
1386
+ };
1387
+ function browserConsoleSink(options) {
1388
+ const isBrowser = typeof globalThis.document !== "undefined";
1389
+ const format = options.format ?? (isBrowser ? "pretty" : "json");
1390
+ const formatter = typeof format === "function" || format !== "pretty" ? resolveFormatter(format, { outputTemplate: options.outputTemplate, colors: false, utc: options.utc }) : null;
1391
+ return {
1392
+ name: "console",
1393
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
1394
+ audit: options.audit,
1395
+ emit(event) {
1396
+ const method = BROWSER_METHOD[event.level];
1397
+ if (formatter) {
1398
+ console[method](formatter(event));
1399
+ return;
1400
+ }
1401
+ const extras = event.extraProperties();
1402
+ delete extras.SourceContext;
1403
+ const args = [`${event.sourceContext ? `[${event.sourceContext}] ` : ""}${event.renderMessage({ literal: true })}`];
1404
+ if (Object.keys(extras).length) args.push(extras);
1405
+ if (event.error) args.push(event.error);
1406
+ console[method](...args);
1407
+ }
1408
+ };
1409
+ }
1410
+
1411
+ // src/sinks/wrappers.ts
1412
+ function restricted(sink, level) {
1413
+ return { ...sink, emit: (e) => sink.emit(e), restrictedToMinimumLevel: level };
1414
+ }
1415
+ function conditional(predicate, sink) {
1416
+ return {
1417
+ name: sink.name ? `conditional(${sink.name})` : "conditional",
1418
+ restrictedToMinimumLevel: sink.restrictedToMinimumLevel,
1419
+ audit: sink.audit,
1420
+ emit(event) {
1421
+ if (predicate(event)) sink.emit(event);
1422
+ },
1423
+ flush: sink.flush ? () => sink.flush() : void 0,
1424
+ close: sink.close ? () => sink.close() : void 0
1425
+ };
1426
+ }
1427
+ function audit(sink) {
1428
+ return { ...sink, emit: (e) => sink.emit(e), audit: true };
1429
+ }
1430
+ function mapSink(keyOf, create, options = {}) {
1431
+ const max = options.maxSinks ?? 100;
1432
+ const sinks = /* @__PURE__ */ new Map();
1433
+ const closeQuietly = async (key, sink) => {
1434
+ try {
1435
+ await sink.close?.();
1436
+ } catch (error) {
1437
+ selfLog.write(`mapSink: closing sink for ${String(key)} failed`, error);
1438
+ }
1439
+ };
1440
+ return {
1441
+ name: "map",
1442
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
1443
+ emit(event) {
1444
+ const key = keyOf(event);
1445
+ if (key === void 0) return;
1446
+ let sink = sinks.get(key);
1447
+ if (sink) {
1448
+ sinks.delete(key);
1449
+ sinks.set(key, sink);
1450
+ } else {
1451
+ sink = create(key);
1452
+ sinks.set(key, sink);
1453
+ if (sinks.size > max) {
1454
+ const [oldestKey, oldest] = sinks.entries().next().value;
1455
+ sinks.delete(oldestKey);
1456
+ void closeQuietly(oldestKey, oldest);
1457
+ }
1458
+ }
1459
+ sink.emit(event);
1460
+ },
1461
+ async flush() {
1462
+ await Promise.all(Array.from(sinks.values(), (s) => s.flush?.()));
1463
+ },
1464
+ async close() {
1465
+ const entries = Array.from(sinks.entries());
1466
+ sinks.clear();
1467
+ await Promise.all(entries.map(([key, sink]) => closeQuietly(key, sink)));
1468
+ }
1469
+ };
1470
+ }
1471
+
1472
+ // src/sinks/batching.ts
1473
+ function batchingSink(send, options = {}) {
1474
+ const batchSize = options.batchSize ?? 100;
1475
+ const flushInterval = options.flushInterval ?? 2e3;
1476
+ const maxQueue = options.maxQueue ?? 1e4;
1477
+ const retries = Math.max(1, options.retries ?? 3);
1478
+ const retryDelay = options.retryDelay ?? 500;
1479
+ const name = options.name ?? "batching";
1480
+ let queue = [];
1481
+ let timer = null;
1482
+ let inFlight = null;
1483
+ let closed = false;
1484
+ let dropped = 0;
1485
+ const schedule = () => {
1486
+ if (timer || closed) return;
1487
+ timer = setTimeout(() => {
1488
+ timer = null;
1489
+ void drain();
1490
+ }, flushInterval);
1491
+ timer.unref?.();
1492
+ };
1493
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1494
+ async function sendWithRetry(batch) {
1495
+ let delay = retryDelay;
1496
+ for (let attempt = 1; ; attempt++) {
1497
+ try {
1498
+ await send(batch);
1499
+ return;
1500
+ } catch (error) {
1501
+ if (attempt >= retries) {
1502
+ selfLog.write(`${name}: giving up on a batch of ${batch.length} after ${attempt} attempts`, error);
1503
+ options.onError?.(error, batch);
1504
+ return;
1505
+ }
1506
+ await sleep(delay);
1507
+ delay *= 2;
1508
+ }
1509
+ }
1510
+ }
1511
+ async function drain() {
1512
+ if (inFlight) return inFlight;
1513
+ inFlight = (async () => {
1514
+ while (queue.length) {
1515
+ const batch = queue.splice(0, batchSize);
1516
+ await sendWithRetry(batch);
1517
+ }
1518
+ })().finally(() => {
1519
+ inFlight = null;
1520
+ });
1521
+ return inFlight;
1522
+ }
1523
+ return {
1524
+ name,
1525
+ restrictedToMinimumLevel: options.restrictedToMinimumLevel,
1526
+ audit: options.audit,
1527
+ get queued() {
1528
+ return queue.length;
1529
+ },
1530
+ emit(event) {
1531
+ if (closed) return;
1532
+ if (queue.length >= maxQueue) {
1533
+ queue.shift();
1534
+ if (dropped++ % 1e3 === 0) selfLog.write(`${name}: queue full (${maxQueue}), dropping oldest events`);
1535
+ }
1536
+ queue.push(event);
1537
+ if (queue.length >= batchSize) void drain();
1538
+ else schedule();
1539
+ },
1540
+ async flush() {
1541
+ if (timer) {
1542
+ clearTimeout(timer);
1543
+ timer = null;
1544
+ }
1545
+ await drain();
1546
+ },
1547
+ async close() {
1548
+ await this.flush();
1549
+ closed = true;
1550
+ queue = [];
1551
+ }
1552
+ };
1553
+ }
1554
+
1555
+ // src/sinks/http.ts
1556
+ function httpSink(options) {
1557
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1558
+ if (!fetchImpl) throw new Error("logit: httpSink needs fetch \u2014 pass one in options.fetch");
1559
+ const mode = options.body ?? "ndjson";
1560
+ const formatter = options.formatter ?? (mode === "clef" ? clefFormatter() : jsonFormatter());
1561
+ const contentType = options.contentType ?? (mode === "clef" ? CLEF_MEDIA_TYPE : mode === "array" ? "application/json" : "application/x-ndjson");
1562
+ const timeout = options.timeout ?? 1e4;
1563
+ const encode = (events) => {
1564
+ if (typeof mode === "function") return mode(events);
1565
+ const lines = events.map(formatter);
1566
+ return mode === "array" ? `[${lines.join(",")}]` : `${lines.join("\n")}
1567
+ `;
1568
+ };
1569
+ const sink = batchingSink(
1570
+ async (events) => {
1571
+ const headers = { "content-type": contentType, ...typeof options.headers === "function" ? options.headers() : options.headers };
1572
+ const controller = typeof AbortController === "function" ? new AbortController() : void 0;
1573
+ const timer = controller ? setTimeout(() => controller.abort(), timeout) : void 0;
1574
+ timer?.unref?.();
1575
+ try {
1576
+ const response = await fetchImpl(options.url, {
1577
+ method: "POST",
1578
+ headers,
1579
+ body: encode(events),
1580
+ signal: controller?.signal,
1581
+ keepalive: true
1582
+ });
1583
+ if (!response.ok) {
1584
+ let detail = "";
1585
+ try {
1586
+ detail = (await response.text()).slice(0, 500);
1587
+ } catch {
1588
+ }
1589
+ throw new Error(`HTTP ${response.status}${detail ? `: ${detail}` : ""}`);
1590
+ }
1591
+ } finally {
1592
+ if (timer) clearTimeout(timer);
1593
+ }
1594
+ },
1595
+ { name: `http(${options.url})`, ...options }
1596
+ );
1597
+ const win = globalThis.document ? globalThis : void 0;
1598
+ win?.addEventListener?.("pagehide", () => {
1599
+ void sink.flush();
1600
+ });
1601
+ return sink;
1602
+ }
1603
+ function seqSink(options) {
1604
+ const { serverUrl, apiKey, headers, ...rest } = options;
1605
+ const base = serverUrl.replace(/\/$/, "");
1606
+ return httpSink({
1607
+ ...rest,
1608
+ url: `${base}/ingest/clef`,
1609
+ body: "clef",
1610
+ headers: () => ({
1611
+ ...typeof headers === "function" ? headers() : headers,
1612
+ ...apiKey ? { "X-Seq-ApiKey": apiKey } : {}
1613
+ }),
1614
+ name: `seq(${base})`
1615
+ });
1616
+ }
1617
+
1618
+ // src/logger.ts
1619
+ function envLevel() {
1620
+ const raw = globalThis.process?.env?.LOGIT_LEVEL;
1621
+ if (!raw) return void 0;
1622
+ try {
1623
+ return parseLevel(raw);
1624
+ } catch (error) {
1625
+ selfLog.write(`ignoring LOGIT_LEVEL="${raw}"`, error);
1626
+ return void 0;
1627
+ }
1628
+ }
1629
+ function envOverrides() {
1630
+ const raw = globalThis.process?.env?.LOGIT_OVERRIDES;
1631
+ if (!raw) return void 0;
1632
+ const out = {};
1633
+ for (const pair of raw.split(",")) {
1634
+ const [source, level] = pair.split("=").map((s) => s.trim());
1635
+ if (!source || !level) continue;
1636
+ try {
1637
+ out[source] = parseLevel(level);
1638
+ } catch (error) {
1639
+ selfLog.write(`ignoring LOGIT_OVERRIDES entry "${pair}"`, error);
1640
+ }
1641
+ }
1642
+ return out;
1643
+ }
1644
+ function buildPipeline(options) {
1645
+ const overrides = Object.entries({ ...envOverrides(), ...options.overrides }).map(([prefix, level]) => ({ prefix, level: level instanceof LevelSwitch ? level : parseLevel(level) })).sort((a, b) => b.prefix.length - a.prefix.length);
1646
+ const enrichers = [];
1647
+ if (options.logContext ?? true) enrichers.push(fromLogContext());
1648
+ if (options.properties) enrichers.push(withProperties(options.properties));
1649
+ enrichers.push(...options.enrichers ?? []);
1650
+ const sinks = [...options.sinks ?? [], ...(options.auditSinks ?? []).map((sink) => ({ ...sink, emit: (e) => sink.emit(e), audit: true }))];
1651
+ const minimumLevel = options.minimumLevel ?? envLevel() ?? "info";
1652
+ return {
1653
+ minimumLevel: minimumLevel instanceof LevelSwitch ? minimumLevel : parseLevel(minimumLevel),
1654
+ overrides,
1655
+ sinks,
1656
+ enrichers,
1657
+ filters: [...options.filters ?? []],
1658
+ destructuring: resolveDestructuring(options.destructuring),
1659
+ onSinkError: options.onSinkError
1660
+ };
1661
+ }
1662
+ function matchOverride(overrides, source) {
1663
+ for (const o of overrides) {
1664
+ if (source === o.prefix || source.startsWith(`${o.prefix}.`)) return o.level;
1665
+ }
1666
+ return void 0;
1667
+ }
1668
+ function escapeTemplate(text) {
1669
+ return text.replace(/{/g, "{{").replace(/}/g, "}}");
1670
+ }
1671
+ var Operation = class {
1672
+ #logger;
1673
+ #template;
1674
+ #args;
1675
+ #options;
1676
+ #start;
1677
+ #done = false;
1678
+ #extra = {};
1679
+ constructor(logger, template, args, options = {}) {
1680
+ this.#logger = logger;
1681
+ this.#template = template;
1682
+ this.#args = args;
1683
+ this.#options = options;
1684
+ this.#start = now();
1685
+ }
1686
+ /** Milliseconds since the operation began. */
1687
+ get elapsed() {
1688
+ return now() - this.#start;
1689
+ }
1690
+ /** Adds a property to the completion event. */
1691
+ enrich(name, value, destructure = false) {
1692
+ this.#extra[name] = destructure ? { __destructure: value } : value;
1693
+ return this;
1694
+ }
1695
+ complete(name, value) {
1696
+ if (name !== void 0) this.enrich(name, value);
1697
+ this.#finish("completed", void 0);
1698
+ }
1699
+ abandon(error) {
1700
+ this.#finish("abandoned", error);
1701
+ }
1702
+ /** Ends the operation without logging anything. */
1703
+ cancel() {
1704
+ this.#done = true;
1705
+ }
1706
+ [Symbol.dispose]() {
1707
+ if (!this.#done) this.abandon();
1708
+ }
1709
+ #finish(outcome, error) {
1710
+ if (this.#done) return;
1711
+ this.#done = true;
1712
+ const elapsed = this.elapsed;
1713
+ let level = outcome === "completed" ? this.#options.completeLevel ?? "info" : this.#options.abandonLevel ?? "warn";
1714
+ if (outcome === "completed" && this.#options.warnAfter !== void 0 && elapsed > this.#options.warnAfter && levelAtLeast("warn", level)) level = "warn";
1715
+ const props = {};
1716
+ for (const [key, value] of Object.entries(this.#extra)) {
1717
+ props[key] = value && typeof value === "object" && "__destructure" in value ? value.__destructure : value;
1718
+ }
1719
+ const logger = Object.keys(props).length ? this.#logger.forContext(props) : this.#logger;
1720
+ const template = `${this.#template} {Outcome:l} in {Elapsed:0.0} ms`;
1721
+ const args = [...this.#args, outcome, elapsed];
1722
+ if (error) logger.write(level, error, template, ...args);
1723
+ else logger.write(level, template, ...args);
1724
+ }
1725
+ };
1726
+ function now() {
1727
+ const perf = globalThis.performance;
1728
+ return perf ? perf.now() : Date.now();
1729
+ }
1730
+ var Logger = class _Logger {
1731
+ #ref;
1732
+ #context;
1733
+ #source;
1734
+ #overrideFor = null;
1735
+ #override;
1736
+ /** @internal */
1737
+ constructor(ref, context = null, source) {
1738
+ this.#ref = ref;
1739
+ this.#context = context;
1740
+ this.#source = source;
1741
+ }
1742
+ name = "logger";
1743
+ /** The `SourceContext` this logger is bound to, if any. */
1744
+ get source() {
1745
+ return this.#source;
1746
+ }
1747
+ /** The current minimum level for this logger's source. */
1748
+ get minimumLevel() {
1749
+ return resolveLevel(this.#effectiveMinimum());
1750
+ }
1751
+ #effectiveMinimum() {
1752
+ const pipeline = this.#ref.current;
1753
+ if (this.#source === void 0) return pipeline.minimumLevel;
1754
+ if (this.#overrideFor !== pipeline) {
1755
+ this.#overrideFor = pipeline;
1756
+ this.#override = matchOverride(pipeline.overrides, this.#source);
1757
+ }
1758
+ return this.#override ?? pipeline.minimumLevel;
1759
+ }
1760
+ /** Cheap check before building anything expensive to log. */
1761
+ isEnabled(level) {
1762
+ return levelAtLeast(level, resolveLevel(this.#effectiveMinimum()));
1763
+ }
1764
+ verbose = (...args) => this.write("verbose", ...args);
1765
+ debug = (...args) => this.write("debug", ...args);
1766
+ info = (...args) => this.write("info", ...args);
1767
+ warn = (...args) => this.write("warn", ...args);
1768
+ error = (...args) => this.write("error", ...args);
1769
+ fatal = (...args) => this.write("fatal", ...args);
1770
+ /**
1771
+ * Writes an event at `level`. Argument shapes:
1772
+ * `(template, ...args)`
1773
+ * `(error, template?, ...args)`
1774
+ * `(properties, template?, ...args)` — one-off properties on this event
1775
+ */
1776
+ write(level, ...args) {
1777
+ if (!this.isEnabled(level)) return;
1778
+ const pipeline = this.#ref.current;
1779
+ let i = 0;
1780
+ let error;
1781
+ let extra;
1782
+ if (args[0] instanceof Error) {
1783
+ error = args[0];
1784
+ i = 1;
1785
+ } else if (args[0] !== null && typeof args[0] === "object" && !Array.isArray(args[0])) {
1786
+ extra = args[0];
1787
+ i = 1;
1788
+ }
1789
+ const head = args[i];
1790
+ let raw;
1791
+ if (typeof head === "string") raw = head;
1792
+ else if (head === void 0) raw = error ? escapeTemplate(error.message || error.name) : "";
1793
+ else raw = escapeTemplate(String(head));
1794
+ const template = parseTemplate(raw);
1795
+ const properties = {};
1796
+ if (template.holes.length) captureArguments(template.holes, template.positional, args.slice(i + 1), pipeline.destructuring, properties);
1797
+ const event = new LogEvent({ level, template, properties, error }, pipeline.destructuring);
1798
+ if (extra) for (const key of Object.keys(extra)) event.addPropertyIfAbsent(key, extra[key], true);
1799
+ this.#dispatch(event, pipeline);
1800
+ }
1801
+ /** Sink entry point: an event from another logger, re-dispatched through this one's level, context, enrichers, filters and sinks. */
1802
+ emit(event) {
1803
+ if (!this.isEnabled(event.level)) return;
1804
+ this.#dispatch(event, this.#ref.current);
1805
+ }
1806
+ #dispatch(event, pipeline) {
1807
+ if (this.#context) {
1808
+ for (const key of Object.keys(this.#context)) {
1809
+ if (!event.hasProperty(key)) event.properties[key] = this.#context[key];
1810
+ }
1811
+ }
1812
+ if (this.#source !== void 0 && !event.hasProperty("SourceContext")) event.properties.SourceContext = this.#source;
1813
+ for (const enricher of pipeline.enrichers) {
1814
+ try {
1815
+ enricher(event);
1816
+ } catch (error) {
1817
+ selfLog.write("an enricher threw", error);
1818
+ }
1819
+ }
1820
+ for (const filter of pipeline.filters) {
1821
+ if (!filter(event)) return;
1822
+ }
1823
+ for (const sink of pipeline.sinks) {
1824
+ if (sink.restrictedToMinimumLevel !== void 0 && !levelAtLeast(event.level, resolveLevel(sink.restrictedToMinimumLevel))) continue;
1825
+ try {
1826
+ sink.emit(event);
1827
+ } catch (error) {
1828
+ if (sink.audit) throw error;
1829
+ if (pipeline.onSinkError) pipeline.onSinkError(error, sink, event);
1830
+ else selfLog.write(`sink ${sink.name ?? "(anonymous)"} threw`, error);
1831
+ }
1832
+ }
1833
+ }
1834
+ forContext(nameOrProps, valueOrDestructure, destructure = false) {
1835
+ const options = this.#ref.current.destructuring;
1836
+ const context = { ...this.#context };
1837
+ if (typeof nameOrProps === "string") {
1838
+ context[nameOrProps] = captureProperty(nameOrProps, valueOrDestructure, destructure ? "@" : void 0, options);
1839
+ } else {
1840
+ const d = valueOrDestructure === true;
1841
+ for (const key of Object.keys(nameOrProps)) context[key] = captureProperty(key, nameOrProps[key], d ? "@" : void 0, options);
1842
+ }
1843
+ return new _Logger(this.#ref, context, this.#source);
1844
+ }
1845
+ /** A logger whose events carry `SourceContext` — the name level overrides match on. Dotted names nest: `'app.db'`. */
1846
+ forSource(source) {
1847
+ return new _Logger(this.#ref, this.#context, source);
1848
+ }
1849
+ /** pino / bunyan spelling of `forContext`. */
1850
+ child(properties, destructure = false) {
1851
+ return this.forContext(properties, destructure);
1852
+ }
1853
+ /** Starts a timed operation; `complete()` / `abandon()` log one event with `Outcome` and `Elapsed`. */
1854
+ beginOperation(template, ...args) {
1855
+ return new Operation(this, template, args);
1856
+ }
1857
+ /** `beginOperation` with options (levels, `warnAfter`). */
1858
+ operation(options, template, ...args) {
1859
+ return new Operation(this, template, args, options);
1860
+ }
1861
+ /**
1862
+ * Runs `fn` as a timed operation: completes when it returns (or its
1863
+ * promise resolves), abandons with the error when it throws (or rejects),
1864
+ * then rethrows.
1865
+ */
1866
+ timed(template, fn, ...args) {
1867
+ const op = new Operation(this, template, args);
1868
+ let result;
1869
+ try {
1870
+ result = fn(op);
1871
+ } catch (error) {
1872
+ op.abandon(error instanceof Error ? error : void 0);
1873
+ throw error;
1874
+ }
1875
+ if (result instanceof Promise) {
1876
+ return result.then(
1877
+ (value) => {
1878
+ op.complete();
1879
+ return value;
1880
+ },
1881
+ (error) => {
1882
+ op.abandon(error instanceof Error ? error : void 0);
1883
+ throw error;
1884
+ }
1885
+ );
1886
+ }
1887
+ op.complete();
1888
+ return result;
1889
+ }
1890
+ /** Waits for every sink that buffers to send what it holds. */
1891
+ async flush() {
1892
+ await Promise.all(this.#ref.current.sinks.map((sink) => safely(() => sink.flush?.(), sink, "flush")));
1893
+ }
1894
+ /** Flushes, then closes the sinks — call once, before the process exits (Serilog's `CloseAndFlush`). */
1895
+ async close() {
1896
+ await this.flush();
1897
+ await Promise.all(this.#ref.current.sinks.map((sink) => safely(() => sink.close?.(), sink, "close")));
1898
+ }
1899
+ /** The sinks this logger writes to. */
1900
+ get sinks() {
1901
+ return this.#ref.current.sinks;
1902
+ }
1903
+ /** @internal — swaps the pipeline for every logger sharing this ref. */
1904
+ _replace(options) {
1905
+ this.#ref.current = buildPipeline(options);
1906
+ }
1907
+ };
1908
+ async function safely(fn, sink, what) {
1909
+ try {
1910
+ await fn();
1911
+ } catch (error) {
1912
+ if (sink.audit) throw error;
1913
+ selfLog.write(`sink ${sink.name ?? "(anonymous)"} failed to ${what}`, error);
1914
+ }
1915
+ }
1916
+ function createLogger(options = {}) {
1917
+ const withDefaults = options.sinks || options.auditSinks ? options : { ...options, sinks: [consoleSink()] };
1918
+ return new Logger({ current: buildPipeline(withDefaults) });
1919
+ }
1920
+ var LoggerConfiguration = class _LoggerConfiguration {
1921
+ #options = {
1922
+ sinks: [],
1923
+ auditSinks: [],
1924
+ enrichers: [],
1925
+ filters: [],
1926
+ overrides: {},
1927
+ destructuring: { policies: [], redact: [] }
1928
+ };
1929
+ minimumLevel = {
1930
+ verbose: () => this.minimumLevel.is("verbose"),
1931
+ debug: () => this.minimumLevel.is("debug"),
1932
+ info: () => this.minimumLevel.is("info"),
1933
+ information: () => this.minimumLevel.is("info"),
1934
+ warn: () => this.minimumLevel.is("warn"),
1935
+ warning: () => this.minimumLevel.is("warn"),
1936
+ error: () => this.minimumLevel.is("error"),
1937
+ fatal: () => this.minimumLevel.is("fatal"),
1938
+ is: (level) => {
1939
+ this.#options.minimumLevel = level;
1940
+ return this;
1941
+ },
1942
+ controlledBy: (levelSwitch) => {
1943
+ this.#options.minimumLevel = levelSwitch;
1944
+ return this;
1945
+ },
1946
+ override: (source, level) => {
1947
+ this.#options.overrides[source] = level;
1948
+ return this;
1949
+ }
1950
+ };
1951
+ writeTo = {
1952
+ sink: (...sinks) => {
1953
+ this.#options.sinks.push(...sinks);
1954
+ return this;
1955
+ },
1956
+ console: (options) => this.writeTo.sink(consoleSink(options)),
1957
+ stream: (stream, options) => this.writeTo.sink(streamSink(stream, options)),
1958
+ http: (options) => this.writeTo.sink(httpSink(options)),
1959
+ seq: (options) => this.writeTo.sink(seqSink(options)),
1960
+ /** A sub-logger with its own filters, enrichers and sinks (Serilog's `WriteTo.Logger`). */
1961
+ logger: (configure2, restrictedToMinimumLevel) => {
1962
+ const child = new _LoggerConfiguration();
1963
+ configure2(child);
1964
+ const sink = child.createLogger();
1965
+ return this.writeTo.sink(restrictedToMinimumLevel ? { ...sink, emit: (e) => sink.emit(e), restrictedToMinimumLevel, flush: () => sink.flush(), close: () => sink.close() } : sink);
1966
+ }
1967
+ };
1968
+ auditTo = {
1969
+ sink: (...sinks) => {
1970
+ this.#options.auditSinks.push(...sinks);
1971
+ return this;
1972
+ }
1973
+ };
1974
+ enrich = {
1975
+ with: (...enrichers) => {
1976
+ this.#options.enrichers.push(...enrichers);
1977
+ return this;
1978
+ },
1979
+ fromLogContext: () => {
1980
+ this.#options.logContext = true;
1981
+ return this;
1982
+ },
1983
+ withProperty: (name, value, destructure = false) => this.enrich.with(withProperty(name, value, destructure)),
1984
+ withProperties: (properties, destructure = false) => this.enrich.with(withProperties(properties, destructure))
1985
+ };
1986
+ filter = {
1987
+ with: (...filters) => {
1988
+ this.#options.filters.push(...filters);
1989
+ return this;
1990
+ },
1991
+ byExcluding: (predicate) => this.filter.with(byExcluding(predicate)),
1992
+ byIncludingOnly: (predicate) => this.filter.with(byIncludingOnly(predicate))
1993
+ };
1994
+ destructure = {
1995
+ toMaximumDepth: (depth) => {
1996
+ this.#options.destructuring.maxDepth = depth;
1997
+ return this;
1998
+ },
1999
+ toMaximumStringLength: (length) => {
2000
+ this.#options.destructuring.maxStringLength = length;
2001
+ return this;
2002
+ },
2003
+ toMaximumCollectionCount: (count) => {
2004
+ this.#options.destructuring.maxCollectionCount = count;
2005
+ return this;
2006
+ },
2007
+ with: (...policies) => {
2008
+ this.#options.destructuring.policies.push(...policies);
2009
+ return this;
2010
+ },
2011
+ byTransforming: (type, transform) => this.destructure.with(byTransforming(type, transform)),
2012
+ /** Keys (or dotted paths) whose values are replaced by `[Redacted]`. */
2013
+ redact: (...keys) => {
2014
+ this.#options.destructuring.redact.push(...keys);
2015
+ return this;
2016
+ }
2017
+ };
2018
+ readFrom = {
2019
+ /** `LOGIT_LEVEL` and `LOGIT_OVERRIDES` from the environment (they are read by default; this makes it explicit). */
2020
+ env: () => this
2021
+ };
2022
+ /** Disables the automatic `LogContext` enricher. */
2023
+ withoutLogContext() {
2024
+ this.#options.logContext = false;
2025
+ return this;
2026
+ }
2027
+ /** The options as a plain object, for `createLogger()` or `configure()`. */
2028
+ toOptions() {
2029
+ return { ...this.#options };
2030
+ }
2031
+ createLogger() {
2032
+ return createLogger(this.toOptions());
2033
+ }
2034
+ };
2035
+ var globalRef = { current: buildPipeline({ sinks: [consoleSink()] }) };
2036
+ var log = new Logger(globalRef);
2037
+ function configure(options = {}) {
2038
+ const opts = options instanceof LoggerConfiguration ? options.toOptions() : options;
2039
+ log._replace(opts.sinks || opts.auditSinks ? opts : { ...opts, sinks: [consoleSink()] });
2040
+ return log;
2041
+ }
2042
+ function closeAndFlush() {
2043
+ return log.close();
2044
+ }
2045
+
2046
+ export {
2047
+ LEVELS,
2048
+ LEVEL_ORDER,
2049
+ SERILOG_LEVEL_NAMES,
2050
+ LEVEL_CODES,
2051
+ LEVEL_NUMBERS,
2052
+ parseLevel,
2053
+ isLevel,
2054
+ levelAtLeast,
2055
+ LevelSwitch,
2056
+ resolveLevel,
2057
+ parseTemplate,
2058
+ templateHash,
2059
+ DEFAULT_DESTRUCTURING,
2060
+ byTransforming,
2061
+ captureValue,
2062
+ captureProperty,
2063
+ captureError,
2064
+ resolveStyles,
2065
+ renderValue,
2066
+ toJson,
2067
+ jsonReplacer,
2068
+ formatNumber,
2069
+ isoTimestamp,
2070
+ formatDate,
2071
+ renderTemplate,
2072
+ LogEvent,
2073
+ LogContext,
2074
+ diagnosticContext,
2075
+ withProperty,
2076
+ withProperties,
2077
+ withComputed,
2078
+ fromLogContext,
2079
+ withEnvironment,
2080
+ withTraceContext,
2081
+ byExcluding,
2082
+ byIncludingOnly,
2083
+ Matching,
2084
+ sampled,
2085
+ rateLimited,
2086
+ selfLog,
2087
+ DEFAULT_OUTPUT_TEMPLATE,
2088
+ formatLevel,
2089
+ formatError,
2090
+ textFormatter,
2091
+ CLEF_MEDIA_TYPE,
2092
+ clefFormatter,
2093
+ jsonFormatter,
2094
+ ansi,
2095
+ detectColors,
2096
+ prettyFormatter,
2097
+ resolveFormatter,
2098
+ callbackSink,
2099
+ memorySink,
2100
+ streamSink,
2101
+ consoleSink,
2102
+ restricted,
2103
+ conditional,
2104
+ audit,
2105
+ mapSink,
2106
+ batchingSink,
2107
+ httpSink,
2108
+ seqSink,
2109
+ Operation,
2110
+ Logger,
2111
+ createLogger,
2112
+ LoggerConfiguration,
2113
+ log,
2114
+ configure,
2115
+ closeAndFlush
2116
+ };
2117
+ //# sourceMappingURL=chunk-GW7WQELF.js.map