@@ -37,10 +37,13 @@ export function safeStringify(obj: unknown, maxSize: number) {
3737// it. Roll back state if fails to serialize.
3838
3939/**
40- * Check if a value is JSON serializable.
40+ * Check if a value is CBOR serializable.
4141 * Optionally pass an onInvalid callback to receive the path to invalid values.
42+ *
43+ * For a complete list of supported CBOR tags, see:
44+ * https://github.com/kriszyp/cbor-x/blob/cc1cf9df8ba72288c7842af1dd374d73e34cdbc1/README.md#list-of-supported-tags-for-decoding
4245 */
43- export function isJsonSerializable (
46+ export function isCborSerializable (
4447 value : unknown ,
4548 onInvalid ?: ( path : string ) => void ,
4649 currentPath = "" ,
@@ -62,30 +65,98 @@ export function isJsonSerializable(
6265 return true ;
6366 }
6467
68+ // Handle BigInt (CBOR tags 2 and 3)
69+ if ( typeof value === "bigint" ) {
70+ return true ;
71+ }
72+
73+ // Handle Date objects (CBOR tags 0 and 1)
74+ if ( value instanceof Date ) {
75+ return true ;
76+ }
77+
78+ // Handle typed arrays (CBOR tags 64-82)
79+ if (
80+ value instanceof Uint8Array ||
81+ value instanceof Uint8ClampedArray ||
82+ value instanceof Uint16Array ||
83+ value instanceof Uint32Array ||
84+ value instanceof BigUint64Array ||
85+ value instanceof Int8Array ||
86+ value instanceof Int16Array ||
87+ value instanceof Int32Array ||
88+ value instanceof BigInt64Array ||
89+ value instanceof Float32Array ||
90+ value instanceof Float64Array
91+ ) {
92+ return true ;
93+ }
94+
95+ // Handle Map (CBOR tag 259)
96+ if ( value instanceof Map ) {
97+ for ( const [ key , val ] of value . entries ( ) ) {
98+ const keyPath = currentPath ? `${ currentPath } .key(${ String ( key ) } )` : `key(${ String ( key ) } )` ;
99+ const valPath = currentPath ? `${ currentPath } .value(${ String ( key ) } )` : `value(${ String ( key ) } )` ;
100+ if ( ! isCborSerializable ( key , onInvalid , keyPath ) || ! isCborSerializable ( val , onInvalid , valPath ) ) {
101+ return false ;
102+ }
103+ }
104+ return true ;
105+ }
106+
107+ // Handle Set (CBOR tag 258)
108+ if ( value instanceof Set ) {
109+ let index = 0 ;
110+ for ( const item of value . values ( ) ) {
111+ const itemPath = currentPath ? `${ currentPath } .set[${ index } ]` : `set[${ index } ]` ;
112+ if ( ! isCborSerializable ( item , onInvalid , itemPath ) ) {
113+ return false ;
114+ }
115+ index ++ ;
116+ }
117+ return true ;
118+ }
119+
120+ // Handle RegExp (CBOR tag 27)
121+ if ( value instanceof RegExp ) {
122+ return true ;
123+ }
124+
125+ // Handle Error objects (CBOR tag 27)
126+ if ( value instanceof Error ) {
127+ return true ;
128+ }
129+
65130 // Handle arrays
66131 if ( Array . isArray ( value ) ) {
67132 for ( let i = 0 ; i < value . length ; i ++ ) {
68133 const itemPath = currentPath ? `${ currentPath } [${ i } ]` : `[${ i } ]` ;
69- if ( ! isJsonSerializable ( value [ i ] , onInvalid , itemPath ) ) {
134+ if ( ! isCborSerializable ( value [ i ] , onInvalid , itemPath ) ) {
70135 return false ;
71136 }
72137 }
73138 return true ;
74139 }
75140
76- // Handle plain objects
141+ // Handle plain objects and records (CBOR tags 105, 51, 57344-57599)
77142 if ( typeof value === "object" ) {
78- // Reject if it's not a plain object
79- if ( Object . getPrototypeOf ( value ) !== Object . prototype ) {
80- onInvalid ?.( currentPath ) ;
81- return false ;
143+ // Allow plain objects and objects with prototypes (for records and named objects)
144+ const proto = Object . getPrototypeOf ( value ) ;
145+ if ( proto !== null && proto !== Object . prototype ) {
146+ // Check if it's a known serializable object type
147+ const constructor = value . constructor ;
148+ if ( constructor && typeof constructor . name === "string" ) {
149+ // Allow objects with named constructors (records, named objects)
150+ // This includes user-defined classes and built-in objects
151+ // that CBOR can serialize with tag 27 or record tags
152+ }
82153 }
83154
84155 // Check all properties recursively
85156 for ( const key in value ) {
86157 const propPath = currentPath ? `${ currentPath } .${ key } ` : key ;
87158 if (
88- ! isJsonSerializable (
159+ ! isCborSerializable (
89160 value [ key as keyof typeof value ] ,
90161 onInvalid ,
91162 propPath ,
0 commit comments