@logtape/otel 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/mod.ts DELETED
@@ -1,696 +0,0 @@
1
- import {
2
- getLogger,
3
- type Logger,
4
- type LogRecord,
5
- type Sink,
6
- } from "@logtape/logtape";
7
- import { diag, type DiagLogger, DiagLogLevel } from "@opentelemetry/api";
8
- import {
9
- type AnyValue,
10
- type Logger as OTLogger,
11
- type LoggerProvider as LoggerProviderBase,
12
- type LogRecord as OTLogRecord,
13
- NOOP_LOGGER,
14
- SeverityNumber,
15
- } from "@opentelemetry/api-logs";
16
- import type { OTLPExporterNodeConfigBase } from "@opentelemetry/otlp-exporter-base";
17
- import type { Resource } from "@opentelemetry/resources";
18
- import {
19
- defaultResource,
20
- resourceFromAttributes,
21
- } from "@opentelemetry/resources";
22
- import {
23
- LoggerProvider,
24
- SimpleLogRecordProcessor,
25
- } from "@opentelemetry/sdk-logs";
26
- import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
27
- import metadata from "../deno.json" with { type: "json" };
28
-
29
- /**
30
- * Gets an environment variable value across different JavaScript runtimes.
31
- * @param name The environment variable name.
32
- * @returns The environment variable value, or undefined if not found.
33
- */
34
- function getEnvironmentVariable(name: string): string | undefined {
35
- // Deno runtime
36
- if (typeof Deno !== "undefined" && Deno.env) {
37
- try {
38
- return Deno.env.get(name);
39
- } catch {
40
- // Deno.env.get() can throw if permissions are not granted
41
- return undefined;
42
- }
43
- }
44
-
45
- // Node.js/Bun runtime
46
- if (
47
- typeof globalThis !== "undefined" && "process" in globalThis &&
48
- // @ts-ignore: process exists in Node.js/Bun
49
- typeof globalThis.process !== "undefined" &&
50
- // @ts-ignore: process.env exists in Node.js/Bun
51
- typeof globalThis.process.env === "object" &&
52
- // @ts-ignore: process.env exists in Node.js/Bun
53
- globalThis.process.env !== null
54
- ) {
55
- // @ts-ignore: process.env exists in Node.js/Bun
56
- return globalThis.process.env[name];
57
- }
58
-
59
- // Browser/other environments - no environment variables available
60
- return undefined;
61
- }
62
-
63
- /**
64
- * Checks if an OTLP endpoint is configured via environment variables or options.
65
- * Checks the following environment variables:
66
- * - `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` (logs-specific endpoint)
67
- * - `OTEL_EXPORTER_OTLP_ENDPOINT` (general OTLP endpoint)
68
- *
69
- * @param config Optional exporter configuration that may contain a URL.
70
- * @returns `true` if an endpoint is configured, `false` otherwise.
71
- */
72
- function hasOtlpEndpoint(config?: OTLPExporterNodeConfigBase): boolean {
73
- // Check if URL is provided in config
74
- if (config?.url) {
75
- return true;
76
- }
77
-
78
- // Check environment variables
79
- const logsEndpoint = getEnvironmentVariable(
80
- "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT",
81
- );
82
- if (logsEndpoint) {
83
- return true;
84
- }
85
-
86
- const endpoint = getEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT");
87
- if (endpoint) {
88
- return true;
89
- }
90
-
91
- return false;
92
- }
93
-
94
- /**
95
- * Detects the OTLP protocol from environment variables.
96
- * Priority:
97
- * 1. `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL`
98
- * 2. `OTEL_EXPORTER_OTLP_PROTOCOL`
99
- * 3. Default: `"http/json"` (for backward compatibility)
100
- *
101
- * @returns The detected OTLP protocol.
102
- */
103
- function detectOtlpProtocol(): OtlpProtocol {
104
- const logsProtocol = getEnvironmentVariable(
105
- "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL",
106
- );
107
- if (
108
- logsProtocol === "grpc" ||
109
- logsProtocol === "http/protobuf" ||
110
- logsProtocol === "http/json"
111
- ) {
112
- return logsProtocol;
113
- }
114
-
115
- const protocol = getEnvironmentVariable("OTEL_EXPORTER_OTLP_PROTOCOL");
116
- if (
117
- protocol === "grpc" ||
118
- protocol === "http/protobuf" ||
119
- protocol === "http/json"
120
- ) {
121
- return protocol;
122
- }
123
-
124
- return "http/json";
125
- }
126
-
127
- /**
128
- * Creates an OTLP log exporter based on the detected protocol.
129
- * Uses dynamic imports to maintain browser compatibility when gRPC is not used.
130
- * @param config Optional exporter configuration.
131
- * @returns A promise that resolves to the appropriate OTLP log exporter.
132
- */
133
- async function createOtlpExporter(
134
- config?: OTLPExporterNodeConfigBase,
135
- // deno-lint-ignore no-explicit-any
136
- ): Promise<any> {
137
- const protocol = detectOtlpProtocol();
138
-
139
- switch (protocol) {
140
- case "grpc": {
141
- const { OTLPLogExporter } = await import(
142
- "@opentelemetry/exporter-logs-otlp-grpc"
143
- );
144
- return new OTLPLogExporter(config);
145
- }
146
- case "http/protobuf": {
147
- const { OTLPLogExporter } = await import(
148
- "@opentelemetry/exporter-logs-otlp-proto"
149
- );
150
- return new OTLPLogExporter(config);
151
- }
152
- case "http/json":
153
- default: {
154
- const { OTLPLogExporter } = await import(
155
- "@opentelemetry/exporter-logs-otlp-http"
156
- );
157
- return new OTLPLogExporter(config);
158
- }
159
- }
160
- }
161
-
162
- /**
163
- * The OpenTelemetry logger provider.
164
- */
165
- type ILoggerProvider = LoggerProviderBase & {
166
- /**
167
- * Flush all buffered data and shut down the LoggerProvider and all registered
168
- * LogRecordProcessor.
169
- *
170
- * Returns a promise which is resolved when all flushes are complete.
171
- */
172
- shutdown?: () => Promise<void>;
173
- };
174
-
175
- /**
176
- * The way to render the object in the log record. If `"json"`,
177
- * the object is rendered as a JSON string. If `"inspect"`,
178
- * the object is rendered using `util.inspect` in Node.js/Bun, or
179
- * `Deno.inspect` in Deno.
180
- */
181
- export type ObjectRenderer = "json" | "inspect";
182
-
183
- type Message = (string | null | undefined)[];
184
-
185
- /**
186
- * Custom `body` attribute formatter.
187
- * @since 0.3.0
188
- */
189
- export type BodyFormatter = (message: Message) => AnyValue;
190
-
191
- /**
192
- * The OTLP protocol to use for exporting logs.
193
- * @since 0.9.0
194
- */
195
- export type OtlpProtocol = "grpc" | "http/protobuf" | "http/json";
196
-
197
- /**
198
- * Base options shared by all OpenTelemetry sink configurations.
199
- */
200
- interface OpenTelemetrySinkOptionsBase {
201
- /**
202
- * The way to render the message in the log record. If `"string"`,
203
- * the message is rendered as a single string with the values are
204
- * interpolated into the message. If `"array"`, the message is
205
- * rendered as an array of strings. `"string"` by default.
206
- *
207
- * Or even fully customizable with a {@link BodyFormatter} function.
208
- * @since 0.2.0
209
- */
210
- messageType?: "string" | "array" | BodyFormatter;
211
-
212
- /**
213
- * The way to render the object in the log record. If `"json"`,
214
- * the object is rendered as a JSON string. If `"inspect"`,
215
- * the object is rendered using `util.inspect` in Node.js/Bun, or
216
- * `Deno.inspect` in Deno. `"inspect"` by default.
217
- */
218
- objectRenderer?: ObjectRenderer;
219
-
220
- /**
221
- * Whether to log diagnostics. Diagnostic logs are logged to
222
- * the `["logtape", "meta", "otel"]` category.
223
- * Turned off by default.
224
- */
225
- diagnostics?: boolean;
226
- }
227
-
228
- /**
229
- * Options for creating an OpenTelemetry sink with a custom logger provider.
230
- * When using this configuration, you are responsible for setting up the
231
- * logger provider with appropriate exporters and processors.
232
- *
233
- * This is the recommended approach for production use as it gives you
234
- * full control over the OpenTelemetry configuration.
235
- * @since 0.9.0
236
- */
237
- export interface OpenTelemetrySinkProviderOptions
238
- extends OpenTelemetrySinkOptionsBase {
239
- /**
240
- * The OpenTelemetry logger provider to use.
241
- */
242
- loggerProvider: ILoggerProvider;
243
- }
244
-
245
- /**
246
- * Options for creating an OpenTelemetry sink with automatic exporter creation.
247
- * The protocol is determined by environment variables:
248
- * - `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` (highest priority)
249
- * - `OTEL_EXPORTER_OTLP_PROTOCOL` (fallback)
250
- * - Default: `"http/json"`
251
- *
252
- * For production use, consider providing your own {@link ILoggerProvider}
253
- * via {@link OpenTelemetrySinkProviderOptions} for more control.
254
- * @since 0.9.0
255
- */
256
- export interface OpenTelemetrySinkExporterOptions
257
- extends OpenTelemetrySinkOptionsBase {
258
- /**
259
- * The OpenTelemetry logger provider to use.
260
- * Must be undefined or omitted when using exporter options.
261
- */
262
- loggerProvider?: undefined;
263
-
264
- /**
265
- * The OpenTelemetry OTLP exporter configuration to use.
266
- */
267
- otlpExporterConfig?: OTLPExporterNodeConfigBase;
268
-
269
- /**
270
- * The service name to use. If not provided, the service name is
271
- * taken from the `OTEL_SERVICE_NAME` environment variable.
272
- */
273
- serviceName?: string;
274
-
275
- /**
276
- * An additional resource to merge with the default resource.
277
- * @since 1.3.0
278
- */
279
- additionalResource?: Resource;
280
- }
281
-
282
- /**
283
- * Options for creating an OpenTelemetry sink.
284
- *
285
- * This is a union type that accepts either:
286
- * - {@link OpenTelemetrySinkProviderOptions}: Provide your own `loggerProvider`
287
- * (recommended for production)
288
- * - {@link OpenTelemetrySinkExporterOptions}: Let the sink create an exporter
289
- * automatically based on environment variables
290
- *
291
- * When no `loggerProvider` is provided, the protocol is determined by:
292
- * 1. `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` environment variable
293
- * 2. `OTEL_EXPORTER_OTLP_PROTOCOL` environment variable
294
- * 3. Default: `"http/json"`
295
- *
296
- * @example Using a custom logger provider (recommended)
297
- * ```typescript
298
- * import { LoggerProvider, SimpleLogRecordProcessor } from "@opentelemetry/sdk-logs";
299
- * import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
300
- *
301
- * const provider = new LoggerProvider();
302
- * provider.addLogRecordProcessor(new SimpleLogRecordProcessor(new OTLPLogExporter()));
303
- *
304
- * const sink = getOpenTelemetrySink({ loggerProvider: provider });
305
- * ```
306
- *
307
- * @example Using automatic exporter creation
308
- * ```typescript
309
- * // Protocol determined by OTEL_EXPORTER_OTLP_PROTOCOL env var
310
- * const sink = getOpenTelemetrySink({
311
- * serviceName: "my-service",
312
- * });
313
- * ```
314
- */
315
- export type OpenTelemetrySinkOptions =
316
- | OpenTelemetrySinkProviderOptions
317
- | OpenTelemetrySinkExporterOptions;
318
-
319
- /**
320
- * A no-op logger provider that returns NOOP_LOGGER for all requests.
321
- * Used when no OTLP endpoint is configured to avoid repeated connection errors.
322
- */
323
- const noopLoggerProvider: ILoggerProvider = {
324
- getLogger: () => NOOP_LOGGER,
325
- };
326
-
327
- /**
328
- * Initializes the logger provider asynchronously.
329
- * This is used when the user doesn't provide a custom logger provider.
330
- *
331
- * If no OTLP endpoint is configured (via options or environment variables),
332
- * returns a noop logger provider to avoid repeated connection errors.
333
- *
334
- * @param options The exporter options.
335
- * @returns A promise that resolves to the initialized logger provider.
336
- */
337
- async function initializeLoggerProvider(
338
- options: OpenTelemetrySinkExporterOptions,
339
- ): Promise<ILoggerProvider> {
340
- // If no endpoint is configured, use noop logger provider to avoid
341
- // repeated transport errors
342
- if (!hasOtlpEndpoint(options.otlpExporterConfig)) {
343
- return noopLoggerProvider;
344
- }
345
-
346
- const resource = defaultResource().merge(
347
- resourceFromAttributes({
348
- [ATTR_SERVICE_NAME]: options.serviceName ??
349
- getEnvironmentVariable("OTEL_SERVICE_NAME"),
350
- })
351
- .merge(options.additionalResource ?? null),
352
- );
353
- const otlpExporter = await createOtlpExporter(options.otlpExporterConfig);
354
- const loggerProvider = new LoggerProvider({
355
- resource,
356
- processors: [
357
- // @ts-ignore: it works anyway...
358
- new SimpleLogRecordProcessor(otlpExporter),
359
- ],
360
- });
361
- return loggerProvider;
362
- }
363
-
364
- /**
365
- * Emits a log record to the OpenTelemetry logger.
366
- * @param logger The OpenTelemetry logger.
367
- * @param record The LogTape log record.
368
- * @param options The sink options.
369
- */
370
- function emitLogRecord(
371
- logger: OTLogger,
372
- record: LogRecord,
373
- options: OpenTelemetrySinkOptions,
374
- ): void {
375
- const objectRenderer = options.objectRenderer ?? "inspect";
376
- const { category, level, message, timestamp, properties } = record;
377
- const severityNumber = mapLevelToSeverityNumber(level);
378
- const attributes = convertToAttributes(properties, objectRenderer);
379
- attributes["category"] = [...category];
380
- logger.emit(
381
- {
382
- severityNumber,
383
- severityText: level,
384
- body: typeof options.messageType === "function"
385
- ? convertMessageToCustomBodyFormat(
386
- message,
387
- objectRenderer,
388
- options.messageType,
389
- )
390
- : options.messageType === "array"
391
- ? convertMessageToArray(message, objectRenderer)
392
- : convertMessageToString(message, objectRenderer),
393
- attributes,
394
- timestamp: new Date(timestamp),
395
- } satisfies OTLogRecord,
396
- );
397
- }
398
-
399
- /**
400
- * An OpenTelemetry sink with async disposal and initialization tracking.
401
- * @since 1.3.1
402
- */
403
- export interface OpenTelemetrySink extends Sink, AsyncDisposable {
404
- /**
405
- * A promise that resolves when the sink's lazy initialization completes.
406
- * For sinks created with an explicit `loggerProvider`, this resolves
407
- * immediately. For sinks using automatic exporter creation, this resolves
408
- * once the OpenTelemetry logger provider is fully initialized.
409
- *
410
- * This is useful for:
411
- * - Ensuring all buffered log records have been sent before shutdown
412
- * - Testing scenarios where you need to verify emitted records
413
- * - Waiting for initialization before proceeding with critical operations
414
- *
415
- * @since 1.3.1
416
- */
417
- readonly ready: Promise<void>;
418
- }
419
-
420
- /**
421
- * Creates a sink that forwards log records to OpenTelemetry.
422
- *
423
- * When a custom `loggerProvider` is provided, it is used directly.
424
- * Otherwise, the sink will lazily initialize a logger provider on the first
425
- * log record, using the protocol determined by environment variables.
426
- *
427
- * @param options Options for creating the sink.
428
- * @returns The sink.
429
- */
430
- export function getOpenTelemetrySink(
431
- options: OpenTelemetrySinkOptions = {},
432
- ): OpenTelemetrySink {
433
- if (options.diagnostics) {
434
- diag.setLogger(new DiagLoggerAdaptor(), DiagLogLevel.DEBUG);
435
- }
436
-
437
- // If loggerProvider is provided, use the synchronous path
438
- if (options.loggerProvider != null) {
439
- const loggerProvider = options.loggerProvider;
440
- const logger = loggerProvider.getLogger(metadata.name, metadata.version);
441
- const shutdown = loggerProvider.shutdown?.bind(loggerProvider);
442
- const sink: OpenTelemetrySink = Object.assign(
443
- (record: LogRecord) => {
444
- const { category } = record;
445
- if (
446
- category[0] === "logtape" && category[1] === "meta" &&
447
- category[2] === "otel"
448
- ) {
449
- return;
450
- }
451
- emitLogRecord(logger, record, options);
452
- },
453
- {
454
- ready: Promise.resolve(),
455
- async [Symbol.asyncDispose](): Promise<void> {
456
- if (shutdown != null) await shutdown();
457
- },
458
- },
459
- );
460
- return sink;
461
- }
462
-
463
- // Lazy initialization for automatic exporter creation
464
- let loggerProvider: ILoggerProvider | null = null;
465
- let logger: OTLogger | null = null;
466
- let initPromise: Promise<void> | null = null;
467
- let initError: Error | null = null;
468
- // Buffer for log records that arrive during initialization
469
- let pendingRecords: LogRecord[] = [];
470
-
471
- const sink: OpenTelemetrySink = Object.assign(
472
- (record: LogRecord) => {
473
- const { category } = record;
474
- if (
475
- category[0] === "logtape" && category[1] === "meta" &&
476
- category[2] === "otel"
477
- ) {
478
- return;
479
- }
480
-
481
- // If already initialized, emit the log
482
- if (logger != null) {
483
- emitLogRecord(logger, record, options);
484
- return;
485
- }
486
-
487
- // If initialization failed, skip silently
488
- if (initError != null) {
489
- return;
490
- }
491
-
492
- // Buffer the record for later emission
493
- pendingRecords.push(record);
494
-
495
- // Start initialization if not already started
496
- if (initPromise == null) {
497
- initPromise = initializeLoggerProvider(options)
498
- .then((provider) => {
499
- loggerProvider = provider;
500
- logger = provider.getLogger(metadata.name, metadata.version);
501
- // Emit all buffered records
502
- for (const pendingRecord of pendingRecords) {
503
- emitLogRecord(logger, pendingRecord, options);
504
- }
505
- pendingRecords = [];
506
- })
507
- .catch((error) => {
508
- initError = error;
509
- pendingRecords = [];
510
- // Log initialization error to console as a fallback
511
- // deno-lint-ignore no-console
512
- console.error("Failed to initialize OpenTelemetry logger:", error);
513
- });
514
- }
515
- },
516
- {
517
- get ready(): Promise<void> {
518
- return initPromise ?? Promise.resolve();
519
- },
520
- async [Symbol.asyncDispose](): Promise<void> {
521
- // Wait for initialization to complete if in progress
522
- if (initPromise != null) {
523
- try {
524
- await initPromise;
525
- } catch {
526
- // Initialization failed, nothing to shut down
527
- return;
528
- }
529
- }
530
- if (loggerProvider?.shutdown != null) {
531
- await loggerProvider.shutdown();
532
- }
533
- },
534
- },
535
- );
536
-
537
- return sink;
538
- }
539
-
540
- function mapLevelToSeverityNumber(level: string): number {
541
- switch (level) {
542
- case "trace":
543
- return SeverityNumber.TRACE;
544
- case "debug":
545
- return SeverityNumber.DEBUG;
546
- case "info":
547
- return SeverityNumber.INFO;
548
- case "warning":
549
- return SeverityNumber.WARN;
550
- case "error":
551
- return SeverityNumber.ERROR;
552
- case "fatal":
553
- return SeverityNumber.FATAL;
554
- default:
555
- return SeverityNumber.UNSPECIFIED;
556
- }
557
- }
558
-
559
- function convertToAttributes(
560
- properties: Record<string, unknown>,
561
- objectRenderer: ObjectRenderer,
562
- ): Record<string, AnyValue> {
563
- const attributes: Record<string, AnyValue> = {};
564
- for (const [name, value] of Object.entries(properties)) {
565
- const key = `attributes.${name}`;
566
- if (value == null) continue;
567
- if (Array.isArray(value)) {
568
- let t = null;
569
- for (const v of value) {
570
- if (v == null) continue;
571
- if (t != null && typeof v !== t) {
572
- attributes[key] = value.map((v) =>
573
- convertToString(v, objectRenderer)
574
- );
575
- break;
576
- }
577
- t = typeof v;
578
- }
579
- attributes[key] = value;
580
- } else {
581
- const encoded = convertToString(value, objectRenderer);
582
- if (encoded == null) continue;
583
- attributes[key] = encoded;
584
- }
585
- }
586
- return attributes;
587
- }
588
-
589
- function convertToString(
590
- value: unknown,
591
- objectRenderer: ObjectRenderer,
592
- ): string | null | undefined {
593
- if (value === null || value === undefined || typeof value === "string") {
594
- return value;
595
- }
596
- if (objectRenderer === "inspect") return inspect(value);
597
- if (typeof value === "number" || typeof value === "boolean") {
598
- return value.toString();
599
- } else if (value instanceof Date) return value.toISOString();
600
- else return JSON.stringify(value);
601
- }
602
-
603
- function convertMessageToArray(
604
- message: readonly unknown[],
605
- objectRenderer: ObjectRenderer,
606
- ): AnyValue {
607
- const body: (string | null | undefined)[] = [];
608
- for (let i = 0; i < message.length; i += 2) {
609
- const msg = message[i] as string;
610
- body.push(msg);
611
- if (message.length <= i + 1) break;
612
- const val = message[i + 1];
613
- body.push(convertToString(val, objectRenderer));
614
- }
615
- return body;
616
- }
617
-
618
- function convertMessageToString(
619
- message: readonly unknown[],
620
- objectRenderer: ObjectRenderer,
621
- ): AnyValue {
622
- let body = "";
623
- for (let i = 0; i < message.length; i += 2) {
624
- const msg = message[i] as string;
625
- body += msg;
626
- if (message.length <= i + 1) break;
627
- const val = message[i + 1];
628
- const extra = convertToString(val, objectRenderer);
629
- body += extra ?? JSON.stringify(extra);
630
- }
631
- return body;
632
- }
633
-
634
- function convertMessageToCustomBodyFormat(
635
- message: readonly unknown[],
636
- objectRenderer: ObjectRenderer,
637
- bodyFormatter: BodyFormatter,
638
- ): AnyValue {
639
- const body = message.map((msg) => convertToString(msg, objectRenderer));
640
- return bodyFormatter(body);
641
- }
642
-
643
- /**
644
- * A platform-specific inspect function. In Deno, this is {@link Deno.inspect},
645
- * and in Node.js/Bun it is {@link util.inspect}. If neither is available, it
646
- * falls back to {@link JSON.stringify}.
647
- *
648
- * @param value The value to inspect.
649
- * @returns The string representation of the value.
650
- */
651
- const inspect: (value: unknown) => string =
652
- // @ts-ignore: Deno global
653
- "Deno" in globalThis && "inspect" in globalThis.Deno &&
654
- // @ts-ignore: Deno global
655
- typeof globalThis.Deno.inspect === "function"
656
- // @ts-ignore: Deno global
657
- ? globalThis.Deno.inspect
658
- // @ts-ignore: Node.js global
659
- : "util" in globalThis && "inspect" in globalThis.util &&
660
- // @ts-ignore: Node.js global
661
- globalThis.util.inspect === "function"
662
- // @ts-ignore: Node.js global
663
- ? globalThis.util.inspect
664
- : JSON.stringify;
665
-
666
- class DiagLoggerAdaptor implements DiagLogger {
667
- logger: Logger;
668
-
669
- constructor() {
670
- this.logger = getLogger(["logtape", "meta", "otel"]);
671
- }
672
-
673
- #escape(msg: string): string {
674
- return msg.replaceAll("{", "{{").replaceAll("}", "}}");
675
- }
676
-
677
- error(msg: string, ...values: unknown[]): void {
678
- this.logger.error(`${this.#escape(msg)}: {values}`, { values });
679
- }
680
-
681
- warn(msg: string, ...values: unknown[]): void {
682
- this.logger.warn(`${this.#escape(msg)}: {values}`, { values });
683
- }
684
-
685
- info(msg: string, ...values: unknown[]): void {
686
- this.logger.info(`${this.#escape(msg)}: {values}`, { values });
687
- }
688
-
689
- debug(msg: string, ...values: unknown[]): void {
690
- this.logger.debug(`${this.#escape(msg)}: {values}`, { values });
691
- }
692
-
693
- verbose(msg: string, ...values: unknown[]): void {
694
- this.logger.debug(`${this.#escape(msg)}: {values}`, { values });
695
- }
696
- }
package/tsdown.config.ts DELETED
@@ -1,11 +0,0 @@
1
- import { defineConfig } from "tsdown";
2
-
3
- export default defineConfig({
4
- entry: "src/mod.ts",
5
- dts: {
6
- sourcemap: true,
7
- },
8
- format: ["esm", "cjs"],
9
- platform: "neutral",
10
- unbundle: true,
11
- });