1+ import { constantCase } from 'constant-case' ;
12import type { ClientEvents , ClientOptions } from 'discord.js' ;
23import type { ZodTypeAny } from 'zod' ;
34import { z } from 'zod' ;
@@ -21,6 +22,7 @@ type EventHandlers = {
2122} ;
2223
2324type BotModule < Env extends Record < string , ZodTypeAny > > = {
25+ name : string ;
2426 env ?: Env ;
2527 intents ?: ClientOptions [ 'intents' ] ;
2628 slashCommands ?: ModuleFunction < Env , Array < BotCommand > > ;
@@ -31,28 +33,56 @@ interface CreatedModuleInput {
3133 env : unknown ;
3234}
3335
36+ type ModuleFactory = ( input : CreatedModuleInput ) => Promise < CreatedModule > ;
37+
3438export interface CreatedModule {
3539 intents : ClientOptions [ 'intents' ] ;
3640 slashCommands : Array < BotCommand > ;
3741 eventHandlers : EventHandlers ;
3842}
3943
40- export type ModuleFactory = ( input : CreatedModuleInput ) => Promise < CreatedModule > ;
44+ export interface ModuleCreator {
45+ name : string ;
46+ factory : ModuleFactory ;
47+ }
4148
4249export const createModule = < Env extends Record < string , ZodTypeAny > > (
4350 module : BotModule < Env > ,
44- ) : ModuleFactory => {
45- return async ( input ) => {
46- const env = await z . object ( module . env ?? ( { } as Env ) ) . parseAsync ( input . env ) ;
51+ ) : ModuleCreator => ( {
52+ name : module . name ,
53+ factory : async ( input ) => {
54+ const result = await z . object ( module . env ?? ( { } as Env ) ) . safeParseAsync ( input . env ) ;
55+
56+ if ( ! result . success ) {
57+ const constantName = constantCase ( module . name ) ;
58+ const zodErrors = result . error . flatten ( ) . fieldErrors ;
59+
60+ const errors = Object . entries ( zodErrors ) . reduce < Record < string , string [ ] > > (
61+ ( acc , [ key , value ] ) => ( {
62+ ...acc ,
63+ ...( Array . isArray ( value ) ? { [ `${ constantName } _${ key } ` ] : value } : { } ) ,
64+ } ) ,
65+ { } ,
66+ ) ;
67+
68+ const formattedErrors = Object . entries ( errors ) . reduce (
69+ ( acc , [ key , values ] ) => values . reduce ( ( acc , value ) => `${ acc } \n\t- ${ key } : ${ value } ` , acc ) ,
70+ '' ,
71+ ) ;
72+
73+ throw new Error (
74+ `Encountered errors while validating environment variables for module ${ module . name } :${ formattedErrors } ` ,
75+ ) ;
76+ }
4777
4878 const context = {
49- env,
79+ env : result . data ,
5080 } ;
5181
5282 return {
5383 intents : module . intents ?? [ ] ,
5484 slashCommands : module . slashCommands ?.( context ) ?? [ ] ,
5585 eventHandlers : module . eventHandlers ?.( context ) ?? { } ,
5686 } ;
57- } ;
58- } ;
87+ } ,
88+ } ) ;
0 commit comments