@@ -169,6 +169,102 @@ console.log('Modified representation data:', JSON.stringify(newData))
169169// ["Home",460,250,[[1,32],[1,30],[1,30],[2,10],[2,11],[3,140],[4,230],[4,200],[2,5]]]
170170```
171171
172+ ### Custom Transforms
173+
174+ The ` typed.js ` module also supports custom transforms for specific types. This allows you to handle custom encoding/decoding logic when the wire format differs from the native JavaScript representation (e.g., base64-encoded bytes as strings, bigints as strings in JSON-RPC).
175+
176+ ``` js
177+ import { fromDSL } from ' @ipld/schema/from-dsl.js'
178+ import { create } from ' @ipld/schema/typed.js'
179+
180+ // Define a schema with custom types
181+ const schema = fromDSL (`
182+ type Base64Bytes bytes
183+ type StringBigInt int
184+ type Transaction struct {
185+ id Base64Bytes
186+ amount StringBigInt
187+ }
188+ ` )
189+
190+ // Define custom transforms for the types
191+ const customTransforms = {
192+ Base64Bytes: {
193+ // Convert base64 string to Uint8Array
194+ toTyped : (obj ) => {
195+ if (typeof obj !== ' string' ) return undefined
196+ try {
197+ // Decode base64 to Uint8Array
198+ const binary = atob (obj)
199+ const bytes = new Uint8Array (binary .length )
200+ for (let i = 0 ; i < binary .length ; i++ ) {
201+ bytes[i] = binary .charCodeAt (i)
202+ }
203+ return bytes
204+ } catch {
205+ return undefined
206+ }
207+ },
208+ // Convert Uint8Array to base64 string
209+ toRepresentation : (obj ) => {
210+ if (! (obj instanceof Uint8Array )) return undefined
211+ // Encode Uint8Array to base64
212+ let binary = ' '
213+ for (let i = 0 ; i < obj .length ; i++ ) {
214+ binary += String .fromCharCode (obj[i])
215+ }
216+ return btoa (binary)
217+ }
218+ },
219+ StringBigInt: {
220+ // Convert string to BigInt
221+ toTyped : (obj ) => {
222+ if (typeof obj !== ' string' ) return undefined
223+ try {
224+ return BigInt (obj)
225+ } catch {
226+ return undefined
227+ }
228+ },
229+ // Convert BigInt to string
230+ toRepresentation : (obj ) => {
231+ if (typeof obj !== ' bigint' ) return undefined
232+ return obj .toString ()
233+ }
234+ }
235+ }
236+
237+ // Create typed converter with custom transforms
238+ const { toTyped , toRepresentation } = create (schema, ' Transaction' , { customTransforms })
239+
240+ // Convert wire format to typed format
241+ const wireData = {
242+ id: ' SGVsbG8gV29ybGQ=' , // "Hello World" in base64
243+ amount: ' 123456789012345678901234567890'
244+ }
245+
246+ const typed = toTyped (wireData)
247+ console .log (' Typed:' , typed)
248+ // → Typed: {
249+ // id: Uint8Array(11) [...], // decoded bytes
250+ // amount: 123456789012345678901234567890n
251+ // }
252+
253+ // Convert back to wire format
254+ const repr = toRepresentation (typed)
255+ console .log (' Representation:' , repr)
256+ // → Representation: {
257+ // id: 'SGVsbG8gV29ybGQ=',
258+ // amount: '123456789012345678901234567890'
259+ // }
260+ ```
261+
262+ Custom transforms can be provided as either:
263+ - Function objects (will be converted to source code for the generated validators)
264+ - String containing the function body (useful for code generation contexts)
265+
266+ If only ` toTyped ` is provided, ` toRepresentation ` defaults to the identity function (returns input unchanged).
267+
172268## Command line
173269
174270** @ipld/schema also exports an executable** : if installed with ` -g ` you will get an ` ipld-schema ` command in your ` PATH ` .
0 commit comments