devink 2.0.0 β 2.0.1
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 +16 -37
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<img src="https://raw.githubusercontent.com/harrymate22/devink/main/media/demo.png" alt="devink demo" width="600" />
|
|
18
18
|
</p>
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Features
|
|
21
21
|
|
|
22
22
|
- **Zero Dependencies** β Ultra-fast, nothing in `node_modules` except your own code.
|
|
23
23
|
- **Child Loggers** β Scoped, namespaced loggers with inherited configuration.
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
- **Log Sampling / Rate Limiting** β Only log a fraction of high-frequency events in production.
|
|
29
29
|
- **Sensitive Field Redaction** β Automatically mask passwords, tokens, and secrets from log output.
|
|
30
30
|
- **Pretty Error Formatting** β Colored stack traces with highlighted source locations.
|
|
31
|
-
- **Full ANSI & 256/RGB Color Support** β Beautiful
|
|
32
|
-
- **Structured JSON Logging** β One-line switch to JSON for Datadog, ELK,
|
|
31
|
+
- **Full ANSI & 256/RGB Color Support** β Beautiful themes for the terminal.
|
|
32
|
+
- **Structured JSON Logging** β One-line switch to JSON for Datadog, ELK, and more.
|
|
33
33
|
- **Log Levels & Priority Filtering** β Granular control via `trace`, `debug`, `info`, `warn`, `error`, and `fatal`.
|
|
34
34
|
- **Custom Transports** β Route logs to files, external APIs, or custom formatting engines.
|
|
35
35
|
- **Terminal Capability Detection** β Auto-detects `TTY`, `FORCE_COLOR`, `NO_COLOR`, and `CI` environments.
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## Installation
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
npm install devink
|
|
@@ -54,7 +54,7 @@ pnpm add devink
|
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Quick Start
|
|
58
58
|
|
|
59
59
|
### Basic Logger
|
|
60
60
|
|
|
@@ -117,7 +117,7 @@ requestLogger.info('Request received');
|
|
|
117
117
|
|
|
118
118
|
---
|
|
119
119
|
|
|
120
|
-
##
|
|
120
|
+
## HTTP Request Middleware
|
|
121
121
|
|
|
122
122
|
Framework-agnostic middleware that auto-logs every HTTP request with method, path, status code, and response time:
|
|
123
123
|
|
|
@@ -140,7 +140,7 @@ Works with **Express**, **Fastify**, **Hono**, **Koa**, and any framework using
|
|
|
140
140
|
|
|
141
141
|
---
|
|
142
142
|
|
|
143
|
-
##
|
|
143
|
+
## Log Grouping
|
|
144
144
|
|
|
145
145
|
Visually group related log lines for multi-step operations:
|
|
146
146
|
|
|
@@ -168,7 +168,7 @@ Output:
|
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
171
|
-
##
|
|
171
|
+
## Performance Timers
|
|
172
172
|
|
|
173
173
|
Measure execution time for any operation directly from the logger:
|
|
174
174
|
|
|
@@ -188,7 +188,7 @@ logger.timeEnd('api-call');
|
|
|
188
188
|
|
|
189
189
|
---
|
|
190
190
|
|
|
191
|
-
##
|
|
191
|
+
## Log Sampling
|
|
192
192
|
|
|
193
193
|
In high-throughput production environments, log only a fraction of repetitive events:
|
|
194
194
|
|
|
@@ -206,7 +206,7 @@ logger.info('Query executed', { table: 'users' });
|
|
|
206
206
|
|
|
207
207
|
---
|
|
208
208
|
|
|
209
|
-
##
|
|
209
|
+
## File Transport
|
|
210
210
|
|
|
211
211
|
Built-in file transport with async writes and automatic log rotation:
|
|
212
212
|
|
|
@@ -231,7 +231,7 @@ When `app.log` exceeds 10 MB, it rotates to `app.log.1`, `app.log.2`, etc., keep
|
|
|
231
231
|
|
|
232
232
|
---
|
|
233
233
|
|
|
234
|
-
##
|
|
234
|
+
## Field Redaction
|
|
235
235
|
|
|
236
236
|
Automatically mask sensitive data before it reaches any transport:
|
|
237
237
|
|
|
@@ -248,7 +248,7 @@ Redaction works recursively on nested objects and in both text and JSON modes.
|
|
|
248
248
|
|
|
249
249
|
---
|
|
250
250
|
|
|
251
|
-
##
|
|
251
|
+
## Error Formatting
|
|
252
252
|
|
|
253
253
|
When you pass an `Error` object, devink renders a beautiful, colored stack trace instead of a raw dump:
|
|
254
254
|
|
|
@@ -268,7 +268,7 @@ try {
|
|
|
268
268
|
|
|
269
269
|
---
|
|
270
270
|
|
|
271
|
-
##
|
|
271
|
+
## Boxed Output
|
|
272
272
|
|
|
273
273
|
Make important startup messages or critical alerts pop in the console:
|
|
274
274
|
|
|
@@ -283,7 +283,7 @@ logger.box(
|
|
|
283
283
|
|
|
284
284
|
---
|
|
285
285
|
|
|
286
|
-
##
|
|
286
|
+
## Configuration
|
|
287
287
|
|
|
288
288
|
The `createLogger` function accepts an optional `LoggerOptions` object:
|
|
289
289
|
|
|
@@ -336,7 +336,7 @@ const logger = createLogger({
|
|
|
336
336
|
|
|
337
337
|
---
|
|
338
338
|
|
|
339
|
-
##
|
|
339
|
+
## ANSI Utilities
|
|
340
340
|
|
|
341
341
|
Build your own CLI tools with devink's high-performance, zero-dependency ANSI utilities:
|
|
342
342
|
|
|
@@ -351,30 +351,9 @@ console.log(ansi.bold(ansi.cyan('Bold and cyan!')));
|
|
|
351
351
|
|
|
352
352
|
---
|
|
353
353
|
|
|
354
|
-
## π Comparison: devink vs pino vs winston vs bunyan
|
|
355
|
-
|
|
356
|
-
| Feature | devink | pino | winston | bunyan |
|
|
357
|
-
| -------------------------- | ------ | -------------- | -------------- | ------------- |
|
|
358
|
-
| Zero Dependencies | β
| β | β | β |
|
|
359
|
-
| TypeScript Native | β
| β (types pkg) | β (types pkg) | β |
|
|
360
|
-
| Child Loggers | β
| β
| β
| β
|
|
|
361
|
-
| HTTP Middleware (built-in) | β
| β (separate) | β (separate) | β |
|
|
362
|
-
| File Transport (built-in) | β
| β (separate) | β
| β
|
|
|
363
|
-
| Log Rotation (built-in) | β
| β | β (separate) | β (separate) |
|
|
364
|
-
| Log Sampling | β
| β | β | β |
|
|
365
|
-
| Field Redaction | β
| β
| β | β |
|
|
366
|
-
| Pretty Error Formatting | β
| β (separate) | β | β |
|
|
367
|
-
| Log Grouping | β
| β | β | β |
|
|
368
|
-
| Performance Timers | β
| β | β | β |
|
|
369
|
-
| Colored ANSI Output | β
| β (separate) | β (separate) | β |
|
|
370
|
-
| Boxed Output | β
| β | β | β |
|
|
371
|
-
| JSON Structured Logging | β
| β
| β
| β
|
|
|
372
|
-
| Custom Themes | β
| β | β | β |
|
|
373
|
-
| Bundle Size | ~8KB | ~120KB | ~280KB | ~95KB |
|
|
374
|
-
|
|
375
354
|
---
|
|
376
355
|
|
|
377
|
-
##
|
|
356
|
+
## Roadmap
|
|
378
357
|
|
|
379
358
|
These features are planned for upcoming releases:
|
|
380
359
|
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=require("fs/promises"),e=require("fs"),s=require("path"),r=Object.defineProperty,i={};((t,e)=>{for(var s in e)r(t,s,{get:e[s],enumerable:!0})})(i,{bgBlack:()=>w,bgBlue:()=>k,bgColor256:()=>N,bgCyan:()=>j,bgGreen:()=>v,bgHex:()=>I,bgMagenta:()=>O,bgRed:()=>x,bgRgb:()=>L,bgWhite:()=>C,bgYellow:()=>y,black:()=>f,blue:()=>u,bold:()=>E,color256:()=>F,cyan:()=>b,dim:()=>T,format:()=>c,gray:()=>$,green:()=>m,hex:()=>A,inverse:()=>M,isColorSupported:()=>o,italic:()=>S,magenta:()=>d,red:()=>l,reset:()=>h,rgb:()=>R,stripAnsi:()=>q,underline:()=>z,white:()=>g,yellow:()=>p});var n=process.env,o=!n.NO_COLOR&&(n.FORCE_COLOR||process.stdout&&process.stdout.isTTY||"xterm-256color"===n.TERM||"true"===n.CI),a=(t,e)=>o?`[${t}m${e}[0m`:e,c=a,h=t=>a(0,t),f=t=>a(30,t),l=t=>a(31,t),m=t=>a(32,t),p=t=>a(33,t),u=t=>a(34,t),d=t=>a(35,t),b=t=>a(36,t),g=t=>a(37,t),$=t=>a(90,t),w=t=>a(40,t),x=t=>a(41,t),v=t=>a(42,t),y=t=>a(43,t),k=t=>a(44,t),O=t=>a(45,t),j=t=>a(46,t),C=t=>a(47,t),E=t=>a(1,t),T=t=>a(2,t),S=t=>a(3,t),z=t=>a(4,t),M=t=>a(7,t),R=(t,e,s,r)=>o?`[38;2;${t};${e};${s}m${r}[0m`:r,L=(t,e,s,r)=>o?`[48;2;${t};${e};${s}m${r}[0m`:r,A=(t,e)=>{if(!o)return e;const s=t.replace("#","");return 6===s.length?R(parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),e):e},I=(t,e)=>{if(!o)return e;const s=t.replace("#","");return 6===s.length?L(parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),e):e},F=(t,e)=>o?`[38;5;${t}m${e}[0m`:e,N=(t,e)=>o?`[48;5;${t}m${e}[0m`:e,q=t=>t.replace(/\x1b\[[0-9;]*m/g,""),P={success:t=>A("#10b981",t),error:t=>A("#f43f5e",t),warn:t=>A("#f59e0b",t),info:t=>A("#38bdf8",t),prefix:{success:A("#10b981","β")+" "+A("#34d399",T("success")),error:A("#f43f5e","β")+" "+A("#fb7185",T("error")),warn:A("#f59e0b","β ")+" "+A("#fbbf24",T("warn")),info:A("#38bdf8","βΉ")+" "+A("#7dd3fc",T("info"))}},W={success:t=>t,error:t=>t,warn:t=>t,info:t=>t,prefix:{success:A("#10b981","β"),error:A("#f43f5e","β"),warn:A("#f59e0b","β "),info:A("#38bdf8","βΉ")}},B={success:t=>m(t),error:t=>l(t),warn:t=>p(t),info:t=>b(t),prefix:{success:m("SUCCESS"),error:l("ERROR"),warn:p("WARN"),info:b("INFO")}},U=P,D=(t=>(t[t.trace=10]="trace",t[t.debug=20]="debug",t[t.info=30]="info",t[t.success=35]="success",t[t.warn=40]="warn",t[t.error=50]="error",t[t.fatal=60]="fatal",t[t.none=100]="none",t))(D||{}),J=class{write(t){(t.levelValue>=50?console.error:console.log)(t.formatted)}},_={iso:"",formatted:""},V=new Set;function Y(t,e){V.clear();const s=JSON.stringify(t,(t,e)=>{if("object"==typeof e&&null!==e){if(V.has(e))return"[Circular]";V.add(e)}return e},e);return V.clear(),s}function G(t,e){if("object"!=typeof t||null===t||t instanceof Error)return t;if(Array.isArray(t))return t.map(t=>G(t,e));const s={};for(const[r,i]of Object.entries(t))s[r]=e.has(r.toLowerCase())?"[REDACTED]":"object"!=typeof i||null===i||i instanceof Error?i:G(i,e);return s}var H=class t{t;ts;c;lv;m;tr;tc={t:"",s:""};sp;rk;ns;gd=0;tm=new Map;sc=new Map;dm;constructor(t={},e={}){this.t={...U,...t.theme,prefix:{...U.prefix,...t.theme?.prefix}},this.ts=t.timestamps??!1,this.c=t.colors??Boolean(o),this.lv=D[t.level??"trace"],this.m=t.mode??"text",this.tr=t.transports??[new J],this.sp=t.sampling??{},this.rk=new Set((t.redact??[]).map(t=>t.toLowerCase())),this.ns=t.namespace??"",this.dm=e}child(e){const{namespace:s,...r}=e;return new t({theme:this.t,timestamps:this.ts,colors:this.c,level:Object.keys(D).find(t=>D[t]===this.lv),mode:this.m,transports:this.tr,sampling:this.sp,redact:Array.from(this.rk),namespace:s?this.ns?`${this.ns}:${s}`:s:this.ns},{...this.dm,...r})}group(t){if(30<this.lv)return;const e=this.getTs(),s=this.nsPrefix(),r=" ".repeat(this.gd);if("json"===this.m){const s=Y({level:"info",type:"groupStart",label:t,time:e.iso});this.dispatch("info",30,[t],s,s,e.iso)}else{const i=`${e.formatted}${s}${r}${this.c?E(b(`βΈ ${t}`)):`βΈ ${t}`}`;this.dispatch("info",30,[t],i,q(i),e.iso)}this.gd++}groupEnd(){this.gd>0&&this.gd--}time(t){this.tm.set(t,performance.now())}timeEnd(t){const e=this.tm.get(t);if(void 0===e)return;this.tm.delete(t);const s=performance.now()-e;this.info(`${t}: ${s<1?s.toFixed(3):Math.round(s)}ms`)}getTs(){if(!this.ts)return _;const t=(new Date).toISOString(),e=t.slice(11,19);if(this.tc.t===e)return{iso:t,formatted:this.tc.s};const s=$(`[${e}] `);return this.tc={t:e,s:s},{iso:t,formatted:s}}nsPrefix(){return this.ns?this.c?A("#a78bfa",`[${this.ns}] `):`[${this.ns}] `:""}hlJson(t){return!this.c||t.length>5e3?t:t.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g,t=>'"'===t[0]?t.endsWith(":")?A("#9ca3af",t.slice(0,-1))+":":A("#34d399",t):A("true"===t||"false"===t?"#c084fc":"null"===t?"#f87171":"#fbbf24",t))}fmtErr(t){const e=t.stack||t.message;return this.c?e.split("\n").map((t,e)=>{if(0===e)return E(l(t));const s=t.match(/^(\s+at\s+)(.+?)(\s+\()?(.+?):(\d+):(\d+)\)?$/);return s?s[4].includes("node_modules")||s[4].startsWith("node:")?T(t):`${T(s[1])}${p(s[2])}${T(s[3]||" ")}${b(s[4])}:${A("#fbbf24",s[5])}:${T(s[6])}${s[3]?T(")"):""}`:t.match(/^\s+at\s+/)?T(t):l(t)}).join("\n"):e}fmtMsg(t){return t.map(t=>{if("string"==typeof t)return t;if(t instanceof Error)return"\n"+this.fmtErr(t);try{return"\n"+this.hlJson(Y(this.rk.size?G(t,this.rk):t,2))}catch{return"[Unserializable]"}}).join(" ")}emit(t,e,s,r){const i=D[t];if(i<this.lv)return;const n=this.getTs(),o=this.nsPrefix(),a=" ".repeat(this.gd);let c,h;if("json"===this.m){const e=r.map(t=>"object"!=typeof t||null===t||t instanceof Error||!this.rk.size?t:G(t,this.rk)),s={level:t,time:n.iso,message:1===e.length?e[0]:e};this.ns&&(s.namespace=this.ns),Object.keys(this.dm).length&&Object.assign(s,this.dm),c=h=Y(s)}else c=`${n.formatted}${o}${a}${e} ${s(this.fmtMsg(r))}`,h=q(c),this.c||(c=h);this.dispatch(t,i,r,c,h,n.iso)}dispatch(t,e,s,r,i,n){const o={level:t,levelValue:e,message:s,formatted:r,raw:i,timestamp:n,namespace:this.ns||void 0,meta:Object.keys(this.dm).length?this.dm:void 0};for(let t=0;t<this.tr.length;t++)this.tr[t]?.write(o)}success(...t){this.emit("success",this.t.prefix.success,this.t.success,t)}error(...t){this.emit("error",this.t.prefix.error,this.t.error,t)}warn(...t){this.emit("warn",this.t.prefix.warn,this.t.warn,t)}info(...t){this.emit("info",this.t.prefix.info,this.t.info,t)}trace(...t){this.emit("trace",$("π"),$,t)}debug(...t){this.emit("debug",A("#94a3b8","π"),t=>A("#94a3b8",t),t)}fatal(...t){this.emit("fatal",A("#be123c","π"),t=>A("#be123c",t),t)}box(t,e){if(30<this.lv)return;const s=e.split("\n"),r=Math.max(t.length,...s.map(t=>q(t).length))+4,i=`ββ ${t} ${"β".repeat(r-t.length-3)}β`,n=`β${"β".repeat(r)}β`;let o=[i,...s.map(t=>`β ${t}${" ".repeat(Math.max(0,r-q(t).length-2))} β`),n].join("\n");const a=q(o),c=this.getTs();if("json"===this.m){const s=Y({level:"info",time:c.iso,title:t,message:e});return void this.dispatch("info",30,[e],s,s,c.iso)}this.c&&(o=A("#38bdf8",o)),this.dispatch("info",30,[e],o,a,c.iso)}},K={b:1,kb:1024,mb:1048576,gb:1073741824};exports.ConsoleTransport=J,exports.FileTransport=class{fp;ms;mf;rot;sz=0;q=Promise.resolve();init=!1;constructor(t){this.fp=t.path,this.ms=function(t){if("number"==typeof t)return t;const e=t.trim().toLowerCase().match(/^([\d.]+)\s*(b|kb|mb|gb)?$/);return e?Math.floor(parseFloat(e[1])*K[e[2]||"b"]):10485760}(t.maxSize??"10mb"),this.mf=t.maxFiles??5,this.rot=t.rotate??!0;const r=s.dirname(this.fp);e.existsSync(r)||e.mkdirSync(r,{recursive:!0})}write(t){const e=t.raw+"\n";this.q=this.q.then(()=>this.flush(e))}async flush(e){if(!this.init){try{this.sz=(await t.stat(this.fp)).size}catch{this.sz=0}this.init=!0}const s=Buffer.byteLength(e,"utf8");if(this.rot&&this.sz+s>this.ms){for(let e=this.mf-1;e>=1;e--)try{await t.rename(1===e?this.fp:`${this.fp}.${e-1}`,`${this.fp}.${e}`)}catch{}try{await t.unlink(this.fp)}catch{}this.sz=0}await t.appendFile(this.fp,e,"utf8"),this.sz+=s}},exports.LogLevel=D,exports.Logger=H,exports.ansi=i,exports.classicTheme=B,exports.createLogger=t=>new H(t),exports.defaultTheme=U,exports.httpMiddleware=function(t,e={}){const s=e.warnAbove??400,r=e.errorAbove??500;return(e,i,n)=>{const o=performance.now(),a=e.method??"UNKNOWN",c=e.originalUrl??e.url??"/",h=()=>{const e=Math.round(performance.now()-o),n=i.statusCode??0,h=`${a} ${c} ${n} ${e}ms`;n>=r?t.error(h):n>=s?t.warn(h):t.info(h)},f=i.on,l=i.once;"function"==typeof f?f.call(i,"finish",h):"function"==typeof l&&l.call(i,"close",h),n()}},exports.minimalTheme=W,exports.modernTheme=P;
|
|
1
|
+
"use strict";var t=require("fs/promises"),e=require("fs"),s=require("path"),r=Object.defineProperty,i={};((t,e)=>{for(var s in e)r(t,s,{get:e[s],enumerable:!0})})(i,{bgBlack:()=>w,bgBlue:()=>k,bgColor256:()=>N,bgCyan:()=>j,bgGreen:()=>v,bgHex:()=>I,bgMagenta:()=>O,bgRed:()=>x,bgRgb:()=>L,bgWhite:()=>C,bgYellow:()=>y,black:()=>f,blue:()=>u,bold:()=>E,color256:()=>F,cyan:()=>b,dim:()=>T,format:()=>c,gray:()=>$,green:()=>m,hex:()=>A,inverse:()=>M,isColorSupported:()=>o,italic:()=>S,magenta:()=>d,red:()=>l,reset:()=>h,rgb:()=>R,stripAnsi:()=>q,underline:()=>z,white:()=>g,yellow:()=>p});var n=process.env,o=!n.NO_COLOR&&(n.FORCE_COLOR||process.stdout&&process.stdout.isTTY||"xterm-256color"===n.TERM||"true"===n.CI),a=(t,e)=>o?`[${t}m${e}[0m`:e,c=a,h=t=>a(0,t),f=t=>a(30,t),l=t=>a(31,t),m=t=>a(32,t),p=t=>a(33,t),u=t=>a(34,t),d=t=>a(35,t),b=t=>a(36,t),g=t=>a(37,t),$=t=>a(90,t),w=t=>a(40,t),x=t=>a(41,t),v=t=>a(42,t),y=t=>a(43,t),k=t=>a(44,t),O=t=>a(45,t),j=t=>a(46,t),C=t=>a(47,t),E=t=>a(1,t),T=t=>a(2,t),S=t=>a(3,t),z=t=>a(4,t),M=t=>a(7,t),R=(t,e,s,r)=>o?`[38;2;${t};${e};${s}m${r}[0m`:r,L=(t,e,s,r)=>o?`[48;2;${t};${e};${s}m${r}[0m`:r,A=(t,e)=>{if(!o)return e;const s=t.replace("#","");return 6===s.length?R(parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),e):e},I=(t,e)=>{if(!o)return e;const s=t.replace("#","");return 6===s.length?L(parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),e):e},F=(t,e)=>o?`[38;5;${t}m${e}[0m`:e,N=(t,e)=>o?`[48;5;${t}m${e}[0m`:e,q=t=>t.replace(/\x1b\[[0-9;]*m/g,""),P={success:t=>A("#10b981",t),error:t=>A("#f43f5e",t),warn:t=>A("#f59e0b",t),info:t=>A("#38bdf8",t),prefix:{success:A("#10b981","β")+" "+A("#34d399",T("success")),error:A("#f43f5e","β")+" "+A("#fb7185",T("error")),warn:A("#f59e0b","β ")+" "+A("#fbbf24",T("warn")),info:A("#38bdf8","βΉ")+" "+A("#7dd3fc",T("info"))}},W={success:t=>t,error:t=>t,warn:t=>t,info:t=>t,prefix:{success:A("#10b981","β"),error:A("#f43f5e","β"),warn:A("#f59e0b","β "),info:A("#38bdf8","βΉ")}},B={success:t=>m(t),error:t=>l(t),warn:t=>p(t),info:t=>b(t),prefix:{success:m("SUCCESS"),error:l("ERROR"),warn:p("WARN"),info:b("INFO")}},U=P,D=(t=>(t[t.trace=10]="trace",t[t.debug=20]="debug",t[t.info=30]="info",t[t.success=35]="success",t[t.warn=40]="warn",t[t.error=50]="error",t[t.fatal=60]="fatal",t[t.none=100]="none",t))(D||{}),J=class{write(t){(t.levelValue>=50?console.error:console.log)(t.formatted)}},_={iso:"",formatted:""},V=new Set;function Y(t,e){V.clear();const s=JSON.stringify(t,(t,e)=>{if("object"==typeof e&&null!==e){if(V.has(e))return"[Circular]";V.add(e)}return e},e);return V.clear(),s}function G(t,e){if("object"!=typeof t||null===t||t instanceof Error)return t;if(Array.isArray(t))return t.map(t=>G(t,e));const s={};for(const[r,i]of Object.entries(t))s[r]=e.has(r.toLowerCase())?"[REDACTED]":"object"!=typeof i||null===i||i instanceof Error?i:G(i,e);return s}var H=class t{t;ts;c;lv;m;tr;tc={t:"",s:""};sp;rk;ns;gd=0;tm=new Map;sc=new Map;dm;constructor(t={},e={}){this.t={...U,...t.theme,prefix:{...U.prefix,...t.theme?.prefix}},this.ts=t.timestamps??!1,this.c=t.colors??Boolean(o),this.lv=D[t.level??"trace"],this.m=t.mode??"text",this.tr=t.transports??[new J],this.sp=t.sampling??{},this.rk=new Set((t.redact??[]).map(t=>t.toLowerCase())),this.ns=t.namespace??"",this.dm=e}child(e){const{namespace:s,...r}=e;return new t({theme:this.t,timestamps:this.ts,colors:this.c,level:Object.keys(D).find(t=>D[t]===this.lv),mode:this.m,transports:this.tr,sampling:this.sp,redact:Array.from(this.rk),namespace:s?this.ns?`${this.ns}:${s}`:s:this.ns},{...this.dm,...r})}group(t){if(30<this.lv)return;const e=this.getTs(),s=this.nsPrefix(),r=" ".repeat(this.gd);if("json"===this.m){const s=Y({level:"info",type:"groupStart",label:t,time:e.iso});this.dispatch("info",30,[t],s,s,e.iso)}else{const i=`${e.formatted}${s}${r}${this.c?E(b(`βΈ ${t}`)):`βΈ ${t}`}`;this.dispatch("info",30,[t],i,q(i),e.iso)}this.gd++}groupEnd(){this.gd>0&&this.gd--}time(t){this.tm.set(t,performance.now())}timeEnd(t){const e=this.tm.get(t);if(void 0===e)return;this.tm.delete(t);const s=performance.now()-e;this.info(`${t}: ${s<1?s.toFixed(3):Math.round(s)}ms`)}getTs(){if(!this.ts)return _;const t=(new Date).toISOString(),e=t.slice(11,19);if(this.tc.t===e)return{iso:t,formatted:this.tc.s};const s=$(`[${e}] `);return this.tc={t:e,s:s},{iso:t,formatted:s}}nsPrefix(){return this.ns?this.c?A("#a78bfa",`[${this.ns}] `):`[${this.ns}] `:""}hlJson(t){return!this.c||t.length>5e3?t:t.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g,t=>'"'===t[0]?t.endsWith(":")?A("#9ca3af",t.slice(0,-1))+":":A("#34d399",t):A("true"===t||"false"===t?"#c084fc":"null"===t?"#f87171":"#fbbf24",t))}fmtErr(t){const e=t.stack||t.message;return this.c?e.split("\n").map((t,e)=>{if(0===e)return E(l(t));const s=t.match(/^(\s+at\s+)(.+?)(\s+\()?(.+?):(\d+):(\d+)\)?$/);return s?s[4].includes("node_modules")||s[4].startsWith("node:")?T(t):`${T(s[1])}${p(s[2])}${T(s[3]||" ")}${b(s[4])}:${A("#fbbf24",s[5])}:${T(s[6])}${s[3]?T(")"):""}`:t.match(/^\s+at\s+/)?T(t):l(t)}).join("\n"):e}fmtMsg(t){return t.map(t=>{if("string"==typeof t)return t;if(t instanceof Error)return"\n"+this.fmtErr(t);try{return"\n"+this.hlJson(Y(this.rk.size?G(t,this.rk):t,2))}catch{return"[Unserializable]"}}).join(" ")}emit(t,e,s,r){const i=D[t];if(i<this.lv)return;const n=this.getTs(),o=this.nsPrefix(),a=" ".repeat(this.gd);let c,h;if("json"===this.m){const e=r.map(t=>"object"!=typeof t||null===t||t instanceof Error||!this.rk.size?t:G(t,this.rk)),s={level:t,time:n.iso,message:1===e.length?e[0]:e};this.ns&&(s.namespace=this.ns),Object.keys(this.dm).length&&Object.assign(s,this.dm),c=h=Y(s)}else c=`${n.formatted}${o}${a}${e} ${s(this.fmtMsg(r))}`,h=q(c),this.c||(c=h);this.dispatch(t,i,r,c,h,n.iso)}dispatch(t,e,s,r,i,n){const o={level:t,levelValue:e,message:s,formatted:r,raw:i,timestamp:n,namespace:this.ns||void 0,meta:Object.keys(this.dm).length?this.dm:void 0};for(let t=0;t<this.tr.length;t++)this.tr[t]?.write(o)}success(...t){this.emit("success",this.t.prefix.success,this.t.success,t)}error(...t){this.emit("error",this.t.prefix.error,this.t.error,t)}warn(...t){this.emit("warn",this.t.prefix.warn,this.t.warn,t)}info(...t){this.emit("info",this.t.prefix.info,this.t.info,t)}trace(...t){this.emit("trace",$("π"),$,t)}debug(...t){this.emit("debug",A("#94a3b8","π"),t=>A("#94a3b8",t),t)}fatal(...t){this.emit("fatal",A("#be123c","π"),t=>A("#be123c",t),t)}box(t,e){if(30<this.lv)return;const s=e.split("\n"),r=Math.max(t.length,...s.map(t=>q(t).length))+4,i=`ββ ${t} ${"β".repeat(r-t.length-3)}β`,n=`β${"β".repeat(r)}β`;let o=[i,...s.map(t=>`β ${t}${" ".repeat(Math.max(0,r-q(t).length-2))} β`),n].join("\n");const a=q(o),c=this.getTs();if("json"===this.m){const s=Y({level:"info",time:c.iso,title:t,message:e});return void this.dispatch("info",30,[e],s,s,c.iso)}this.c&&(o=A("#38bdf8",o)),this.dispatch("info",30,[e],o,a,c.iso)}},K={b:1,kb:1024,mb:1048576,gb:1073741824};exports.ConsoleTransport=J,exports.FileTransport=class{fp;ms;mf;rot;sz=0;q=Promise.resolve();init=!1;constructor(t){this.fp=t.path,this.ms=function(t){if("number"==typeof t)return t;const e=t.trim().toLowerCase().match(/^([\d.]+)\s*(b|kb|mb|gb)?$/);return e?Math.floor(parseFloat(e[1])*K[e[2]||"b"]):10485760}(t.maxSize??"10mb"),this.mf=t.maxFiles??5,this.rot=t.rotate??!0;const r=s.dirname(this.fp);e.existsSync(r)||e.mkdirSync(r,{recursive:!0})}write(t){const e=t.raw+"\n";this.q=this.q.then(()=>this.flush(e))}async flush(e){if(!this.init){try{this.sz=(await t.stat(this.fp)).size}catch{this.sz=0}this.init=!0}const s=Buffer.byteLength(e,"utf8");if(this.rot&&this.sz+s>this.ms){for(let e=this.mf-1;e>=1;e--)try{await t.rename(1===e?this.fp:`${this.fp}.${e-1}`,`${this.fp}.${e}`)}catch{}try{await t.unlink(this.fp)}catch{}this.sz=0}await t.appendFile(this.fp,e,"utf8"),this.sz+=s}},exports.LogLevel=D,exports.Logger=H,exports.ansi=i,exports.classicTheme=B,exports.createLogger=t=>new H(t),exports.defaultTheme=U,exports.httpMiddleware=function(t,e={}){const s=e.warnAbove??400,r=e.errorAbove??500;return(e,i,n)=>{const o=performance.now(),a=e.method??"UNKNOWN",c=e.originalUrl??e.url??"/",h=()=>{const e=Math.round(performance.now()-o),n=i.statusCode??0,h=`${a} ${c} ${n} ${e}ms`;n>=r?t.error(h):n>=s?t.warn(h):t.info(h)},f=i.on,l=i.once;"function"==typeof f?f.call(i,"finish",h):"function"==typeof l&&l.call(i,"close",h),n()}},exports.minimalTheme=W,exports.modernTheme=P;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devink",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Fast, lightweight, professional TypeScript logger with child loggers, HTTP middleware, file transport, log sampling, field redaction, and zero dependencies.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|