@@ -105,6 +105,19 @@ function validateParams(p5, fn, lifecycles) {
105105 return { funcName, funcClass } ;
106106 }
107107
108+ function validBracketNesting ( type ) {
109+ let level = 0 ;
110+ for ( let i = 0 ; i < type . length ; i ++ ) {
111+ if ( type [ i ] === '[' ) {
112+ level ++ ;
113+ } else if ( type [ i ] === ']' ) {
114+ level -- ;
115+ if ( level < 0 ) return false ;
116+ }
117+ }
118+ return level === 0 ;
119+ }
120+
108121 /**
109122 * This is a helper function that generates Zod schemas for a function based on
110123 * the parameter data from `docs/parameterData.json`.
@@ -139,11 +152,8 @@ function validateParams(p5, fn, lifecycles) {
139152 }
140153
141154 // Returns a schema for a single type, i.e. z.boolean() for `boolean`.
142- const generateTypeSchema = type => {
143- if ( ! type ) return z . any ( ) ;
144-
145- const isArray = type . endsWith ( '[]' ) ;
146- const baseType = isArray ? type . slice ( 0 , - 2 ) : type ;
155+ const generateTypeSchema = baseType => {
156+ if ( ! baseType ) return z . any ( ) ;
147157
148158 let typeSchema ;
149159
@@ -162,7 +172,7 @@ function validateParams(p5, fn, lifecycles) {
162172 typeSchema = z . function ( ) ;
163173 }
164174 // All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`.
165- else if ( baseType . startsWith ( 'p5' ) ) {
175+ else if ( / ^ p 5 \. [ a - z A - Z 0 - 9 ] + $ / . exec ( baseType ) || baseType === 'p5' ) {
166176 const className = baseType . substring ( baseType . indexOf ( '.' ) + 1 ) ;
167177 typeSchema = z . instanceof ( p5Constructors [ className ] ) ;
168178 }
@@ -171,7 +181,11 @@ function validateParams(p5, fn, lifecycles) {
171181 typeSchema = schemaMap [ baseType ] ;
172182 }
173183 // Tuple types
174- else if ( baseType . startsWith ( '[' ) && baseType . endsWith ( ']' ) ) {
184+ else if (
185+ baseType . startsWith ( '[' ) &&
186+ baseType . endsWith ( ']' ) &&
187+ validBracketNesting ( baseType . slice ( 1 , - 1 ) )
188+ ) {
175189 typeSchema = z . tuple (
176190 baseType
177191 . slice ( 1 , - 1 )
@@ -182,21 +196,7 @@ function validateParams(p5, fn, lifecycles) {
182196 // JavaScript classes, e.g. Request
183197 else if ( baseType . match ( / ^ [ A - Z ] / ) && baseType in window ) {
184198 typeSchema = z . instanceof ( window [ baseType ] ) ;
185- } else {
186- throw new Error ( `Unsupported type '${ type } ' in parameter validation. Please report this issue.` ) ;
187199 }
188-
189- return isArray ? z . array ( typeSchema ) : typeSchema ;
190- } ;
191-
192- // Generate a schema for a single parameter. In the case where a parameter can
193- // be of multiple types, `generateTypeSchema` is called for each type.
194- const generateParamSchema = param => {
195- const isOptional = param ?. endsWith ( '?' ) ;
196- param = param ?. replace ( / \? $ / , '' ) ;
197-
198- let schema ;
199-
200200 // Generate a schema for a single parameter that can be of multiple
201201 // types / constants, i.e. `String|Number|Array`.
202202 //
@@ -206,15 +206,28 @@ function validateParams(p5, fn, lifecycles) {
206206 // our constants sometimes have numeric or non-primitive values.
207207 // 2) In some cases, the type can be constants or strings, making z.enum()
208208 // insufficient for the use case.
209- if ( param ? .includes ( '|' ) ) {
210- const types = param . split ( '|' ) ;
211- schema = z . union ( types
209+ else if ( baseType . includes ( '|' ) && baseType . split ( '|' ) . every ( t => validBracketNesting ( t ) ) ) {
210+ const types = baseType . split ( '|' ) ;
211+ typeSchema = z . union ( types
212212 . map ( t => generateTypeSchema ( t ) )
213213 . filter ( s => s !== undefined ) ) ;
214+ } else if ( baseType . endsWith ( '[]' ) ) {
215+ typeSchema = z . array ( generateTypeSchema ( baseType . slice ( 0 , - 2 ) ) ) ;
214216 } else {
215- schema = generateTypeSchema ( param ) ;
217+ throw new Error ( `Unsupported type ' ${ baseType } ' in parameter validation. Please report this issue.` ) ;
216218 }
217219
220+ return typeSchema ;
221+ } ;
222+
223+ // Generate a schema for a single parameter. In the case where a parameter can
224+ // be of multiple types, `generateTypeSchema` is called for each type.
225+ const generateParamSchema = param => {
226+ const isOptional = param ?. endsWith ( '?' ) ;
227+ param = param ?. replace ( / \? $ / , '' ) ;
228+
229+ let schema = generateTypeSchema ( param ) ;
230+
218231 return isOptional ? schema . optional ( ) : schema ;
219232 } ;
220233
0 commit comments