@dxos/log 0.10.0 → 0.11.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 (61) hide show
  1. package/dist/lib/chunk-context.mjs +307 -0
  2. package/dist/lib/chunk-context.mjs.map +1 -0
  3. package/dist/lib/index.mjs +619 -0
  4. package/dist/lib/index.mjs.map +1 -0
  5. package/dist/lib/platform/browser.mjs +18 -0
  6. package/dist/lib/platform/browser.mjs.map +1 -0
  7. package/dist/lib/platform/node.mjs +18 -0
  8. package/dist/lib/platform/node.mjs.map +1 -0
  9. package/dist/lib/processors/console-processor.mjs +86 -0
  10. package/dist/lib/processors/console-processor.mjs.map +1 -0
  11. package/dist/lib/processors/console-stub.mjs +6 -0
  12. package/dist/lib/processors/console-stub.mjs.map +1 -0
  13. package/dist/lib/processors/file-processor.mjs +62 -0
  14. package/dist/lib/processors/file-processor.mjs.map +1 -0
  15. package/dist/types/src/index.d.ts +1 -0
  16. package/dist/types/src/index.d.ts.map +1 -1
  17. package/dist/types/src/registry.d.ts +28 -0
  18. package/dist/types/src/registry.d.ts.map +1 -0
  19. package/dist/types/src/registry.test.d.ts +2 -0
  20. package/dist/types/src/registry.test.d.ts.map +1 -0
  21. package/dist/types/tsconfig.tsbuildinfo +1 -1
  22. package/package.json +9 -18
  23. package/src/context.ts +32 -3
  24. package/src/index.ts +1 -0
  25. package/src/platform/browser/index.ts +2 -2
  26. package/src/registry.test.ts +56 -0
  27. package/src/registry.ts +63 -0
  28. package/dist/lib/browser/chunk-ALZAGDFJ.mjs +0 -311
  29. package/dist/lib/browser/chunk-ALZAGDFJ.mjs.map +0 -7
  30. package/dist/lib/browser/chunk-IEP6GGEX.mjs +0 -23
  31. package/dist/lib/browser/chunk-IEP6GGEX.mjs.map +0 -7
  32. package/dist/lib/browser/index.mjs +0 -667
  33. package/dist/lib/browser/index.mjs.map +0 -7
  34. package/dist/lib/browser/meta.json +0 -1
  35. package/dist/lib/browser/platform/browser/index.mjs +0 -26
  36. package/dist/lib/browser/platform/browser/index.mjs.map +0 -7
  37. package/dist/lib/browser/platform/node/index.mjs +0 -21
  38. package/dist/lib/browser/platform/node/index.mjs.map +0 -7
  39. package/dist/lib/browser/processors/console-processor.mjs +0 -102
  40. package/dist/lib/browser/processors/console-processor.mjs.map +0 -7
  41. package/dist/lib/browser/processors/console-stub.mjs +0 -9
  42. package/dist/lib/browser/processors/console-stub.mjs.map +0 -7
  43. package/dist/lib/browser/processors/file-processor.mjs +0 -75
  44. package/dist/lib/browser/processors/file-processor.mjs.map +0 -7
  45. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +0 -24
  46. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +0 -7
  47. package/dist/lib/node-esm/chunk-RKEZ3A6V.mjs +0 -313
  48. package/dist/lib/node-esm/chunk-RKEZ3A6V.mjs.map +0 -7
  49. package/dist/lib/node-esm/index.mjs +0 -668
  50. package/dist/lib/node-esm/index.mjs.map +0 -7
  51. package/dist/lib/node-esm/meta.json +0 -1
  52. package/dist/lib/node-esm/platform/browser/index.mjs +0 -27
  53. package/dist/lib/node-esm/platform/browser/index.mjs.map +0 -7
  54. package/dist/lib/node-esm/platform/node/index.mjs +0 -22
  55. package/dist/lib/node-esm/platform/node/index.mjs.map +0 -7
  56. package/dist/lib/node-esm/processors/console-processor.mjs +0 -103
  57. package/dist/lib/node-esm/processors/console-processor.mjs.map +0 -7
  58. package/dist/lib/node-esm/processors/console-stub.mjs +0 -10
  59. package/dist/lib/node-esm/processors/console-stub.mjs.map +0 -7
  60. package/dist/lib/node-esm/processors/file-processor.mjs +0 -76
  61. package/dist/lib/node-esm/processors/file-processor.mjs.map +0 -7
@@ -0,0 +1,619 @@
1
+ import { a as logInfo, c as LogProcessorType, i as gatherLogInfoFromScope, l as levels, n as getContextFromEntry, o as getRelativeFilename, r as shouldLog, s as LogLevel, t as LogEntry, u as shortLevelName } from "./chunk-context.mjs";
2
+ import { CircularBuffer, omit, pick, safariCheck } from "@dxos/util";
3
+ import chalk from "chalk";
4
+ import { inspect } from "@dxos/node-std/util";
5
+ import defaultsDeep from "lodash.defaultsdeep";
6
+ export * from "#console-processor";
7
+ //#region \0rolldown/runtime.js
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
+ var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __exportAll = (all, no_symbols) => {
13
+ let target = {};
14
+ for (var name in all) __defProp(target, name, {
15
+ get: all[name],
16
+ enumerable: true
17
+ });
18
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
19
+ return target;
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
23
+ key = keys[i];
24
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
25
+ get: ((k) => from[k]).bind(null, key),
26
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
27
+ });
28
+ }
29
+ return to;
30
+ };
31
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
32
+ //#endregion
33
+ //#region src/environment.ts
34
+ /**
35
+ * Per-tab session-storage key used to stabilize the random suffix for the main thread.
36
+ * `sessionStorage` is per-tab and survives reloads of the same tab.
37
+ */
38
+ var TAB_SUFFIX_STORAGE_KEY = "@dxos/log:env-suffix";
39
+ var SUFFIX_LENGTH = 6;
40
+ /**
41
+ * Generate a 6-character lowercase-alphanumeric suffix.
42
+ * Cryptographically random when `crypto` is available; falls back to `Math.random`.
43
+ */
44
+ var randomSuffix = () => {
45
+ const cryptoRef = globalThis.crypto;
46
+ if (cryptoRef?.getRandomValues) {
47
+ const bytes = new Uint8Array(SUFFIX_LENGTH);
48
+ cryptoRef.getRandomValues(bytes);
49
+ let suffix = "";
50
+ for (const byte of bytes) suffix += (byte % 36).toString(36);
51
+ return suffix;
52
+ }
53
+ return Math.random().toString(36).slice(2, 8).padEnd(SUFFIX_LENGTH, "0");
54
+ };
55
+ /**
56
+ * Look up (or create) a stable per-tab suffix in `sessionStorage`.
57
+ * Same browser tab keeps the same suffix across reloads; different tabs get
58
+ * different suffixes; private/blocked storage falls back to a fresh random.
59
+ */
60
+ var getOrCreateTabSuffix = (session) => {
61
+ if (!session) return randomSuffix();
62
+ try {
63
+ const existing = session.getItem(TAB_SUFFIX_STORAGE_KEY);
64
+ if (existing && existing.length > 0) return existing;
65
+ const suffix = randomSuffix();
66
+ session.setItem(TAB_SUFFIX_STORAGE_KEY, suffix);
67
+ return suffix;
68
+ } catch {
69
+ return randomSuffix();
70
+ }
71
+ };
72
+ var isInstanceOf = (scope, ctorName) => {
73
+ const ctor = scope?.[ctorName];
74
+ return typeof ctor === "function" && scope instanceof ctor;
75
+ };
76
+ /**
77
+ * Cloudflare Workers set `navigator.userAgent` to this exact string, regardless of
78
+ * whether the worker is using modules or service-worker syntax. This is the most
79
+ * stable signal and is checked before browser worker scopes because CF workers in
80
+ * service-worker syntax also expose a `ServiceWorkerGlobalScope`.
81
+ */
82
+ var CF_WORKER_USER_AGENT = "Cloudflare-Workers";
83
+ /**
84
+ * Infer a writer/environment identifier from the current execution context.
85
+ *
86
+ * Safe to invoke in any JS runtime — never throws. Falls back to `unknown::<suffix>`
87
+ * when the runtime can't be classified.
88
+ *
89
+ * Format is always three colon-separated segments: `<scope>:<name>:<suffix>`.
90
+ * - `scope` — `tab | dedicated-worker | shared-worker | service-worker | cf-worker | node | unknown`.
91
+ * - `name` — `location.origin` for tabs, `self.name` for browser workers, `process.pid`
92
+ * for node, empty for cf-workers / service workers / anonymous workers.
93
+ * Note that `name` may itself contain `:` (e.g. `http://localhost:5173`); when parsing,
94
+ * take the first segment as scope and the last as suffix, and treat everything in
95
+ * between as the name.
96
+ * - `suffix` — 6-char random; stable per-tab via `sessionStorage`, fresh per worker / process instance.
97
+ */
98
+ var inferEnvironmentName = (options = {}) => {
99
+ const scope = options.scope ?? globalThis;
100
+ if (scope.navigator?.userAgent === CF_WORKER_USER_AGENT) return `cf-worker::${randomSuffix()}`;
101
+ if (isInstanceOf(scope, "SharedWorkerGlobalScope")) return `shared-worker:${scope.name ?? ""}:${randomSuffix()}`;
102
+ if (isInstanceOf(scope, "ServiceWorkerGlobalScope")) return `service-worker::${randomSuffix()}`;
103
+ if (isInstanceOf(scope, "DedicatedWorkerGlobalScope")) return `dedicated-worker:${scope.name ?? ""}:${randomSuffix()}`;
104
+ if (scope.window !== void 0 && scope.window === scope) return `tab:${scope.location?.origin ?? ""}:${getOrCreateTabSuffix(scope.sessionStorage)}`;
105
+ const proc = scope.process;
106
+ if (proc && typeof proc === "object" && proc.versions?.node) return `node:${typeof proc.pid === "number" ? String(proc.pid) : ""}:${randomSuffix()}`;
107
+ return `unknown::${randomSuffix()}`;
108
+ };
109
+ //#endregion
110
+ //#region src/jsonl.ts
111
+ /**
112
+ * Serialize a {@link LogEntry} to a single compact JSON line (no trailing newline).
113
+ *
114
+ * Returns `undefined` for entries at TRACE level — callers can use this to skip them.
115
+ *
116
+ * The output is compatible with newline-delimited JSON (NDJSON / JSONL): join multiple
117
+ * results with `\n` for a stream / file representation.
118
+ *
119
+ * Context is taken from {@link LogEntry.computedContext}, which has already flattened
120
+ * nested objects to strings (see `stringifyOneLevel` in `context.ts`), so the resulting
121
+ * `c` field is a JSON string of a flat `Record<string, primitive>` map. The function
122
+ * does **not** truncate context — callers that care about line size should set their own
123
+ * cap before calling, or trim post-hoc.
124
+ */
125
+ var serializeToJsonl = (entry, opts = {}) => {
126
+ if (entry.level <= LogLevel.TRACE) return;
127
+ const { filename, line, context: scopeName } = entry.computedMeta;
128
+ const record = {
129
+ t: new Date(entry.timestamp).toISOString(),
130
+ l: shortLevelName[entry.level] ?? "?",
131
+ m: entry.message ?? ""
132
+ };
133
+ if (filename !== void 0) record.f = filename;
134
+ if (line !== void 0) record.n = line;
135
+ if (scopeName !== void 0) record.o = scopeName;
136
+ if (entry.computedError !== void 0) record.e = entry.computedError;
137
+ if (opts.env !== void 0) record.i = opts.env;
138
+ const computedContext = entry.computedContext;
139
+ if (Object.keys(computedContext).length > 0) try {
140
+ record.c = JSON.stringify(computedContext);
141
+ } catch {}
142
+ try {
143
+ return JSON.stringify(record);
144
+ } catch {
145
+ return;
146
+ }
147
+ };
148
+ //#endregion
149
+ //#region src/decorators.ts
150
+ var nextPromiseId = 0;
151
+ var createMethodLogDecorator = (log) => (arg0, arg1, meta) => (target, propertyKey, descriptor) => {
152
+ const method = descriptor.value;
153
+ const methodName = propertyKey;
154
+ descriptor.value = function(...args) {
155
+ const combinedMeta = {
156
+ F: "",
157
+ L: 0,
158
+ ...meta ?? {},
159
+ S: this
160
+ };
161
+ const formattedArgs = args.map((arg) => inspect(arg, false, 1, true)).join(", ");
162
+ try {
163
+ const startTime = performance.now();
164
+ const result = method.apply(this, args);
165
+ if (isThenable(result)) {
166
+ const id = nextPromiseId++;
167
+ logAsyncBegin(log, methodName, formattedArgs, id, combinedMeta);
168
+ result.then((resolvedValue) => {
169
+ logAsyncResolved(log, methodName, resolvedValue, id, startTime, combinedMeta);
170
+ }, (err) => {
171
+ logAsyncRejected(log, methodName, err, id, startTime, combinedMeta);
172
+ });
173
+ } else logSyncCall(log, methodName, formattedArgs, result, combinedMeta);
174
+ return result;
175
+ } catch (err) {
176
+ logSyncError(log, methodName, formattedArgs, err, combinedMeta);
177
+ throw err;
178
+ }
179
+ };
180
+ Object.defineProperty(descriptor.value, "name", { value: methodName + "$log" });
181
+ };
182
+ var createFunctionLogDecorator = (log) => (name, fn, opts = {}) => {
183
+ const decoratedFn = function(...args) {
184
+ const combinedMeta = {
185
+ F: "",
186
+ L: 0
187
+ };
188
+ const formattedArgs = args.map((arg) => inspect(arg, false, 1, true)).join(", ");
189
+ try {
190
+ const startTime = performance.now();
191
+ const result = fn.apply(this, args);
192
+ let transformedResult = result;
193
+ if (opts.transformOutput) if (isThenable(result)) transformedResult = result.then(opts.transformOutput);
194
+ else transformedResult = opts.transformOutput(result);
195
+ if (isThenable(transformedResult)) {
196
+ const id = nextPromiseId++;
197
+ logAsyncBegin(log, name, formattedArgs, id, combinedMeta);
198
+ transformedResult.then((resolvedValue) => {
199
+ logAsyncResolved(log, name, resolvedValue, id, startTime, combinedMeta);
200
+ }, (err) => {
201
+ logAsyncRejected(log, name, err, id, startTime, combinedMeta);
202
+ });
203
+ } else logSyncCall(log, name, formattedArgs, transformedResult, combinedMeta);
204
+ return result;
205
+ } catch (err) {
206
+ logSyncError(log, name, formattedArgs, err, combinedMeta);
207
+ throw err;
208
+ }
209
+ };
210
+ Object.defineProperty(decoratedFn, "name", { value: name + "$log" });
211
+ return decoratedFn;
212
+ };
213
+ var isThenable = (obj) => obj && typeof obj.then === "function";
214
+ var logSyncCall = (log, methodName, formattedArgs, result, combinedMeta) => {
215
+ log.info(`.${formatFunction(methodName)} (${formattedArgs}) ${chalk.gray("=>")} ${inspect(result, false, 1, true)}`, {}, combinedMeta);
216
+ };
217
+ var logSyncError = (log, methodName, formattedArgs, err, combinedMeta) => {
218
+ log.error(`.${formatFunction(methodName)} (${formattedArgs}) 🔥 ${err}`, {}, combinedMeta);
219
+ };
220
+ var logAsyncBegin = (log, methodName, formattedArgs, promiseId, combinedMeta) => {
221
+ log.info(`.${formatFunction(methodName)} ↴ (${formattedArgs}) ${chalk.gray("=>")} ${formatPromise(promiseId)}`, {}, combinedMeta);
222
+ };
223
+ var logAsyncResolved = (log, methodName, resolvedValue, promiseId, startTime, combinedMeta) => {
224
+ if (resolvedValue !== void 0) log.info(`.${formatFunction(methodName)} ↲ ${greenCheck} ${chalk.gray("resolve")} ${formatPromise(promiseId)} ${formatTimeElapsed(startTime)} ${chalk.gray("=>")} ${inspect(resolvedValue, false, 1, true)}`, {}, combinedMeta);
225
+ else log.info(`.${formatFunction(methodName)} ↲ ${greenCheck} ${chalk.gray("resolve")} ${formatPromise(promiseId)} ${formatTimeElapsed(startTime)}`, {}, combinedMeta);
226
+ };
227
+ var logAsyncRejected = (log, methodName, err, promiseId, startTime, combinedMeta) => {
228
+ log.info(`.${formatFunction(methodName)} ↲ 🔥 ${chalk.gray("reject")} ${formatPromise(promiseId)} ${formatTimeElapsed(startTime)} ${chalk.gray("=>")} ${err}`, {}, combinedMeta);
229
+ };
230
+ var COLOR_FUNCTION = [
231
+ 220,
232
+ 220,
233
+ 170
234
+ ];
235
+ var greenCheck = typeof chalk.green === "function" ? chalk.green("✔") : "✔";
236
+ var formatTimeElapsed = (startTime) => chalk.gray(`${(performance.now() - startTime).toFixed(0)}ms`);
237
+ var formatFunction = (name) => chalk.bold(chalk.rgb(...COLOR_FUNCTION)(name));
238
+ var formatPromise = (id) => chalk.blue(`Promise#${id}`);
239
+ //#endregion
240
+ //#region src/platform/index.ts
241
+ var platform_exports = /* @__PURE__ */ __exportAll({});
242
+ import * as import__platform from "#platform";
243
+ __reExport(platform_exports, import__platform);
244
+ //#endregion
245
+ //#region src/processors/browser-processor.ts
246
+ var CONFIG = {
247
+ useTestProcessor: false,
248
+ printFileLinks: false
249
+ };
250
+ /**
251
+ * For running apps in the browser normally.
252
+ */
253
+ var APP_BROWSER_PROCESSOR = (config, entry) => {
254
+ if (!shouldLog(entry, config.filters)) return;
255
+ const LOG_BROWSER_PREFIX = config.prefix ?? "https://vscode.dev/github.com/dxos/dxos/blob/main/";
256
+ const LOG_BROWSER_CSS = [];
257
+ const { filename, line: lineNumber, context: scopeDebugName } = entry.computedMeta;
258
+ let link = "";
259
+ if (filename !== void 0 && lineNumber !== void 0) link = `${`${LOG_BROWSER_PREFIX.replace(/\/$/, "")}/${filename}`}#L${lineNumber}`;
260
+ let args = [];
261
+ const scope = entry.meta?.S;
262
+ if (scope) {
263
+ const scopeName = scope.name || scopeDebugName;
264
+ if (scopeName) {
265
+ const processPrefix = scope.hostSessionId ? "[worker] " : "";
266
+ args.push(`%c${processPrefix}${scopeName}`, "color:#C026D3;font-weight:bold");
267
+ }
268
+ }
269
+ if (entry.message) args.push(entry.message);
270
+ const context = getContextFromEntry(entry);
271
+ if (context) if (Object.keys(context).length === 1 && "error" in context) args.push(unwrapEffectError(context.error));
272
+ else if (Object.keys(context).length === 1 && "err" in context) args.push(unwrapEffectError(context.err));
273
+ else args.push(context);
274
+ const levels = {
275
+ [LogLevel.ERROR]: console.error.bind(console),
276
+ [LogLevel.WARN]: console.warn.bind(console),
277
+ [LogLevel.DEBUG]: console.log.bind(console)
278
+ };
279
+ if (CONFIG.printFileLinks || safariCheck()) if (LOG_BROWSER_CSS?.length) args = [`%c${link}\n%c${args.join(" ")}`, ...LOG_BROWSER_CSS];
280
+ else args = [link + "\n", ...args];
281
+ const level = levels[entry.level] ?? console.log.bind(console);
282
+ if (typeof entry.meta?.C === "function") entry.meta.C(level, args);
283
+ else level(...args);
284
+ };
285
+ /**
286
+ * For running unit tests in the headless browser.
287
+ */
288
+ var TEST_BROWSER_PROCESSOR = (config, entry) => {
289
+ if (!shouldLog(entry, config.filters)) return;
290
+ const { filename, line: lineNumber } = entry.computedMeta;
291
+ const path = filename !== void 0 && lineNumber !== void 0 ? `${filename}:${lineNumber}` : "";
292
+ let args = [];
293
+ const processPrefix = entry.meta?.S?.hostSessionId ? "[worker] " : "";
294
+ args.push(`${processPrefix}${entry.message}`);
295
+ const context = getContextFromEntry(entry);
296
+ if (context) args.push(context);
297
+ const levels = {
298
+ [LogLevel.ERROR]: console.error,
299
+ [LogLevel.WARN]: console.warn,
300
+ [LogLevel.DEBUG]: console.log
301
+ };
302
+ if (CONFIG.printFileLinks) args = [path, ...args];
303
+ const level = levels[entry.level] ?? console.log;
304
+ if (typeof entry.meta?.C === "function") entry.meta.C(level, args);
305
+ else level(...args);
306
+ };
307
+ var BROWSER_PROCESSOR = CONFIG.useTestProcessor ? TEST_BROWSER_PROCESSOR : APP_BROWSER_PROCESSOR;
308
+ var originalSymbol = Symbol.for("effect/OriginalAnnotation");
309
+ var unwrapEffectError = (error) => {
310
+ if (typeof error === "object" && error !== null && originalSymbol in error) return error[originalSymbol];
311
+ return error;
312
+ };
313
+ //#endregion
314
+ //#region src/processors/debug-processor.ts
315
+ var DEBUG_PROCESSOR = (config, entry) => {
316
+ console.log(inspect(entry, false, null, true));
317
+ };
318
+ //#endregion
319
+ //#region src/processors/index.ts
320
+ var processors_exports = /* @__PURE__ */ __exportAll({
321
+ BROWSER_PROCESSOR: () => BROWSER_PROCESSOR,
322
+ DEBUG_PROCESSOR: () => DEBUG_PROCESSOR,
323
+ getRelativeFilename: () => getRelativeFilename
324
+ });
325
+ import * as import__console_processor from "#console-processor";
326
+ __reExport(processors_exports, import__console_processor);
327
+ //#endregion
328
+ //#region src/options.ts
329
+ /**
330
+ * Processor variants.
331
+ */
332
+ var processors = {
333
+ [LogProcessorType.CONSOLE]: processors_exports.CONSOLE_PROCESSOR,
334
+ [LogProcessorType.BROWSER]: BROWSER_PROCESSOR,
335
+ [LogProcessorType.DEBUG]: DEBUG_PROCESSOR
336
+ };
337
+ var DEFAULT_PROCESSORS = [(typeof window !== "undefined" || typeof navigator !== "undefined") && !(typeof process !== "undefined" && process?.env?.VITEST) ? BROWSER_PROCESSOR : processors_exports.CONSOLE_PROCESSOR];
338
+ var parseLogLevel = (level, defValue = LogLevel.WARN) => levels[level.toLowerCase()] ?? defValue;
339
+ /**
340
+ * @internal
341
+ */
342
+ var parseFilter = (filter) => {
343
+ if (typeof filter === "number") return [{ level: filter }];
344
+ return (typeof filter === "string" ? filter.split(/,\s*/) : filter).map((filter) => {
345
+ const [pattern, level] = filter.split(":");
346
+ return level ? {
347
+ level: parseLogLevel(level),
348
+ pattern
349
+ } : { level: parseLogLevel(pattern) };
350
+ });
351
+ };
352
+ /**
353
+ * @internal
354
+ */
355
+ var createConfig = (options) => {
356
+ const envOptions = "process" in globalThis ? {
357
+ file: process.env.LOG_CONFIG,
358
+ filter: process.env.LOG_FILTER,
359
+ processor: process.env.LOG_PROCESSOR
360
+ } : void 0;
361
+ const mergedOptions = defaultsDeep({}, (0, platform_exports.loadOptions)(envOptions?.file), envOptions, options);
362
+ return {
363
+ options: mergedOptions,
364
+ filters: parseFilter(mergedOptions.filter ?? LogLevel.INFO),
365
+ captureFilters: parseFilter(mergedOptions.captureFilter ?? LogLevel.WARN),
366
+ processors: mergedOptions.processor ? [processors[mergedOptions.processor]] : [...DEFAULT_PROCESSORS],
367
+ prefix: mergedOptions.prefix
368
+ };
369
+ };
370
+ //#endregion
371
+ //#region src/log.ts
372
+ var logCount = 0;
373
+ /**
374
+ * Create a logging function with properties.
375
+ * @internal
376
+ */
377
+ var createLog = () => {
378
+ const log = ((...params) => processLog(LogLevel.DEBUG, ...params));
379
+ Object.assign(log, {
380
+ _id: `log-${++logCount}`,
381
+ _config: createConfig()
382
+ });
383
+ Object.defineProperty(log, "runtimeConfig", { get: () => log._config });
384
+ /**
385
+ * Process the current log call.
386
+ */
387
+ const processLog = (level, message, context = {}, meta, error) => {
388
+ const entry = new LogEntry({
389
+ level,
390
+ message,
391
+ context,
392
+ meta,
393
+ error
394
+ });
395
+ log._config.processors.forEach((processor) => processor(log._config, entry));
396
+ };
397
+ /**
398
+ * API.
399
+ */
400
+ Object.assign(log, {
401
+ /**
402
+ * Update config.
403
+ * NOTE: Preserves any processors that were already added to this logger instance
404
+ * unless an explicit processor option is provided.
405
+ */
406
+ config: ({ processor, ...options } = {}) => {
407
+ const config = createConfig(options);
408
+ const processors = processor ? config.processors : log._config.processors;
409
+ log._config = {
410
+ ...config,
411
+ processors
412
+ };
413
+ return log;
414
+ },
415
+ /**
416
+ * Adds a processor to the logger.
417
+ */
418
+ addProcessor: (processor) => {
419
+ if (log._config.processors.filter((p) => p === processor).length === 0) log._config.processors.push(processor);
420
+ return () => {
421
+ log._config.processors = log._config.processors.filter((p) => p !== processor);
422
+ };
423
+ },
424
+ trace: (...params) => processLog(LogLevel.TRACE, ...params),
425
+ debug: (...params) => processLog(LogLevel.DEBUG, ...params),
426
+ verbose: (...params) => processLog(LogLevel.VERBOSE, ...params),
427
+ info: (...params) => processLog(LogLevel.INFO, ...params),
428
+ warn: (...params) => processLog(LogLevel.WARN, ...params),
429
+ error: (...params) => processLog(LogLevel.ERROR, ...params),
430
+ catch: (error, context, meta) => processLog(LogLevel.ERROR, void 0, context, meta, error),
431
+ method: createMethodLogDecorator(log),
432
+ function: createFunctionLogDecorator(log),
433
+ break: () => log.info("-".repeat(80)),
434
+ stack: (message, context, meta) => {
435
+ return processLog(LogLevel.INFO, `${message ?? "Stack Dump"}\n${getFormattedStackTrace()}`, context, meta);
436
+ }
437
+ });
438
+ return log;
439
+ };
440
+ /**
441
+ * Global logging function.
442
+ */
443
+ var log = globalThis.DX_LOG ??= createLog();
444
+ var start = Date.now();
445
+ var last = start;
446
+ /**
447
+ * Log debug stack.
448
+ */
449
+ var debug = (label, args) => {
450
+ const now = Date.now();
451
+ const err = /* @__PURE__ */ new Error();
452
+ console.group(`DEBUG[${label}]`, JSON.stringify({
453
+ t: Number(now - start).toLocaleString(),
454
+ dt: Number(now - last).toLocaleString(),
455
+ ...args
456
+ }));
457
+ console.warn(err.stack);
458
+ console.groupEnd();
459
+ last = Date.now();
460
+ };
461
+ var getFormattedStackTrace = () => (/* @__PURE__ */ new Error()).stack.split("\n").slice(3).join("\n");
462
+ //#endregion
463
+ //#region src/registry.ts
464
+ /** Create an isolated {@link LogFileRegistry} backed by an in-memory set with change notification. */
465
+ var createLogFileRegistry = () => {
466
+ const files = /* @__PURE__ */ new Set();
467
+ const listeners = /* @__PURE__ */ new Set();
468
+ const notify = () => {
469
+ for (const listener of listeners) listener();
470
+ };
471
+ return {
472
+ register: (file) => {
473
+ if (typeof file !== "string" || file.length === 0 || files.has(file)) return;
474
+ files.add(file);
475
+ notify();
476
+ },
477
+ getFiles: () => [...files].sort(),
478
+ subscribe: (listener) => {
479
+ listeners.add(listener);
480
+ return () => listeners.delete(listener);
481
+ },
482
+ clear: () => {
483
+ files.clear();
484
+ notify();
485
+ }
486
+ };
487
+ };
488
+ /**
489
+ * Global singleton so all (possibly duplicated) copies of `@dxos/log` and the
490
+ * transform-injected `globalThis.DX_LOG_FILES.register(...)` calls share one registry —
491
+ * mirrors how `log` is `globalThis.DX_LOG`.
492
+ */
493
+ var logFileRegistry = globalThis.DX_LOG_FILES ??= createLogFileRegistry();
494
+ //#endregion
495
+ //#region src/meta.ts
496
+ /**
497
+ * Marker key + value injected on every {@link CallMetadata} object by the log transform plugin.
498
+ * Used by {@link isLogMeta} to detect a log-meta argument at runtime (e.g. for variadic
499
+ * `param_index: 'last'` callees that don't have a fixed meta slot).
500
+ */
501
+ var LOG_META_MARKER = "~LogMeta";
502
+ /**
503
+ * Type guard: `true` when `value` is a {@link CallMetadata} object emitted by the log transform plugin.
504
+ * Detection is based on the presence of the {@link LOG_META_MARKER} marker key/value.
505
+ */
506
+ var isLogMeta = (value) => {
507
+ return value != null && typeof value === "object" && value["~LogMeta"] === "~LogMeta";
508
+ };
509
+ //#endregion
510
+ //#region src/dbg.ts
511
+ /**
512
+ * Debug-log value to console.
513
+ * Log's the expression being evaluated.
514
+ *
515
+ * If only one argument is provided, it will also be returned.
516
+ *
517
+ * @example
518
+ * ```ts
519
+ * dbg(foo, bar);
520
+ * // foo = 1
521
+ * // bar = 2
522
+ *
523
+ * bar = dbg(foo * 2);
524
+ * // foo * 2 = 2
525
+ * ```
526
+ *
527
+ * NOTE: The second argument is injected by the log transform plugin.
528
+ */
529
+ var dbg = (arg, meta) => {
530
+ if (meta?.A) console.log(`${meta.A[0]} =`, arg);
531
+ else console.log(arg);
532
+ return arg;
533
+ };
534
+ //#endregion
535
+ //#region src/log-buffer.ts
536
+ var DEFAULT_BUFFER_SIZE = 2e3;
537
+ var MAX_CONTEXT_LENGTH = 500;
538
+ /**
539
+ * Captures recent log entries in a circular buffer for debug log dump.
540
+ */
541
+ var LogBuffer = class {
542
+ _buffer;
543
+ constructor(size = DEFAULT_BUFFER_SIZE) {
544
+ this._buffer = new CircularBuffer(size);
545
+ }
546
+ /**
547
+ * Log processor that can be registered with `log.runtimeConfig.processors`.
548
+ * Captures every level except TRACE (does not apply `shouldLog` / filter; use for full debug dumps).
549
+ */
550
+ logProcessor = (_config, entry) => {
551
+ if (entry.level <= LogLevel.TRACE) return;
552
+ const { filename, line, context: scopeName } = entry.computedMeta;
553
+ const record = {
554
+ t: new Date(entry.timestamp).toISOString(),
555
+ l: shortLevelName[entry.level] ?? "?",
556
+ m: entry.message ?? ""
557
+ };
558
+ if (filename !== void 0) record.f = filename;
559
+ if (line !== void 0) record.n = line;
560
+ if (scopeName !== void 0) record.o = scopeName;
561
+ if (entry.computedError !== void 0) record.e = entry.computedError;
562
+ const computedContext = entry.computedContext;
563
+ if (Object.keys(computedContext).length > 0) try {
564
+ let json = JSON.stringify(computedContext);
565
+ if (json.length > MAX_CONTEXT_LENGTH) json = json.slice(0, MAX_CONTEXT_LENGTH);
566
+ record.c = json;
567
+ } catch {}
568
+ this._buffer.push(record);
569
+ };
570
+ /** Number of entries currently in the buffer. */
571
+ get size() {
572
+ return this._buffer.elementCount;
573
+ }
574
+ /** Discard all buffered entries. */
575
+ clear() {
576
+ this._buffer.clear();
577
+ }
578
+ /** Serialize buffer contents as NDJSON (newline-delimited JSON). */
579
+ serialize() {
580
+ const lines = [];
581
+ for (const record of this._buffer) lines.push(JSON.stringify(record));
582
+ return lines.join("\n");
583
+ }
584
+ };
585
+ inspect.custom;
586
+ var getCurrentOwnershipScope = (thisRef) => thisRef;
587
+ __reExport(/* @__PURE__ */ __exportAll({
588
+ BROWSER_PROCESSOR: () => BROWSER_PROCESSOR,
589
+ DEBUG_PROCESSOR: () => DEBUG_PROCESSOR,
590
+ LOG_META_MARKER: () => LOG_META_MARKER,
591
+ LogBuffer: () => LogBuffer,
592
+ LogEntry: () => LogEntry,
593
+ LogLevel: () => LogLevel,
594
+ LogProcessorType: () => LogProcessorType,
595
+ createLog: () => createLog,
596
+ createLogFileRegistry: () => createLogFileRegistry,
597
+ dbg: () => dbg,
598
+ debug: () => debug,
599
+ gatherLogInfoFromScope: () => gatherLogInfoFromScope,
600
+ getContextFromEntry: () => getContextFromEntry,
601
+ getCurrentOwnershipScope: () => getCurrentOwnershipScope,
602
+ getRelativeFilename: () => getRelativeFilename,
603
+ inferEnvironmentName: () => inferEnvironmentName,
604
+ isLogMeta: () => isLogMeta,
605
+ levels: () => levels,
606
+ log: () => log,
607
+ logFileRegistry: () => logFileRegistry,
608
+ logInfo: () => logInfo,
609
+ omit: () => omit,
610
+ parseFilter: () => parseFilter,
611
+ pick: () => pick,
612
+ serializeToJsonl: () => serializeToJsonl,
613
+ shortLevelName: () => shortLevelName,
614
+ shouldLog: () => shouldLog
615
+ }), processors_exports);
616
+ //#endregion
617
+ export { BROWSER_PROCESSOR, DEBUG_PROCESSOR, LOG_META_MARKER, LogBuffer, LogEntry, LogLevel, LogProcessorType, createLog, createLogFileRegistry, dbg, debug, gatherLogInfoFromScope, getContextFromEntry, getCurrentOwnershipScope, getRelativeFilename, inferEnvironmentName, isLogMeta, levels, log, logFileRegistry, logInfo, omit, parseFilter, pick, serializeToJsonl, shortLevelName, shouldLog };
618
+
619
+ //# sourceMappingURL=index.mjs.map