@@ -5,11 +5,8 @@ import type {
5
5
} from "../types/hooks.js" ;
6
6
import type { HardhatPlugin } from "../types/plugins.js" ;
7
7
8
- import {
9
- isOptionDefinition ,
10
- isPositionalArgumentDefinition ,
11
- isTaskDefinition ,
12
- } from "../type-guards.js" ;
8
+ import { isObject } from "@ignored/hardhat-vnext-utils/lang" ;
9
+
13
10
import {
14
11
ArgumentType ,
15
12
type OptionDefinition ,
@@ -23,6 +20,50 @@ import {
23
20
type TaskOverrideDefinition ,
24
21
} from "../types/tasks.js" ;
25
22
23
+ function isValidEnumValue (
24
+ theEnum : Record < string , string > ,
25
+ value : string ,
26
+ ) : boolean {
27
+ // Enums are objects that have entries that map:
28
+ // 1) keys to values
29
+ // 2) values to keys
30
+ const key = theEnum [ value ] ;
31
+ if ( key === undefined ) {
32
+ return false ;
33
+ }
34
+
35
+ return theEnum [ key ] === value ;
36
+ }
37
+
38
+ /**
39
+ * Returns true if `potential` is a `TaskDefinition`.
40
+ */
41
+ function isTaskDefinition ( potential : unknown ) : potential is TaskDefinition {
42
+ return (
43
+ typeof potential === "object" &&
44
+ potential !== null &&
45
+ "type" in potential &&
46
+ typeof potential . type === "string" &&
47
+ isValidEnumValue ( TaskDefinitionType , potential . type )
48
+ ) ;
49
+ }
50
+
51
+ /**
52
+ * Returns true if `potential` is a `PositionalArgumentDefinition`.
53
+ */
54
+ function isPositionalArgumentDefinition (
55
+ potential : unknown ,
56
+ ) : potential is PositionalArgumentDefinition {
57
+ return (
58
+ typeof potential === "object" &&
59
+ potential !== null &&
60
+ "type" in potential &&
61
+ typeof potential . type === "string" &&
62
+ isValidEnumValue ( ArgumentType , potential . type ) &&
63
+ "isVariadic" in potential
64
+ ) ;
65
+ }
66
+
26
67
export async function validateUserConfig (
27
68
hooks : HookManager ,
28
69
config : HardhatUserConfig ,
@@ -39,7 +80,7 @@ export async function validateUserConfig(
39
80
return [ ...validationErrors , ...results . flat ( 1 ) ] ;
40
81
}
41
82
42
- function collectValidationErrorsForUserConfig (
83
+ export function collectValidationErrorsForUserConfig (
43
84
config : HardhatUserConfig ,
44
85
) : HardhatUserConfigValidationError [ ] {
45
86
const validationErrors : HardhatUserConfigValidationError [ ] = [ ] ;
@@ -69,7 +110,7 @@ function collectValidationErrorsForUserConfig(
69
110
return validationErrors ;
70
111
}
71
112
72
- function validateTasksConfig (
113
+ export function validateTasksConfig (
73
114
tasks : TaskDefinition [ ] ,
74
115
path : Array < string | number > = [ ] ,
75
116
) : HardhatUserConfigValidationError [ ] {
@@ -110,7 +151,7 @@ function validateTasksConfig(
110
151
return validationErrors ;
111
152
}
112
153
113
- function validateEmptyTask (
154
+ export function validateEmptyTask (
114
155
task : EmptyTaskDefinition ,
115
156
path : Array < string | number > ,
116
157
) : HardhatUserConfigValidationError [ ] {
@@ -136,7 +177,7 @@ function validateEmptyTask(
136
177
return validationErrors ;
137
178
}
138
179
139
- function validateNewTask (
180
+ export function validateNewTask (
140
181
task : NewTaskDefinition ,
141
182
path : Array < string | number > ,
142
183
) : HardhatUserConfigValidationError [ ] {
@@ -166,7 +207,7 @@ function validateNewTask(
166
207
} ) ;
167
208
}
168
209
169
- if ( typeof task . options === "object" && task . options !== null ) {
210
+ if ( isObject ( task . options ) ) {
170
211
validationErrors . push (
171
212
...validateOptions ( task . options , [ ...path , "options" ] ) ,
172
213
) ;
@@ -191,7 +232,7 @@ function validateNewTask(
191
232
return validationErrors ;
192
233
}
193
234
194
- function validateTaskOverride (
235
+ export function validateTaskOverride (
195
236
task : TaskOverrideDefinition ,
196
237
path : Array < string | number > ,
197
238
) : HardhatUserConfigValidationError [ ] {
@@ -221,7 +262,7 @@ function validateTaskOverride(
221
262
} ) ;
222
263
}
223
264
224
- if ( typeof task . options === "object" && task . options !== null ) {
265
+ if ( isObject ( task . options ) ) {
225
266
validationErrors . push (
226
267
...validateOptions ( task . options , [ ...path , "options" ] ) ,
227
268
) ;
@@ -235,7 +276,7 @@ function validateTaskOverride(
235
276
return validationErrors ;
236
277
}
237
278
238
- function validateOptions (
279
+ export function validateOptions (
239
280
options : Record < string , OptionDefinition > ,
240
281
path : Array < string | number > ,
241
282
) : HardhatUserConfigValidationError [ ] {
@@ -256,7 +297,7 @@ function validateOptions(
256
297
} ) ;
257
298
}
258
299
259
- if ( ! isOptionDefinition ( option ) ) {
300
+ if ( ArgumentType [ option . type ] === undefined ) {
260
301
validationErrors . push ( {
261
302
path : [ ...path , name , "type" ] ,
262
303
message : "option type must be a valid ArgumentType" ,
@@ -270,7 +311,8 @@ function validateOptions(
270
311
} ) ;
271
312
} else {
272
313
switch ( option . type ) {
273
- case ArgumentType . STRING : {
314
+ case ArgumentType . STRING :
315
+ case ArgumentType . FILE : {
274
316
if ( typeof option . defaultValue !== "string" ) {
275
317
validationErrors . push ( {
276
318
path : [ ...path , name , "defaultValue" ] ,
@@ -288,7 +330,8 @@ function validateOptions(
288
330
}
289
331
break ;
290
332
}
291
- case ArgumentType . INT : {
333
+ case ArgumentType . INT :
334
+ case ArgumentType . FLOAT : {
292
335
if ( typeof option . defaultValue !== "number" ) {
293
336
validationErrors . push ( {
294
337
path : [ ...path , name , "defaultValue" ] ,
@@ -306,32 +349,14 @@ function validateOptions(
306
349
}
307
350
break ;
308
351
}
309
- case ArgumentType . FLOAT : {
310
- if ( typeof option . defaultValue !== "number" ) {
311
- validationErrors . push ( {
312
- path : [ ...path , name , "defaultValue" ] ,
313
- message : "option defaultValue must be a number" ,
314
- } ) ;
315
- }
316
- break ;
317
- }
318
- case ArgumentType . FILE : {
319
- if ( typeof option . defaultValue !== "string" ) {
320
- validationErrors . push ( {
321
- path : [ ...path , name , "defaultValue" ] ,
322
- message : "option defaultValue must be a string" ,
323
- } ) ;
324
- }
325
- break ;
326
- }
327
352
}
328
353
}
329
354
}
330
355
331
356
return validationErrors ;
332
357
}
333
358
334
- function validatePositionalArguments (
359
+ export function validatePositionalArguments (
335
360
positionalArgs : PositionalArgumentDefinition [ ] ,
336
361
path : Array < string | number > ,
337
362
) : HardhatUserConfigValidationError [ ] {
@@ -361,95 +386,67 @@ function validatePositionalArguments(
361
386
362
387
if ( arg . defaultValue !== undefined ) {
363
388
switch ( arg . type ) {
364
- case ArgumentType . STRING : {
389
+ case ArgumentType . STRING :
390
+ case ArgumentType . FILE : {
365
391
if (
366
- typeof arg . defaultValue === "string" ||
367
- ( Array . isArray ( arg . defaultValue ) &&
368
- arg . defaultValue . every ( ( v ) => typeof v = == "string" ) )
392
+ typeof arg . defaultValue !== "string" &&
393
+ ( ! Array . isArray ( arg . defaultValue ) ||
394
+ arg . defaultValue . some ( ( v ) => typeof v ! == "string" ) )
369
395
) {
370
- break ;
396
+ validationErrors . push ( {
397
+ path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
398
+ message :
399
+ "positional argument defaultValue must be a string or an array of strings" ,
400
+ } ) ;
371
401
}
372
402
373
- validationErrors . push ( {
374
- path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
375
- message :
376
- "positional argument defaultValue must be a string or an array of strings" ,
377
- } ) ;
403
+ break ;
378
404
}
379
405
case ArgumentType . BOOLEAN : {
380
406
if (
381
- typeof arg . defaultValue === "boolean" ||
382
- ( Array . isArray ( arg . defaultValue ) &&
383
- arg . defaultValue . every ( ( v ) => typeof v === "boolean" ) )
384
- ) {
385
- break ;
386
- }
387
-
388
- validationErrors . push ( {
389
- path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
390
- message :
391
- "positional argument defaultValue must be a boolean or an array of booleans" ,
392
- } ) ;
393
- }
394
- case ArgumentType . INT : {
395
- if (
396
- typeof arg . defaultValue === "number" ||
397
- ( Array . isArray ( arg . defaultValue ) &&
398
- arg . defaultValue . every ( ( v ) => typeof v === "number" ) )
399
- ) {
400
- break ;
401
- }
402
-
403
- validationErrors . push ( {
404
- path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
405
- message :
406
- "positional argument defaultValue must be a number or an array of numbers" ,
407
- } ) ;
408
- }
409
- case ArgumentType . BIGINT : {
410
- if (
411
- typeof arg . defaultValue === "bigint" ||
412
- ( Array . isArray ( arg . defaultValue ) &&
413
- arg . defaultValue . every ( ( v ) => typeof v === "bigint" ) )
407
+ typeof arg . defaultValue !== "boolean" &&
408
+ ( ! Array . isArray ( arg . defaultValue ) ||
409
+ arg . defaultValue . some ( ( v ) => typeof v !== "boolean" ) )
414
410
) {
415
- break ;
411
+ validationErrors . push ( {
412
+ path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
413
+ message :
414
+ "positional argument defaultValue must be a boolean or an array of booleans" ,
415
+ } ) ;
416
416
}
417
417
418
- validationErrors . push ( {
419
- path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
420
- message :
421
- "positional argument defaultValue must be a bigint or an array of bigints" ,
422
- } ) ;
418
+ break ;
423
419
}
420
+ case ArgumentType . INT :
424
421
case ArgumentType . FLOAT : {
425
422
if (
426
- typeof arg . defaultValue === "number" ||
427
- ( Array . isArray ( arg . defaultValue ) &&
428
- arg . defaultValue . every ( ( v ) => typeof v = == "number" ) )
423
+ typeof arg . defaultValue !== "number" &&
424
+ ( ! Array . isArray ( arg . defaultValue ) ||
425
+ arg . defaultValue . some ( ( v ) => typeof v ! == "number" ) )
429
426
) {
430
- break ;
427
+ validationErrors . push ( {
428
+ path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
429
+ message :
430
+ "positional argument defaultValue must be a number or an array of numbers" ,
431
+ } ) ;
431
432
}
432
433
433
- validationErrors . push ( {
434
- path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
435
- message :
436
- "positional argument defaultValue must be a number or an array of numbers" ,
437
- } ) ;
434
+ break ;
438
435
}
439
- case ArgumentType . FILE : {
436
+ case ArgumentType . BIGINT : {
440
437
if (
441
- typeof arg . defaultValue === "string" ||
442
- ( Array . isArray ( arg . defaultValue ) &&
443
- arg . defaultValue . every ( ( v ) => typeof v === "string ") )
438
+ typeof arg . defaultValue !== "bigint" &&
439
+ ( ! Array . isArray ( arg . defaultValue ) ||
440
+ arg . defaultValue . some ( ( v ) => typeof v !== "bigint ") )
444
441
) {
445
- break ;
442
+ validationErrors . push ( {
443
+ path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
444
+ message :
445
+ "positional argument defaultValue must be a bigint or an array of bigints" ,
446
+ } ) ;
446
447
}
447
448
448
- validationErrors . push ( {
449
- path : [ ...path , "positionalArguments" , index , "defaultValue" ] ,
450
- message :
451
- "positional argument defaultValue must be a string or an array of strings" ,
452
- } ) ;
449
+ break ;
453
450
}
454
451
}
455
452
}
@@ -470,7 +467,7 @@ function validatePositionalArguments(
470
467
return validationErrors ;
471
468
}
472
469
473
- function validatePluginsConfig (
470
+ export function validatePluginsConfig (
474
471
plugins : HardhatPlugin [ ] ,
475
472
path : Array < string | number > = [ ] ,
476
473
) : HardhatUserConfigValidationError [ ] {
@@ -527,16 +524,19 @@ function validatePluginsConfig(
527
524
plugin . hookHandlers !== null
528
525
) {
529
526
for ( const [ hookName , handler ] of Object . entries ( plugin . hookHandlers ) ) {
530
- if ( typeof handler === "function" || typeof handler === "string" ) {
531
- continue ;
527
+ if ( typeof handler !== "function" && typeof handler !== "string" ) {
528
+ validationErrors . push ( {
529
+ path : [ ...path , "plugins" , index , "hookHandlers" , hookName ] ,
530
+ message :
531
+ "plugin hookHandlers must be an object of functions or strings" ,
532
+ } ) ;
532
533
}
533
-
534
- validationErrors . push ( {
535
- path : [ ...path , "plugins" , index , "hookHandlers" , hookName ] ,
536
- message :
537
- "plugin hookHandlers must be an object of functions or strings" ,
538
- } ) ;
539
534
}
535
+ } else {
536
+ validationErrors . push ( {
537
+ path : [ ...path , "plugins" , index , "hookHandlers" ] ,
538
+ message : "plugin hookHandlers must be an object" ,
539
+ } ) ;
540
540
}
541
541
}
542
542
0 commit comments