@stacksjs/logging 0.73.1 → 0.73.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/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Logger } from '@stacksjs/clarity';
1
2
  import type { LogContext, LogLevel, LogRecord, LogTransport } from '@stacksjs/types';
2
3
  // Request context propagation for structured logging, and the transport
3
4
  // contract. Both are declared in `@stacksjs/types` so `config/logging.ts` can
@@ -25,6 +26,20 @@ export declare function transports(): readonly LogTransport[];
25
26
  * for clarity's `warning`.
26
27
  */
27
28
  export declare function parseLogLevel(raw: string | undefined, fallback?: LogLevel): LogLevel;
29
+ /**
30
+ * The level in force right now, at the same precedence the logger itself was
31
+ * built with: **env var > config file > default**.
32
+ *
33
+ * Exists because the synchronous fast paths need an answer without awaiting
34
+ * the logger, and the env var is the only part of that answer available
35
+ * synchronously. The config half arrives later and is filled in by the
36
+ * refresh; until then this reports what the logger is actually doing.
37
+ *
38
+ * Env is re-read per call rather than snapshotted: `LOG_LEVEL` is routinely
39
+ * set from inside a process (tests, `buddy` subcommands) after this module has
40
+ * loaded, and a snapshot would ignore it.
41
+ */
42
+ export declare function currentLevel(): LogLevel;
28
43
  /** Parse + validate `LOG_FORMAT`; defaults to json in prod, text in dev. */
29
44
  export declare function parseLogFormat(raw: string | undefined): LogFormat;
30
45
  /**
@@ -70,7 +85,12 @@ export declare function withLogContext<T>(context: LogContext, fn: () => T): T;
70
85
  * ambient one.
71
86
  */
72
87
  export declare function getLogContext(): LogContext | undefined;
73
- declare function getLogger(): Promise<Logger>;
88
+ /*.ts` file,
89
+ * or from a module one of them imports at evaluation time: it waits on the
90
+ * very load those files are part of. The `log.*` methods have no such
91
+ * restriction - they never wait on config - and are what that code wants.
92
+ */
93
+ export declare function logger(): Promise<Logger>;
74
94
  // Helper function to format message for logging, including request context.
75
95
  // Exported for direct unit testing of arg handling (stacksjs/stacks#2047).
76
96
  export declare function formatMessage(...args: unknown[]): string;
@@ -212,5 +232,3 @@ export declare interface ReportOptions {
212
232
  declare interface StructuredFields { [key: string]: unknown }
213
233
  export type LogFormat = 'json' | 'text';
214
234
  export type ErrorMessage = string;
215
- // Export logger getter for debugging
216
- export { getLogger as logger };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // @bun
2
- var L=import.meta.require;import{AsyncLocalStorage as z}from"async_hooks";import s from"process";import{Logger as A}from"@stacksjs/clarity";import{handleError as V}from"@stacksjs/error-handling";import{ExitCode as x}from"@stacksjs/types";var b=null,v=null,E=new Set;function P(e){return E.add(e),e.finally(()=>E.delete(e)).catch(()=>{}),e}var O=!1;function D(){if(O)return;O=!0,s.on("beforeExit",()=>{g.flush()})}var u=[],T=new Set,C={debug:0,info:1,success:1,warning:2,error:3};function N(e){let t=e;if(!t||typeof t!=="object"||typeof t.log!=="function")return s.stderr.write(`[logging] Ignoring a transport without a log() function.
3
- `),null;if(typeof t.name!=="string"||!t.name)return s.stderr.write(`[logging] Ignoring a transport without a name.
4
- `),null;return u.push(t),()=>{let n=u.indexOf(t);if(n!==-1)u.splice(n,1)}}function ne(e){let t=N(e);if(!t)return()=>{};return I(),t}function re(){return[...u]}function l(e,t,n){if(u.length===0)return;let r;try{r={level:e,message:t,args:n,context:S(),timestamp:new Date().toISOString()}}catch{return}for(let o of u){if(o.level&&C[e]<C[o.level])continue;try{o.log(r)}catch(i){if(!T.has(o.name)){T.add(o.name);let p=i instanceof Error?i.message:String(i);s.stderr.write(`[logging] Transport "${o.name}" threw: ${p}. Further throws from it are silent.
5
- `)}}}}async function G(){let e=u.filter((t)=>typeof t.flush==="function").map((t)=>t.flush().catch(()=>{}));if(e.length>0)await Promise.allSettled(e)}var j=new Set(["debug","info","success","warning","error"]);function R(e,t="info"){if(!e)return t;let n=e.toLowerCase();if(n==="warn")return"warning";if(j.has(n))return n;return s.stderr.write(`[logging] Ignoring invalid LOG_LEVEL="${e}" (expected: ${[...j].join(", ")}); using "${t}".
6
- `),t}function M(e){if(e==="json"||e==="text")return e;if(e)s.stderr.write(`[logging] Ignoring invalid LOG_FORMAT="${e}" (expected "json" or "text").
7
- `);return s.env.NODE_ENV==="production"?"json":"text"}function W(e){let t=e.envLevel?R(e.envLevel):e.cfgLevel?R(e.cfgLevel):"info",n=e.envFormat?M(e.envFormat):e.cfgFormat==="json"||e.cfgFormat==="text"?e.cfgFormat:e.isProduction?"json":"text";return{level:t,format:n,writeToFile:e.cfgWriteToFile??!0}}function m(e,t=0){if(t>8)return{name:"Error",message:"[cause chain truncated]"};if(e instanceof Error)return{name:e.name,message:e.message,stack:e.stack,cause:e.cause!=null?m(e.cause,t+1):void 0};if(typeof e==="string")return{name:"Error",message:e};if(e==null)return{name:"Error",message:String(e)};try{return{name:"Error",message:JSON.stringify(w(e))}}catch{return{name:"Error",message:String(e)}}}function h(e){let t=e.stack||`${e.name}: ${e.message}`,n=e.cause;while(n)t+=`
8
- caused by: ${n.stack||`${n.name}: ${n.message}`}`,n=n.cause;return t}function w(e,t=0){if(e instanceof Error)return m(e);if(t>=4||e===null||typeof e!=="object")return e;if(Array.isArray(e))return e.map((o)=>w(o,t+1));let n=Object.getPrototypeOf(e);if(n!==Object.prototype&&n!==null)return e;let r={};for(let[o,i]of Object.entries(e))r[o]=w(i,t+1);return r}function _(e){return w(e)}var k=new z;function oe(e,t){return k.run(e,t)}function S(){let e=k.getStore(),t=J();if(!t)return e;return{trace_id:t,...e}}function J(){try{let t=globalThis[Symbol.for("stacks.router.traceStorage")]?.getStore?.();if(t)return t;return globalThis[Symbol.for("stacks.router.requestStorage")]?.getStore?.()?._requestId}catch{return}}async function I(){if(b)return;if(v)return v;return D(),v=(async()=>{let e,t,n,r;try{let c=(await import("@stacksjs/config")).logging;if(c){if(e=c.level,t=c.format,typeof c.writeToFile==="boolean")r=c.writeToFile;if(c.logsPath)n=(await import("path")).dirname(c.logsPath);if(Array.isArray(c.transports))for(let F of c.transports)N(F)}}catch{}let{level:o,format:i,writeToFile:p}=W({envLevel:s.env.LOG_LEVEL,envFormat:s.env.LOG_FORMAT,cfgLevel:e,cfgFormat:t,cfgWriteToFile:r,isProduction:s.env.NODE_ENV==="production"}),f=n;if(!f)try{f=(await import("@stacksjs/path")).projectPath("storage/logs")}catch{f="storage/logs"}b=new A("stacks",{level:o,logDirectory:f,showTags:!1,fancy:i!=="json",format:i,writeToFile:p})})(),v}async function a(){return await I(),b}function d(...e){let t=e.filter((r)=>r!==void 0).map((r)=>{if(r instanceof Error)return h(m(r));if(typeof r==="object"&&r!==null)return JSON.stringify(w(r),null,2);return String(r)}).join(" "),n=k.getStore();if(n?.requestId)return`[${n.requestId}] ${t}`;return t}var K=new Set(["shouldExit","silent","message"]);function U(e){if(!e||typeof e!=="object"||e instanceof Error)return!1;if(!(("shouldExit"in e)||("silent"in e)))return!1;return Object.keys(e).every((t)=>K.has(t))}var g={info:async(...e)=>{let t=d(...e),n=await a();l("info",t,e),await n.info(t)},success:async(e)=>{let t=await a();l("success",e,[e]),await t.success(e)},warn:async(e,t)=>{let n=await a();if(l("warning",e,t===void 0?[e]:[e,t]),t==null){await n.warn(e);return}let r=w(t);await n.warn(e,r)},warning:async(e)=>{let t=await a();l("warning",e,[e]),await t.warn(e)},error:async(e,t,n)=>{let r=U(t)?t:void 0,o;if(typeof e==="string")o=e;else o=h(m(e));if(t!==void 0&&!r)o=`${o} ${h(m(t))}`;let i={...S(),...n};if(Object.keys(i).length>0)try{o=`${o} ${JSON.stringify(_(i))}`}catch{}let p=await a();if(l("error",o,r?[e]:[e,t,n].filter((f)=>f!==void 0)),await p.error(o),r?.shouldExit)V(e,r)},debug:async(...e)=>{let t=(s.env.LOG_LEVEL||"info").toLowerCase(),n=t==="info"||t==="warn"||t==="error";if(n&&u.length===0)return;let r=d(...e);if(n){l("debug",r,e);return}let o=await a();l("debug",r,e),await o.debug(r)},dump:async(...e)=>{let t=d(...e);await(await a()).debug(`DUMP: ${t}`)},dd:async(...e)=>{let t=d(...e);await(await a()).error(t),s.exit(x.FatalError)},echo:async(...e)=>{let t=d(...e);await(await a()).info(`ECHO: ${t}`)},time:(e)=>{let t=performance.now();return async(n)=>{let r=performance.now()-t,o=await a(),i=n?` ${JSON.stringify(_(n))}`:"";await o.info(`${e}: ${r.toFixed(2)}ms${i}`)}},syncWarn:(e)=>{s.stderr.write(`${e}
2
+ var d=import.meta.require;import{AsyncLocalStorage as M}from"async_hooks";import s from"process";import{Logger as A}from"@stacksjs/clarity";import{handleError as J}from"@stacksjs/error-handling";import{ExitCode as v}from"@stacksjs/types";var c=null,f=null,b=new Set;function O(e){return b.add(e),e.finally(()=>b.delete(e)).catch(()=>{}),e}var R=!1;function Y(){if(R)return;R=!0,s.on("beforeExit",()=>{g.flush()})}var u=[],_=new Set,j={debug:0,info:1,success:1,warning:2,error:3};function z(e){let n=e;if(!n||typeof n!=="object"||typeof n.log!=="function")return s.stderr.write(`[logging] Ignoring a transport without a log() function.
3
+ `),null;if(typeof n.name!=="string"||!n.name)return s.stderr.write(`[logging] Ignoring a transport without a name.
4
+ `),null;return u.push(n),()=>{let t=u.indexOf(n);if(t!==-1)u.splice(t,1)}}function le(e){let n=z(e);if(!n)return()=>{};return E(),n}function fe(){return[...u]}function l(e,n,t){if(u.length===0)return;let o;try{o={level:e,message:n,args:t,context:T(),timestamp:new Date().toISOString()}}catch{return}for(let r of u){if(r.level&&j[e]<j[r.level])continue;try{r.log(o)}catch(i){if(!_.has(r.name)){_.add(r.name);let L=i instanceof Error?i.message:String(i);s.stderr.write(`[logging] Transport "${r.name}" threw: ${L}. Further throws from it are silent.
5
+ `)}}}}async function B(){let e=u.filter((n)=>typeof n.flush==="function").map((n)=>n.flush().catch(()=>{}));if(e.length>0)await Promise.allSettled(e)}var N=new Set(["debug","info","success","warning","error"]);function x(e,n="info"){if(!e)return n;let t=e.toLowerCase();if(t==="warn")return"warning";if(N.has(t))return t;return s.stderr.write(`[logging] Ignoring invalid LOG_LEVEL="${e}" (expected: ${[...N].join(", ")}); using "${n}".
6
+ `),n}var P,D,I;function K(){let e=s.env.LOG_LEVEL;if(e){if(e!==D)D=e,I=x(e);return I}return P??"info"}function U(e){if(e==="json"||e==="text")return e;if(e)s.stderr.write(`[logging] Ignoring invalid LOG_FORMAT="${e}" (expected "json" or "text").
7
+ `);return s.env.NODE_ENV==="production"?"json":"text"}function H(e){let n=e.envLevel?x(e.envLevel):e.cfgLevel?x(e.cfgLevel):"info",t=e.envFormat?U(e.envFormat):e.cfgFormat==="json"||e.cfgFormat==="text"?e.cfgFormat:e.isProduction?"json":"text";return{level:n,format:t,writeToFile:e.cfgWriteToFile??!0}}function w(e,n=0){if(n>8)return{name:"Error",message:"[cause chain truncated]"};if(e instanceof Error)return{name:e.name,message:e.message,stack:e.stack,cause:e.cause!=null?w(e.cause,n+1):void 0};if(typeof e==="string")return{name:"Error",message:e};if(e==null)return{name:"Error",message:String(e)};try{return{name:"Error",message:JSON.stringify(y(e))}}catch{return{name:"Error",message:String(e)}}}function S(e){let n=e.stack||`${e.name}: ${e.message}`,t=e.cause;while(t)n+=`
8
+ caused by: ${t.stack||`${t.name}: ${t.message}`}`,t=t.cause;return n}function y(e,n=0){if(e instanceof Error)return w(e);if(n>=4||e===null||typeof e!=="object")return e;if(Array.isArray(e))return e.map((r)=>y(r,n+1));let t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null)return e;let o={};for(let[r,i]of Object.entries(e))o[r]=y(i,n+1);return o}function q(e){return y(e)}var F=new M;function de(e,n){return F.run(e,n)}function T(){let e=F.getStore(),n=Q();if(!n)return e;return{trace_id:n,...e}}function Q(){try{let n=globalThis[Symbol.for("stacks.router.traceStorage")]?.getStore?.();if(n)return n;return globalThis[Symbol.for("stacks.router.requestStorage")]?.getStore?.()?._requestId}catch{return}}var X=Symbol.for("@stacksjs/config:overridesReady"),k=null;async function Z(){try{return(await import("@stacksjs/config")).logging??null}catch{return null}}function ee(){let e=globalThis[X];if(!e||typeof e.then!=="function")return null;return e}async function V(e,n){let{level:t,format:o,writeToFile:r}=H({envLevel:s.env.LOG_LEVEL,envFormat:s.env.LOG_FORMAT,cfgLevel:e?.level,cfgFormat:e?.format,cfgWriteToFile:typeof e?.writeToFile==="boolean"?e.writeToFile:void 0,isProduction:s.env.NODE_ENV==="production"}),i;if(e?.logsPath)i=(await import("path")).dirname(e.logsPath);if(!i)i=n;if(!i)try{i=(await import("@stacksjs/path")).projectPath("storage/logs")}catch{i="storage/logs"}return{level:t,format:o,writeToFile:r,logDirectory:i}}function W(e){if(!Array.isArray(e?.transports))return;for(let n of e.transports)if(!u.includes(n))z(n)}var h=null;function C(){if(h)return;let e=ee();if(!e)return;h=e.then(async(n)=>{let t=n?.logging;if(!t)return;if(W(t),t.level)P=x(t.level);let o=k;if(!o||!c)return;let r=await V(t,o.logDirectory);if(o.level===r.level&&o.format===r.format&&o.writeToFile===r.writeToFile&&o.logDirectory===r.logDirectory)return;let i=c;c=new A("stacks",{level:r.level,logDirectory:r.logDirectory,showTags:!1,fancy:r.format!=="json",format:r.format,writeToFile:r.writeToFile}),k=r;try{await i.flush?.(),await i.destroy?.()}catch{}}).catch(()=>{})}async function E(){if(c)return;if(f)return f;return Y(),f=(async()=>{let e=await Z();if(W(e),e?.level)P=x(e.level);let n=await V(e);c=new A("stacks",{level:n.level,logDirectory:n.logDirectory,showTags:!1,fancy:n.format!=="json",format:n.format,writeToFile:n.writeToFile}),k=n})(),f.then(C),f}async function a(){return await E(),c}async function me(){if(await E(),C(),h)await h;return c}function m(...e){let n=e.filter((o)=>o!==void 0).map((o)=>{if(o instanceof Error)return S(w(o));if(typeof o==="object"&&o!==null)return JSON.stringify(y(o),null,2);return String(o)}).join(" "),t=F.getStore();if(t?.requestId)return`[${t.requestId}] ${n}`;return n}var ne=new Set(["shouldExit","silent","message"]);function te(e){if(!e||typeof e!=="object"||e instanceof Error)return!1;if(!(("shouldExit"in e)||("silent"in e)))return!1;return Object.keys(e).every((n)=>ne.has(n))}var g={info:async(...e)=>{let n=m(...e),t=await a();l("info",n,e),await t.info(n)},success:async(e)=>{let n=await a();l("success",e,[e]),await n.success(e)},warn:async(e,n)=>{let t=await a();if(l("warning",e,n===void 0?[e]:[e,n]),n==null){await t.warn(e);return}let o=y(n);await t.warn(e,o)},warning:async(e)=>{let n=await a();l("warning",e,[e]),await n.warn(e)},error:async(e,n,t)=>{let o=te(n)?n:void 0,r;if(typeof e==="string")r=e;else r=S(w(e));if(n!==void 0&&!o)r=`${r} ${S(w(n))}`;let i={...T(),...t};if(Object.keys(i).length>0)try{r=`${r} ${JSON.stringify(q(i))}`}catch{}let L=await a();if(l("error",r,o?[e]:[e,n,t].filter((G)=>G!==void 0)),await L.error(r),o?.shouldExit)J(e,o)},debug:async(...e)=>{let n=K()!=="debug";if(n&&u.length===0){if(!c&&!f)E();else if(!h)C();return}let t=m(...e);if(n){l("debug",t,e);return}let o=await a();l("debug",t,e),await o.debug(t)},dump:async(...e)=>{let n=m(...e);await(await a()).debug(`DUMP: ${n}`)},dd:async(...e)=>{let n=m(...e);await(await a()).error(n),s.exit(v.FatalError)},echo:async(...e)=>{let n=m(...e);await(await a()).info(`ECHO: ${n}`)},time:(e)=>{let n=performance.now();return async(t)=>{let o=performance.now()-n,r=await a(),i=t?` ${JSON.stringify(q(t))}`:"";await r.info(`${e}: ${o.toFixed(2)}ms${i}`)}},syncWarn:(e)=>{s.stderr.write(`${e}
9
9
  `)},syncError:(e)=>{s.stderr.write(`${e}
10
- `)},fatal:(e,t=x.FatalError)=>{s.stderr.write(`${e}
11
- `),s.exit(t)},exit:async(e,t=x.Success)=>{if(e)await(t===x.Success?g.success(e):g.error(e));await g.flush(),s.exit(t)},flush:async()=>{if(E.size>0)await Promise.allSettled([...E]);if(await G(),!b&&!v)return;try{let e=await a(),t=e.flush;if(typeof t==="function")await t.call(e)}catch{}}};async function se(...e){for(let t of e)await g.debug(t)}async function ie(...e){let t=d(...e);console.log(t),s.exit(x.FatalError)}async function ae(...e){await g.debug(...e)}function Y(e){if(e&&typeof e==="object"){let t=e;if(typeof t.status==="number")return t.status;if(typeof t.statusCode==="number")return t.statusCode}return}function ge(e,t={}){let n=t.status??Y(e),r=typeof n==="number"&&n>=400&&n<500,o=t.label??"Unhandled error",i={...t.context,...n!=null?{status:n}:{}};if(r){g.debug(`${o} (client error ${n}): ${m(e).message}`);return}g.error(o,e,i)}function y(e,t,n){let r=S(),o={event:t,traceId:r?.requestId,...n};if(e==="warn")P(g.warn(`[${t}]`,o));else P(g[e](o))}var H={request(e,t,n,r,o={}){let i=n>=500?"error":n>=400?"warn":"info";y(i,"http.request",{method:e,path:t,status:n,durationMs:r,...o})},query(e,t,n={}){y("debug","db.query",{sql:e,durationMs:t,...n})},slowQuery(e,t,n={}){y("warn","db.slow_query",{sql:e,durationMs:t,...n})},job(e,t,n={}){y(t==="failed"?"error":"info",`job.${t}`,{jobName:e,...n})},cache(e,t,n={}){y("debug",`cache.${e}`,{key:t,...n})}};g.struct=H;export{ie as dd,se as dump,ae as echo,d as formatMessage,S as getLogContext,g as log,a as logger,_ as normalizeContext,m as normalizeError,M as parseLogFormat,R as parseLogLevel,ne as registerTransport,h as renderNormalizedError,ge as report,W as resolveLogSettings,H as struct,re as transports,oe as withLogContext};
10
+ `)},fatal:(e,n=v.FatalError)=>{s.stderr.write(`${e}
11
+ `),s.exit(n)},exit:async(e,n=v.Success)=>{if(e)await(n===v.Success?g.success(e):g.error(e));await g.flush(),s.exit(n)},flush:async()=>{if(b.size>0)await Promise.allSettled([...b]);if(await B(),!c&&!f)return;try{let e=await a(),n=e.flush;if(typeof n==="function")await n.call(e)}catch{}}};async function we(...e){for(let n of e)await g.debug(n)}async function ye(...e){let n=m(...e);console.log(n),s.exit(v.FatalError)}async function Le(...e){await g.debug(...e)}function re(e){if(e&&typeof e==="object"){let n=e;if(typeof n.status==="number")return n.status;if(typeof n.statusCode==="number")return n.statusCode}return}function pe(e,n={}){let t=n.status??re(e),o=typeof t==="number"&&t>=400&&t<500,r=n.label??"Unhandled error",i={...n.context,...t!=null?{status:t}:{}};if(o){g.debug(`${r} (client error ${t}): ${w(e).message}`);return}g.error(r,e,i)}function p(e,n,t){let o=T(),r={event:n,traceId:o?.requestId,...t};if(e==="warn")O(g.warn(`[${n}]`,r));else O(g[e](r))}var oe={request(e,n,t,o,r={}){let i=t>=500?"error":t>=400?"warn":"info";p(i,"http.request",{method:e,path:n,status:t,durationMs:o,...r})},query(e,n,t={}){p("debug","db.query",{sql:e,durationMs:n,...t})},slowQuery(e,n,t={}){p("warn","db.slow_query",{sql:e,durationMs:n,...t})},job(e,n,t={}){p(n==="failed"?"error":"info",`job.${n}`,{jobName:e,...t})},cache(e,n,t={}){p("debug",`cache.${e}`,{key:n,...t})}};g.struct=oe;export{K as currentLevel,ye as dd,we as dump,Le as echo,m as formatMessage,T as getLogContext,g as log,me as logger,q as normalizeContext,w as normalizeError,U as parseLogFormat,x as parseLogLevel,le as registerTransport,S as renderNormalizedError,pe as report,H as resolveLogSettings,oe as struct,fe as transports,de as withLogContext};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/logging",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.73.1",
5
+ "version": "0.73.3",
6
6
  "description": "The Stacks logging system.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -58,15 +58,16 @@
58
58
  "prepublishOnly": "bun run build"
59
59
  },
60
60
  "dependencies": {
61
+ "@loghq/stacks": "^0.2.3",
61
62
  "@stacksjs/clarity": "^0.3.33"
62
63
  },
63
64
  "devDependencies": {
64
- "@stacksjs/cli": "0.73.1",
65
- "@stacksjs/config": "0.73.1",
66
- "@stacksjs/error-handling": "0.73.1",
67
- "@stacksjs/path": "0.73.1",
68
- "@stacksjs/storage": "0.73.1",
69
- "@stacksjs/validation": "0.73.1",
65
+ "@stacksjs/cli": "0.73.3",
66
+ "@stacksjs/config": "0.73.3",
67
+ "@stacksjs/error-handling": "0.73.3",
68
+ "@stacksjs/path": "0.73.3",
69
+ "@stacksjs/storage": "0.73.3",
70
+ "@stacksjs/validation": "0.73.3",
70
71
  "better-dx": "^0.2.24"
71
72
  }
72
73
  }