@@ -5,7 +5,6 @@ import { isError, truncate } from '@sentry/utils';
55import { defineIntegration } from './integration' ;
66
77import type { Event , EventHint } from '@sentry/types' ;
8- import type { ZodError , ZodIssue } from 'zod' ;
98
109const INTEGRATION_NAME = 'ZodErrors' ;
1110const DEFAULT_LIMIT = 10 ;
@@ -18,7 +17,9 @@ interface ZodErrorsOptions {
1817 */
1918 limit ?: number ;
2019 /**
21- * Optionally save full error info as an attachment in Sentry
20+ * Save full list of Zod issues as an attachment in Sentry
21+ *
22+ * @default false
2223 */
2324 saveAttachments ?: boolean ;
2425}
@@ -29,24 +30,28 @@ function originalExceptionIsZodError(
2930 return (
3031 isError ( originalException ) &&
3132 originalException . name === 'ZodError' &&
32- Array . isArray ( ( originalException as ZodError ) . errors )
33+ Array . isArray ( ( originalException as ZodError ) . issues )
3334 ) ;
3435}
3536
3637/**
3738 * Simplified ZodIssue type definition
3839 */
39- type SimpleZodIssue = {
40- path : Array < string | number > ;
40+ interface ZodIssue {
41+ path : ( string | number ) [ ] ;
4142 message ?: string ;
4243 expected ?: unknown ;
4344 received ?: unknown ;
4445 unionErrors ?: unknown [ ] ;
4546 keys ?: unknown [ ] ;
4647 invalid_literal ?: unknown ;
47- } ;
48+ }
4849
49- type SingleLevelZodIssue < T extends SimpleZodIssue > = {
50+ interface ZodError extends Error {
51+ issues : ZodIssue [ ] ;
52+ }
53+
54+ type SingleLevelZodIssue < T extends ZodIssue > = {
5055 [ P in keyof T ] : T [ P ] extends string | number | undefined
5156 ? T [ P ]
5257 : T [ P ] extends unknown [ ]
@@ -67,9 +72,7 @@ type SingleLevelZodIssue<T extends SimpleZodIssue> = {
6772 * [Object]
6873 * ]
6974 */
70- export function flattenIssue (
71- issue : ZodIssue ,
72- ) : SingleLevelZodIssue < SimpleZodIssue > {
75+ export function flattenIssue ( issue : ZodIssue ) : SingleLevelZodIssue < ZodIssue > {
7376 return {
7477 ...issue ,
7578 path :
@@ -128,7 +131,11 @@ export function formatIssueMessage(zodError: ZodError): string {
128131 let rootExpectedType = 'variable' ;
129132 if ( zodError . issues . length > 0 ) {
130133 const iss = zodError . issues [ 0 ] ;
131- if ( 'expected' in iss && typeof iss . expected === 'string' ) {
134+ if (
135+ iss !== undefined &&
136+ 'expected' in iss &&
137+ typeof iss . expected === 'string'
138+ ) {
132139 rootExpectedType = iss . expected ;
133140 }
134141 }
@@ -138,38 +145,39 @@ export function formatIssueMessage(zodError: ZodError): string {
138145}
139146
140147/**
141- * Applies ZodError issues to an event context and replaces the error message
148+ * Applies ZodError issues to an event extra and replaces the error message
142149 */
143- function applyZodErrorsToEvent (
150+ export function applyZodErrorsToEvent (
144151 limit : number ,
145152 event : Event ,
146- saveAttachments ? : boolean ,
147- hint ? : EventHint ,
153+ saveAttachments : boolean = false ,
154+ hint : EventHint ,
148155) : Event {
149156 if (
150- event . exception === undefined ||
151- event . exception . values === undefined ||
152- hint === undefined ||
153- hint . originalException === undefined ||
157+ ! event . exception ?. values ||
158+ ! hint . originalException ||
154159 ! originalExceptionIsZodError ( hint . originalException ) ||
155160 hint . originalException . issues . length === 0
156161 ) {
157162 return event ;
158163 }
159164
160165 try {
161- const flattenedIssues = hint . originalException . errors . map ( flattenIssue ) ;
162-
163- if ( saveAttachments === true ) {
164- // Add an attachment with all issues (no limits), as well as the default
165- // flatten format to see if it's preferred over our custom flatten format.
166+ const issuesToFlatten = saveAttachments
167+ ? hint . originalException . issues
168+ : hint . originalException . issues . slice ( 0 , limit ) ;
169+ const flattenedIssues = issuesToFlatten . map ( flattenIssue ) ;
170+
171+ if ( saveAttachments ) {
172+ // Sometimes having the full error details can be helpful.
173+ // Attachments have much higher limits, so we can include the full list of issues.
166174 if ( ! Array . isArray ( hint . attachments ) ) {
167175 hint . attachments = [ ] ;
168176 }
169177 hint . attachments . push ( {
170178 filename : 'zod_issues.json' ,
171179 data : JSON . stringify ( {
172- issueDetails : hint . originalException . flatten ( flattenIssue ) ,
180+ issues : flattenedIssues ,
173181 } ) ,
174182 } ) ;
175183 }
@@ -199,7 +207,8 @@ function applyZodErrorsToEvent(
199207 extra : {
200208 ...event . extra ,
201209 'zoderrors sentry integration parse error' : {
202- message : `an exception was thrown while processing ZodError within applyZodErrorsToEvent()` ,
210+ message :
211+ 'an exception was thrown while processing ZodError within applyZodErrorsToEvent()' ,
203212 error :
204213 e instanceof Error
205214 ? `${ e . name } : ${ e . message } \n${ e . stack } `
0 commit comments