Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@loglayer/shared

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@loglayer/shared - npm Package Compare versions

Comparing version
4.0.0
to
4.0.1
+176
-1
dist/index.cjs

@@ -36,4 +36,179 @@

//#endregion
//#region src/lazy.ts
/**
* Symbol used to identify lazy values in context and metadata.
* Can be used to check if a value is a lazy wrapper: `LAZY_SYMBOL in value`.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
const LAZY_SYMBOL = Symbol.for("loglayer.lazy");
/**
* String constant used as a replacement value when a lazy callback fails during evaluation.
* Exported so users can programmatically detect lazy evaluation failures in their log output.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation#error-handling | Lazy Evaluation Error Handling Docs}
*/
const LAZY_EVAL_ERROR = "[LazyEvalError]";
/**
* Wraps a callback function to defer its evaluation until log time.
*
* The callback will only be invoked if the log level is enabled,
* avoiding unnecessary computation for disabled log levels.
*
* Can be used in both `withContext()` and `withMetadata()` at the root level.
*
* When the callback returns a `Promise` (i.e., is an async function), the
* log method will return `Promise<void>` so TypeScript can track that the
* operation is asynchronous.
*
* Adapted from [LogTape's lazy evaluation](https://logtape.org/manual/lazy).
*
* @example
* ```typescript
* import { LogLayer, lazy } from "loglayer";
*
* const log = new LogLayer({ ... });
*
* // Dynamic context - evaluated on each log call
* log.withContext({
* memoryUsage: lazy(() => process.memoryUsage().heapUsed),
* });
*
* // Dynamic metadata - evaluated only if debug is enabled
* log.withMetadata({
* data: lazy(() => JSON.stringify(largeObject)),
* }).debug("Processing complete");
* ```
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
function lazy(fn) {
return { [LAZY_SYMBOL]: fn };
}
/**
* Checks if a value is a lazy value created by {@link lazy}.
* @internal
*/
function isLazy(value) {
return value != null && typeof value === "object" && LAZY_SYMBOL in value;
}
/**
* Counts the number of lazy values in a record.
* @internal
*/
function countLazyValues(obj) {
let count = 0;
for (const key of Object.keys(obj)) if (isLazy(obj[key])) count++;
return count;
}
/**
* Resolves any lazy values in a record at the root level.
* Returns the original object if no lazy values are found (optimization).
* If a lazy callback throws, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
function resolveLazyValues(obj) {
let hasLazy = false;
for (const key of Object.keys(obj)) if (isLazy(obj[key])) {
hasLazy = true;
break;
}
if (!hasLazy) return {
resolved: obj,
errors: null
};
const result = {};
let errors = null;
for (const key of Object.keys(obj)) {
const value = obj[key];
if (isLazy(value)) try {
result[key] = value[LAZY_SYMBOL]();
} catch (e) {
result[key] = LAZY_EVAL_ERROR;
if (!errors) errors = [];
errors.push({
key,
error: e
});
}
else result[key] = value;
}
return {
resolved: result,
errors
};
}
/**
* Checks if any values in a record are Promises.
* @internal
*/
function hasPromiseValues(obj) {
for (const key of Object.keys(obj)) if (obj[key] instanceof Promise) return true;
return false;
}
/**
* Replaces any Promise values in a record with LAZY_EVAL_ERROR.
* Used to strip async lazy values from context where only sync lazy is supported.
* Returns the keys that were replaced.
* @internal
*/
function replacePromiseValues(obj) {
let asyncKeys = null;
const result = {};
for (const key of Object.keys(obj)) if (obj[key] instanceof Promise) {
result[key] = LAZY_EVAL_ERROR;
if (!asyncKeys) asyncKeys = [];
asyncKeys.push(key);
} else result[key] = obj[key];
if (!asyncKeys) return {
resolved: obj,
asyncKeys: null
};
return {
resolved: result,
asyncKeys
};
}
/**
* Resolves any Promise values in a record using Promise.allSettled.
* If a Promise rejects, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
async function resolvePromiseValues(obj) {
const keys = Object.keys(obj);
const settled = await Promise.allSettled(keys.map((key) => Promise.resolve(obj[key])));
const result = {};
let errors = null;
for (let i = 0; i < keys.length; i++) {
const s = settled[i];
if (s.status === "fulfilled") result[keys[i]] = s.value;
else {
result[keys[i]] = LAZY_EVAL_ERROR;
if (!errors) errors = [];
errors.push({
key: keys[i],
error: s.reason
});
}
}
return {
resolved: result,
errors
};
}
//#endregion
exports.LAZY_EVAL_ERROR = LAZY_EVAL_ERROR;
exports.LAZY_SYMBOL = LAZY_SYMBOL;
exports.LogLevel = LogLevel;
exports.LogLevelPriority = LogLevelPriority;
exports.LogLevelPriorityToNames = LogLevelPriorityToNames;
exports.LogLevelPriorityToNames = LogLevelPriorityToNames;
exports.countLazyValues = countLazyValues;
exports.hasPromiseValues = hasPromiseValues;
exports.isLazy = isLazy;
exports.lazy = lazy;
exports.replacePromiseValues = replacePromiseValues;
exports.resolveLazyValues = resolveLazyValues;
exports.resolvePromiseValues = resolvePromiseValues;

@@ -0,1 +1,120 @@

//#region src/lazy.d.ts
/**
* Symbol used to identify lazy values in context and metadata.
* Can be used to check if a value is a lazy wrapper: `LAZY_SYMBOL in value`.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
declare const LAZY_SYMBOL: unique symbol;
/**
* String constant used as a replacement value when a lazy callback fails during evaluation.
* Exported so users can programmatically detect lazy evaluation failures in their log output.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation#error-handling | Lazy Evaluation Error Handling Docs}
*/
declare const LAZY_EVAL_ERROR = "[LazyEvalError]";
/**
* Describes a single lazy evaluation failure.
* @internal
*/
interface LazyEvalFailure {
key: string;
error: unknown;
}
/**
* Result of resolving lazy values, including any errors that occurred.
* @internal
*/
interface ResolveLazyResult<T> {
resolved: T;
errors: LazyEvalFailure[] | null;
}
/**
* Represents a lazy value that defers evaluation until log time.
*
* Created by the {@link lazy} function.
*
* When the type parameter `T` is a `Promise`, log methods that receive this
* lazy value in metadata will return `Promise<void>` instead of `void`.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
interface LazyLogValue<T = any> {
[LAZY_SYMBOL]: () => T;
}
/**
* Wraps a callback function to defer its evaluation until log time.
*
* The callback will only be invoked if the log level is enabled,
* avoiding unnecessary computation for disabled log levels.
*
* Can be used in both `withContext()` and `withMetadata()` at the root level.
*
* When the callback returns a `Promise` (i.e., is an async function), the
* log method will return `Promise<void>` so TypeScript can track that the
* operation is asynchronous.
*
* Adapted from [LogTape's lazy evaluation](https://logtape.org/manual/lazy).
*
* @example
* ```typescript
* import { LogLayer, lazy } from "loglayer";
*
* const log = new LogLayer({ ... });
*
* // Dynamic context - evaluated on each log call
* log.withContext({
* memoryUsage: lazy(() => process.memoryUsage().heapUsed),
* });
*
* // Dynamic metadata - evaluated only if debug is enabled
* log.withMetadata({
* data: lazy(() => JSON.stringify(largeObject)),
* }).debug("Processing complete");
* ```
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
declare function lazy<T>(fn: () => T): LazyLogValue<T>;
/**
* Checks if a value is a lazy value created by {@link lazy}.
* @internal
*/
declare function isLazy(value: unknown): value is LazyLogValue;
/**
* Counts the number of lazy values in a record.
* @internal
*/
declare function countLazyValues(obj: Record<string, any>): number;
/**
* Resolves any lazy values in a record at the root level.
* Returns the original object if no lazy values are found (optimization).
* If a lazy callback throws, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
declare function resolveLazyValues<T extends Record<string, any>>(obj: T): ResolveLazyResult<T>;
/**
* Checks if any values in a record are Promises.
* @internal
*/
declare function hasPromiseValues(obj: Record<string, any>): boolean;
/**
* Replaces any Promise values in a record with LAZY_EVAL_ERROR.
* Used to strip async lazy values from context where only sync lazy is supported.
* Returns the keys that were replaced.
* @internal
*/
declare function replacePromiseValues<T extends Record<string, any>>(obj: T): {
resolved: T;
asyncKeys: string[] | null;
};
/**
* Resolves any Promise values in a record using Promise.allSettled.
* If a Promise rejects, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
declare function resolvePromiseValues<T extends Record<string, any>>(obj: T): Promise<ResolveLazyResult<T>>;
//#endregion
//#region src/common.types.d.ts

@@ -38,3 +157,3 @@ declare enum LogLevel {

*/
logLevel?: LogLevel;
logLevel?: LogLevelType;
/**

@@ -63,2 +182,21 @@ * If `true`, copies the `error.message` if available to the transport library's

interface LogLayerData extends Record<string, any> {}
/**
* Type-level helper that checks whether a metadata/context record type
* contains any {@link LazyLogValue} whose callback returns a `Promise`.
*
* Evaluates to `true` if any property is `LazyLogValue<Promise<any>>`,
* `false` otherwise. Returns `false` for `undefined` or `null` inputs.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
type ContainsAsyncLazy<M> = M extends undefined | null ? false : true extends { [K in keyof M]: M[K] extends LazyLogValue<infer T> ? (T extends Promise<any> ? true : false) : false }[keyof M] ? true : false;
/**
* Helper type that resolves the return type of log methods based on whether
* async lazy values are present.
*
* - `true` → `Promise<void>` (async lazy values detected)
* - `false` → `void` (no async lazy values)
* - `boolean` → `void | Promise<void>` (indeterminate, used by implementation classes)
*/
type LogReturnType<IsAsync extends boolean> = IsAsync extends true ? Promise<void> : IsAsync extends false ? void : void | Promise<void>;
interface LogLayerCommonDataParams {

@@ -477,41 +615,48 @@ /**

* Interface for implementing a LogLayer builder instance.
*
* @typeParam This - The concrete builder type for polymorphic chaining.
* @typeParam IsAsync - Whether the builder contains async lazy metadata.
* When `true`, log methods return `Promise<void>`. When `false`, they return `void`.
* When `boolean` (indeterminate), they return `void | Promise<void>`.
*
* @see {@link https://loglayer.dev | LogLayer Documentation}
*/
interface ILogBuilder<This = ILogBuilder<any>> {
interface ILogBuilder<This = ILogBuilder<any, any>, IsAsync extends boolean = false> {
/**
* Sends a log message to the logging library under an info log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
info(...messages: MessageDataType[]): void | Promise<void>;
info(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the warn log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
warn(...messages: MessageDataType[]): void | Promise<void>;
warn(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the error log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
error(...messages: MessageDataType[]): void | Promise<void>;
error(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the debug log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
debug(...messages: MessageDataType[]): void | Promise<void>;
debug(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the trace log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
trace(...messages: MessageDataType[]): void | Promise<void>;
trace(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the fatal log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
fatal(...messages: MessageDataType[]): void | Promise<void>;
fatal(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Specifies metadata to include with the log message
* Specifies metadata to include with the log message.
* If the metadata contains async lazy values, subsequent log methods will return `Promise<void>`.
*
* @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs}
*/
withMetadata(metadata?: LogLayerMetadata): This;
withMetadata<M extends LogLayerMetadata>(metadata?: M): ILogBuilder<This, ContainsAsyncLazy<NonNullable<M>> extends true ? true : IsAsync>;
/**

@@ -522,3 +667,3 @@ * Specifies an Error to include with the log message

*/
withError(error: any): This;
withError(error: any): ILogBuilder<This, IsAsync>;
/**

@@ -529,3 +674,3 @@ * Enable sending logs to the logging library.

*/
enableLogging(): This;
enableLogging(): ILogBuilder<This, IsAsync>;
/**

@@ -536,3 +681,3 @@ * All logging inputs are dropped and stops sending logs to the logging library.

*/
disableLogging(): This;
disableLogging(): ILogBuilder<This, IsAsync>;
}

@@ -546,36 +691,31 @@ /**

* Sends a log message to the logging library under an info log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
info(...messages: MessageDataType[]): void | Promise<void>;
info(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the warn log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
warn(...messages: MessageDataType[]): void | Promise<void>;
warn(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the error log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
error(...messages: MessageDataType[]): void | Promise<void>;
error(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the debug log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
debug(...messages: MessageDataType[]): void | Promise<void>;
debug(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the trace log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
trace(...messages: MessageDataType[]): void | Promise<void>;
trace(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the fatal log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
fatal(...messages: MessageDataType[]): void | Promise<void>;
fatal(...messages: MessageDataType[]): void;
/**
* Specifies metadata to include with the log message
* Specifies metadata to include with the log message.
* If the metadata contains async lazy values, the builder's log methods will return `Promise<void>`.
*
* @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs}
*/
withMetadata(metadata?: LogLayerMetadata): ILogBuilder<any>;
withMetadata<M extends LogLayerMetadata>(metadata?: M): ILogBuilder<any, ContainsAsyncLazy<NonNullable<M>>>;
/**

@@ -586,3 +726,3 @@ * Specifies an Error to include with the log message

*/
withError(error: any): ILogBuilder<any>;
withError(error: any): ILogBuilder<any, false>;
/**

@@ -629,9 +769,10 @@ * Enable sending logs to the logging library.

*/
errorOnly(error: any, opts?: ErrorOnlyOpts): void | Promise<void>;
errorOnly(error: any, opts?: ErrorOnlyOpts): void;
/**
* Logs only metadata without a log message
* Logs only metadata without a log message.
* Returns a Promise when async lazy values are present in metadata.
*
* @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs}
*/
metadataOnly(metadata?: LogLayerMetadata, logLevel?: LogLevelType): void | Promise<void>;
metadataOnly<M extends LogLayerMetadata>(metadata?: M, logLevel?: LogLevelType): LogReturnType<ContainsAsyncLazy<NonNullable<M>>>;
/**

@@ -820,8 +961,9 @@ * Returns the context used.

* The raw entry will still go through all LogLayer processing.
* Returns a Promise when async lazy values are present in the entry's metadata.
*
* @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs}
*/
raw(rawEntry: RawLogEntry): void | Promise<void>;
raw<R extends RawLogEntry>(rawEntry: R): LogReturnType<ContainsAsyncLazy<NonNullable<R["metadata"]>>>;
}
//#endregion
export { ErrorOnlyOpts, IContextManager, ILogBuilder, ILogLayer, ILogLevelManager, LogLayerCommonDataParams, LogLayerContext, LogLayerData, LogLayerMetadata, LogLayerPlugin, LogLayerPluginParams, LogLayerTransport, LogLayerTransportParams, LogLevel, LogLevelPriority, LogLevelPriorityToNames, LogLevelType, MessageDataType, OnChildLogLevelManagerCreatedParams, OnChildLoggerCreatedParams, PluginBeforeDataOutParams, PluginBeforeMessageOutParams, PluginShouldSendToLoggerParams, PluginTransformLogLevelParams, RawLogEntry };
export { ContainsAsyncLazy, ErrorOnlyOpts, IContextManager, ILogBuilder, ILogLayer, ILogLevelManager, LAZY_EVAL_ERROR, LAZY_SYMBOL, LazyEvalFailure, LazyLogValue, LogLayerCommonDataParams, LogLayerContext, LogLayerData, LogLayerMetadata, LogLayerPlugin, LogLayerPluginParams, LogLayerTransport, LogLayerTransportParams, LogLevel, LogLevelPriority, LogLevelPriorityToNames, LogLevelType, LogReturnType, MessageDataType, OnChildLogLevelManagerCreatedParams, OnChildLoggerCreatedParams, PluginBeforeDataOutParams, PluginBeforeMessageOutParams, PluginShouldSendToLoggerParams, PluginTransformLogLevelParams, RawLogEntry, ResolveLazyResult, countLazyValues, hasPromiseValues, isLazy, lazy, replacePromiseValues, resolveLazyValues, resolvePromiseValues };

@@ -0,1 +1,120 @@

//#region src/lazy.d.ts
/**
* Symbol used to identify lazy values in context and metadata.
* Can be used to check if a value is a lazy wrapper: `LAZY_SYMBOL in value`.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
declare const LAZY_SYMBOL: unique symbol;
/**
* String constant used as a replacement value when a lazy callback fails during evaluation.
* Exported so users can programmatically detect lazy evaluation failures in their log output.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation#error-handling | Lazy Evaluation Error Handling Docs}
*/
declare const LAZY_EVAL_ERROR = "[LazyEvalError]";
/**
* Describes a single lazy evaluation failure.
* @internal
*/
interface LazyEvalFailure {
key: string;
error: unknown;
}
/**
* Result of resolving lazy values, including any errors that occurred.
* @internal
*/
interface ResolveLazyResult<T> {
resolved: T;
errors: LazyEvalFailure[] | null;
}
/**
* Represents a lazy value that defers evaluation until log time.
*
* Created by the {@link lazy} function.
*
* When the type parameter `T` is a `Promise`, log methods that receive this
* lazy value in metadata will return `Promise<void>` instead of `void`.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
interface LazyLogValue<T = any> {
[LAZY_SYMBOL]: () => T;
}
/**
* Wraps a callback function to defer its evaluation until log time.
*
* The callback will only be invoked if the log level is enabled,
* avoiding unnecessary computation for disabled log levels.
*
* Can be used in both `withContext()` and `withMetadata()` at the root level.
*
* When the callback returns a `Promise` (i.e., is an async function), the
* log method will return `Promise<void>` so TypeScript can track that the
* operation is asynchronous.
*
* Adapted from [LogTape's lazy evaluation](https://logtape.org/manual/lazy).
*
* @example
* ```typescript
* import { LogLayer, lazy } from "loglayer";
*
* const log = new LogLayer({ ... });
*
* // Dynamic context - evaluated on each log call
* log.withContext({
* memoryUsage: lazy(() => process.memoryUsage().heapUsed),
* });
*
* // Dynamic metadata - evaluated only if debug is enabled
* log.withMetadata({
* data: lazy(() => JSON.stringify(largeObject)),
* }).debug("Processing complete");
* ```
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
declare function lazy<T>(fn: () => T): LazyLogValue<T>;
/**
* Checks if a value is a lazy value created by {@link lazy}.
* @internal
*/
declare function isLazy(value: unknown): value is LazyLogValue;
/**
* Counts the number of lazy values in a record.
* @internal
*/
declare function countLazyValues(obj: Record<string, any>): number;
/**
* Resolves any lazy values in a record at the root level.
* Returns the original object if no lazy values are found (optimization).
* If a lazy callback throws, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
declare function resolveLazyValues<T extends Record<string, any>>(obj: T): ResolveLazyResult<T>;
/**
* Checks if any values in a record are Promises.
* @internal
*/
declare function hasPromiseValues(obj: Record<string, any>): boolean;
/**
* Replaces any Promise values in a record with LAZY_EVAL_ERROR.
* Used to strip async lazy values from context where only sync lazy is supported.
* Returns the keys that were replaced.
* @internal
*/
declare function replacePromiseValues<T extends Record<string, any>>(obj: T): {
resolved: T;
asyncKeys: string[] | null;
};
/**
* Resolves any Promise values in a record using Promise.allSettled.
* If a Promise rejects, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
declare function resolvePromiseValues<T extends Record<string, any>>(obj: T): Promise<ResolveLazyResult<T>>;
//#endregion
//#region src/common.types.d.ts

@@ -38,3 +157,3 @@ declare enum LogLevel {

*/
logLevel?: LogLevel;
logLevel?: LogLevelType;
/**

@@ -63,2 +182,21 @@ * If `true`, copies the `error.message` if available to the transport library's

interface LogLayerData extends Record<string, any> {}
/**
* Type-level helper that checks whether a metadata/context record type
* contains any {@link LazyLogValue} whose callback returns a `Promise`.
*
* Evaluates to `true` if any property is `LazyLogValue<Promise<any>>`,
* `false` otherwise. Returns `false` for `undefined` or `null` inputs.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
type ContainsAsyncLazy<M> = M extends undefined | null ? false : true extends { [K in keyof M]: M[K] extends LazyLogValue<infer T> ? (T extends Promise<any> ? true : false) : false }[keyof M] ? true : false;
/**
* Helper type that resolves the return type of log methods based on whether
* async lazy values are present.
*
* - `true` → `Promise<void>` (async lazy values detected)
* - `false` → `void` (no async lazy values)
* - `boolean` → `void | Promise<void>` (indeterminate, used by implementation classes)
*/
type LogReturnType<IsAsync extends boolean> = IsAsync extends true ? Promise<void> : IsAsync extends false ? void : void | Promise<void>;
interface LogLayerCommonDataParams {

@@ -477,41 +615,48 @@ /**

* Interface for implementing a LogLayer builder instance.
*
* @typeParam This - The concrete builder type for polymorphic chaining.
* @typeParam IsAsync - Whether the builder contains async lazy metadata.
* When `true`, log methods return `Promise<void>`. When `false`, they return `void`.
* When `boolean` (indeterminate), they return `void | Promise<void>`.
*
* @see {@link https://loglayer.dev | LogLayer Documentation}
*/
interface ILogBuilder<This = ILogBuilder<any>> {
interface ILogBuilder<This = ILogBuilder<any, any>, IsAsync extends boolean = false> {
/**
* Sends a log message to the logging library under an info log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
info(...messages: MessageDataType[]): void | Promise<void>;
info(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the warn log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
warn(...messages: MessageDataType[]): void | Promise<void>;
warn(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the error log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
error(...messages: MessageDataType[]): void | Promise<void>;
error(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the debug log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
debug(...messages: MessageDataType[]): void | Promise<void>;
debug(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the trace log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
trace(...messages: MessageDataType[]): void | Promise<void>;
trace(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Sends a log message to the logging library under the fatal log level.
* Returns a Promise when async lazy values are present in context or metadata.
* Returns a Promise when async lazy values are present in metadata.
*/
fatal(...messages: MessageDataType[]): void | Promise<void>;
fatal(...messages: MessageDataType[]): LogReturnType<IsAsync>;
/**
* Specifies metadata to include with the log message
* Specifies metadata to include with the log message.
* If the metadata contains async lazy values, subsequent log methods will return `Promise<void>`.
*
* @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs}
*/
withMetadata(metadata?: LogLayerMetadata): This;
withMetadata<M extends LogLayerMetadata>(metadata?: M): ILogBuilder<This, ContainsAsyncLazy<NonNullable<M>> extends true ? true : IsAsync>;
/**

@@ -522,3 +667,3 @@ * Specifies an Error to include with the log message

*/
withError(error: any): This;
withError(error: any): ILogBuilder<This, IsAsync>;
/**

@@ -529,3 +674,3 @@ * Enable sending logs to the logging library.

*/
enableLogging(): This;
enableLogging(): ILogBuilder<This, IsAsync>;
/**

@@ -536,3 +681,3 @@ * All logging inputs are dropped and stops sending logs to the logging library.

*/
disableLogging(): This;
disableLogging(): ILogBuilder<This, IsAsync>;
}

@@ -546,36 +691,31 @@ /**

* Sends a log message to the logging library under an info log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
info(...messages: MessageDataType[]): void | Promise<void>;
info(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the warn log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
warn(...messages: MessageDataType[]): void | Promise<void>;
warn(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the error log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
error(...messages: MessageDataType[]): void | Promise<void>;
error(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the debug log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
debug(...messages: MessageDataType[]): void | Promise<void>;
debug(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the trace log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
trace(...messages: MessageDataType[]): void | Promise<void>;
trace(...messages: MessageDataType[]): void;
/**
* Sends a log message to the logging library under the fatal log level.
* Returns a Promise when async lazy values are present in context or metadata.
*/
fatal(...messages: MessageDataType[]): void | Promise<void>;
fatal(...messages: MessageDataType[]): void;
/**
* Specifies metadata to include with the log message
* Specifies metadata to include with the log message.
* If the metadata contains async lazy values, the builder's log methods will return `Promise<void>`.
*
* @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs}
*/
withMetadata(metadata?: LogLayerMetadata): ILogBuilder<any>;
withMetadata<M extends LogLayerMetadata>(metadata?: M): ILogBuilder<any, ContainsAsyncLazy<NonNullable<M>>>;
/**

@@ -586,3 +726,3 @@ * Specifies an Error to include with the log message

*/
withError(error: any): ILogBuilder<any>;
withError(error: any): ILogBuilder<any, false>;
/**

@@ -629,9 +769,10 @@ * Enable sending logs to the logging library.

*/
errorOnly(error: any, opts?: ErrorOnlyOpts): void | Promise<void>;
errorOnly(error: any, opts?: ErrorOnlyOpts): void;
/**
* Logs only metadata without a log message
* Logs only metadata without a log message.
* Returns a Promise when async lazy values are present in metadata.
*
* @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs}
*/
metadataOnly(metadata?: LogLayerMetadata, logLevel?: LogLevelType): void | Promise<void>;
metadataOnly<M extends LogLayerMetadata>(metadata?: M, logLevel?: LogLevelType): LogReturnType<ContainsAsyncLazy<NonNullable<M>>>;
/**

@@ -820,8 +961,9 @@ * Returns the context used.

* The raw entry will still go through all LogLayer processing.
* Returns a Promise when async lazy values are present in the entry's metadata.
*
* @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs}
*/
raw(rawEntry: RawLogEntry): void | Promise<void>;
raw<R extends RawLogEntry>(rawEntry: R): LogReturnType<ContainsAsyncLazy<NonNullable<R["metadata"]>>>;
}
//#endregion
export { ErrorOnlyOpts, IContextManager, ILogBuilder, ILogLayer, ILogLevelManager, LogLayerCommonDataParams, LogLayerContext, LogLayerData, LogLayerMetadata, LogLayerPlugin, LogLayerPluginParams, LogLayerTransport, LogLayerTransportParams, LogLevel, LogLevelPriority, LogLevelPriorityToNames, LogLevelType, MessageDataType, OnChildLogLevelManagerCreatedParams, OnChildLoggerCreatedParams, PluginBeforeDataOutParams, PluginBeforeMessageOutParams, PluginShouldSendToLoggerParams, PluginTransformLogLevelParams, RawLogEntry };
export { ContainsAsyncLazy, ErrorOnlyOpts, IContextManager, ILogBuilder, ILogLayer, ILogLevelManager, LAZY_EVAL_ERROR, LAZY_SYMBOL, LazyEvalFailure, LazyLogValue, LogLayerCommonDataParams, LogLayerContext, LogLayerData, LogLayerMetadata, LogLayerPlugin, LogLayerPluginParams, LogLayerTransport, LogLayerTransportParams, LogLevel, LogLevelPriority, LogLevelPriorityToNames, LogLevelType, LogReturnType, MessageDataType, OnChildLogLevelManagerCreatedParams, OnChildLoggerCreatedParams, PluginBeforeDataOutParams, PluginBeforeMessageOutParams, PluginShouldSendToLoggerParams, PluginTransformLogLevelParams, RawLogEntry, ResolveLazyResult, countLazyValues, hasPromiseValues, isLazy, lazy, replacePromiseValues, resolveLazyValues, resolvePromiseValues };

@@ -35,2 +35,168 @@ //#region src/common.types.ts

//#endregion
export { LogLevel, LogLevelPriority, LogLevelPriorityToNames };
//#region src/lazy.ts
/**
* Symbol used to identify lazy values in context and metadata.
* Can be used to check if a value is a lazy wrapper: `LAZY_SYMBOL in value`.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
const LAZY_SYMBOL = Symbol.for("loglayer.lazy");
/**
* String constant used as a replacement value when a lazy callback fails during evaluation.
* Exported so users can programmatically detect lazy evaluation failures in their log output.
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation#error-handling | Lazy Evaluation Error Handling Docs}
*/
const LAZY_EVAL_ERROR = "[LazyEvalError]";
/**
* Wraps a callback function to defer its evaluation until log time.
*
* The callback will only be invoked if the log level is enabled,
* avoiding unnecessary computation for disabled log levels.
*
* Can be used in both `withContext()` and `withMetadata()` at the root level.
*
* When the callback returns a `Promise` (i.e., is an async function), the
* log method will return `Promise<void>` so TypeScript can track that the
* operation is asynchronous.
*
* Adapted from [LogTape's lazy evaluation](https://logtape.org/manual/lazy).
*
* @example
* ```typescript
* import { LogLayer, lazy } from "loglayer";
*
* const log = new LogLayer({ ... });
*
* // Dynamic context - evaluated on each log call
* log.withContext({
* memoryUsage: lazy(() => process.memoryUsage().heapUsed),
* });
*
* // Dynamic metadata - evaluated only if debug is enabled
* log.withMetadata({
* data: lazy(() => JSON.stringify(largeObject)),
* }).debug("Processing complete");
* ```
*
* @see {@link https://loglayer.dev/logging-api/lazy-evaluation | Lazy Evaluation Docs}
*/
function lazy(fn) {
return { [LAZY_SYMBOL]: fn };
}
/**
* Checks if a value is a lazy value created by {@link lazy}.
* @internal
*/
function isLazy(value) {
return value != null && typeof value === "object" && LAZY_SYMBOL in value;
}
/**
* Counts the number of lazy values in a record.
* @internal
*/
function countLazyValues(obj) {
let count = 0;
for (const key of Object.keys(obj)) if (isLazy(obj[key])) count++;
return count;
}
/**
* Resolves any lazy values in a record at the root level.
* Returns the original object if no lazy values are found (optimization).
* If a lazy callback throws, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
function resolveLazyValues(obj) {
let hasLazy = false;
for (const key of Object.keys(obj)) if (isLazy(obj[key])) {
hasLazy = true;
break;
}
if (!hasLazy) return {
resolved: obj,
errors: null
};
const result = {};
let errors = null;
for (const key of Object.keys(obj)) {
const value = obj[key];
if (isLazy(value)) try {
result[key] = value[LAZY_SYMBOL]();
} catch (e) {
result[key] = LAZY_EVAL_ERROR;
if (!errors) errors = [];
errors.push({
key,
error: e
});
}
else result[key] = value;
}
return {
resolved: result,
errors
};
}
/**
* Checks if any values in a record are Promises.
* @internal
*/
function hasPromiseValues(obj) {
for (const key of Object.keys(obj)) if (obj[key] instanceof Promise) return true;
return false;
}
/**
* Replaces any Promise values in a record with LAZY_EVAL_ERROR.
* Used to strip async lazy values from context where only sync lazy is supported.
* Returns the keys that were replaced.
* @internal
*/
function replacePromiseValues(obj) {
let asyncKeys = null;
const result = {};
for (const key of Object.keys(obj)) if (obj[key] instanceof Promise) {
result[key] = LAZY_EVAL_ERROR;
if (!asyncKeys) asyncKeys = [];
asyncKeys.push(key);
} else result[key] = obj[key];
if (!asyncKeys) return {
resolved: obj,
asyncKeys: null
};
return {
resolved: result,
asyncKeys
};
}
/**
* Resolves any Promise values in a record using Promise.allSettled.
* If a Promise rejects, the value is replaced with LAZY_EVAL_ERROR
* and the error is collected in the result.
* @internal
*/
async function resolvePromiseValues(obj) {
const keys = Object.keys(obj);
const settled = await Promise.allSettled(keys.map((key) => Promise.resolve(obj[key])));
const result = {};
let errors = null;
for (let i = 0; i < keys.length; i++) {
const s = settled[i];
if (s.status === "fulfilled") result[keys[i]] = s.value;
else {
result[keys[i]] = LAZY_EVAL_ERROR;
if (!errors) errors = [];
errors.push({
key: keys[i],
error: s.reason
});
}
}
return {
resolved: result,
errors
};
}
//#endregion
export { LAZY_EVAL_ERROR, LAZY_SYMBOL, LogLevel, LogLevelPriority, LogLevelPriorityToNames, countLazyValues, hasPromiseValues, isLazy, lazy, replacePromiseValues, resolveLazyValues, resolvePromiseValues };
+1
-1
{
"name": "@loglayer/shared",
"description": "Shared utilities and types for loglayer packages.",
"version": "4.0.0",
"version": "4.0.1",
"type": "module",

@@ -6,0 +6,0 @@ "main": "./dist/index.cjs",