@mugenlabs/logtape-devtools 0.4.0 → 0.4.2

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 CHANGED
@@ -213,8 +213,10 @@ The shared `LogStore` instance (created with the default `maxRecords: 1000`) use
213
213
  | `timestamp` | `number` | Creation time in ms since the Unix epoch |
214
214
  | `level` | `LogLevel` | Severity of the record |
215
215
  | `category` | `string[]` | Logger category path, e.g. `["app", "auth"]` |
216
+ | `categoryKey` | `string \| undefined` | Precomputed `category.join(".")` for filter/search (set by the sink) |
216
217
  | `message` | `unknown[]` | Raw message parts, alternating literals and interpolated values |
217
218
  | `messageText` | `string` | Message parts rendered into one searchable string (computed lazily on first access) |
219
+ | `messageSearchText` | `string \| undefined` | Cached lowercase `messageText` for search (lazy; set by the sink) |
218
220
  | `properties` | `Record<string, unknown>` | Structured properties, deep-cloned for safety |
219
221
  | `caller` | `string \| undefined` | Source location, present only when stack capture ran |
220
222
 
@@ -244,12 +246,12 @@ The shared `LogStore` instance (created with the default `maxRecords: 1000`) use
244
246
 
245
247
  | Peer dependency | Range | Notes |
246
248
  | --- | --- | --- |
247
- | `@logtape/logtape` | `>=2.0.0` | **Optional** — only types are imported; you need it to configure LogTape anyway |
249
+ | `@logtape/logtape` | `^2.0.0` | **Optional** — only types are imported; you need it to configure LogTape anyway |
248
250
  | `react` | `^18.0.0 \|\| ^19.0.0` | Required for the panel |
249
251
  | `react-dom` | `^18.0.0 \|\| ^19.0.0` | Required for the panel |
250
- | `@tanstack/react-devtools` | `>=0.9.0` | **Optional** — only needed to host the panel |
252
+ | `@tanstack/react-devtools` | `^0.9.0` | **Optional** — only needed to host the panel. Bound to 0.9.x because 0.10 changed how props are passed into plugins |
251
253
 
252
- Node `>=18`. The package is published as ESM only (`import` condition, no `require()`). `@tanstack/react-devtools` being optional means you can depend on this package purely for the sink (via `@mugenlabs/logtape-devtools/sink`) without installing the DevTools shell.
254
+ Node `>=24.0.0` (Active LTS). The package is published as ESM only (`import` condition, no `require()`). `@tanstack/react-devtools` being optional means you can depend on this package purely for the sink (via `@mugenlabs/logtape-devtools/sink`) without installing the DevTools shell.
253
255
 
254
256
  ## Demo
255
257
 
@@ -0,0 +1,2 @@
1
+ function m(e){let t=Math.floor(Number(e??1e3));return Number.isFinite(t)&&t>0?t:0}function h(e){if(typeof queueMicrotask=="function"){queueMicrotask(e);return}Promise.resolve().then(e)}function x(e){let t=m(e?.maxRecords),r=[],n=0,o=0,c=[],s=!1,a=new Set,u=!1;function d(){for(let i of a)i()}function l(){u||(u=!0,h(()=>{u=!1,d()}))}function g(){let i=new Array(o);for(let f=0;f<o;f+=1)i[f]=r[(n+f)%r.length];return i}function R(){let i=o>t,f=i?g().slice(o-t):g();return r=f,n=0,o=f.length,i}return{addRecord:i=>{t!==0&&(o<t?(r.push(i),o+=1):(r[n]=i,n=(n+1)%r.length),s=!0,l())},clear:()=>{r=[],n=0,o=0,s=!0,l()},getMaxRecords:()=>t,getSnapshot:()=>(s&&(c=g(),s=!1),c),hasListeners:()=>a.size>0,setMaxSize:i=>{t=m(i),R()&&(s=!0,l())},subscribe:i=>(a.add(i),()=>{a.delete(i)})}}var S=x();var E=["trace","debug","info","warning","error","fatal"];function y(e){switch(typeof e){case"bigint":return`${e}n`;case"symbol":return e.toString();case"function":return`[Function ${e.name||"anonymous"}]`;default:break}if(e instanceof Error){let t={message:e.message,name:e.name};return e.stack&&(t.stack=e.stack),"cause"in e&&e.cause!==void 0&&(t.cause=e.cause),t}return e instanceof Map?[...e.entries()]:e instanceof Set?[...e]:e}function w(){let e=[];return function(r,n){for(;e.length>0&&e.at(-1)?.serialized!==this;)e.pop();if(typeof n=="object"&&n!==null){if(e.some(c=>c.original===n))return"[Circular]";let o=y(n);return typeof o=="object"&&o!==null&&e.push({original:n,serialized:o}),o}return y(n)}}function p(e,t){try{let r=JSON.stringify(e,w(),t);if(r!==void 0)return r}catch{}return String(e)}function k(e){return JSON.parse(p(e))}function L(e){if(typeof structuredClone=="function")try{return structuredClone(e)}catch{}try{return k(e)}catch{}let t={};for(let[r,n]of Object.entries(e))try{t[r]=k(n)}catch{t[r]=String(n)}return t}function b(e){return e.map(t=>typeof t=="string"?t:t==null?String(t):p(t)).join("")}var D=/at\s+(?:.*?\s+\()?(.+?):(\d+):(\d+)\)?$/,v=/(?:^|@)(.+?):(\d+):(\d+)$/;function z(){let{stack:e}=new Error;if(!e)return;let t=e.split(`
2
+ `);for(let r of t){let n=r.trim();if(!n||n==="Error"||/logtape/i.test(n))continue;let o=D.exec(n)??v.exec(n);if(!o)continue;let[,c,s,a]=o;return`${c.replace(/[?#].*$/,"").split("/").pop()??c}:${s}:${a}`}}function M(e,t,r){let n=[...e.message],o=[...e.category],c={category:o,categoryKey:o.join("."),id:r,level:e.level,message:n,properties:L(e.properties),timestamp:e.timestamp},s;Object.defineProperty(c,"messageText",{configurable:!0,enumerable:!0,get:()=>(s??=b(n),s)});let a;if(Object.defineProperty(c,"messageSearchText",{configurable:!0,enumerable:!0,get:()=>(a===void 0&&(s??=b(n),a=s.toLowerCase()),a)}),t){let u=z();u&&(c.caller=u)}return c}function O(){try{if(typeof process<"u"&&process.env?.NODE_ENV==="production")return!0}catch{}return!1}function A(e){let t=e?.store??S,r=e?.captureStackTrace??!0,n=e?.forceStackTrace??!1,o=r&&(n||!O()),c=Math.random().toString(36).slice(2,8),s=0,a=!1;return Object.assign(d=>{if(!(a||t.getMaxRecords?.()===0))try{let l=o&&(n||t.hasListeners());s+=1;let g=M(d,l,`log-${c}-${s}-${d.timestamp}`);t.addRecord(g)}catch{}},{[Symbol.dispose]:()=>{a=!0}})}export{x as a,S as b,p as c,E as d,A as e};