@stacksjs/logging 0.74.45 → 0.74.47
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/dist/index.d.ts +0 -86
- package/dist/index.js +10 -11
- package/dist/runtime.d.ts +11 -0
- package/dist/runtime.js +1 -0
- package/package.json +14 -8
package/dist/index.d.ts
CHANGED
|
@@ -102,68 +102,7 @@ export declare function logger(): Promise<Logger>;
|
|
|
102
102
|
// Helper function to format message for logging, including request context.
|
|
103
103
|
// Exported for direct unit testing of arg handling (stacksjs/stacks#2047).
|
|
104
104
|
export declare function formatMessage(...args: unknown[]): string;
|
|
105
|
-
// Export convenience functions
|
|
106
|
-
export declare function dump(...args: any[]): Promise<void>;
|
|
107
|
-
export declare function dd(...args: any[]): Promise<never>;
|
|
108
|
-
export declare function echo(...args: any[]): Promise<void>;
|
|
109
|
-
/**
|
|
110
|
-
* Single error→log chokepoint (stacksjs/stacks#1933) — Laravel's
|
|
111
|
-
* `report()`. Every automatic error-logging path (router action catch,
|
|
112
|
-
* request catch, process-level handlers) funnels through here so the
|
|
113
|
-
* policy lives in one place:
|
|
114
|
-
*
|
|
115
|
-
* - **4xx** (client errors — a thrown `HttpError(404)` / `422`) are
|
|
116
|
-
* NOT reported at error level; they're expected control flow, not
|
|
117
|
-
* server faults. Logged at debug so they stay traceable without
|
|
118
|
-
* spamming the error stream.
|
|
119
|
-
* - **5xx** and any non-HTTP throw are always reported at `error`
|
|
120
|
-
* with the full normalized stack + cause chain + request context.
|
|
121
|
-
*
|
|
122
|
-
* Fire-and-forget by design (callers are on a response / exit path);
|
|
123
|
-
* the write is queued through the shared logger so a flush-on-exit
|
|
124
|
-
* (stacksjs/stacks#1934) drains it.
|
|
125
|
-
*/
|
|
126
|
-
export declare function report(error: unknown, options?: ReportOptions): void;
|
|
127
|
-
declare function emit(level: 'debug' | 'info' | 'warn' | 'error', event: string, fields: StructuredFields): void;
|
|
128
105
|
export declare const log: Log;
|
|
129
|
-
/**
|
|
130
|
-
* @defaultValue
|
|
131
|
-
* ```ts
|
|
132
|
-
* {
|
|
133
|
-
* request: (method: string, path: string, status: number, durationMs: number, fields?: StructuredFields) => void,
|
|
134
|
-
* query: (sql: string, durationMs: number, fields?: StructuredFields) => void,
|
|
135
|
-
* slowQuery: (sql: string, durationMs: number, fields?: StructuredFields) => void,
|
|
136
|
-
* job: (name: string, phase: 'started' | 'succeeded' | 'failed' | 'released', fields?: StructuredFields) => void,
|
|
137
|
-
* cache: (op: 'hit' | 'miss' | 'set' | 'del', key: string, fields?: StructuredFields) => void
|
|
138
|
-
* }
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
export declare const struct: {
|
|
142
|
-
/**
|
|
143
|
-
* HTTP request completed. `status` is the response status code,
|
|
144
|
-
* `durationMs` the wall time from request start to response sent.
|
|
145
|
-
*/
|
|
146
|
-
request: (method: string, path: string, status: number, durationMs: number, fields?: StructuredFields) => void;
|
|
147
|
-
/**
|
|
148
|
-
* Database query completed. `durationMs` is the wall time at the
|
|
149
|
-
* driver boundary.
|
|
150
|
-
*/
|
|
151
|
-
query: (sql: string, durationMs: number, fields?: StructuredFields) => void;
|
|
152
|
-
/**
|
|
153
|
-
* A slow query (over the slow-threshold) — emits at warn so it
|
|
154
|
-
* surfaces in the default log filter.
|
|
155
|
-
*/
|
|
156
|
-
slowQuery: (sql: string, durationMs: number, fields?: StructuredFields) => void;
|
|
157
|
-
/**
|
|
158
|
-
* Queue job lifecycle event. `phase` is `'started' | 'succeeded' |
|
|
159
|
-
* 'failed' | 'released'`.
|
|
160
|
-
*/
|
|
161
|
-
job: (name: string, phase: 'started' | 'succeeded' | 'failed' | 'released', fields?: StructuredFields) => void;
|
|
162
|
-
/**
|
|
163
|
-
* Cache hit/miss event for warm-path debugging.
|
|
164
|
-
*/
|
|
165
|
-
cache: (op: 'hit' | 'miss' | 'set' | 'del', key: string, fields?: StructuredFields) => void
|
|
166
|
-
};
|
|
167
106
|
export declare interface ResolvedLogSettings {
|
|
168
107
|
level: LogLevel
|
|
169
108
|
format: LogFormat
|
|
@@ -213,30 +152,5 @@ export declare interface LogErrorOptions {
|
|
|
213
152
|
silent?: boolean
|
|
214
153
|
message?: ErrorMessage
|
|
215
154
|
}
|
|
216
|
-
export declare interface ReportOptions {
|
|
217
|
-
status?: number
|
|
218
|
-
context?: LogContext
|
|
219
|
-
label?: string
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Structured logging shorthands for common framework events.
|
|
223
|
-
*
|
|
224
|
-
* The bare `log.info("…")` form is good for ad-hoc messages, but the
|
|
225
|
-
* framework emits a predictable set of events (HTTP requests, DB
|
|
226
|
-
* queries, queued jobs, cache operations) that benefit from a stable
|
|
227
|
-
* shape so downstream log shippers can index on consistent field
|
|
228
|
-
* names.
|
|
229
|
-
*
|
|
230
|
-
* Each helper:
|
|
231
|
-
* 1. Attaches the current trace id (if any) automatically
|
|
232
|
-
* 2. Picks the appropriate severity based on outcome
|
|
233
|
-
* 3. Emits a consistent JSON shape in production (`event`, `level`,
|
|
234
|
-
* `traceId`, …) while keeping the human-readable form in dev
|
|
235
|
-
*
|
|
236
|
-
* Helpers are batched onto `log.struct` so they don't pollute the
|
|
237
|
-
* top-level `log` namespace, and so users can opt out by routing
|
|
238
|
-
* `log.struct` to a custom transport in tests.
|
|
239
|
-
*/
|
|
240
|
-
declare interface StructuredFields { [key: string]: unknown }
|
|
241
155
|
export type LogFormat = 'json' | 'text';
|
|
242
156
|
export type ErrorMessage = string;
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
`)
|
|
4
|
-
`)
|
|
5
|
-
`)}
|
|
6
|
-
`)
|
|
7
|
-
`);return
|
|
8
|
-
|
|
9
|
-
`)},
|
|
10
|
-
`)},
|
|
11
|
-
`),s.exit(n)},exit:async(e,n=_)=>{if(e)await(n===_?c.success(e):c.error(e));await c.flush(),s.exit(n)},flush:async()=>{if(x.size>0)await Promise.allSettled([...x]);if(await K(),!f&&!d)return;try{let e=await a(),n=e.flush;if(typeof n==="function")await n.call(e)}catch{}}};async function ue(...e){for(let n of e)await c.debug(n)}async function le(...e){let n=m(...e);console.log(n),s.exit(S)}async function fe(...e){await c.debug(...e)}function te(e){if(e&&typeof e==="object"){let n=e;if(typeof n.status==="number")return n.status;if(typeof n.statusCode==="number")return n.statusCode}return}function de(e,n={}){let t=n.status??te(e),r=typeof t==="number"&&t>=400&&t<500,o=n.label??"Unhandled error",i={...n.context,...t!=null?{status:t}:{}};if(r){c.debug(`${o} (client error ${t}): ${w(e).message}`);return}c.error(o,e,i)}function L(e,n,t){let r=F(),o={event:n,traceId:r?.requestId,...t};if(e==="warn")R(c.warn(`[${n}]`,o));else R(c[e](o))}var re={request(e,n,t,r,o={}){let i=t>=500?"error":t>=400?"warn":"info";L(i,"http.request",{method:e,path:n,status:t,durationMs:r,...o})},query(e,n,t={}){L("debug","db.query",{sql:e,durationMs:n,...t})},slowQuery(e,n,t={}){L("warn","db.slow_query",{sql:e,durationMs:n,...t})},job(e,n,t={}){L(n==="failed"?"error":"info",`job.${n}`,{jobName:e,...t})},cache(e,n,t={}){L("debug",`cache.${e}`,{key:n,...t})}};c.struct=re;export{W as currentLevel,le as dd,ue as dump,fe as echo,m as formatMessage,F as getLogContext,c as log,ce as logger,z as normalizeContext,w as normalizeError,U as parseLogFormat,p as parseLogLevel,se as registerTransport,k as renderNormalizedError,de as report,X as resolveLogSettings,re as struct,I as suppressedAtCurrentLevel,ae as transports,ge as withLogContext};
|
|
1
|
+
import{AsyncLocalStorage}from"node:async_hooks";import process from"node:process";const EXIT_CODE_SUCCESS=0,EXIT_CODE_FATAL_ERROR=1;let _logger=null,_loggerInitPromise=null;const pendingWrites=new Set;function track(p){pendingWrites.add(p);p.finally(()=>pendingWrites.delete(p)).catch(()=>{});return p}let _flushOnExitRegistered=!1;function registerFlushOnExit(){if(_flushOnExitRegistered)return;_flushOnExitRegistered=!0;process.on("beforeExit",()=>{log.flush()})}const _transports=[],_brokenTransports=new Set,LEVEL_RANK={debug:0,info:1,success:1,warning:2,error:3};export function suppressedAtCurrentLevel(level){return LEVEL_RANK[level]<LEVEL_RANK[currentLevel()]}function addTransport(candidate){const t=candidate;if(!t||typeof t!=="object"||typeof t.log!=="function"){process.stderr.write(`[logging] Ignoring a transport without a log() function.
|
|
2
|
+
`);return null}if(typeof t.name!=="string"||!t.name){process.stderr.write(`[logging] Ignoring a transport without a name.
|
|
3
|
+
`);return null}_transports.push(t);return()=>{const at=_transports.indexOf(t);if(at!==-1)_transports.splice(at,1)}}export function registerTransport(transport){const detach=addTransport(transport);if(!detach)return()=>{};initLogger();return detach}export function transports(){return[..._transports]}function dispatch(level,message,args){if(_transports.length===0)return;let record;try{record={level,message,args,context:getLogContext(),timestamp:new Date().toISOString()}}catch{return}for(const transport of _transports){if(transport.level&&LEVEL_RANK[level]<LEVEL_RANK[transport.level])continue;try{transport.log(record)}catch(err){if(!_brokenTransports.has(transport.name)){_brokenTransports.add(transport.name);const reason=err instanceof Error?err.message:String(err);process.stderr.write(`[logging] Transport "${transport.name}" threw: ${reason}. Further throws from it are silent.
|
|
4
|
+
`)}}}}async function flushTransports(){const pending=_transports.filter((t)=>typeof t.flush==="function").map((t)=>t.flush().catch(()=>{}));if(pending.length>0)await Promise.allSettled(pending)}const VALID_LEVELS=new Set(["debug","info","success","warning","error"]);export function parseLogLevel(raw,fallback="info"){if(!raw)return fallback;const v=raw.toLowerCase();if(v==="warn")return"warning";if(VALID_LEVELS.has(v))return v;process.stderr.write(`[logging] Ignoring invalid LOG_LEVEL="${raw}" (expected: ${[...VALID_LEVELS].join(", ")}); using "${fallback}".
|
|
5
|
+
`);return fallback}let _configLevel,_envLevelRaw,_envLevelParsed;export function currentLevel(){const raw=process.env.LOG_LEVEL;if(raw){if(raw!==_envLevelRaw){_envLevelRaw=raw;_envLevelParsed=parseLogLevel(raw)}return _envLevelParsed}return _configLevel??"info"}export function parseLogFormat(raw){if(raw==="json"||raw==="text")return raw;if(raw)process.stderr.write(`[logging] Ignoring invalid LOG_FORMAT="${raw}" (expected "json" or "text").
|
|
6
|
+
`);return process.env.NODE_ENV==="production"?"json":"text"}export function resolveLogSettings(input){const level=input.envLevel?parseLogLevel(input.envLevel):input.cfgLevel?parseLogLevel(input.cfgLevel):"info",format=input.envFormat?parseLogFormat(input.envFormat):input.cfgFormat==="json"||input.cfgFormat==="text"?input.cfgFormat:input.isProduction?"json":"text";return{level,format,writeToFile:input.cfgWriteToFile??!0}}export function normalizeError(err,depth=0){if(depth>8)return{name:"Error",message:"[cause chain truncated]"};if(err instanceof Error)return{name:err.name,message:err.message,stack:err.stack,cause:err.cause!=null?normalizeError(err.cause,depth+1):void 0};if(typeof err==="string")return{name:"Error",message:err};if(err==null)return{name:"Error",message:String(err)};try{return{name:"Error",message:JSON.stringify(normalizeContextValue(err))}}catch{return{name:"Error",message:String(err)}}}export function renderNormalizedError(n){let out=n.stack||`${n.name}: ${n.message}`,cause=n.cause;while(cause){out+=`
|
|
7
|
+
caused by: ${cause.stack||`${cause.name}: ${cause.message}`}`;cause=cause.cause}return out}function normalizeContextValue(value,depth=0){if(value instanceof Error)return normalizeError(value);if(depth>=4||value===null||typeof value!=="object")return value;if(Array.isArray(value))return value.map((v)=>normalizeContextValue(v,depth+1));const proto=Object.getPrototypeOf(value);if(proto!==Object.prototype&&proto!==null)return value;const out={};for(const[k,v]of Object.entries(value))out[k]=normalizeContextValue(v,depth+1);return out}export function normalizeContext(ctx){return normalizeContextValue(ctx)}const logContextStorage=new AsyncLocalStorage;export function withLogContext(context,fn){return logContextStorage.run(context,fn)}export function getLogContext(){const store=logContextStorage.getStore(),trace=activeTraceId();if(!trace)return store;return{trace_id:trace,...store}}function activeTraceId(){try{const explicit=globalThis[Symbol.for("stacks.router.traceStorage")]?.getStore?.();if(explicit)return explicit;return globalThis[Symbol.for("stacks.router.requestStorage")]?.getStore?.()?._requestId}catch{return}}const CONFIG_READY_KEY=Symbol.for("@stacksjs/config:overridesReady");let _builtWith=null;async function readLoggingConfigNow(){try{return(await import("@stacksjs/config")).logging??null}catch{return null}}function configReadySignal(){const anchored=globalThis[CONFIG_READY_KEY];if(!anchored||typeof anchored.then!=="function")return null;return anchored}async function resolveSettings(logging,fallbackDirectory){const{level,format,writeToFile}=resolveLogSettings({envLevel:process.env.LOG_LEVEL,envFormat:process.env.LOG_FORMAT,cfgLevel:logging?.level,cfgFormat:logging?.format,cfgWriteToFile:typeof logging?.writeToFile==="boolean"?logging.writeToFile:void 0,isProduction:process.env.NODE_ENV==="production"});let logDirectory;if(logging?.logsPath)logDirectory=(await import("node:path")).dirname(logging.logsPath);if(!logDirectory)logDirectory=fallbackDirectory;if(!logDirectory)try{logDirectory=(await import("@stacksjs/path")).projectPath("storage/logs")}catch{logDirectory="storage/logs"}return{level,format,writeToFile,logDirectory}}function attachDeclaredTransports(logging){if(!Array.isArray(logging?.transports))return;for(const transport of logging.transports)if(!_transports.includes(transport))addTransport(transport)}let _configApplied=null;function applyConfigWhenReady(){if(_configApplied)return;const ready=configReadySignal();if(!ready)return;_configApplied=ready.then(async(resolved)=>{const logging=resolved?.logging;if(!logging)return;attachDeclaredTransports(logging);if(logging.level)_configLevel=parseLogLevel(logging.level);const built=_builtWith;if(!built||!_logger)return;const next=await resolveSettings(logging,built.logDirectory);if(built.level===next.level&&built.format===next.format&&built.writeToFile===next.writeToFile&&built.logDirectory===next.logDirectory)return;const previous=_logger,{Logger}=await import("@stacksjs/clarity");_logger=new Logger("stacks",{level:next.level,logDirectory:next.logDirectory,showTags:!1,fancy:next.format!=="json",format:next.format,writeToFile:next.writeToFile});_builtWith=next;try{await previous.flush?.();await previous.destroy?.()}catch{}}).catch(()=>{})}async function initLogger(){if(_logger)return;if(_loggerInitPromise)return _loggerInitPromise;registerFlushOnExit();_loggerInitPromise=(async()=>{const logging=await readLoggingConfigNow();attachDeclaredTransports(logging);if(logging?.level)_configLevel=parseLogLevel(logging.level);const settings=await resolveSettings(logging),{Logger}=await import("@stacksjs/clarity");_logger=new Logger("stacks",{level:settings.level,logDirectory:settings.logDirectory,showTags:!1,fancy:settings.format!=="json",format:settings.format,writeToFile:settings.writeToFile});_builtWith=settings})();_loggerInitPromise.then(applyConfigWhenReady);return _loggerInitPromise}async function getLogger(){await initLogger();return _logger}export async function logger(){await initLogger();applyConfigWhenReady();if(_configApplied)await _configApplied;return _logger}export function formatMessage(...args){const base=args.filter((arg)=>arg!==void 0).map((arg)=>{if(arg instanceof Error)return renderNormalizedError(normalizeError(arg));if(typeof arg==="object"&&arg!==null)return JSON.stringify(normalizeContextValue(arg),null,2);return String(arg)}).join(" "),ctx=logContextStorage.getStore();if(ctx?.requestId)return`[${ctx.requestId}] ${base}`;return base}const LEGACY_ERROR_OPTION_KEYS=new Set(["shouldExit","silent","message"]);function isLegacyErrorOptions(v){if(!v||typeof v!=="object"||v instanceof Error)return!1;if(!(("shouldExit"in v)||("silent"in v)))return!1;return Object.keys(v).every((k)=>LEGACY_ERROR_OPTION_KEYS.has(k))}export const log={info:async(...args)=>{const suppressed=suppressedAtCurrentLevel("info");if(suppressed&&_transports.length===0)return;const message=formatMessage(...args);if(suppressed){dispatch("info",message,args);return}const logger=await getLogger();dispatch("info",message,args);await logger.info(message)},success:async(message)=>{const suppressed=suppressedAtCurrentLevel("success");if(suppressed&&_transports.length===0)return;if(suppressed){dispatch("success",message,[message]);return}const logger=await getLogger();dispatch("success",message,[message]);await logger.success(message)},warn:async(message,context)=>{const logger=await getLogger();dispatch("warning",message,context===void 0?[message]:[message,context]);if(context==null){await logger.warn(message);return}const normalized=normalizeContextValue(context);await logger.warn(message,normalized)},warning:async(message)=>{const logger=await getLogger();dispatch("warning",message,[message]);await logger.warn(message)},error:async(message,error,context)=>{const legacyOptions=isLegacyErrorOptions(error)?error:void 0;let line;if(typeof message==="string")line=message;else line=renderNormalizedError(normalizeError(message));if(error!==void 0&&!legacyOptions)line=`${line} ${renderNormalizedError(normalizeError(error))}`;const mergedCtx={...getLogContext(),...context};if(Object.keys(mergedCtx).length>0)try{line=`${line} ${JSON.stringify(normalizeContext(mergedCtx))}`}catch{}const logger=await getLogger();dispatch("error",line,legacyOptions?[message]:[message,error,context].filter((a)=>a!==void 0));await logger.error(line);if(legacyOptions?.shouldExit){const{handleError}=await import("@stacksjs/error-handling/handler");handleError(message,legacyOptions)}},debug:async(...args)=>{const suppressed=currentLevel()!=="debug";if(suppressed&&_transports.length===0){if(configReadySignal()){if(!_logger&&!_loggerInitPromise)initLogger();else if(!_configApplied)applyConfigWhenReady()}return}const message=formatMessage(...args);if(suppressed){dispatch("debug",message,args);return}const logger=await getLogger();dispatch("debug",message,args);await logger.debug(message)},dump:async(...args)=>{const message=formatMessage(...args);await(await getLogger()).debug(`DUMP: ${message}`)},dd:async(...args)=>{const message=formatMessage(...args);await(await getLogger()).error(message);process.exit(EXIT_CODE_FATAL_ERROR)},echo:async(...args)=>{const message=formatMessage(...args);await(await getLogger()).info(`ECHO: ${message}`)},time:(label)=>{const start=performance.now();return async(metadata)=>{const duration=performance.now()-start,logger=await getLogger(),meta=metadata?` ${JSON.stringify(normalizeContext(metadata))}`:"";await logger.info(`${label}: ${duration.toFixed(2)}ms${meta}`)}},syncWarn:(msg)=>{process.stderr.write(`${msg}
|
|
8
|
+
`)},syncError:(msg)=>{process.stderr.write(`${msg}
|
|
9
|
+
`)},fatal:(msg,exitCode=EXIT_CODE_FATAL_ERROR)=>{process.stderr.write(`${msg}
|
|
10
|
+
`);process.exit(exitCode)},exit:async(msg,exitCode=EXIT_CODE_SUCCESS)=>{if(msg)await(exitCode===EXIT_CODE_SUCCESS?log.success(msg):log.error(msg));await log.flush();process.exit(exitCode)},flush:async()=>{if(pendingWrites.size>0)await Promise.allSettled([...pendingWrites]);await flushTransports();if(!_logger&&!_loggerInitPromise)return;try{const logger=await getLogger(),maybeFlush=logger.flush;if(typeof maybeFlush==="function")await maybeFlush.call(logger)}catch{}}};globalThis[Symbol.for("@stacksjs/logging:implementation-loaded")]=!0;export async function dump(...args){for(const arg of args)await log.debug(arg)}export async function dd(...args){const message=formatMessage(...args);console.log(message);process.exit(EXIT_CODE_FATAL_ERROR)}export async function echo(...args){await log.debug(...args)}function statusOf(error){if(error&&typeof error==="object"){const e=error;if(typeof e.status==="number")return e.status;if(typeof e.statusCode==="number")return e.statusCode}return}export function report(error,options={}){const status=options.status??statusOf(error),isClientError=typeof status==="number"&&status>=400&&status<500,message=options.label??"Unhandled error",context={...options.context,...status!=null?{status}:{}};if(isClientError){log.debug(`${message} (client error ${status}): ${normalizeError(error).message}`);return}log.error(message,error,context)}function emit(level,event,fields){const ctx=getLogContext(),payload={event,traceId:ctx?.requestId,...fields};if(level==="warn")track(log.warn(`[${event}]`,payload));else track(log[level](payload))}export const struct={request(method,path,status,durationMs,fields={}){const level=status>=500?"error":status>=400?"warn":"info";emit(level,"http.request",{method,path,status,durationMs,...fields})},query(sql,durationMs,fields={}){emit("debug","db.query",{sql,durationMs,...fields})},slowQuery(sql,durationMs,fields={}){emit("warn","db.slow_query",{sql,durationMs,...fields})},job(name,phase,fields={}){emit(phase==="failed"?"error":"info",`job.${phase}`,{jobName:name,...fields})},cache(op,key,fields={}){emit("debug",`cache.${op}`,{key,...fields})}};log.struct=struct;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Log, ReportOptions } from './index';
|
|
2
|
+
export declare function report(error: unknown, options?: ReportOptions): void;
|
|
3
|
+
/**
|
|
4
|
+
* Quiet server processes only need the logging facade when a record is
|
|
5
|
+
* emitted. Keep router imports small, then hand every real record to the
|
|
6
|
+
* complete logger so formatting, transports, context, and file output retain
|
|
7
|
+
* one implementation.
|
|
8
|
+
*/
|
|
9
|
+
export declare const log: RuntimeLog;
|
|
10
|
+
declare type RuntimeLog = Pick<Log, 'info' | 'warn' | 'error' | 'debug'>;
|
|
11
|
+
declare type LoggingModule = typeof import('./index');
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import process from"node:process";const CONFIG_READY_KEY=Symbol.for("@stacksjs/config:overridesReady"),IMPLEMENTATION_LOADED_KEY=Symbol.for("@stacksjs/logging:implementation-loaded"),SUPPRESSED_LEVELS=new Set(["info","success","warn","warning","error"]);let implementationLoad;function loadImplementation(){return implementationLoad??=import("./index")}function implementationIsLoaded(){return globalThis[IMPLEMENTATION_LOADED_KEY]===!0}function configurationNeedsDebug(configuration,envLevel){const logging=configuration?.logging;if(Array.isArray(logging?.transports)&&logging.transports.length>0)return!0;if(envLevel)return envLevel==="debug";const level=logging?.level?.toLowerCase();return level==="debug"||level!==void 0&&!SUPPRESSED_LEVELS.has(level)}function delegateDebug(args){if(implementationIsLoaded())return loadImplementation().then((module)=>module.log.debug(...args));const envLevel=process.env.LOG_LEVEL?.toLowerCase();if(envLevel&&!SUPPRESSED_LEVELS.has(envLevel))return loadImplementation().then((module)=>module.log.debug(...args));const ready=globalThis[CONFIG_READY_KEY];if(!ready||typeof ready.then!=="function")return Promise.resolve();const signal=ready,current=Bun.peek(signal);if(current!==signal)return configurationNeedsDebug(current,envLevel)?loadImplementation().then((module)=>module.log.debug(...args)):Promise.resolve();return signal.then((configuration)=>{if(configurationNeedsDebug(configuration,envLevel))return loadImplementation().then((module)=>module.log.debug(...args))})}export const log={info:(...args)=>loadImplementation().then((module)=>module.log.info(...args)),warn:(...args)=>loadImplementation().then((module)=>module.log.warn(...args)),error:(...args)=>loadImplementation().then((module)=>module.log.error(...args)),debug:(...args)=>delegateDebug(args)};export function report(error,options={}){loadImplementation().then((module)=>module.report(error,options))}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/logging",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.74.
|
|
5
|
+
"version": "0.74.47",
|
|
6
6
|
"description": "The Stacks logging system.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -33,6 +33,12 @@
|
|
|
33
33
|
"import": "./dist/index.js",
|
|
34
34
|
"default": "./dist/index.js"
|
|
35
35
|
},
|
|
36
|
+
"./runtime": {
|
|
37
|
+
"types": "./dist/runtime.d.ts",
|
|
38
|
+
"bun": "./dist/runtime.js",
|
|
39
|
+
"import": "./dist/runtime.js",
|
|
40
|
+
"default": "./dist/runtime.js"
|
|
41
|
+
},
|
|
36
42
|
"./*": {
|
|
37
43
|
"types": "./dist/*.d.ts",
|
|
38
44
|
"bun": "./dist/*.js",
|
|
@@ -60,15 +66,15 @@
|
|
|
60
66
|
"dependencies": {
|
|
61
67
|
"@loghq/stacks": "^0.2.3",
|
|
62
68
|
"@stacksjs/clarity": "^0.3.33",
|
|
63
|
-
"@stacksjs/config": "0.74.
|
|
64
|
-
"@stacksjs/error-handling": "0.74.
|
|
65
|
-
"@stacksjs/path": "0.74.
|
|
66
|
-
"@stacksjs/types": "0.74.
|
|
69
|
+
"@stacksjs/config": "0.74.47",
|
|
70
|
+
"@stacksjs/error-handling": "0.74.47",
|
|
71
|
+
"@stacksjs/path": "0.74.47",
|
|
72
|
+
"@stacksjs/types": "0.74.47"
|
|
67
73
|
},
|
|
68
74
|
"devDependencies": {
|
|
69
|
-
"@stacksjs/cli": "0.74.
|
|
70
|
-
"@stacksjs/storage": "0.74.
|
|
71
|
-
"@stacksjs/validation": "0.74.
|
|
75
|
+
"@stacksjs/cli": "0.74.47",
|
|
76
|
+
"@stacksjs/storage": "0.74.47",
|
|
77
|
+
"@stacksjs/validation": "0.74.47",
|
|
72
78
|
"better-dx": "^0.2.24"
|
|
73
79
|
}
|
|
74
80
|
}
|