flexily 0.5.2 → 0.6.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.
Files changed (50) hide show
  1. package/dist/chunk-CBBoxR_p.mjs +26 -0
  2. package/dist/constants-BNURa6H7.mjs +65 -0
  3. package/dist/constants-BNURa6H7.mjs.map +1 -0
  4. package/dist/constants-D7ythAJC.d.mts +64 -0
  5. package/dist/constants-D7ythAJC.d.mts.map +1 -0
  6. package/{src/classic/node.ts → dist/index-classic.d.mts} +118 -619
  7. package/dist/index-classic.d.mts.map +1 -0
  8. package/dist/index-classic.mjs +1909 -0
  9. package/dist/index-classic.mjs.map +1 -0
  10. package/dist/index.d.mts +195 -0
  11. package/dist/index.d.mts.map +1 -0
  12. package/dist/index.mjs +3279 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/node-zero-75maLs2s.d.mts +762 -0
  15. package/dist/node-zero-75maLs2s.d.mts.map +1 -0
  16. package/dist/src-BWyhokNZ.mjs +692 -0
  17. package/dist/src-BWyhokNZ.mjs.map +1 -0
  18. package/dist/src-DdSLylRA.mjs +816 -0
  19. package/dist/src-DdSLylRA.mjs.map +1 -0
  20. package/dist/testing.d.mts +55 -0
  21. package/dist/testing.d.mts.map +1 -0
  22. package/dist/testing.mjs +154 -0
  23. package/dist/testing.mjs.map +1 -0
  24. package/dist/types--IozHd4V.mjs +283 -0
  25. package/dist/types--IozHd4V.mjs.map +1 -0
  26. package/dist/types-DG1H4DVR.d.mts +157 -0
  27. package/dist/types-DG1H4DVR.d.mts.map +1 -0
  28. package/package.json +33 -24
  29. package/src/CLAUDE.md +0 -527
  30. package/src/classic/layout.ts +0 -1843
  31. package/src/constants.ts +0 -82
  32. package/src/create-flexily.ts +0 -153
  33. package/src/index-classic.ts +0 -110
  34. package/src/index.ts +0 -133
  35. package/src/layout-flex-lines.ts +0 -413
  36. package/src/layout-helpers.ts +0 -160
  37. package/src/layout-measure.ts +0 -259
  38. package/src/layout-stats.ts +0 -41
  39. package/src/layout-traversal.ts +0 -70
  40. package/src/layout-zero.ts +0 -2219
  41. package/src/logger.ts +0 -68
  42. package/src/monospace-measurer.ts +0 -68
  43. package/src/node-zero.ts +0 -1508
  44. package/src/pretext-measurer.ts +0 -86
  45. package/src/test-measurer.ts +0 -219
  46. package/src/testing.ts +0 -215
  47. package/src/text-layout.ts +0 -75
  48. package/src/trace.ts +0 -252
  49. package/src/types.ts +0 -236
  50. package/src/utils.ts +0 -243
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-zero-75maLs2s.d.mts","names":[],"sources":["../src/node-zero.ts"],"mappings":"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"}
@@ -0,0 +1,692 @@
1
+ import { closeSync, openSync, writeSync } from "node:fs";
2
+ //#region ../loggily/src/colors.ts
3
+ /**
4
+ * Vendored ANSI color functions — replaces picocolors dependency.
5
+ * Supports NO_COLOR, FORCE_COLOR, and TTY detection.
6
+ */
7
+ const _process$1 = typeof process !== "undefined" ? process : void 0;
8
+ const enabled = _process$1?.env?.["FORCE_COLOR"] !== void 0 && _process$1?.env?.["FORCE_COLOR"] !== "0" ? true : _process$1?.env?.["NO_COLOR"] !== void 0 ? false : _process$1?.stdout?.isTTY ?? false;
9
+ function wrap(open, close) {
10
+ if (!enabled) return (str) => str;
11
+ return (str) => open + str + close;
12
+ }
13
+ const colors = {
14
+ dim: wrap("\x1B[2m", "\x1B[22m"),
15
+ blue: wrap("\x1B[34m", "\x1B[39m"),
16
+ yellow: wrap("\x1B[33m", "\x1B[39m"),
17
+ red: wrap("\x1B[31m", "\x1B[39m"),
18
+ magenta: wrap("\x1B[35m", "\x1B[39m"),
19
+ cyan: wrap("\x1B[36m", "\x1B[39m")
20
+ };
21
+ //#endregion
22
+ //#region ../loggily/src/file-writer.ts
23
+ /**
24
+ * File writer for loggily — Node.js/Bun only.
25
+ *
26
+ * Separated from core logger to allow tree-shaking in browser bundles.
27
+ * Uses dynamic import("node:fs") to avoid static dependency on Node APIs.
28
+ */
29
+ /**
30
+ * Create an async buffered file writer for log output.
31
+ * Buffers writes and flushes on size threshold or interval.
32
+ * Registers a process.on('exit') handler to flush remaining buffer.
33
+ *
34
+ * **Node.js/Bun only** — not available in browser environments.
35
+ *
36
+ * @param filePath - Path to the log file (opened in append mode)
37
+ * @param options - Buffer size and flush interval configuration
38
+ * @returns FileWriter with write, flush, and close methods
39
+ *
40
+ * @example
41
+ * const writer = createFileWriter('/tmp/app.log')
42
+ * const unsubscribe = addWriter((formatted) => writer.write(formatted))
43
+ *
44
+ * // On shutdown:
45
+ * unsubscribe()
46
+ * writer.close()
47
+ */
48
+ function createFileWriter(filePath, options = {}) {
49
+ const bufferSize = options.bufferSize ?? 4096;
50
+ const flushInterval = options.flushInterval ?? 100;
51
+ let buffer = "";
52
+ let fd = null;
53
+ let timer = null;
54
+ let closed = false;
55
+ fd = openSync(filePath, "a");
56
+ /** Flush buffer contents to disk synchronously */
57
+ function flush() {
58
+ if (buffer.length === 0 || fd === null) return;
59
+ writeSync(fd, buffer);
60
+ buffer = "";
61
+ }
62
+ timer = setInterval(flush, flushInterval);
63
+ if (timer && typeof timer === "object" && "unref" in timer) timer.unref();
64
+ const exitHandler = () => flush();
65
+ process.on("exit", exitHandler);
66
+ return {
67
+ write(line) {
68
+ if (closed) return;
69
+ buffer += line + "\n";
70
+ if (buffer.length >= bufferSize) flush();
71
+ },
72
+ flush,
73
+ close() {
74
+ if (closed) return;
75
+ closed = true;
76
+ if (timer !== null) {
77
+ clearInterval(timer);
78
+ timer = null;
79
+ }
80
+ try {
81
+ flush();
82
+ } catch {} finally {
83
+ if (fd !== null) {
84
+ closeSync(fd);
85
+ fd = null;
86
+ }
87
+ process.removeListener("exit", exitHandler);
88
+ }
89
+ }
90
+ };
91
+ }
92
+ //#endregion
93
+ //#region ../loggily/src/pipeline.ts
94
+ const LOG_LEVEL_PRIORITY = {
95
+ trace: 0,
96
+ debug: 1,
97
+ info: 2,
98
+ warn: 3,
99
+ error: 4,
100
+ silent: 5
101
+ };
102
+ const _process = typeof process !== "undefined" ? process : void 0;
103
+ function getEnv(key) {
104
+ return _process?.env?.[key];
105
+ }
106
+ function writeStderr(text) {
107
+ if (_process?.stderr?.write) _process.stderr.write(text + "\n");
108
+ else console.error(text);
109
+ }
110
+ function safeStringify(value) {
111
+ const seen = /* @__PURE__ */ new WeakSet();
112
+ return JSON.stringify(value, (_key, val) => {
113
+ if (typeof val === "bigint") return val.toString();
114
+ if (typeof val === "symbol") return val.toString();
115
+ if (val instanceof Error) return {
116
+ message: val.message,
117
+ stack: val.stack,
118
+ name: val.name
119
+ };
120
+ if (typeof val === "object" && val !== null) {
121
+ if (seen.has(val)) return "[Circular]";
122
+ seen.add(val);
123
+ }
124
+ return val;
125
+ });
126
+ }
127
+ function formatConsoleEvent(event) {
128
+ const time = colors.dim(new Date(event.time).toISOString().split("T")[1]?.split(".")[0] || "");
129
+ const ns = colors.cyan(event.namespace);
130
+ if (event.kind === "span") {
131
+ const message = `(${event.duration}ms)`;
132
+ let output = `${time} ${colors.magenta("SPAN")} ${ns} ${message}`;
133
+ if (event.props && Object.keys(event.props).length > 0) output += ` ${colors.dim(safeStringify(event.props))}`;
134
+ return output;
135
+ }
136
+ let levelStr;
137
+ switch (event.level) {
138
+ case "trace":
139
+ levelStr = colors.dim("TRACE");
140
+ break;
141
+ case "debug":
142
+ levelStr = colors.dim("DEBUG");
143
+ break;
144
+ case "info":
145
+ levelStr = colors.blue("INFO");
146
+ break;
147
+ case "warn":
148
+ levelStr = colors.yellow("WARN");
149
+ break;
150
+ case "error":
151
+ levelStr = colors.red("ERROR");
152
+ break;
153
+ }
154
+ let output = `${time} ${levelStr} ${ns} ${event.message}`;
155
+ if (event.props && Object.keys(event.props).length > 0) output += ` ${colors.dim(safeStringify(event.props))}`;
156
+ return output;
157
+ }
158
+ function formatJSONEvent(event) {
159
+ if (event.kind === "span") return safeStringify({
160
+ time: new Date(event.time).toISOString(),
161
+ level: "span",
162
+ name: event.namespace,
163
+ msg: `(${event.duration}ms)`,
164
+ duration: event.duration,
165
+ span_id: event.spanId,
166
+ trace_id: event.traceId,
167
+ parent_id: event.parentId,
168
+ ...event.props
169
+ });
170
+ return safeStringify({
171
+ time: new Date(event.time).toISOString(),
172
+ level: event.level,
173
+ name: event.namespace,
174
+ msg: event.message,
175
+ ...event.props
176
+ });
177
+ }
178
+ function matchesPattern(namespace, pattern) {
179
+ if (pattern === "*") return true;
180
+ return namespace === pattern || namespace.startsWith(pattern + ":");
181
+ }
182
+ function parseNsFilter(ns) {
183
+ const patterns = typeof ns === "string" ? ns.split(",").map((s) => s.trim()) : ns;
184
+ const includes = [];
185
+ const excludes = [];
186
+ for (const p of patterns) if (p.startsWith("-")) excludes.push(p.slice(1));
187
+ else includes.push(p);
188
+ return (namespace) => {
189
+ for (const exc of excludes) if (matchesPattern(namespace, exc)) return false;
190
+ if (includes.length > 0) {
191
+ for (const inc of includes) if (matchesPattern(namespace, inc)) return true;
192
+ return false;
193
+ }
194
+ return true;
195
+ };
196
+ }
197
+ function createConsoleSink(format) {
198
+ const formatter = format === "json" ? formatJSONEvent : formatConsoleEvent;
199
+ return (event) => {
200
+ const text = formatter(event);
201
+ if (event.kind === "span") {
202
+ writeStderr(text);
203
+ return;
204
+ }
205
+ switch (event.level) {
206
+ case "trace":
207
+ case "debug":
208
+ console.debug(text);
209
+ break;
210
+ case "info":
211
+ console.info(text);
212
+ break;
213
+ case "warn":
214
+ console.warn(text);
215
+ break;
216
+ case "error":
217
+ console.error(text);
218
+ break;
219
+ }
220
+ };
221
+ }
222
+ function createFileSink(path, format) {
223
+ const writer = createFileWriter(path);
224
+ const formatter = format === "json" ? formatJSONEvent : formatConsoleEvent;
225
+ return {
226
+ write: (event) => writer.write(formatter(event)),
227
+ dispose: () => writer.close()
228
+ };
229
+ }
230
+ function createWritableSink(writable, format) {
231
+ const formatter = format === "json" ? formatJSONEvent : formatConsoleEvent;
232
+ return (event) => writable.write(formatter(event) + "\n");
233
+ }
234
+ const VALID_CONFIG_KEYS = new Set([
235
+ "level",
236
+ "ns",
237
+ "format"
238
+ ]);
239
+ const SINK_KEYS = new Set(["file", "otel"]);
240
+ function isPojo(obj) {
241
+ if (typeof obj !== "object" || obj === null) return false;
242
+ const proto = Object.getPrototypeOf(obj);
243
+ return proto === Object.prototype || proto === null;
244
+ }
245
+ function isWritable(obj) {
246
+ return typeof obj === "object" && obj !== null && "write" in obj && typeof obj.write === "function" && !isPojo(obj);
247
+ }
248
+ function isValidLogLevel(val) {
249
+ return typeof val === "string" && val in LOG_LEVEL_PRIORITY;
250
+ }
251
+ function buildPipeline(elements, parentConfig) {
252
+ const config = {
253
+ level: parentConfig?.level ?? readEnvLevel(),
254
+ ns: parentConfig?.ns ?? readEnvNs(),
255
+ format: parentConfig?.format ?? readEnvFormat()
256
+ };
257
+ const stages = [];
258
+ const outputs = [];
259
+ const branches = [];
260
+ const disposables = [];
261
+ for (const element of elements) {
262
+ if (Array.isArray(element)) {
263
+ const branch = buildPipeline(element, { ...config });
264
+ branches.push(branch);
265
+ disposables.push(() => branch.dispose());
266
+ continue;
267
+ }
268
+ if (typeof element === "function" && element !== console) {
269
+ stages.push(element);
270
+ continue;
271
+ }
272
+ if (element === console) {
273
+ outputs.push({
274
+ levelPriority: LOG_LEVEL_PRIORITY[config.level],
275
+ nsFilter: config.ns,
276
+ write: createConsoleSink(config.format)
277
+ });
278
+ continue;
279
+ }
280
+ if (isWritable(element)) {
281
+ outputs.push({
282
+ levelPriority: LOG_LEVEL_PRIORITY[config.level],
283
+ nsFilter: config.ns,
284
+ write: createWritableSink(element, config.format)
285
+ });
286
+ continue;
287
+ }
288
+ if (isPojo(element)) {
289
+ const obj = element;
290
+ const keys = Object.keys(obj);
291
+ const hasSinkKey = keys.some((k) => SINK_KEYS.has(k));
292
+ if (keys.some((k) => !VALID_CONFIG_KEYS.has(k) && !SINK_KEYS.has(k))) {
293
+ const unknown = keys.find((k) => !VALID_CONFIG_KEYS.has(k) && !SINK_KEYS.has(k));
294
+ throw new Error(`loggily: unknown config key "${unknown}" in config object. Valid keys: ${[...VALID_CONFIG_KEYS, ...SINK_KEYS].join(", ")}`);
295
+ }
296
+ if (hasSinkKey) {
297
+ if (typeof obj.file === "string") {
298
+ const outputLevel = isValidLogLevel(obj.level) ? obj.level : config.level;
299
+ const outputNs = obj.ns ? parseNsFilter(obj.ns) : config.ns;
300
+ const outputFormat = obj.format ?? config.format;
301
+ const sink = createFileSink(obj.file, outputFormat);
302
+ disposables.push(sink.dispose);
303
+ outputs.push({
304
+ levelPriority: LOG_LEVEL_PRIORITY[outputLevel],
305
+ nsFilter: outputNs,
306
+ write: sink.write,
307
+ dispose: sink.dispose
308
+ });
309
+ }
310
+ continue;
311
+ }
312
+ if (isValidLogLevel(obj.level)) config.level = obj.level;
313
+ if (obj.ns !== void 0) config.ns = parseNsFilter(obj.ns);
314
+ if (obj.format === "console" || obj.format === "json") config.format = obj.format;
315
+ continue;
316
+ }
317
+ throw new Error(`loggily: unsupported config element of type "${typeof element}". Config arrays accept: objects (config), arrays (branches), functions (stages), console, or writables ({ write }).`);
318
+ }
319
+ const dispatch = (event) => {
320
+ let e = event;
321
+ for (const stage of stages) {
322
+ const result = stage(e);
323
+ if (result === null) return;
324
+ if (result !== void 0) e = result;
325
+ }
326
+ for (const output of outputs) {
327
+ if (e.kind === "log" && LOG_LEVEL_PRIORITY[e.level] < output.levelPriority) continue;
328
+ if (output.nsFilter && !output.nsFilter(e.namespace)) continue;
329
+ output.write(e);
330
+ }
331
+ for (const branch of branches) branch.dispatch(e);
332
+ };
333
+ return {
334
+ dispatch,
335
+ level: config.level,
336
+ dispose: () => {
337
+ for (const d of disposables) d();
338
+ }
339
+ };
340
+ }
341
+ const runtimeState = {
342
+ suppressConsole: false,
343
+ writers: []
344
+ };
345
+ function defaultPipeline() {
346
+ const rt = runtimeState;
347
+ const disposables = [];
348
+ let fileSink = null;
349
+ const logFile = getEnv("LOG_FILE");
350
+ if (logFile) {
351
+ const sink = createFileSink(logFile, "json");
352
+ fileSink = sink.write;
353
+ disposables.push(sink.dispose);
354
+ }
355
+ const dispatch = (event) => {
356
+ const currentLevel = readEnvLevel();
357
+ if (event.kind === "log") {
358
+ if (LOG_LEVEL_PRIORITY[event.level] < LOG_LEVEL_PRIORITY[currentLevel]) return;
359
+ } else if (event.kind === "span") {
360
+ const trace = readEnvTrace();
361
+ if (!trace.enabled) return;
362
+ if (trace.filter && !trace.filter(event.namespace)) return;
363
+ }
364
+ const currentNs = readEnvNs();
365
+ if (currentNs && !currentNs(event.namespace)) return;
366
+ const formatter = readEnvFormat() === "json" || getEnv("NODE_ENV") === "production" || getEnv("TRACE_FORMAT") === "json" ? formatJSONEvent : formatConsoleEvent;
367
+ if (rt.writers.length > 0) {
368
+ const formatted = formatter(event);
369
+ const lvl = event.kind === "log" ? event.level : "span";
370
+ for (const w of rt.writers) w(formatted, lvl);
371
+ }
372
+ if (rt.suppressConsole) {
373
+ fileSink?.(event);
374
+ return;
375
+ }
376
+ const text = formatter(event);
377
+ if (event.kind === "span") writeStderr(text);
378
+ else switch (event.level) {
379
+ case "trace":
380
+ case "debug":
381
+ console.debug(text);
382
+ break;
383
+ case "info":
384
+ console.info(text);
385
+ break;
386
+ case "warn":
387
+ console.warn(text);
388
+ break;
389
+ case "error":
390
+ console.error(text);
391
+ break;
392
+ }
393
+ fileSink?.(event);
394
+ };
395
+ return {
396
+ dispatch,
397
+ get level() {
398
+ return readEnvLevel();
399
+ },
400
+ dispose: () => {
401
+ for (const d of disposables) d();
402
+ }
403
+ };
404
+ }
405
+ function readEnvLevel() {
406
+ const env = getEnv("LOG_LEVEL")?.toLowerCase();
407
+ let level = env === "trace" || env === "debug" || env === "info" || env === "warn" || env === "error" || env === "silent" ? env : "info";
408
+ if (getEnv("DEBUG") && LOG_LEVEL_PRIORITY[level] > LOG_LEVEL_PRIORITY.debug) level = "debug";
409
+ return level;
410
+ }
411
+ function readEnvNs() {
412
+ const debugEnv = getEnv("DEBUG");
413
+ if (!debugEnv) return null;
414
+ return parseNsFilter(debugEnv.split(",").map((s) => s.trim()));
415
+ }
416
+ function readEnvFormat() {
417
+ const envFormat = getEnv("LOG_FORMAT")?.toLowerCase();
418
+ if (envFormat === "json") return "json";
419
+ if (envFormat === "console") return "console";
420
+ if (getEnv("TRACE_FORMAT") === "json") return "json";
421
+ if (getEnv("NODE_ENV") === "production") return "json";
422
+ return "console";
423
+ }
424
+ function readEnvTrace() {
425
+ const traceEnv = getEnv("TRACE");
426
+ if (!traceEnv) return {
427
+ enabled: false,
428
+ filter: null
429
+ };
430
+ if (traceEnv === "1" || traceEnv === "true") return {
431
+ enabled: true,
432
+ filter: null
433
+ };
434
+ const prefixes = traceEnv.split(",").map((s) => s.trim());
435
+ return {
436
+ enabled: true,
437
+ filter: (namespace) => {
438
+ for (const prefix of prefixes) if (matchesPattern(namespace, prefix)) return true;
439
+ return false;
440
+ }
441
+ };
442
+ }
443
+ //#endregion
444
+ //#region ../loggily/src/tracing.ts
445
+ let currentIdFormat = "simple";
446
+ let simpleSpanCounter = 0;
447
+ let simpleTraceCounter = 0;
448
+ /** Generate a hex string of the given byte length using crypto.randomUUID */
449
+ function randomHex(bytes) {
450
+ return crypto.randomUUID().replace(/-/g, "").slice(0, bytes * 2);
451
+ }
452
+ /** Generate a span ID according to the current format */
453
+ function generateSpanId() {
454
+ if (currentIdFormat === "w3c") return randomHex(8);
455
+ return `sp_${(++simpleSpanCounter).toString(36)}`;
456
+ }
457
+ /** Generate a trace ID according to the current format */
458
+ function generateTraceId() {
459
+ if (currentIdFormat === "w3c") return randomHex(16);
460
+ return `tr_${(++simpleTraceCounter).toString(36)}`;
461
+ }
462
+ let sampleRate = 1;
463
+ /**
464
+ * Determine whether a new trace should be sampled.
465
+ * Called at trace creation time (head-based sampling).
466
+ */
467
+ function shouldSample() {
468
+ if (sampleRate >= 1) return true;
469
+ if (sampleRate <= 0) return false;
470
+ return Math.random() < sampleRate;
471
+ }
472
+ //#endregion
473
+ //#region ../loggily/src/core.ts
474
+ /**
475
+ * loggily v2 — Structured logging with spans
476
+ *
477
+ * One import. Objects configure. Arrays branch. Values write.
478
+ *
479
+ * @example
480
+ * const log = createLogger('myapp')
481
+ * log.info?.('starting')
482
+ *
483
+ * @example
484
+ * const log = createLogger('myapp', [
485
+ * { level: 'debug', ns: '-sql' },
486
+ * console,
487
+ * { file: '/tmp/app.log', level: 'info', format: 'json' },
488
+ * ])
489
+ * log.info?.('server started', { port: 3000 })
490
+ */
491
+ /** @internal */
492
+ let _ambientRecorder = null;
493
+ let _getContextTags = null;
494
+ let _enterContext = null;
495
+ let _exitContext = null;
496
+ function createSpanDataProxy(getFields, attrs) {
497
+ const READONLY_KEYS = new Set([
498
+ "id",
499
+ "traceId",
500
+ "parentId",
501
+ "startTime",
502
+ "endTime",
503
+ "duration"
504
+ ]);
505
+ return new Proxy(attrs, {
506
+ get(_target, prop) {
507
+ if (READONLY_KEYS.has(prop)) return getFields()[prop];
508
+ return attrs[prop];
509
+ },
510
+ set(_target, prop, value) {
511
+ if (READONLY_KEYS.has(prop)) return false;
512
+ attrs[prop] = value;
513
+ return true;
514
+ }
515
+ });
516
+ }
517
+ function resolveMessage(msg) {
518
+ return typeof msg === "function" ? msg() : msg;
519
+ }
520
+ function createLoggerImpl(name, props, pipeline, spanMeta, parentSpanId, traceId, traceSampled = true) {
521
+ const emitLog = (level, msgOrError, dataOrMsg, extraData) => {
522
+ let message;
523
+ let data;
524
+ if (msgOrError instanceof Error) {
525
+ const err = msgOrError;
526
+ if (typeof dataOrMsg === "string") {
527
+ message = dataOrMsg;
528
+ data = {
529
+ ...props,
530
+ ...extraData,
531
+ error_type: err.name,
532
+ error_message: err.message,
533
+ error_stack: err.stack,
534
+ error_code: err.code
535
+ };
536
+ } else {
537
+ message = err.message;
538
+ data = {
539
+ ...props,
540
+ ...dataOrMsg,
541
+ error_type: err.name,
542
+ error_stack: err.stack,
543
+ error_code: err.code
544
+ };
545
+ }
546
+ } else {
547
+ message = resolveMessage(msgOrError);
548
+ const contextTags = _getContextTags?.();
549
+ data = contextTags && Object.keys(contextTags).length > 0 ? {
550
+ ...contextTags,
551
+ ...props,
552
+ ...dataOrMsg
553
+ } : Object.keys(props).length > 0 || dataOrMsg ? {
554
+ ...props,
555
+ ...dataOrMsg
556
+ } : void 0;
557
+ }
558
+ const event = {
559
+ kind: "log",
560
+ time: Date.now(),
561
+ namespace: name,
562
+ level,
563
+ message,
564
+ props: data
565
+ };
566
+ pipeline.dispatch(event);
567
+ };
568
+ return {
569
+ name,
570
+ props: Object.freeze({ ...props }),
571
+ get spanData() {
572
+ if (!spanMeta) return null;
573
+ return createSpanDataProxy(() => ({
574
+ id: spanMeta.id,
575
+ traceId: spanMeta.traceId,
576
+ parentId: spanMeta.parentId,
577
+ startTime: spanMeta.startTime,
578
+ endTime: spanMeta.endTime,
579
+ duration: spanMeta.endTime !== null ? spanMeta.endTime - spanMeta.startTime : Date.now() - spanMeta.startTime
580
+ }), spanMeta.attrs);
581
+ },
582
+ trace: (msg, data) => emitLog("trace", msg, data),
583
+ debug: (msg, data) => emitLog("debug", msg, data),
584
+ info: (msg, data) => emitLog("info", msg, data),
585
+ warn: (msg, data) => emitLog("warn", msg, data),
586
+ error: (msgOrError, dataOrMsg, extraData) => emitLog("error", msgOrError, dataOrMsg, extraData),
587
+ logger(namespace, childProps) {
588
+ return wrapConditional(createLoggerImpl(namespace ? `${name}:${namespace}` : name, {
589
+ ...props,
590
+ ...childProps
591
+ }, pipeline, null, parentSpanId, traceId, traceSampled), () => pipeline.level);
592
+ },
593
+ span(namespace, childProps) {
594
+ const childName = namespace ? `${name}:${namespace}` : name;
595
+ const resolvedChildProps = typeof childProps === "function" ? childProps() : childProps;
596
+ const mergedProps = {
597
+ ...props,
598
+ ...resolvedChildProps
599
+ };
600
+ const newSpanId = generateSpanId();
601
+ let resolvedParentId = parentSpanId;
602
+ let resolvedTraceId = traceId;
603
+ const isNewTrace = !resolvedTraceId;
604
+ const finalTraceId = resolvedTraceId || generateTraceId();
605
+ const sampled = isNewTrace ? shouldSample() : traceSampled;
606
+ const newSpanData = {
607
+ id: newSpanId,
608
+ traceId: finalTraceId,
609
+ parentId: resolvedParentId,
610
+ startTime: Date.now(),
611
+ endTime: null,
612
+ duration: null,
613
+ attrs: {}
614
+ };
615
+ const spanLogger = createLoggerImpl(childName, mergedProps, pipeline, newSpanData, newSpanId, finalTraceId, sampled);
616
+ _enterContext?.(newSpanId, finalTraceId, resolvedParentId);
617
+ spanLogger[Symbol.dispose] = () => {
618
+ if (newSpanData.endTime !== null) return;
619
+ newSpanData.endTime = Date.now();
620
+ newSpanData.duration = newSpanData.endTime - newSpanData.startTime;
621
+ _exitContext?.(newSpanId);
622
+ _ambientRecorder?.recordSpan({
623
+ name: childName,
624
+ durationMs: newSpanData.duration
625
+ });
626
+ if (sampled) {
627
+ const spanEvent = {
628
+ kind: "span",
629
+ time: newSpanData.endTime,
630
+ namespace: childName,
631
+ name: childName,
632
+ duration: newSpanData.duration,
633
+ props: {
634
+ ...mergedProps,
635
+ ...newSpanData.attrs
636
+ },
637
+ spanId: newSpanData.id,
638
+ traceId: newSpanData.traceId,
639
+ parentId: newSpanData.parentId
640
+ };
641
+ pipeline.dispatch(spanEvent);
642
+ }
643
+ };
644
+ return spanLogger;
645
+ },
646
+ child(context) {
647
+ if (typeof context === "string") return this.logger(context);
648
+ return wrapConditional(createLoggerImpl(name, {
649
+ ...props,
650
+ ...context
651
+ }, pipeline, null, parentSpanId, traceId, traceSampled), () => pipeline.level);
652
+ },
653
+ end() {
654
+ if (spanMeta?.endTime === null) this[Symbol.dispose]?.();
655
+ }
656
+ };
657
+ }
658
+ function wrapConditional(logger, getLevel) {
659
+ return new Proxy(logger, { get(target, prop) {
660
+ if (prop in LOG_LEVEL_PRIORITY && prop !== "silent") {
661
+ if (LOG_LEVEL_PRIORITY[prop] < LOG_LEVEL_PRIORITY[getLevel()]) return;
662
+ }
663
+ return target[prop];
664
+ } });
665
+ }
666
+ /**
667
+ * Create a logger.
668
+ *
669
+ * @param name - Logger namespace (e.g., 'myapp', 'myapp:db')
670
+ * @param config - Optional config array. Objects configure, arrays branch, values write.
671
+ *
672
+ * @example
673
+ * // Zero config (reads LOG_LEVEL, DEBUG, LOG_FORMAT from env)
674
+ * const log = createLogger('myapp')
675
+ *
676
+ * @example
677
+ * // Configured pipeline
678
+ * const log = createLogger('myapp', [
679
+ * { level: 'debug', ns: '-sql' },
680
+ * console,
681
+ * { file: '/tmp/app.log', level: 'info', format: 'json' },
682
+ * ])
683
+ */
684
+ function createLogger(name, config) {
685
+ const pipeline = config ? buildPipeline(config) : defaultPipeline();
686
+ return wrapConditional(createLoggerImpl(name, {}, pipeline, null, null, null), () => pipeline.level);
687
+ }
688
+ (typeof process !== "undefined" ? process : void 0)?.env;
689
+ //#endregion
690
+ export { createLogger };
691
+
692
+ //# sourceMappingURL=src-BWyhokNZ.mjs.map