@vielzeug/logit 2.1.0 → 3.0.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/README.md +26 -12
- package/dist/logit.cjs +1 -1
- package/dist/logit.cjs.map +1 -1
- package/dist/logit.d.ts +38 -45
- package/dist/logit.d.ts.map +1 -1
- package/dist/logit.js +176 -128
- package/dist/logit.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -25,16 +25,23 @@ pnpm add @vielzeug/logit
|
|
|
25
25
|
```ts
|
|
26
26
|
import { createLogger, Logit } from '@vielzeug/logit';
|
|
27
27
|
|
|
28
|
-
Logit.info(
|
|
28
|
+
Logit.info({ port: 3000 }, 'Server started');
|
|
29
29
|
Logit.warn('High memory usage');
|
|
30
|
+
Logit.error(new Error('connection lost')); // auto-serializes Error
|
|
31
|
+
Logit.fatal('unrecoverable state');
|
|
30
32
|
|
|
31
33
|
const api = Logit.scope('api');
|
|
32
|
-
api.info('GET /users');
|
|
34
|
+
api.info({ method: 'GET', path: '/users' }, 'incoming request');
|
|
35
|
+
|
|
36
|
+
// pin fields to every call in a request context
|
|
37
|
+
const reqLog = api.withBindings({ requestId: 'abc-123' });
|
|
38
|
+
reqLog.info('processing');
|
|
39
|
+
reqLog.warn('slow query');
|
|
33
40
|
|
|
34
41
|
const log = createLogger({ logLevel: 'warn', namespace: 'Worker' });
|
|
35
42
|
|
|
36
43
|
if (log.enabled('debug')) {
|
|
37
|
-
log.debug(
|
|
44
|
+
log.debug({ diagnostics: buildDiagnostics() }, 'diagnostics');
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
await log.time('sync-task', async () => {
|
|
@@ -44,21 +51,23 @@ await log.time('sync-task', async () => {
|
|
|
44
51
|
|
|
45
52
|
## Features
|
|
46
53
|
|
|
47
|
-
- Log levels: `debug`, `
|
|
54
|
+
- Log levels: `debug`, `info`, `warn`, `error`, `fatal`, `off`
|
|
55
|
+
- Structured call signature: `log.info('msg')`, `log.info({ key }, 'msg')`, `log.error(new Error())`
|
|
56
|
+
- Auto-serializes `Error` objects into `{ message, name, stack }` — survives `JSON.stringify`
|
|
57
|
+
- Pinned context bindings via `withBindings({ requestId })` — merged into every log call
|
|
48
58
|
- `enabled(level)` guard for expensive payload computation
|
|
49
59
|
- Scoped logger composition via `scope(name)`
|
|
50
60
|
- Independent logger cloning via `child(overrides?)`
|
|
51
61
|
- Browser badge variants: `symbol`, `icon`, `text`
|
|
52
|
-
- Callback wrappers: `time(label, fn)` and `
|
|
53
|
-
-
|
|
62
|
+
- Callback wrappers: `time(label, fn)`, `group(label, fn)`, and `groupCollapsed(label, fn)`
|
|
63
|
+
- Structured remote payload: `{ level, message, context, env, namespace?, timestamp? }`
|
|
54
64
|
- Remote log forwarding with independent threshold (`remote.logLevel`)
|
|
55
65
|
- Zero runtime dependencies
|
|
56
66
|
|
|
57
67
|
## Configuration
|
|
58
68
|
|
|
59
69
|
```ts
|
|
60
|
-
Logit.
|
|
61
|
-
environment: true,
|
|
70
|
+
const Log = Logit.child({
|
|
62
71
|
logLevel: 'warn',
|
|
63
72
|
namespace: 'App',
|
|
64
73
|
timestamp: true,
|
|
@@ -66,26 +75,31 @@ Logit.setConfig({
|
|
|
66
75
|
remote: {
|
|
67
76
|
logLevel: 'error',
|
|
68
77
|
handler: (type, data) => {
|
|
78
|
+
// data: { level, message, context, env, namespace?, timestamp? }
|
|
69
79
|
void fetch('/api/logs', {
|
|
70
|
-
body: JSON.stringify(
|
|
80
|
+
body: JSON.stringify(data),
|
|
71
81
|
method: 'POST',
|
|
72
82
|
});
|
|
73
83
|
},
|
|
74
84
|
},
|
|
75
85
|
});
|
|
76
86
|
|
|
77
|
-
const cfg =
|
|
87
|
+
const cfg = Log.config; // snapshot copy
|
|
78
88
|
```
|
|
79
89
|
|
|
80
90
|
## API At a Glance
|
|
81
91
|
|
|
82
92
|
- `createLogger(initial?) => Logger`
|
|
83
93
|
- `Logit` (default logger instance)
|
|
84
|
-
- `logger.setConfig(opts) => Logger`
|
|
85
94
|
- `logger.scope(name) => Logger`
|
|
86
95
|
- `logger.child(overrides?) => Logger`
|
|
96
|
+
- `logger.withBindings(bindings) => Logger`
|
|
97
|
+
- `logger.bindings` (readonly snapshot)
|
|
87
98
|
- `logger.time(label, fn)`
|
|
88
|
-
- `logger.group(label, fn
|
|
99
|
+
- `logger.group(label, fn)`
|
|
100
|
+
- `logger.groupCollapsed(label, fn)`
|
|
101
|
+
|
|
102
|
+
Structured context is always passed first: `logger.info({ userId: 42 }, 'signed in')`. String-first calls accept only a single message argument.
|
|
89
103
|
|
|
90
104
|
## Documentation
|
|
91
105
|
|
package/dist/logit.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={debug:0,error:
|
|
1
|
+
var e={debug:0,error:3,fatal:4,info:1,off:5,warn:2},t={debug:{bg:`#616161`,border:`#424242`,color:`#fff`,icon:`☕`,symbol:`🅳`},error:{bg:`#d32f2f`,border:`#c62828`,color:`#fff`,icon:`✘`,symbol:`🅴`},fatal:{bg:`#4a148c`,border:`#38006b`,color:`#fff`,icon:`💀`,symbol:`🅵`},group:{bg:`#546e7a`,border:`#455a64`,color:`#fff`,icon:`⚭`,symbol:`🅶`},info:{bg:`#1976d2`,border:`#1565c0`,color:`#fff`,icon:`ℹ`,symbol:`🅸`},ns:{bg:`#424242`,border:`#212121`,color:`#fff`},warn:{bg:`#ffb300`,border:`#ffa000`,color:`#fff`,icon:`⚠`,symbol:`🆆`}},n=`border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;`,r=typeof window>`u`,i=globalThis.process,a=r?i?.env?.NODE_ENV===`production`:!0,o={debug:`log`,error:`error`,fatal:`error`,info:`info`,warn:`warn`};function s(e){return{message:e.message,name:e.name,stack:e.stack}}function c(e){throw TypeError(`[logit] ${e}`)}function l(e,t){return e===void 0?{context:void 0,message:void 0}:e instanceof Error?(t!==void 0&&typeof t!=`string`&&c(`error override messages must be strings.`),{context:{err:s(e)},message:t??e.message}):typeof e==`string`?(t!==void 0&&c(`string-first log calls accept only one argument. Use log.info({ ... }, "message") for structured context.`),{context:void 0,message:e}):(t!==void 0&&typeof t!=`string`&&c(`context-first log calls require the optional second argument to be a string message.`),{context:e,message:t})}function u(e,n){let r=t[e];return n===`text`||!r[n]?e.toUpperCase():r[n]}function d(e,n,r=``){let{bg:i,border:a,color:o}=t[e],s=`border: 1px solid ${a}; border-radius: 4px`;switch(n){case`icon`:return`color: ${i}; ${s}; padding: 0 3px${r}`;case`symbol`:return`color: ${i}; ${s}; padding: 0 1px${r}`;default:return`background: ${i}; color: ${o}; ${s}; font-weight: bold; padding: 0 3px${r}`}}function f(e,t){if(!(!(Object.keys(e).length>0)&&!t))return{...e,...t}}function p(e,t){return e&&t!==void 0?[e,t]:e?[e]:t===void 0?[]:[t]}function m(e,t,n,r){let i=[u(e,r)];return t&&i.push(`[${t}]`),n&&i.push(n),`${i.join(` | `)} |`}function h(e,t,r,i){let a=`%c${u(e,i)}%c`,o=[d(e,i),``];return t&&(a+=` %c${t}%c`,o.push(d(`ns`,i,`; ${n}`),``)),r&&(a+=` %c${r}%c`,o.push(`color: gray`,``)),{fmt:a,parts:o}}function g(e,t){return e?`[${e}] ${t}`:t}function _(e,t){if(e===void 0)return t?{...t}:void 0;if(e===null)return;let n=e.handler??t?.handler;if(!n){if(e.logLevel!==void 0)throw Error(`[logit] remote.logLevel requires a remote.handler (or inherited handler via child())`);return}return{handler:n,logLevel:e.logLevel??t?.logLevel??`debug`}}function v(e){let t=e.namespace??``,n=e.logLevel??`debug`,r=_(e.remote),i=e.timestamp??!0,a=e.variant??`symbol`;return r?{logLevel:n,namespace:t,remote:r,timestamp:i,variant:a}:{logLevel:n,namespace:t,timestamp:i,variant:a}}function y(t={},i={}){let s=v(typeof t==`string`?{namespace:t}:t),c={...i},b=t=>e[s.logLevel]<=e[t],x=()=>new Date().toISOString().slice(11,23),S=(t,n,i)=>{if(!b(t))return;let{context:u,message:d}=l(n,i);if(u===void 0&&d===void 0)return;let g=s.namespace,_=s.timestamp?x():``,v=f(c,u),y=p(v,d),S=console[o[t]];if(r)S(m(t,g,_,s.variant),...y);else{let{fmt:e,parts:n}=h(t,g,_,s.variant);S(e,...n,...y)}if(!s.remote||e[s.remote.logLevel]>e[t])return;let C={context:v,env:a?`production`:`development`,level:t,message:d,namespace:g||void 0,timestamp:s.timestamp?new Date().toISOString():void 0};Promise.resolve().then(()=>s.remote.handler(t,C)).catch(e=>{console.warn(`[logit] remote handler error:`,e)})},C=(e,t)=>{let i=s.namespace,a=s.timestamp?x():``,o=e?console.groupCollapsed:console.group;if(r){let e=[u(`group`,s.variant),t];i&&e.push(`[${i}]`),a&&e.push(a),o(e.join(` | `));return}let c=`%c${t}%c`,l=[d(`group`,s.variant,`; margin-right: 6px; padding: 1px 3px 0`),``];i&&(c+=` %c${i}%c`,l.push(d(`ns`,s.variant,`; ${n}; margin-right: 6px`),``)),a&&(c+=` %c${a}%c`,l.push(`color: gray; font-weight: lighter; margin-right: 6px`,``)),o(c,...l)},w=(e,t,n)=>{if(s.logLevel===`off`)return n();C(e,t);try{let e=n();return e instanceof Promise?e.finally(()=>console.groupEnd()):(console.groupEnd(),e)}catch(e){throw console.groupEnd(),e}},T={get bindings(){return{...c}},child:(e={})=>{let t=_(e.remote,s.remote);return y({logLevel:e.logLevel??s.logLevel,namespace:e.namespace??s.namespace,remote:t,timestamp:e.timestamp??s.timestamp,variant:e.variant??s.variant},c)},get config(){return s.remote?{...s,remote:{...s.remote}}:{...s}},debug:(e,t)=>S(`debug`,e,t),enabled:e=>b(e),error:(e,t)=>S(`error`,e,t),fatal:(e,t)=>S(`fatal`,e,t),group:(e,t)=>w(!1,e,t),groupCollapsed:(e,t)=>w(!0,e,t),info:(e,t)=>S(`info`,e,t),scope:e=>T.child({namespace:s.namespace?`${s.namespace}.${e}`:e}),time:(e,t)=>{if(s.logLevel===`off`)return t();let n=g(s.namespace,e);console.time(n);try{let e=t();return e instanceof Promise?e.finally(()=>console.timeEnd(n)):(console.timeEnd(n),e)}catch(e){throw console.timeEnd(n),e}},warn:(e,t)=>S(`warn`,e,t),withBindings:e=>y(s,{...c,...e})};return T}var b=y();exports.Logit=b,exports.createLogger=y;
|
|
2
2
|
//# sourceMappingURL=logit.cjs.map
|
package/dist/logit.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.cjs","names":[],"sources":["../src/logit.ts"],"sourcesContent":["/* -------------------- Types -------------------- */\n\nexport type LogType = 'debug' | 'trace' | 'info' | 'success' | 'warn' | 'error';\nexport type LogLevel = LogType | 'off';\nexport type Variant = 'text' | 'symbol' | 'icon';\n\nexport type RemoteHandler = (type: LogType, data: RemoteLogData) => void;\n\nexport type RemoteOptions = { handler?: RemoteHandler; logLevel?: LogLevel };\n\nexport type RemoteLogData = {\n args: unknown[];\n env: 'production' | 'development';\n namespace?: string;\n timestamp?: string;\n};\n\nexport type LogitOptions = {\n environment?: boolean;\n logLevel?: LogLevel;\n namespace?: string;\n remote?: RemoteOptions;\n timestamp?: boolean;\n variant?: Variant;\n};\n\n/** The shape of a fully resolved logger config (all fields present). */\ntype ResolvedRemote = { handler?: RemoteHandler; logLevel: LogLevel };\nexport type LogitConfig = Omit<Required<LogitOptions>, 'remote'> & { remote: ResolvedRemote };\n\nexport type Logger = {\n assert: (condition: boolean, ...args: unknown[]) => void;\n child: (overrides?: LogitOptions) => Logger;\n readonly config: Readonly<LogitConfig>;\n debug: (...args: unknown[]) => void;\n enabled: (type: LogLevel) => boolean;\n error: (...args: unknown[]) => void;\n group: <T>(label: string, fn: () => T, collapsed?: boolean) => T;\n info: (...args: unknown[]) => void;\n scope: (name: string) => Logger;\n setConfig: (opts: LogitOptions) => Logger;\n success: (...args: unknown[]) => void;\n table: (data: unknown, properties?: string[]) => void;\n time: <T>(label: string, fn: () => T) => T;\n trace: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n};\n\n/* -------------------- Priority -------------------- */\n\nconst PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 5,\n info: 2,\n off: 6,\n success: 3,\n trace: 1,\n warn: 4,\n};\n\n/* -------------------- Theme -------------------- */\n\ntype Theme = { bg: string; border: string; color: string; icon?: string; symbol?: string };\n\nconst isDarkMode = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\nconst THEME: Record<LogType | 'group' | 'ns', Theme> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '☕', symbol: '🅳' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '✘', symbol: '🅴' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '⚭', symbol: '🅶' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: 'ℹ', symbol: '🅸' },\n ns: isDarkMode\n ? { bg: '#fafafa', border: '#c7c7c7', color: '#000' }\n : { bg: '#424242', border: '#212121', color: '#fff' },\n success: { bg: '#689f38', border: '#558b2f', color: '#fff', icon: '✔', symbol: '🆂' },\n trace: { bg: '#d81b60', border: '#c2185b', color: '#fff', icon: '⛢', symbol: '🆃' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '⚠', symbol: '🆆' },\n};\n\nconst NS_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;';\n\n/* -------------------- createLogger -------------------- */\n\nconst IS_NODE = typeof window === 'undefined';\nconst IS_PROD = IS_NODE\n ? // @ts-expect-error - process is Node-only\n (process as any).env?.NODE_ENV === 'production'\n : (import.meta as any)?.env?.NODE_ENV === 'production';\n\nconst ENV_BADGE = IS_PROD ? '🅿' : '🅳';\n\nconst LOG_METHOD: Record<LogType, 'log' | 'info' | 'warn' | 'error' | 'trace'> = {\n debug: 'log',\n error: 'error',\n info: 'info',\n success: 'log',\n trace: 'trace',\n warn: 'warn',\n};\n\n/**\n * Creates an independent logger instance with its own isolated configuration.\n *\n * @example\n * ```ts\n * const log = createLogger({ logLevel: 'info', namespace: 'App' });\n * log.info('Hello');\n *\n * const apiLog = log.scope('api');\n * apiLog.warn('slow request');\n * ```\n */\nexport function createLogger(initial: LogitOptions | string = {}): Logger {\n const opts: LogitOptions = typeof initial === 'string' ? { namespace: initial } : initial;\n const cfg: LogitConfig = {\n environment: true,\n logLevel: 'debug',\n namespace: '',\n timestamp: true,\n variant: 'symbol',\n ...opts,\n remote: { logLevel: 'debug', ...opts.remote }, // 'debug' default means a handler just works; set 'off' explicitly to disable\n };\n\n /* ---- helpers ---- */\n\n const passes = (type: LogLevel): boolean => PRIORITY[cfg.logLevel] <= PRIORITY[type];\n\n const ts = (): string => new Date().toISOString().slice(11, 23);\n\n const badge = (type: LogType | 'group'): string => {\n const theme = THEME[type];\n\n if (cfg.variant === 'text' || !theme[cfg.variant]) return type.toUpperCase();\n\n return theme[cfg.variant]!;\n };\n\n const style = (type: LogType | 'group' | 'ns', extra = ''): string => {\n const { bg, border, color } = THEME[type];\n const base = `border: 1px solid ${border}; border-radius: 4px`;\n\n switch (cfg.variant) {\n case 'icon':\n return `color: ${bg}; ${base}; padding: 0 3px${extra}`;\n case 'symbol':\n return `color: ${bg}; ${base}; padding: 0 1px${extra}`;\n default:\n return `background: ${bg}; color: ${color}; ${base}; font-weight: bold; padding: 0 3px${extra}`;\n }\n };\n\n const emitNode = (type: LogType, ns: string, stamp: string, args: unknown[]): void => {\n const meta = [badge(type)];\n\n if (cfg.environment) meta.push(ENV_BADGE);\n\n if (ns) meta.push(`[${ns}]`);\n\n if (stamp) meta.push(stamp);\n\n const method = console[LOG_METHOD[type]] as (...a: unknown[]) => void;\n\n method(`${meta.join(' | ')} |`, ...args);\n };\n\n const emitBrowser = (type: LogType, ns: string, stamp: string, args: unknown[]): void => {\n let fmt = `%c${badge(type)}%c`;\n const parts: string[] = [style(type), ''];\n\n if (ns) {\n fmt += ` %c${ns}%c`;\n parts.push(style('ns', `; ${NS_STYLE}`), '');\n }\n\n if (cfg.environment) {\n fmt += ` %c${ENV_BADGE}%c`;\n parts.push('color: darkgray', '');\n }\n\n if (stamp) {\n fmt += ` %c${stamp}%c`;\n parts.push('color: gray', '');\n }\n\n const method = console[LOG_METHOD[type]] as (...a: unknown[]) => void;\n\n method(fmt, ...parts, ...args);\n };\n\n const emit = (type: LogType, args: unknown[]): void => {\n if (!passes(type)) return;\n\n const ns = cfg.namespace;\n const stamp = cfg.timestamp ? ts() : '';\n\n if (IS_NODE) emitNode(type, ns, stamp, args);\n else emitBrowser(type, ns, stamp, args);\n\n /* remote dispatch — snapshot data now, dispatch in microtask to avoid blocking caller */\n const { handler, logLevel } = cfg.remote;\n\n if (handler && PRIORITY[logLevel] <= PRIORITY[type]) {\n const data: RemoteLogData = {\n args,\n env: IS_PROD ? 'production' : 'development',\n namespace: ns || undefined,\n timestamp: cfg.timestamp ? new Date().toISOString() : undefined,\n };\n\n Promise.resolve()\n .then(() => handler(type, data))\n .catch(() => {});\n }\n };\n\n const timeLabel = (label: string): string => (cfg.namespace ? `[${cfg.namespace}] ${label}` : label);\n\n /* ---- child factory ---- */\n const makeChild = (overrides: LogitOptions = {}): Logger => {\n const { remote: overrideRemote, ...overrideRest } = overrides;\n\n return createLogger({ ...cfg, ...overrideRest, remote: { ...cfg.remote, ...overrideRemote } });\n };\n\n /* ---- group renderer ---- */\n\n const renderGroupNode = (collapsed: boolean, label: string, ns: string, stamp: string): void => {\n const fn = collapsed ? console.groupCollapsed : console.group;\n const meta = [badge('group')];\n\n if (cfg.environment) meta.push(ENV_BADGE);\n\n meta.push(label);\n\n if (ns) meta.push(`[${ns}]`);\n\n if (stamp) meta.push(stamp);\n\n fn(meta.join(' | '));\n };\n\n const renderGroupBrowser = (collapsed: boolean, label: string, ns: string, stamp: string): void => {\n const fn = collapsed ? console.groupCollapsed : console.group;\n let fmt = `%c${label}%c`;\n const parts: string[] = [style('group', '; margin-right: 6px; padding: 1px 3px 0'), ''];\n\n if (ns) {\n fmt += ` %c${ns}%c`;\n parts.push(style('ns', `; ${NS_STYLE}; margin-right: 6px`), '');\n }\n\n if (cfg.environment) {\n fmt += ` %c${ENV_BADGE}%c`;\n parts.push('color: darkgray; margin-right: 6px', '');\n }\n\n if (stamp) {\n fmt += ` %c${stamp}%c`;\n parts.push('color: gray; font-weight: lighter; margin-right: 6px', '');\n }\n\n fn(fmt, ...parts);\n };\n\n const renderGroup = (collapsed: boolean, label: string): void => {\n const ns = cfg.namespace;\n const stamp = cfg.timestamp ? ts() : '';\n\n if (IS_NODE) renderGroupNode(collapsed, label, ns, stamp);\n else renderGroupBrowser(collapsed, label, ns, stamp);\n };\n\n /* ---- public API ---- */\n\n const logger: Logger = {\n assert: (condition: boolean, ...args: unknown[]): void => {\n if (passes('error')) console.assert(condition, ...args);\n },\n\n child: makeChild,\n\n get config(): Readonly<LogitConfig> {\n return { ...cfg, remote: { ...cfg.remote } };\n },\n\n debug: (...a) => emit('debug', a),\n\n enabled: (type: LogLevel): boolean => passes(type),\n error: (...a) => emit('error', a),\n\n group: <T>(label: string, fn: () => T, collapsed = false): T => {\n if (!passes('debug')) return fn();\n\n renderGroup(collapsed, label);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) {\n return result.finally(() => console.groupEnd()) as T;\n }\n\n console.groupEnd();\n\n return result;\n } catch (e) {\n console.groupEnd();\n throw e;\n }\n },\n\n info: (...a) => emit('info', a),\n\n scope: (name: string): Logger => makeChild({ namespace: cfg.namespace ? `${cfg.namespace}.${name}` : name }),\n\n setConfig: (opts: LogitOptions): Logger => {\n const { remote, ...rest } = opts;\n\n if (remote !== undefined) Object.assign(cfg.remote, remote);\n\n Object.assign(cfg, rest);\n\n return logger;\n },\n success: (...a) => emit('success', a),\n\n table: (data: unknown, properties?: string[]): void => {\n if (passes('debug')) console.table(data, properties);\n },\n\n time: <T>(label: string, fn: () => T): T => {\n if (!passes('debug')) return fn();\n\n const tl = timeLabel(label);\n\n console.time(tl);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) {\n return result.finally(() => console.timeEnd(tl)) as T;\n }\n\n console.timeEnd(tl);\n\n return result;\n } catch (e) {\n console.timeEnd(tl);\n throw e;\n }\n },\n\n trace: (...a) => emit('trace', a),\n warn: (...a) => emit('warn', a),\n };\n\n return logger;\n}\n\n/* -------------------- Default instance -------------------- */\n\n/**\n * Shared default logger instance. For isolated configurations use `createLogger()`.\n *\n * @example\n * ```ts\n * import { Logit } from '@vielzeug/logit';\n * Logit.info('Hello');\n * ```\n */\nexport const Logit = createLogger();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logit.cjs","names":[],"sources":["../src/logit.ts"],"sourcesContent":["/* -------------------- Types -------------------- */\n\nexport type LogType = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\nexport type LogLevel = LogType | 'off';\nexport type Variant = 'text' | 'symbol' | 'icon';\nexport type Bindings = Record<string, unknown>;\n\nexport type SerializedError = {\n message: string;\n name: string;\n stack?: string;\n};\n\nexport type RemoteLogData = {\n context?: Bindings;\n env: 'production' | 'development';\n level: LogType;\n message?: string;\n namespace?: string;\n timestamp?: string;\n};\n\nexport type RemoteHandler = (type: LogType, data: RemoteLogData) => void;\n\nexport type RemoteOptions = {\n handler?: RemoteHandler;\n logLevel?: LogLevel;\n};\n\nexport type LogitOptions = {\n logLevel?: LogLevel;\n namespace?: string;\n remote?: RemoteOptions | null;\n timestamp?: boolean;\n variant?: Variant;\n};\n\nexport type LogitConfig = {\n logLevel: LogLevel;\n namespace: string;\n remote?: {\n handler: RemoteHandler;\n logLevel: LogLevel;\n };\n timestamp: boolean;\n variant: Variant;\n};\n\ntype LogMethod = {\n (): void;\n (message: string): void;\n (context: Bindings, message?: string): void;\n (error: Error, message?: string): void;\n};\n\nexport type Logger = {\n readonly bindings: Readonly<Bindings>;\n child: (overrides?: LogitOptions) => Logger;\n readonly config: Readonly<LogitConfig>;\n debug: LogMethod;\n enabled: (type: LogLevel) => boolean;\n error: LogMethod;\n fatal: LogMethod;\n group: <T>(label: string, fn: () => T) => T;\n groupCollapsed: <T>(label: string, fn: () => T) => T;\n info: LogMethod;\n scope: (name: string) => Logger;\n time: <T>(label: string, fn: () => T) => T;\n warn: LogMethod;\n withBindings: (bindings: Bindings) => Logger;\n};\n\n/* -------------------- Constants -------------------- */\n\nconst PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 3,\n fatal: 4,\n info: 1,\n off: 5,\n warn: 2,\n};\n\ntype Theme = { bg: string; border: string; color: string; icon?: string; symbol?: string };\n\nconst THEME: Record<LogType | 'group' | 'ns', Theme> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '☕', symbol: '🅳' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '✘', symbol: '🅴' },\n fatal: { bg: '#4a148c', border: '#38006b', color: '#fff', icon: '💀', symbol: '🅵' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '⚭', symbol: '🅶' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: 'ℹ', symbol: '🅸' },\n ns: { bg: '#424242', border: '#212121', color: '#fff' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '⚠', symbol: '🆆' },\n};\n\nconst NS_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;';\n\nconst IS_NODE = typeof window === 'undefined';\nconst NODE_PROCESS = (globalThis as typeof globalThis & { process?: { env?: { NODE_ENV?: string } } }).process;\nconst IS_PROD = IS_NODE ? NODE_PROCESS?.env?.NODE_ENV === 'production' : (import.meta as ImportMeta).env.PROD;\n\nconst LOG_METHOD: Record<LogType, 'log' | 'info' | 'warn' | 'error'> = {\n debug: 'log',\n error: 'error',\n fatal: 'error',\n info: 'info',\n warn: 'warn',\n};\n\n/* -------------------- Pure Helpers -------------------- */\n\nfunction serializeError(err: Error): SerializedError {\n return { message: err.message, name: err.name, stack: err.stack };\n}\n\nfunction failInvalidArgs(message: string): never {\n throw new TypeError(`[logit] ${message}`);\n}\n\nfunction parseArgs(\n msgOrCtx: string | Bindings | Error | undefined,\n msg: unknown,\n): { context: Bindings | undefined; message: string | undefined } {\n if (msgOrCtx === undefined) return { context: undefined, message: undefined };\n\n if (msgOrCtx instanceof Error) {\n if (msg !== undefined && typeof msg !== 'string') {\n failInvalidArgs('error override messages must be strings.');\n }\n\n return {\n context: { err: serializeError(msgOrCtx) },\n message: (msg as string | undefined) ?? msgOrCtx.message,\n };\n }\n\n if (typeof msgOrCtx === 'string') {\n if (msg !== undefined) {\n failInvalidArgs(\n 'string-first log calls accept only one argument. Use log.info({ ... }, \"message\") for structured context.',\n );\n }\n\n return { context: undefined, message: msgOrCtx };\n }\n\n if (msg !== undefined && typeof msg !== 'string') {\n failInvalidArgs('context-first log calls require the optional second argument to be a string message.');\n }\n\n return { context: msgOrCtx as Bindings, message: msg as string | undefined };\n}\n\nfunction badge(type: LogType | 'group', variant: Variant): string {\n const theme = THEME[type];\n\n if (variant === 'text' || !theme[variant]) return type.toUpperCase();\n\n return theme[variant]!;\n}\n\nfunction style(type: LogType | 'group' | 'ns', variant: Variant, extra = ''): string {\n const { bg, border, color } = THEME[type];\n const base = `border: 1px solid ${border}; border-radius: 4px`;\n\n switch (variant) {\n case 'icon':\n return `color: ${bg}; ${base}; padding: 0 3px${extra}`;\n case 'symbol':\n return `color: ${bg}; ${base}; padding: 0 1px${extra}`;\n default:\n return `background: ${bg}; color: ${color}; ${base}; font-weight: bold; padding: 0 3px${extra}`;\n }\n}\n\nfunction mergeContext(base: Bindings, callCtx: Bindings | undefined): Bindings | undefined {\n const hasBase = Object.keys(base).length > 0;\n\n if (!hasBase && !callCtx) return undefined;\n\n return { ...base, ...callCtx };\n}\n\nfunction buildPayload(mergedContext: Bindings | undefined, message: string | undefined): unknown[] {\n if (mergedContext && message !== undefined) return [mergedContext, message];\n\n if (mergedContext) return [mergedContext];\n\n if (message !== undefined) return [message];\n\n return [];\n}\n\nfunction buildNodePrefix(type: LogType, namespace: string, timestamp: string, variant: Variant): string {\n const meta = [badge(type, variant)];\n\n if (namespace) meta.push(`[${namespace}]`);\n\n if (timestamp) meta.push(timestamp);\n\n return `${meta.join(' | ')} |`;\n}\n\nfunction buildBrowserPrefix(\n type: LogType,\n namespace: string,\n timestamp: string,\n variant: Variant,\n): { fmt: string; parts: string[] } {\n let fmt = `%c${badge(type, variant)}%c`;\n const parts: string[] = [style(type, variant), ''];\n\n if (namespace) {\n fmt += ` %c${namespace}%c`;\n parts.push(style('ns', variant, `; ${NS_STYLE}`), '');\n }\n\n if (timestamp) {\n fmt += ` %c${timestamp}%c`;\n parts.push('color: gray', '');\n }\n\n return { fmt, parts };\n}\n\nfunction toTimeLabel(namespace: string, label: string): string {\n return namespace ? `[${namespace}] ${label}` : label;\n}\n\nfunction resolveRemote(\n remote: LogitOptions['remote'],\n inherited?: LogitConfig['remote'],\n): LogitConfig['remote'] | undefined {\n if (remote === undefined) return inherited ? { ...inherited } : undefined;\n\n if (remote === null) return undefined;\n\n const handler = remote.handler ?? inherited?.handler;\n\n if (!handler) {\n if (remote.logLevel !== undefined) {\n throw new Error('[logit] remote.logLevel requires a remote.handler (or inherited handler via child())');\n }\n\n return undefined;\n }\n\n return {\n handler,\n logLevel: remote.logLevel ?? inherited?.logLevel ?? 'debug',\n };\n}\n\nfunction resolveConfig(opts: LogitOptions): LogitConfig {\n const namespace = opts.namespace ?? '';\n const logLevel = opts.logLevel ?? 'debug';\n const remote = resolveRemote(opts.remote);\n const timestamp = opts.timestamp ?? true;\n const variant = opts.variant ?? 'symbol';\n\n return remote ? { logLevel, namespace, remote, timestamp, variant } : { logLevel, namespace, timestamp, variant };\n}\n\n/* -------------------- createLogger -------------------- */\n\nexport function createLogger(initial: LogitOptions | string = {}, initialBindings: Bindings = {}): Logger {\n const initialOpts: LogitOptions = typeof initial === 'string' ? { namespace: initial } : initial;\n const cfg = resolveConfig(initialOpts);\n const ownBindings: Bindings = { ...initialBindings };\n\n const passes = (type: LogLevel): boolean => PRIORITY[cfg.logLevel] <= PRIORITY[type];\n\n const ts = (): string => new Date().toISOString().slice(11, 23);\n\n const emit = (type: LogType, msgOrCtx?: string | Bindings | Error, msg?: unknown): void => {\n if (!passes(type)) return;\n\n const { context, message } = parseArgs(msgOrCtx, msg);\n\n if (context === undefined && message === undefined) return;\n\n const namespace = cfg.namespace;\n const timestamp = cfg.timestamp ? ts() : '';\n const mergedContext = mergeContext(ownBindings, context);\n const payload = buildPayload(mergedContext, message);\n const method = console[LOG_METHOD[type]] as (...a: unknown[]) => void;\n\n if (IS_NODE) {\n method(buildNodePrefix(type, namespace, timestamp, cfg.variant), ...payload);\n } else {\n const { fmt, parts } = buildBrowserPrefix(type, namespace, timestamp, cfg.variant);\n\n method(fmt, ...parts, ...payload);\n }\n\n if (!cfg.remote) return;\n\n if (PRIORITY[cfg.remote.logLevel] > PRIORITY[type]) return;\n\n const data: RemoteLogData = {\n context: mergedContext,\n env: IS_PROD ? 'production' : 'development',\n level: type,\n message,\n namespace: namespace || undefined,\n timestamp: cfg.timestamp ? new Date().toISOString() : undefined,\n };\n\n Promise.resolve()\n .then(() => cfg.remote!.handler(type, data))\n .catch((err: unknown) => {\n console.warn('[logit] remote handler error:', err);\n });\n };\n\n const renderGroup = (collapsed: boolean, label: string): void => {\n const namespace = cfg.namespace;\n const timestamp = cfg.timestamp ? ts() : '';\n const fn = collapsed ? console.groupCollapsed : console.group;\n\n if (IS_NODE) {\n const meta = [badge('group', cfg.variant), label];\n\n if (namespace) meta.push(`[${namespace}]`);\n\n if (timestamp) meta.push(timestamp);\n\n fn(meta.join(' | '));\n\n return;\n }\n\n let fmt = `%c${label}%c`;\n const parts: string[] = [style('group', cfg.variant, '; margin-right: 6px; padding: 1px 3px 0'), ''];\n\n if (namespace) {\n fmt += ` %c${namespace}%c`;\n parts.push(style('ns', cfg.variant, `; ${NS_STYLE}; margin-right: 6px`), '');\n }\n\n if (timestamp) {\n fmt += ` %c${timestamp}%c`;\n parts.push('color: gray; font-weight: lighter; margin-right: 6px', '');\n }\n\n fn(fmt, ...parts);\n };\n\n const wrapGroup = <T>(collapsed: boolean, label: string, fn: () => T): T => {\n if (cfg.logLevel === 'off') return fn();\n\n renderGroup(collapsed, label);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) return result.finally(() => console.groupEnd()) as T;\n\n console.groupEnd();\n\n return result;\n } catch (err) {\n console.groupEnd();\n throw err;\n }\n };\n\n const logger: Logger = {\n get bindings(): Readonly<Bindings> {\n return { ...ownBindings };\n },\n\n child: (overrides: LogitOptions = {}): Logger => {\n const remote = resolveRemote(overrides.remote, cfg.remote);\n\n return createLogger(\n {\n logLevel: overrides.logLevel ?? cfg.logLevel,\n namespace: overrides.namespace ?? cfg.namespace,\n remote,\n timestamp: overrides.timestamp ?? cfg.timestamp,\n variant: overrides.variant ?? cfg.variant,\n },\n ownBindings,\n );\n },\n\n get config(): Readonly<LogitConfig> {\n return cfg.remote ? { ...cfg, remote: { ...cfg.remote } } : { ...cfg };\n },\n\n debug: (m?: string | Bindings | Error, s?: string) => emit('debug', m, s),\n\n enabled: (type: LogLevel): boolean => passes(type),\n\n error: (m?: string | Bindings | Error, s?: string) => emit('error', m, s),\n\n fatal: (m?: string | Bindings | Error, s?: string) => emit('fatal', m, s),\n\n group: (label, fn) => wrapGroup(false, label, fn),\n\n groupCollapsed: (label, fn) => wrapGroup(true, label, fn),\n\n info: (m?: string | Bindings | Error, s?: string) => emit('info', m, s),\n\n scope: (name: string): Logger => logger.child({ namespace: cfg.namespace ? `${cfg.namespace}.${name}` : name }),\n\n time: <T>(label: string, fn: () => T): T => {\n if (cfg.logLevel === 'off') return fn();\n\n const tl = toTimeLabel(cfg.namespace, label);\n\n console.time(tl);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) return result.finally(() => console.timeEnd(tl)) as T;\n\n console.timeEnd(tl);\n\n return result;\n } catch (err) {\n console.timeEnd(tl);\n throw err;\n }\n },\n\n warn: (m?: string | Bindings | Error, s?: string) => emit('warn', m, s),\n\n withBindings: (bindings: Bindings): Logger => createLogger(cfg, { ...ownBindings, ...bindings }),\n };\n\n return logger;\n}\n\nexport const Logit = createLogger();\n"],"mappings":"AA0EA,IAAM,EAAqC,CACzC,MAAO,EACP,MAAO,EACP,MAAO,EACP,KAAM,EACN,IAAK,EACL,KAAM,CACR,EAIM,EAAiD,CACrD,MAAO,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,OAAQ,KAAM,IAAK,OAAQ,IAAK,EAClF,MAAO,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,OAAQ,KAAM,IAAK,OAAQ,IAAK,EAClF,MAAO,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,OAAQ,KAAM,KAAM,OAAQ,IAAK,EACnF,MAAO,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,OAAQ,KAAM,IAAK,OAAQ,IAAK,EAClF,KAAM,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,OAAQ,KAAM,IAAK,OAAQ,IAAK,EACjF,GAAI,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,MAAO,EACtD,KAAM,CAAE,GAAI,UAAW,OAAQ,UAAW,MAAO,OAAQ,KAAM,IAAK,OAAQ,IAAK,CACnF,EAEM,EAAW,+FAEX,EAAU,OAAO,OAAW,IAC5B,EAAgB,WAAiF,QACjG,EAAU,EAAU,GAAc,KAAK,WAAa,aAAA,GAEpD,EAAiE,CACrE,MAAO,MACP,MAAO,QACP,MAAO,QACP,KAAM,OACN,KAAM,MACR,EAIA,SAAS,EAAe,EAA6B,CACnD,MAAO,CAAE,QAAS,EAAI,QAAS,KAAM,EAAI,KAAM,MAAO,EAAI,KAAM,CAClE,CAEA,SAAS,EAAgB,EAAwB,CAC/C,MAAU,UAAU,WAAW,GAAS,CAC1C,CAEA,SAAS,EACP,EACA,EACgE,CA4BhE,OA3BI,IAAa,IAAA,GAAkB,CAAE,QAAS,IAAA,GAAW,QAAS,IAAA,EAAU,EAExE,aAAoB,OAClB,IAAQ,IAAA,IAAa,OAAO,GAAQ,UACtC,EAAgB,0CAA0C,EAGrD,CACL,QAAS,CAAE,IAAK,EAAe,CAAQ,CAAE,EACzC,QAAU,GAA8B,EAAS,OACnD,GAGE,OAAO,GAAa,UAClB,IAAQ,IAAA,IACV,EACE,2GACF,EAGK,CAAE,QAAS,IAAA,GAAW,QAAS,CAAS,IAG7C,IAAQ,IAAA,IAAa,OAAO,GAAQ,UACtC,EAAgB,sFAAsF,EAGjG,CAAE,QAAS,EAAsB,QAAS,CAA0B,EAC7E,CAEA,SAAS,EAAM,EAAyB,EAA0B,CAChE,IAAM,EAAQ,EAAM,GAIpB,OAFI,IAAY,QAAU,CAAC,EAAM,GAAiB,EAAK,YAAY,EAE5D,EAAM,EACf,CAEA,SAAS,EAAM,EAAgC,EAAkB,EAAQ,GAAY,CACnF,GAAM,CAAE,KAAI,SAAQ,SAAU,EAAM,GAC9B,EAAO,qBAAqB,EAAO,sBAEzC,OAAQ,EAAR,CACE,IAAK,OACH,MAAO,UAAU,EAAG,IAAI,EAAK,kBAAkB,IACjD,IAAK,SACH,MAAO,UAAU,EAAG,IAAI,EAAK,kBAAkB,IACjD,QACE,MAAO,eAAe,EAAG,WAAW,EAAM,IAAI,EAAK,qCAAqC,GAC5F,CACF,CAEA,SAAS,EAAa,EAAgB,EAAqD,CAGrF,OAFY,OAAO,KAAK,CAAI,EAAE,OAAS,IAE3B,CAAC,GAEjB,MAAO,CAAE,GAAG,EAAM,GAAG,CAAQ,CAC/B,CAEA,SAAS,EAAa,EAAqC,EAAwC,CAOjG,OANI,GAAiB,IAAY,IAAA,GAAkB,CAAC,EAAe,CAAO,EAEtE,EAAsB,CAAC,CAAa,EAEpC,IAAY,IAAA,GAET,CAAC,EAF0B,CAAC,CAAO,CAG5C,CAEA,SAAS,EAAgB,EAAe,EAAmB,EAAmB,EAA0B,CACtG,IAAM,EAAO,CAAC,EAAM,EAAM,CAAO,CAAC,EAMlC,OAJI,GAAW,EAAK,KAAK,IAAI,EAAU,EAAE,EAErC,GAAW,EAAK,KAAK,CAAS,EAE3B,GAAG,EAAK,KAAK,KAAK,EAAE,GAC7B,CAEA,SAAS,EACP,EACA,EACA,EACA,EACkC,CAClC,IAAI,EAAM,KAAK,EAAM,EAAM,CAAO,EAAE,IAC9B,EAAkB,CAAC,EAAM,EAAM,CAAO,EAAG,EAAE,EAYjD,OAVI,IACF,GAAO,MAAM,EAAU,IACvB,EAAM,KAAK,EAAM,KAAM,EAAS,KAAK,GAAU,EAAG,EAAE,GAGlD,IACF,GAAO,MAAM,EAAU,IACvB,EAAM,KAAK,cAAe,EAAE,GAGvB,CAAE,MAAK,OAAM,CACtB,CAEA,SAAS,EAAY,EAAmB,EAAuB,CAC7D,OAAO,EAAY,IAAI,EAAU,IAAI,IAAU,CACjD,CAEA,SAAS,EACP,EACA,EACmC,CACnC,GAAI,IAAW,IAAA,GAAW,OAAO,EAAY,CAAE,GAAG,CAAU,EAAI,IAAA,GAEhE,GAAI,IAAW,KAAM,OAErB,IAAM,EAAU,EAAO,SAAW,GAAW,QAE7C,GAAI,CAAC,EAAS,CACZ,GAAI,EAAO,WAAa,IAAA,GACtB,MAAU,MAAM,sFAAsF,EAGxG,MACF,CAEA,MAAO,CACL,UACA,SAAU,EAAO,UAAY,GAAW,UAAY,OACtD,CACF,CAEA,SAAS,EAAc,EAAiC,CACtD,IAAM,EAAY,EAAK,WAAa,GAC9B,EAAW,EAAK,UAAY,QAC5B,EAAS,EAAc,EAAK,MAAM,EAClC,EAAY,EAAK,WAAa,GAC9B,EAAU,EAAK,SAAW,SAEhC,OAAO,EAAS,CAAE,WAAU,YAAW,SAAQ,YAAW,SAAQ,EAAI,CAAE,WAAU,YAAW,YAAW,SAAQ,CAClH,CAIA,SAAgB,EAAa,EAAiC,CAAC,EAAG,EAA4B,CAAC,EAAW,CAExG,IAAM,EAAM,EADsB,OAAO,GAAY,SAAW,CAAE,UAAW,CAAQ,EAAI,CACpD,EAC/B,EAAwB,CAAE,GAAG,CAAgB,EAE7C,EAAU,GAA4B,EAAS,EAAI,WAAa,EAAS,GAEzE,MAAmB,IAAI,KAAK,EAAE,YAAY,EAAE,MAAM,GAAI,EAAE,EAExD,GAAQ,EAAe,EAAsC,IAAwB,CACzF,GAAI,CAAC,EAAO,CAAI,EAAG,OAEnB,GAAM,CAAE,UAAS,WAAY,EAAU,EAAU,CAAG,EAEpD,GAAI,IAAY,IAAA,IAAa,IAAY,IAAA,GAAW,OAEpD,IAAM,EAAY,EAAI,UAChB,EAAY,EAAI,UAAY,EAAG,EAAI,GACnC,EAAgB,EAAa,EAAa,CAAO,EACjD,EAAU,EAAa,EAAe,CAAO,EAC7C,EAAS,QAAQ,EAAW,IAElC,GAAI,EACF,EAAO,EAAgB,EAAM,EAAW,EAAW,EAAI,OAAO,EAAG,GAAG,CAAO,MACtE,CACL,GAAM,CAAE,MAAK,SAAU,EAAmB,EAAM,EAAW,EAAW,EAAI,OAAO,EAEjF,EAAO,EAAK,GAAG,EAAO,GAAG,CAAO,CAClC,CAIA,GAFI,CAAC,EAAI,QAEL,EAAS,EAAI,OAAO,UAAY,EAAS,GAAO,OAEpD,IAAM,EAAsB,CAC1B,QAAS,EACT,IAAK,EAAU,aAAe,cAC9B,MAAO,EACP,UACA,UAAW,GAAa,IAAA,GACxB,UAAW,EAAI,UAAY,IAAI,KAAK,EAAE,YAAY,EAAI,IAAA,EACxD,EAEA,QAAQ,QAAQ,EACb,SAAW,EAAI,OAAQ,QAAQ,EAAM,CAAI,CAAC,EAC1C,MAAO,GAAiB,CACvB,QAAQ,KAAK,gCAAiC,CAAG,CACnD,CAAC,CACL,EAEM,GAAe,EAAoB,IAAwB,CAC/D,IAAM,EAAY,EAAI,UAChB,EAAY,EAAI,UAAY,EAAG,EAAI,GACnC,EAAK,EAAY,QAAQ,eAAiB,QAAQ,MAExD,GAAI,EAAS,CACX,IAAM,EAAO,CAAC,EAAM,QAAS,EAAI,OAAO,EAAG,CAAK,EAE5C,GAAW,EAAK,KAAK,IAAI,EAAU,EAAE,EAErC,GAAW,EAAK,KAAK,CAAS,EAElC,EAAG,EAAK,KAAK,KAAK,CAAC,EAEnB,MACF,CAEA,IAAI,EAAM,KAAK,EAAM,IACf,EAAkB,CAAC,EAAM,QAAS,EAAI,QAAS,yCAAyC,EAAG,EAAE,EAE/F,IACF,GAAO,MAAM,EAAU,IACvB,EAAM,KAAK,EAAM,KAAM,EAAI,QAAS,KAAK,EAAS,oBAAoB,EAAG,EAAE,GAGzE,IACF,GAAO,MAAM,EAAU,IACvB,EAAM,KAAK,uDAAwD,EAAE,GAGvE,EAAG,EAAK,GAAG,CAAK,CAClB,EAEM,GAAgB,EAAoB,EAAe,IAAmB,CAC1E,GAAI,EAAI,WAAa,MAAO,OAAO,EAAG,EAEtC,EAAY,EAAW,CAAK,EAE5B,GAAI,CACF,IAAM,EAAS,EAAG,EAMlB,OAJI,aAAkB,QAAgB,EAAO,YAAc,QAAQ,SAAS,CAAC,GAE7E,QAAQ,SAAS,EAEV,EACT,OAAS,EAAK,CAEZ,MADA,QAAQ,SAAS,EACX,CACR,CACF,EAEM,EAAiB,CACrB,IAAI,UAA+B,CACjC,MAAO,CAAE,GAAG,CAAY,CAC1B,EAEA,OAAQ,EAA0B,CAAC,IAAc,CAC/C,IAAM,EAAS,EAAc,EAAU,OAAQ,EAAI,MAAM,EAEzD,OAAO,EACL,CACE,SAAU,EAAU,UAAY,EAAI,SACpC,UAAW,EAAU,WAAa,EAAI,UACtC,SACA,UAAW,EAAU,WAAa,EAAI,UACtC,QAAS,EAAU,SAAW,EAAI,OACpC,EACA,CACF,CACF,EAEA,IAAI,QAAgC,CAClC,OAAO,EAAI,OAAS,CAAE,GAAG,EAAK,OAAQ,CAAE,GAAG,EAAI,MAAO,CAAE,EAAI,CAAE,GAAG,CAAI,CACvE,EAEA,OAAQ,EAA+B,IAAe,EAAK,QAAS,EAAG,CAAC,EAExE,QAAU,GAA4B,EAAO,CAAI,EAEjD,OAAQ,EAA+B,IAAe,EAAK,QAAS,EAAG,CAAC,EAExE,OAAQ,EAA+B,IAAe,EAAK,QAAS,EAAG,CAAC,EAExE,OAAQ,EAAO,IAAO,EAAU,GAAO,EAAO,CAAE,EAEhD,gBAAiB,EAAO,IAAO,EAAU,GAAM,EAAO,CAAE,EAExD,MAAO,EAA+B,IAAe,EAAK,OAAQ,EAAG,CAAC,EAEtE,MAAQ,GAAyB,EAAO,MAAM,CAAE,UAAW,EAAI,UAAY,GAAG,EAAI,UAAU,GAAG,IAAS,CAAK,CAAC,EAE9G,MAAU,EAAe,IAAmB,CAC1C,GAAI,EAAI,WAAa,MAAO,OAAO,EAAG,EAEtC,IAAM,EAAK,EAAY,EAAI,UAAW,CAAK,EAE3C,QAAQ,KAAK,CAAE,EAEf,GAAI,CACF,IAAM,EAAS,EAAG,EAMlB,OAJI,aAAkB,QAAgB,EAAO,YAAc,QAAQ,QAAQ,CAAE,CAAC,GAE9E,QAAQ,QAAQ,CAAE,EAEX,EACT,OAAS,EAAK,CAEZ,MADA,QAAQ,QAAQ,CAAE,EACZ,CACR,CACF,EAEA,MAAO,EAA+B,IAAe,EAAK,OAAQ,EAAG,CAAC,EAEtE,aAAe,GAA+B,EAAa,EAAK,CAAE,GAAG,EAAa,GAAG,CAAS,CAAC,CACjG,EAEA,OAAO,CACT,CAEA,IAAa,EAAQ,EAAa"}
|
package/dist/logit.d.ts
CHANGED
|
@@ -1,72 +1,65 @@
|
|
|
1
|
-
export type LogType = 'debug' | '
|
|
1
|
+
export type LogType = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
2
2
|
export type LogLevel = LogType | 'off';
|
|
3
3
|
export type Variant = 'text' | 'symbol' | 'icon';
|
|
4
|
-
export type
|
|
5
|
-
export type
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
export type Bindings = Record<string, unknown>;
|
|
5
|
+
export type SerializedError = {
|
|
6
|
+
message: string;
|
|
7
|
+
name: string;
|
|
8
|
+
stack?: string;
|
|
8
9
|
};
|
|
9
10
|
export type RemoteLogData = {
|
|
10
|
-
|
|
11
|
+
context?: Bindings;
|
|
11
12
|
env: 'production' | 'development';
|
|
13
|
+
level: LogType;
|
|
14
|
+
message?: string;
|
|
12
15
|
namespace?: string;
|
|
13
16
|
timestamp?: string;
|
|
14
17
|
};
|
|
18
|
+
export type RemoteHandler = (type: LogType, data: RemoteLogData) => void;
|
|
19
|
+
export type RemoteOptions = {
|
|
20
|
+
handler?: RemoteHandler;
|
|
21
|
+
logLevel?: LogLevel;
|
|
22
|
+
};
|
|
15
23
|
export type LogitOptions = {
|
|
16
|
-
environment?: boolean;
|
|
17
24
|
logLevel?: LogLevel;
|
|
18
25
|
namespace?: string;
|
|
19
|
-
remote?: RemoteOptions;
|
|
26
|
+
remote?: RemoteOptions | null;
|
|
20
27
|
timestamp?: boolean;
|
|
21
28
|
variant?: Variant;
|
|
22
29
|
};
|
|
23
|
-
|
|
24
|
-
type ResolvedRemote = {
|
|
25
|
-
handler?: RemoteHandler;
|
|
30
|
+
export type LogitConfig = {
|
|
26
31
|
logLevel: LogLevel;
|
|
32
|
+
namespace: string;
|
|
33
|
+
remote?: {
|
|
34
|
+
handler: RemoteHandler;
|
|
35
|
+
logLevel: LogLevel;
|
|
36
|
+
};
|
|
37
|
+
timestamp: boolean;
|
|
38
|
+
variant: Variant;
|
|
27
39
|
};
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
type LogMethod = {
|
|
41
|
+
(): void;
|
|
42
|
+
(message: string): void;
|
|
43
|
+
(context: Bindings, message?: string): void;
|
|
44
|
+
(error: Error, message?: string): void;
|
|
30
45
|
};
|
|
31
46
|
export type Logger = {
|
|
32
|
-
|
|
47
|
+
readonly bindings: Readonly<Bindings>;
|
|
33
48
|
child: (overrides?: LogitOptions) => Logger;
|
|
34
49
|
readonly config: Readonly<LogitConfig>;
|
|
35
|
-
debug:
|
|
50
|
+
debug: LogMethod;
|
|
36
51
|
enabled: (type: LogLevel) => boolean;
|
|
37
|
-
error:
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
error: LogMethod;
|
|
53
|
+
fatal: LogMethod;
|
|
54
|
+
group: <T>(label: string, fn: () => T) => T;
|
|
55
|
+
groupCollapsed: <T>(label: string, fn: () => T) => T;
|
|
56
|
+
info: LogMethod;
|
|
40
57
|
scope: (name: string) => Logger;
|
|
41
|
-
setConfig: (opts: LogitOptions) => Logger;
|
|
42
|
-
success: (...args: unknown[]) => void;
|
|
43
|
-
table: (data: unknown, properties?: string[]) => void;
|
|
44
58
|
time: <T>(label: string, fn: () => T) => T;
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
warn: LogMethod;
|
|
60
|
+
withBindings: (bindings: Bindings) => Logger;
|
|
47
61
|
};
|
|
48
|
-
|
|
49
|
-
* Creates an independent logger instance with its own isolated configuration.
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```ts
|
|
53
|
-
* const log = createLogger({ logLevel: 'info', namespace: 'App' });
|
|
54
|
-
* log.info('Hello');
|
|
55
|
-
*
|
|
56
|
-
* const apiLog = log.scope('api');
|
|
57
|
-
* apiLog.warn('slow request');
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
export declare function createLogger(initial?: LogitOptions | string): Logger;
|
|
61
|
-
/**
|
|
62
|
-
* Shared default logger instance. For isolated configurations use `createLogger()`.
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* import { Logit } from '@vielzeug/logit';
|
|
67
|
-
* Logit.info('Hello');
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
62
|
+
export declare function createLogger(initial?: LogitOptions | string, initialBindings?: Bindings): Logger;
|
|
70
63
|
export declare const Logit: Logger;
|
|
71
64
|
export {};
|
|
72
65
|
//# sourceMappingURL=logit.d.ts.map
|
package/dist/logit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.d.ts","sourceRoot":"","sources":["../src/logit.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"logit.d.ts","sourceRoot":"","sources":["../src/logit.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AACpE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AACvC,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AACjD,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,GAAG,EAAE,YAAY,GAAG,aAAa,CAAC;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;AAEzE,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,aAAa,CAAC;QACvB,QAAQ,EAAE,QAAQ,CAAC;KACpB,CAAC;IACF,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,IAAI,IAAI,CAAC;IACT,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,YAAY,KAAK,MAAM,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvC,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC;IACrC,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5C,cAAc,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC;CAC9C,CAAC;AAmMF,wBAAgB,YAAY,CAAC,OAAO,GAAE,YAAY,GAAG,MAAW,EAAE,eAAe,GAAE,QAAa,GAAG,MAAM,CAyKxG;AAED,eAAO,MAAM,KAAK,QAAiB,CAAC"}
|
package/dist/logit.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
//#region src/logit.ts
|
|
2
2
|
var e = {
|
|
3
3
|
debug: 0,
|
|
4
|
-
error:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
warn: 4
|
|
4
|
+
error: 3,
|
|
5
|
+
fatal: 4,
|
|
6
|
+
info: 1,
|
|
7
|
+
off: 5,
|
|
8
|
+
warn: 2
|
|
10
9
|
}, t = {
|
|
11
10
|
debug: {
|
|
12
11
|
bg: "#616161",
|
|
@@ -22,6 +21,13 @@ var e = {
|
|
|
22
21
|
icon: "✘",
|
|
23
22
|
symbol: "🅴"
|
|
24
23
|
},
|
|
24
|
+
fatal: {
|
|
25
|
+
bg: "#4a148c",
|
|
26
|
+
border: "#38006b",
|
|
27
|
+
color: "#fff",
|
|
28
|
+
icon: "💀",
|
|
29
|
+
symbol: "🅵"
|
|
30
|
+
},
|
|
25
31
|
group: {
|
|
26
32
|
bg: "#546e7a",
|
|
27
33
|
border: "#455a64",
|
|
@@ -36,29 +42,11 @@ var e = {
|
|
|
36
42
|
icon: "ℹ",
|
|
37
43
|
symbol: "🅸"
|
|
38
44
|
},
|
|
39
|
-
ns:
|
|
40
|
-
bg: "#fafafa",
|
|
41
|
-
border: "#c7c7c7",
|
|
42
|
-
color: "#000"
|
|
43
|
-
} : {
|
|
45
|
+
ns: {
|
|
44
46
|
bg: "#424242",
|
|
45
47
|
border: "#212121",
|
|
46
48
|
color: "#fff"
|
|
47
49
|
},
|
|
48
|
-
success: {
|
|
49
|
-
bg: "#689f38",
|
|
50
|
-
border: "#558b2f",
|
|
51
|
-
color: "#fff",
|
|
52
|
-
icon: "✔",
|
|
53
|
-
symbol: "🆂"
|
|
54
|
-
},
|
|
55
|
-
trace: {
|
|
56
|
-
bg: "#d81b60",
|
|
57
|
-
border: "#c2185b",
|
|
58
|
-
color: "#fff",
|
|
59
|
-
icon: "⛢",
|
|
60
|
-
symbol: "🆃"
|
|
61
|
-
},
|
|
62
50
|
warn: {
|
|
63
51
|
bg: "#ffb300",
|
|
64
52
|
border: "#ffa000",
|
|
@@ -66,116 +54,173 @@ var e = {
|
|
|
66
54
|
icon: "⚠",
|
|
67
55
|
symbol: "🆆"
|
|
68
56
|
}
|
|
69
|
-
}, n = "border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;", r = typeof window > "u", i = r ?
|
|
57
|
+
}, n = "border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;", r = typeof window > "u", i = globalThis.process, a = r ? i?.env?.NODE_ENV === "production" : !0, o = {
|
|
70
58
|
debug: "log",
|
|
71
59
|
error: "error",
|
|
60
|
+
fatal: "error",
|
|
72
61
|
info: "info",
|
|
73
|
-
success: "log",
|
|
74
|
-
trace: "trace",
|
|
75
62
|
warn: "warn"
|
|
76
63
|
};
|
|
77
|
-
function s(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
64
|
+
function s(e) {
|
|
65
|
+
return {
|
|
66
|
+
message: e.message,
|
|
67
|
+
name: e.name,
|
|
68
|
+
stack: e.stack
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function c(e) {
|
|
72
|
+
throw TypeError(`[logit] ${e}`);
|
|
73
|
+
}
|
|
74
|
+
function l(e, t) {
|
|
75
|
+
return e === void 0 ? {
|
|
76
|
+
context: void 0,
|
|
77
|
+
message: void 0
|
|
78
|
+
} : e instanceof Error ? (t !== void 0 && typeof t != "string" && c("error override messages must be strings."), {
|
|
79
|
+
context: { err: s(e) },
|
|
80
|
+
message: t ?? e.message
|
|
81
|
+
}) : typeof e == "string" ? (t !== void 0 && c("string-first log calls accept only one argument. Use log.info({ ... }, \"message\") for structured context."), {
|
|
82
|
+
context: void 0,
|
|
83
|
+
message: e
|
|
84
|
+
}) : (t !== void 0 && typeof t != "string" && c("context-first log calls require the optional second argument to be a string message."), {
|
|
85
|
+
context: e,
|
|
86
|
+
message: t
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function u(e, n) {
|
|
90
|
+
let r = t[e];
|
|
91
|
+
return n === "text" || !r[n] ? e.toUpperCase() : r[n];
|
|
92
|
+
}
|
|
93
|
+
function d(e, n, r = "") {
|
|
94
|
+
let { bg: i, border: a, color: o } = t[e], s = `border: 1px solid ${a}; border-radius: 4px`;
|
|
95
|
+
switch (n) {
|
|
96
|
+
case "icon": return `color: ${i}; ${s}; padding: 0 3px${r}`;
|
|
97
|
+
case "symbol": return `color: ${i}; ${s}; padding: 0 1px${r}`;
|
|
98
|
+
default: return `background: ${i}; color: ${o}; ${s}; font-weight: bold; padding: 0 3px${r}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function f(e, t) {
|
|
102
|
+
if (!(!(Object.keys(e).length > 0) && !t)) return {
|
|
103
|
+
...e,
|
|
104
|
+
...t
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function p(e, t) {
|
|
108
|
+
return e && t !== void 0 ? [e, t] : e ? [e] : t === void 0 ? [] : [t];
|
|
109
|
+
}
|
|
110
|
+
function m(e, t, n, r) {
|
|
111
|
+
let i = [u(e, r)];
|
|
112
|
+
return t && i.push(`[${t}]`), n && i.push(n), `${i.join(" | ")} |`;
|
|
113
|
+
}
|
|
114
|
+
function h(e, t, r, i) {
|
|
115
|
+
let a = `%c${u(e, i)}%c`, o = [d(e, i), ""];
|
|
116
|
+
return t && (a += ` %c${t}%c`, o.push(d("ns", i, `; ${n}`), "")), r && (a += ` %c${r}%c`, o.push("color: gray", "")), {
|
|
117
|
+
fmt: a,
|
|
118
|
+
parts: o
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function g(e, t) {
|
|
122
|
+
return e ? `[${e}] ${t}` : t;
|
|
123
|
+
}
|
|
124
|
+
function _(e, t) {
|
|
125
|
+
if (e === void 0) return t ? { ...t } : void 0;
|
|
126
|
+
if (e === null) return;
|
|
127
|
+
let n = e.handler ?? t?.handler;
|
|
128
|
+
if (!n) {
|
|
129
|
+
if (e.logLevel !== void 0) throw Error("[logit] remote.logLevel requires a remote.handler (or inherited handler via child())");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
handler: n,
|
|
134
|
+
logLevel: e.logLevel ?? t?.logLevel ?? "debug"
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function v(e) {
|
|
138
|
+
let t = e.namespace ?? "", n = e.logLevel ?? "debug", r = _(e.remote), i = e.timestamp ?? !0, a = e.variant ?? "symbol";
|
|
139
|
+
return r ? {
|
|
140
|
+
logLevel: n,
|
|
141
|
+
namespace: t,
|
|
142
|
+
remote: r,
|
|
143
|
+
timestamp: i,
|
|
144
|
+
variant: a
|
|
145
|
+
} : {
|
|
146
|
+
logLevel: n,
|
|
147
|
+
namespace: t,
|
|
148
|
+
timestamp: i,
|
|
149
|
+
variant: a
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function y(t = {}, i = {}) {
|
|
153
|
+
let s = v(typeof t == "string" ? { namespace: t } : t), c = { ...i }, b = (t) => e[s.logLevel] <= e[t], x = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 23), S = (t, n, i) => {
|
|
154
|
+
if (!b(t)) return;
|
|
155
|
+
let { context: u, message: d } = l(n, i);
|
|
156
|
+
if (u === void 0 && d === void 0) return;
|
|
157
|
+
let g = s.namespace, _ = s.timestamp ? x() : "", v = f(c, u), y = p(v, d), S = console[o[t]];
|
|
158
|
+
if (r) S(m(t, g, _, s.variant), ...y);
|
|
159
|
+
else {
|
|
160
|
+
let { fmt: e, parts: n } = h(t, g, _, s.variant);
|
|
161
|
+
S(e, ...n, ...y);
|
|
88
162
|
}
|
|
89
|
-
|
|
90
|
-
let
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
163
|
+
if (!s.remote || e[s.remote.logLevel] > e[t]) return;
|
|
164
|
+
let C = {
|
|
165
|
+
context: v,
|
|
166
|
+
env: a ? "production" : "development",
|
|
167
|
+
level: t,
|
|
168
|
+
message: d,
|
|
169
|
+
namespace: g || void 0,
|
|
170
|
+
timestamp: s.timestamp ? (/* @__PURE__ */ new Date()).toISOString() : void 0
|
|
171
|
+
};
|
|
172
|
+
Promise.resolve().then(() => s.remote.handler(t, C)).catch((e) => {
|
|
173
|
+
console.warn("[logit] remote handler error:", e);
|
|
174
|
+
});
|
|
175
|
+
}, C = (e, t) => {
|
|
176
|
+
let i = s.namespace, a = s.timestamp ? x() : "", o = e ? console.groupCollapsed : console.group;
|
|
177
|
+
if (r) {
|
|
178
|
+
let e = [u("group", s.variant), t];
|
|
179
|
+
i && e.push(`[${i}]`), a && e.push(a), o(e.join(" | "));
|
|
180
|
+
return;
|
|
98
181
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}, _ = (t, n) => {
|
|
110
|
-
if (!d(t)) return;
|
|
111
|
-
let a = u.namespace, o = u.timestamp ? f() : "";
|
|
112
|
-
r ? h(t, a, o, n) : g(t, a, o, n);
|
|
113
|
-
let { handler: s, logLevel: c } = u.remote;
|
|
114
|
-
if (s && e[c] <= e[t]) {
|
|
115
|
-
let e = {
|
|
116
|
-
args: n,
|
|
117
|
-
env: i ? "production" : "development",
|
|
118
|
-
namespace: a || void 0,
|
|
119
|
-
timestamp: u.timestamp ? (/* @__PURE__ */ new Date()).toISOString() : void 0
|
|
120
|
-
};
|
|
121
|
-
Promise.resolve().then(() => s(t, e)).catch(() => {});
|
|
182
|
+
let c = `%c${t}%c`, l = [d("group", s.variant, "; margin-right: 6px; padding: 1px 3px 0"), ""];
|
|
183
|
+
i && (c += ` %c${i}%c`, l.push(d("ns", s.variant, `; ${n}; margin-right: 6px`), "")), a && (c += ` %c${a}%c`, l.push("color: gray; font-weight: lighter; margin-right: 6px", "")), o(c, ...l);
|
|
184
|
+
}, w = (e, t, n) => {
|
|
185
|
+
if (s.logLevel === "off") return n();
|
|
186
|
+
C(e, t);
|
|
187
|
+
try {
|
|
188
|
+
let e = n();
|
|
189
|
+
return e instanceof Promise ? e.finally(() => console.groupEnd()) : (console.groupEnd(), e);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
throw console.groupEnd(), e;
|
|
122
192
|
}
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
...u,
|
|
127
|
-
...n,
|
|
128
|
-
remote: {
|
|
129
|
-
...u.remote,
|
|
130
|
-
...t
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
}, b = (e, t, n, r) => {
|
|
134
|
-
let i = e ? console.groupCollapsed : console.group, o = [p("group")];
|
|
135
|
-
u.environment && o.push(a), o.push(t), n && o.push(`[${n}]`), r && o.push(r), i(o.join(" | "));
|
|
136
|
-
}, x = (e, t, r, i) => {
|
|
137
|
-
let o = e ? console.groupCollapsed : console.group, s = `%c${t}%c`, c = [m("group", "; margin-right: 6px; padding: 1px 3px 0"), ""];
|
|
138
|
-
r && (s += ` %c${r}%c`, c.push(m("ns", `; ${n}; margin-right: 6px`), "")), u.environment && (s += ` %c${a}%c`, c.push("color: darkgray; margin-right: 6px", "")), i && (s += ` %c${i}%c`, c.push("color: gray; font-weight: lighter; margin-right: 6px", "")), o(s, ...c);
|
|
139
|
-
}, S = (e, t) => {
|
|
140
|
-
let n = u.namespace, i = u.timestamp ? f() : "";
|
|
141
|
-
r ? b(e, t, n, i) : x(e, t, n, i);
|
|
142
|
-
}, C = {
|
|
143
|
-
assert: (e, ...t) => {
|
|
144
|
-
d("error") && console.assert(e, ...t);
|
|
193
|
+
}, T = {
|
|
194
|
+
get bindings() {
|
|
195
|
+
return { ...c };
|
|
145
196
|
},
|
|
146
|
-
child:
|
|
147
|
-
|
|
148
|
-
return {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
197
|
+
child: (e = {}) => {
|
|
198
|
+
let t = _(e.remote, s.remote);
|
|
199
|
+
return y({
|
|
200
|
+
logLevel: e.logLevel ?? s.logLevel,
|
|
201
|
+
namespace: e.namespace ?? s.namespace,
|
|
202
|
+
remote: t,
|
|
203
|
+
timestamp: e.timestamp ?? s.timestamp,
|
|
204
|
+
variant: e.variant ?? s.variant
|
|
205
|
+
}, c);
|
|
152
206
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
S(n, e);
|
|
159
|
-
try {
|
|
160
|
-
let e = t();
|
|
161
|
-
return e instanceof Promise ? e.finally(() => console.groupEnd()) : (console.groupEnd(), e);
|
|
162
|
-
} catch (e) {
|
|
163
|
-
throw console.groupEnd(), e;
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
info: (...e) => _("info", e),
|
|
167
|
-
scope: (e) => y({ namespace: u.namespace ? `${u.namespace}.${e}` : e }),
|
|
168
|
-
setConfig: (e) => {
|
|
169
|
-
let { remote: t, ...n } = e;
|
|
170
|
-
return t !== void 0 && Object.assign(u.remote, t), Object.assign(u, n), C;
|
|
171
|
-
},
|
|
172
|
-
success: (...e) => _("success", e),
|
|
173
|
-
table: (e, t) => {
|
|
174
|
-
d("debug") && console.table(e, t);
|
|
207
|
+
get config() {
|
|
208
|
+
return s.remote ? {
|
|
209
|
+
...s,
|
|
210
|
+
remote: { ...s.remote }
|
|
211
|
+
} : { ...s };
|
|
175
212
|
},
|
|
213
|
+
debug: (e, t) => S("debug", e, t),
|
|
214
|
+
enabled: (e) => b(e),
|
|
215
|
+
error: (e, t) => S("error", e, t),
|
|
216
|
+
fatal: (e, t) => S("fatal", e, t),
|
|
217
|
+
group: (e, t) => w(!1, e, t),
|
|
218
|
+
groupCollapsed: (e, t) => w(!0, e, t),
|
|
219
|
+
info: (e, t) => S("info", e, t),
|
|
220
|
+
scope: (e) => T.child({ namespace: s.namespace ? `${s.namespace}.${e}` : e }),
|
|
176
221
|
time: (e, t) => {
|
|
177
|
-
if (
|
|
178
|
-
let n =
|
|
222
|
+
if (s.logLevel === "off") return t();
|
|
223
|
+
let n = g(s.namespace, e);
|
|
179
224
|
console.time(n);
|
|
180
225
|
try {
|
|
181
226
|
let e = t();
|
|
@@ -184,13 +229,16 @@ function s(c = {}) {
|
|
|
184
229
|
throw console.timeEnd(n), e;
|
|
185
230
|
}
|
|
186
231
|
},
|
|
187
|
-
|
|
188
|
-
|
|
232
|
+
warn: (e, t) => S("warn", e, t),
|
|
233
|
+
withBindings: (e) => y(s, {
|
|
234
|
+
...c,
|
|
235
|
+
...e
|
|
236
|
+
})
|
|
189
237
|
};
|
|
190
|
-
return
|
|
238
|
+
return T;
|
|
191
239
|
}
|
|
192
|
-
var
|
|
240
|
+
var b = y();
|
|
193
241
|
//#endregion
|
|
194
|
-
export {
|
|
242
|
+
export { b as Logit, y as createLogger };
|
|
195
243
|
|
|
196
244
|
//# sourceMappingURL=logit.js.map
|
package/dist/logit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logit.js","names":[],"sources":["../src/logit.ts"],"sourcesContent":["/* -------------------- Types -------------------- */\n\nexport type LogType = 'debug' | 'trace' | 'info' | 'success' | 'warn' | 'error';\nexport type LogLevel = LogType | 'off';\nexport type Variant = 'text' | 'symbol' | 'icon';\n\nexport type RemoteHandler = (type: LogType, data: RemoteLogData) => void;\n\nexport type RemoteOptions = { handler?: RemoteHandler; logLevel?: LogLevel };\n\nexport type RemoteLogData = {\n args: unknown[];\n env: 'production' | 'development';\n namespace?: string;\n timestamp?: string;\n};\n\nexport type LogitOptions = {\n environment?: boolean;\n logLevel?: LogLevel;\n namespace?: string;\n remote?: RemoteOptions;\n timestamp?: boolean;\n variant?: Variant;\n};\n\n/** The shape of a fully resolved logger config (all fields present). */\ntype ResolvedRemote = { handler?: RemoteHandler; logLevel: LogLevel };\nexport type LogitConfig = Omit<Required<LogitOptions>, 'remote'> & { remote: ResolvedRemote };\n\nexport type Logger = {\n assert: (condition: boolean, ...args: unknown[]) => void;\n child: (overrides?: LogitOptions) => Logger;\n readonly config: Readonly<LogitConfig>;\n debug: (...args: unknown[]) => void;\n enabled: (type: LogLevel) => boolean;\n error: (...args: unknown[]) => void;\n group: <T>(label: string, fn: () => T, collapsed?: boolean) => T;\n info: (...args: unknown[]) => void;\n scope: (name: string) => Logger;\n setConfig: (opts: LogitOptions) => Logger;\n success: (...args: unknown[]) => void;\n table: (data: unknown, properties?: string[]) => void;\n time: <T>(label: string, fn: () => T) => T;\n trace: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n};\n\n/* -------------------- Priority -------------------- */\n\nconst PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 5,\n info: 2,\n off: 6,\n success: 3,\n trace: 1,\n warn: 4,\n};\n\n/* -------------------- Theme -------------------- */\n\ntype Theme = { bg: string; border: string; color: string; icon?: string; symbol?: string };\n\nconst isDarkMode = typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches;\n\nconst THEME: Record<LogType | 'group' | 'ns', Theme> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '☕', symbol: '🅳' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '✘', symbol: '🅴' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '⚭', symbol: '🅶' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: 'ℹ', symbol: '🅸' },\n ns: isDarkMode\n ? { bg: '#fafafa', border: '#c7c7c7', color: '#000' }\n : { bg: '#424242', border: '#212121', color: '#fff' },\n success: { bg: '#689f38', border: '#558b2f', color: '#fff', icon: '✔', symbol: '🆂' },\n trace: { bg: '#d81b60', border: '#c2185b', color: '#fff', icon: '⛢', symbol: '🆃' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '⚠', symbol: '🆆' },\n};\n\nconst NS_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;';\n\n/* -------------------- createLogger -------------------- */\n\nconst IS_NODE = typeof window === 'undefined';\nconst IS_PROD = IS_NODE\n ? // @ts-expect-error - process is Node-only\n (process as any).env?.NODE_ENV === 'production'\n : (import.meta as any)?.env?.NODE_ENV === 'production';\n\nconst ENV_BADGE = IS_PROD ? '🅿' : '🅳';\n\nconst LOG_METHOD: Record<LogType, 'log' | 'info' | 'warn' | 'error' | 'trace'> = {\n debug: 'log',\n error: 'error',\n info: 'info',\n success: 'log',\n trace: 'trace',\n warn: 'warn',\n};\n\n/**\n * Creates an independent logger instance with its own isolated configuration.\n *\n * @example\n * ```ts\n * const log = createLogger({ logLevel: 'info', namespace: 'App' });\n * log.info('Hello');\n *\n * const apiLog = log.scope('api');\n * apiLog.warn('slow request');\n * ```\n */\nexport function createLogger(initial: LogitOptions | string = {}): Logger {\n const opts: LogitOptions = typeof initial === 'string' ? { namespace: initial } : initial;\n const cfg: LogitConfig = {\n environment: true,\n logLevel: 'debug',\n namespace: '',\n timestamp: true,\n variant: 'symbol',\n ...opts,\n remote: { logLevel: 'debug', ...opts.remote }, // 'debug' default means a handler just works; set 'off' explicitly to disable\n };\n\n /* ---- helpers ---- */\n\n const passes = (type: LogLevel): boolean => PRIORITY[cfg.logLevel] <= PRIORITY[type];\n\n const ts = (): string => new Date().toISOString().slice(11, 23);\n\n const badge = (type: LogType | 'group'): string => {\n const theme = THEME[type];\n\n if (cfg.variant === 'text' || !theme[cfg.variant]) return type.toUpperCase();\n\n return theme[cfg.variant]!;\n };\n\n const style = (type: LogType | 'group' | 'ns', extra = ''): string => {\n const { bg, border, color } = THEME[type];\n const base = `border: 1px solid ${border}; border-radius: 4px`;\n\n switch (cfg.variant) {\n case 'icon':\n return `color: ${bg}; ${base}; padding: 0 3px${extra}`;\n case 'symbol':\n return `color: ${bg}; ${base}; padding: 0 1px${extra}`;\n default:\n return `background: ${bg}; color: ${color}; ${base}; font-weight: bold; padding: 0 3px${extra}`;\n }\n };\n\n const emitNode = (type: LogType, ns: string, stamp: string, args: unknown[]): void => {\n const meta = [badge(type)];\n\n if (cfg.environment) meta.push(ENV_BADGE);\n\n if (ns) meta.push(`[${ns}]`);\n\n if (stamp) meta.push(stamp);\n\n const method = console[LOG_METHOD[type]] as (...a: unknown[]) => void;\n\n method(`${meta.join(' | ')} |`, ...args);\n };\n\n const emitBrowser = (type: LogType, ns: string, stamp: string, args: unknown[]): void => {\n let fmt = `%c${badge(type)}%c`;\n const parts: string[] = [style(type), ''];\n\n if (ns) {\n fmt += ` %c${ns}%c`;\n parts.push(style('ns', `; ${NS_STYLE}`), '');\n }\n\n if (cfg.environment) {\n fmt += ` %c${ENV_BADGE}%c`;\n parts.push('color: darkgray', '');\n }\n\n if (stamp) {\n fmt += ` %c${stamp}%c`;\n parts.push('color: gray', '');\n }\n\n const method = console[LOG_METHOD[type]] as (...a: unknown[]) => void;\n\n method(fmt, ...parts, ...args);\n };\n\n const emit = (type: LogType, args: unknown[]): void => {\n if (!passes(type)) return;\n\n const ns = cfg.namespace;\n const stamp = cfg.timestamp ? ts() : '';\n\n if (IS_NODE) emitNode(type, ns, stamp, args);\n else emitBrowser(type, ns, stamp, args);\n\n /* remote dispatch — snapshot data now, dispatch in microtask to avoid blocking caller */\n const { handler, logLevel } = cfg.remote;\n\n if (handler && PRIORITY[logLevel] <= PRIORITY[type]) {\n const data: RemoteLogData = {\n args,\n env: IS_PROD ? 'production' : 'development',\n namespace: ns || undefined,\n timestamp: cfg.timestamp ? new Date().toISOString() : undefined,\n };\n\n Promise.resolve()\n .then(() => handler(type, data))\n .catch(() => {});\n }\n };\n\n const timeLabel = (label: string): string => (cfg.namespace ? `[${cfg.namespace}] ${label}` : label);\n\n /* ---- child factory ---- */\n const makeChild = (overrides: LogitOptions = {}): Logger => {\n const { remote: overrideRemote, ...overrideRest } = overrides;\n\n return createLogger({ ...cfg, ...overrideRest, remote: { ...cfg.remote, ...overrideRemote } });\n };\n\n /* ---- group renderer ---- */\n\n const renderGroupNode = (collapsed: boolean, label: string, ns: string, stamp: string): void => {\n const fn = collapsed ? console.groupCollapsed : console.group;\n const meta = [badge('group')];\n\n if (cfg.environment) meta.push(ENV_BADGE);\n\n meta.push(label);\n\n if (ns) meta.push(`[${ns}]`);\n\n if (stamp) meta.push(stamp);\n\n fn(meta.join(' | '));\n };\n\n const renderGroupBrowser = (collapsed: boolean, label: string, ns: string, stamp: string): void => {\n const fn = collapsed ? console.groupCollapsed : console.group;\n let fmt = `%c${label}%c`;\n const parts: string[] = [style('group', '; margin-right: 6px; padding: 1px 3px 0'), ''];\n\n if (ns) {\n fmt += ` %c${ns}%c`;\n parts.push(style('ns', `; ${NS_STYLE}; margin-right: 6px`), '');\n }\n\n if (cfg.environment) {\n fmt += ` %c${ENV_BADGE}%c`;\n parts.push('color: darkgray; margin-right: 6px', '');\n }\n\n if (stamp) {\n fmt += ` %c${stamp}%c`;\n parts.push('color: gray; font-weight: lighter; margin-right: 6px', '');\n }\n\n fn(fmt, ...parts);\n };\n\n const renderGroup = (collapsed: boolean, label: string): void => {\n const ns = cfg.namespace;\n const stamp = cfg.timestamp ? ts() : '';\n\n if (IS_NODE) renderGroupNode(collapsed, label, ns, stamp);\n else renderGroupBrowser(collapsed, label, ns, stamp);\n };\n\n /* ---- public API ---- */\n\n const logger: Logger = {\n assert: (condition: boolean, ...args: unknown[]): void => {\n if (passes('error')) console.assert(condition, ...args);\n },\n\n child: makeChild,\n\n get config(): Readonly<LogitConfig> {\n return { ...cfg, remote: { ...cfg.remote } };\n },\n\n debug: (...a) => emit('debug', a),\n\n enabled: (type: LogLevel): boolean => passes(type),\n error: (...a) => emit('error', a),\n\n group: <T>(label: string, fn: () => T, collapsed = false): T => {\n if (!passes('debug')) return fn();\n\n renderGroup(collapsed, label);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) {\n return result.finally(() => console.groupEnd()) as T;\n }\n\n console.groupEnd();\n\n return result;\n } catch (e) {\n console.groupEnd();\n throw e;\n }\n },\n\n info: (...a) => emit('info', a),\n\n scope: (name: string): Logger => makeChild({ namespace: cfg.namespace ? `${cfg.namespace}.${name}` : name }),\n\n setConfig: (opts: LogitOptions): Logger => {\n const { remote, ...rest } = opts;\n\n if (remote !== undefined) Object.assign(cfg.remote, remote);\n\n Object.assign(cfg, rest);\n\n return logger;\n },\n success: (...a) => emit('success', a),\n\n table: (data: unknown, properties?: string[]): void => {\n if (passes('debug')) console.table(data, properties);\n },\n\n time: <T>(label: string, fn: () => T): T => {\n if (!passes('debug')) return fn();\n\n const tl = timeLabel(label);\n\n console.time(tl);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) {\n return result.finally(() => console.timeEnd(tl)) as T;\n }\n\n console.timeEnd(tl);\n\n return result;\n } catch (e) {\n console.timeEnd(tl);\n throw e;\n }\n },\n\n trace: (...a) => emit('trace', a),\n warn: (...a) => emit('warn', a),\n };\n\n return logger;\n}\n\n/* -------------------- Default instance -------------------- */\n\n/**\n * Shared default logger instance. For isolated configurations use `createLogger()`.\n *\n * @example\n * ```ts\n * import { Logit } from '@vielzeug/logit';\n * Logit.info('Hello');\n * ```\n */\nexport const Logit = createLogger();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logit.js","names":[],"sources":["../src/logit.ts"],"sourcesContent":["/* -------------------- Types -------------------- */\n\nexport type LogType = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\nexport type LogLevel = LogType | 'off';\nexport type Variant = 'text' | 'symbol' | 'icon';\nexport type Bindings = Record<string, unknown>;\n\nexport type SerializedError = {\n message: string;\n name: string;\n stack?: string;\n};\n\nexport type RemoteLogData = {\n context?: Bindings;\n env: 'production' | 'development';\n level: LogType;\n message?: string;\n namespace?: string;\n timestamp?: string;\n};\n\nexport type RemoteHandler = (type: LogType, data: RemoteLogData) => void;\n\nexport type RemoteOptions = {\n handler?: RemoteHandler;\n logLevel?: LogLevel;\n};\n\nexport type LogitOptions = {\n logLevel?: LogLevel;\n namespace?: string;\n remote?: RemoteOptions | null;\n timestamp?: boolean;\n variant?: Variant;\n};\n\nexport type LogitConfig = {\n logLevel: LogLevel;\n namespace: string;\n remote?: {\n handler: RemoteHandler;\n logLevel: LogLevel;\n };\n timestamp: boolean;\n variant: Variant;\n};\n\ntype LogMethod = {\n (): void;\n (message: string): void;\n (context: Bindings, message?: string): void;\n (error: Error, message?: string): void;\n};\n\nexport type Logger = {\n readonly bindings: Readonly<Bindings>;\n child: (overrides?: LogitOptions) => Logger;\n readonly config: Readonly<LogitConfig>;\n debug: LogMethod;\n enabled: (type: LogLevel) => boolean;\n error: LogMethod;\n fatal: LogMethod;\n group: <T>(label: string, fn: () => T) => T;\n groupCollapsed: <T>(label: string, fn: () => T) => T;\n info: LogMethod;\n scope: (name: string) => Logger;\n time: <T>(label: string, fn: () => T) => T;\n warn: LogMethod;\n withBindings: (bindings: Bindings) => Logger;\n};\n\n/* -------------------- Constants -------------------- */\n\nconst PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n error: 3,\n fatal: 4,\n info: 1,\n off: 5,\n warn: 2,\n};\n\ntype Theme = { bg: string; border: string; color: string; icon?: string; symbol?: string };\n\nconst THEME: Record<LogType | 'group' | 'ns', Theme> = {\n debug: { bg: '#616161', border: '#424242', color: '#fff', icon: '☕', symbol: '🅳' },\n error: { bg: '#d32f2f', border: '#c62828', color: '#fff', icon: '✘', symbol: '🅴' },\n fatal: { bg: '#4a148c', border: '#38006b', color: '#fff', icon: '💀', symbol: '🅵' },\n group: { bg: '#546e7a', border: '#455a64', color: '#fff', icon: '⚭', symbol: '🅶' },\n info: { bg: '#1976d2', border: '#1565c0', color: '#fff', icon: 'ℹ', symbol: '🅸' },\n ns: { bg: '#424242', border: '#212121', color: '#fff' },\n warn: { bg: '#ffb300', border: '#ffa000', color: '#fff', icon: '⚠', symbol: '🆆' },\n};\n\nconst NS_STYLE = 'border-radius: 8px; font: italic small-caps bold 12px; font-weight: lighter; padding: 0 4px;';\n\nconst IS_NODE = typeof window === 'undefined';\nconst NODE_PROCESS = (globalThis as typeof globalThis & { process?: { env?: { NODE_ENV?: string } } }).process;\nconst IS_PROD = IS_NODE ? NODE_PROCESS?.env?.NODE_ENV === 'production' : (import.meta as ImportMeta).env.PROD;\n\nconst LOG_METHOD: Record<LogType, 'log' | 'info' | 'warn' | 'error'> = {\n debug: 'log',\n error: 'error',\n fatal: 'error',\n info: 'info',\n warn: 'warn',\n};\n\n/* -------------------- Pure Helpers -------------------- */\n\nfunction serializeError(err: Error): SerializedError {\n return { message: err.message, name: err.name, stack: err.stack };\n}\n\nfunction failInvalidArgs(message: string): never {\n throw new TypeError(`[logit] ${message}`);\n}\n\nfunction parseArgs(\n msgOrCtx: string | Bindings | Error | undefined,\n msg: unknown,\n): { context: Bindings | undefined; message: string | undefined } {\n if (msgOrCtx === undefined) return { context: undefined, message: undefined };\n\n if (msgOrCtx instanceof Error) {\n if (msg !== undefined && typeof msg !== 'string') {\n failInvalidArgs('error override messages must be strings.');\n }\n\n return {\n context: { err: serializeError(msgOrCtx) },\n message: (msg as string | undefined) ?? msgOrCtx.message,\n };\n }\n\n if (typeof msgOrCtx === 'string') {\n if (msg !== undefined) {\n failInvalidArgs(\n 'string-first log calls accept only one argument. Use log.info({ ... }, \"message\") for structured context.',\n );\n }\n\n return { context: undefined, message: msgOrCtx };\n }\n\n if (msg !== undefined && typeof msg !== 'string') {\n failInvalidArgs('context-first log calls require the optional second argument to be a string message.');\n }\n\n return { context: msgOrCtx as Bindings, message: msg as string | undefined };\n}\n\nfunction badge(type: LogType | 'group', variant: Variant): string {\n const theme = THEME[type];\n\n if (variant === 'text' || !theme[variant]) return type.toUpperCase();\n\n return theme[variant]!;\n}\n\nfunction style(type: LogType | 'group' | 'ns', variant: Variant, extra = ''): string {\n const { bg, border, color } = THEME[type];\n const base = `border: 1px solid ${border}; border-radius: 4px`;\n\n switch (variant) {\n case 'icon':\n return `color: ${bg}; ${base}; padding: 0 3px${extra}`;\n case 'symbol':\n return `color: ${bg}; ${base}; padding: 0 1px${extra}`;\n default:\n return `background: ${bg}; color: ${color}; ${base}; font-weight: bold; padding: 0 3px${extra}`;\n }\n}\n\nfunction mergeContext(base: Bindings, callCtx: Bindings | undefined): Bindings | undefined {\n const hasBase = Object.keys(base).length > 0;\n\n if (!hasBase && !callCtx) return undefined;\n\n return { ...base, ...callCtx };\n}\n\nfunction buildPayload(mergedContext: Bindings | undefined, message: string | undefined): unknown[] {\n if (mergedContext && message !== undefined) return [mergedContext, message];\n\n if (mergedContext) return [mergedContext];\n\n if (message !== undefined) return [message];\n\n return [];\n}\n\nfunction buildNodePrefix(type: LogType, namespace: string, timestamp: string, variant: Variant): string {\n const meta = [badge(type, variant)];\n\n if (namespace) meta.push(`[${namespace}]`);\n\n if (timestamp) meta.push(timestamp);\n\n return `${meta.join(' | ')} |`;\n}\n\nfunction buildBrowserPrefix(\n type: LogType,\n namespace: string,\n timestamp: string,\n variant: Variant,\n): { fmt: string; parts: string[] } {\n let fmt = `%c${badge(type, variant)}%c`;\n const parts: string[] = [style(type, variant), ''];\n\n if (namespace) {\n fmt += ` %c${namespace}%c`;\n parts.push(style('ns', variant, `; ${NS_STYLE}`), '');\n }\n\n if (timestamp) {\n fmt += ` %c${timestamp}%c`;\n parts.push('color: gray', '');\n }\n\n return { fmt, parts };\n}\n\nfunction toTimeLabel(namespace: string, label: string): string {\n return namespace ? `[${namespace}] ${label}` : label;\n}\n\nfunction resolveRemote(\n remote: LogitOptions['remote'],\n inherited?: LogitConfig['remote'],\n): LogitConfig['remote'] | undefined {\n if (remote === undefined) return inherited ? { ...inherited } : undefined;\n\n if (remote === null) return undefined;\n\n const handler = remote.handler ?? inherited?.handler;\n\n if (!handler) {\n if (remote.logLevel !== undefined) {\n throw new Error('[logit] remote.logLevel requires a remote.handler (or inherited handler via child())');\n }\n\n return undefined;\n }\n\n return {\n handler,\n logLevel: remote.logLevel ?? inherited?.logLevel ?? 'debug',\n };\n}\n\nfunction resolveConfig(opts: LogitOptions): LogitConfig {\n const namespace = opts.namespace ?? '';\n const logLevel = opts.logLevel ?? 'debug';\n const remote = resolveRemote(opts.remote);\n const timestamp = opts.timestamp ?? true;\n const variant = opts.variant ?? 'symbol';\n\n return remote ? { logLevel, namespace, remote, timestamp, variant } : { logLevel, namespace, timestamp, variant };\n}\n\n/* -------------------- createLogger -------------------- */\n\nexport function createLogger(initial: LogitOptions | string = {}, initialBindings: Bindings = {}): Logger {\n const initialOpts: LogitOptions = typeof initial === 'string' ? { namespace: initial } : initial;\n const cfg = resolveConfig(initialOpts);\n const ownBindings: Bindings = { ...initialBindings };\n\n const passes = (type: LogLevel): boolean => PRIORITY[cfg.logLevel] <= PRIORITY[type];\n\n const ts = (): string => new Date().toISOString().slice(11, 23);\n\n const emit = (type: LogType, msgOrCtx?: string | Bindings | Error, msg?: unknown): void => {\n if (!passes(type)) return;\n\n const { context, message } = parseArgs(msgOrCtx, msg);\n\n if (context === undefined && message === undefined) return;\n\n const namespace = cfg.namespace;\n const timestamp = cfg.timestamp ? ts() : '';\n const mergedContext = mergeContext(ownBindings, context);\n const payload = buildPayload(mergedContext, message);\n const method = console[LOG_METHOD[type]] as (...a: unknown[]) => void;\n\n if (IS_NODE) {\n method(buildNodePrefix(type, namespace, timestamp, cfg.variant), ...payload);\n } else {\n const { fmt, parts } = buildBrowserPrefix(type, namespace, timestamp, cfg.variant);\n\n method(fmt, ...parts, ...payload);\n }\n\n if (!cfg.remote) return;\n\n if (PRIORITY[cfg.remote.logLevel] > PRIORITY[type]) return;\n\n const data: RemoteLogData = {\n context: mergedContext,\n env: IS_PROD ? 'production' : 'development',\n level: type,\n message,\n namespace: namespace || undefined,\n timestamp: cfg.timestamp ? new Date().toISOString() : undefined,\n };\n\n Promise.resolve()\n .then(() => cfg.remote!.handler(type, data))\n .catch((err: unknown) => {\n console.warn('[logit] remote handler error:', err);\n });\n };\n\n const renderGroup = (collapsed: boolean, label: string): void => {\n const namespace = cfg.namespace;\n const timestamp = cfg.timestamp ? ts() : '';\n const fn = collapsed ? console.groupCollapsed : console.group;\n\n if (IS_NODE) {\n const meta = [badge('group', cfg.variant), label];\n\n if (namespace) meta.push(`[${namespace}]`);\n\n if (timestamp) meta.push(timestamp);\n\n fn(meta.join(' | '));\n\n return;\n }\n\n let fmt = `%c${label}%c`;\n const parts: string[] = [style('group', cfg.variant, '; margin-right: 6px; padding: 1px 3px 0'), ''];\n\n if (namespace) {\n fmt += ` %c${namespace}%c`;\n parts.push(style('ns', cfg.variant, `; ${NS_STYLE}; margin-right: 6px`), '');\n }\n\n if (timestamp) {\n fmt += ` %c${timestamp}%c`;\n parts.push('color: gray; font-weight: lighter; margin-right: 6px', '');\n }\n\n fn(fmt, ...parts);\n };\n\n const wrapGroup = <T>(collapsed: boolean, label: string, fn: () => T): T => {\n if (cfg.logLevel === 'off') return fn();\n\n renderGroup(collapsed, label);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) return result.finally(() => console.groupEnd()) as T;\n\n console.groupEnd();\n\n return result;\n } catch (err) {\n console.groupEnd();\n throw err;\n }\n };\n\n const logger: Logger = {\n get bindings(): Readonly<Bindings> {\n return { ...ownBindings };\n },\n\n child: (overrides: LogitOptions = {}): Logger => {\n const remote = resolveRemote(overrides.remote, cfg.remote);\n\n return createLogger(\n {\n logLevel: overrides.logLevel ?? cfg.logLevel,\n namespace: overrides.namespace ?? cfg.namespace,\n remote,\n timestamp: overrides.timestamp ?? cfg.timestamp,\n variant: overrides.variant ?? cfg.variant,\n },\n ownBindings,\n );\n },\n\n get config(): Readonly<LogitConfig> {\n return cfg.remote ? { ...cfg, remote: { ...cfg.remote } } : { ...cfg };\n },\n\n debug: (m?: string | Bindings | Error, s?: string) => emit('debug', m, s),\n\n enabled: (type: LogLevel): boolean => passes(type),\n\n error: (m?: string | Bindings | Error, s?: string) => emit('error', m, s),\n\n fatal: (m?: string | Bindings | Error, s?: string) => emit('fatal', m, s),\n\n group: (label, fn) => wrapGroup(false, label, fn),\n\n groupCollapsed: (label, fn) => wrapGroup(true, label, fn),\n\n info: (m?: string | Bindings | Error, s?: string) => emit('info', m, s),\n\n scope: (name: string): Logger => logger.child({ namespace: cfg.namespace ? `${cfg.namespace}.${name}` : name }),\n\n time: <T>(label: string, fn: () => T): T => {\n if (cfg.logLevel === 'off') return fn();\n\n const tl = toTimeLabel(cfg.namespace, label);\n\n console.time(tl);\n\n try {\n const result = fn();\n\n if (result instanceof Promise) return result.finally(() => console.timeEnd(tl)) as T;\n\n console.timeEnd(tl);\n\n return result;\n } catch (err) {\n console.timeEnd(tl);\n throw err;\n }\n },\n\n warn: (m?: string | Bindings | Error, s?: string) => emit('warn', m, s),\n\n withBindings: (bindings: Bindings): Logger => createLogger(cfg, { ...ownBindings, ...bindings }),\n };\n\n return logger;\n}\n\nexport const Logit = createLogger();\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/logit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"registry": "https://registry.npmjs.org/"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/node": "^25.
|
|
34
|
-
"typescript": "~6.0.
|
|
35
|
-
"vite": "^8.0.
|
|
36
|
-
"vitest": "^4.1.
|
|
33
|
+
"@types/node": "^25.8.0",
|
|
34
|
+
"typescript": "~6.0.3",
|
|
35
|
+
"vite": "^8.0.13",
|
|
36
|
+
"vitest": "^4.1.6"
|
|
37
37
|
}
|
|
38
38
|
}
|