|
| 1 | +/* eslint-disable no-unused-vars */ |
| 2 | +import{ |
| 3 | +z, |
| 4 | +// infer as _infer, |
| 5 | +ZodObject, |
| 6 | +ZodRawShape, |
| 7 | +ZodSchema, |
| 8 | +ZodTypeAny, |
| 9 | +ZodType, |
| 10 | +}from'zod'; |
| 11 | +import{Simplify,zInfer}from'./utils/type-utils'; |
| 12 | + |
| 13 | +// Generic type for resolver functions |
| 14 | +exporttypeResolver< |
| 15 | +TInputSchemaextendsZodTypeAny|undefined, |
| 16 | +TOutputSchemaextendsZodTypeAny|undefined|unknown, |
| 17 | +TContextextendsRecord<string,any>|unknown=unknown, |
| 18 | +>=(opts:{ |
| 19 | +input:TInputSchemaextendsZodTypeAny ?zInfer<TInputSchema> :null; |
| 20 | +ctx:Simplify<TContext>; |
| 21 | +})=>Promise<TOutputSchemaextendsZodTypeAny ?zInfer<TOutputSchema> :void>; |
| 22 | + |
| 23 | +// Define the builder interface capturing generic types for input and output |
| 24 | + |
| 25 | +exporttypeZodSchemaOrRawShape=ZodSchema<any>|ZodRawShape; |
| 26 | +exporttypeInferZodSchemaOrRawShape<TextendsZodSchemaOrRawShape>= |
| 27 | +TextendsZodRawShape ?ZodObject<T> :T; |
| 28 | + |
| 29 | +exporttypeMiddleware< |
| 30 | +TContextextendsRecord<string,any>|unknown, |
| 31 | +TNewContextextendsunknown=unknown, |
| 32 | +>=(opts:{ |
| 33 | +ctx:TContext; |
| 34 | +next:(ctx?:TNewContext)=>Promise<TNewContext>; |
| 35 | +})=>Promise<TNewContext>; |
| 36 | + |
| 37 | +exporttypeActionDef< |
| 38 | +TResolverextendsResolver<any,any,any>, |
| 39 | +TInputSchemaextendsZodTypeAny|undefined, |
| 40 | +TOutputSchemaextendsZodTypeAny|undefined|unknown, |
| 41 | +TTypeextends'mutation'|'query'|undefined, |
| 42 | +TContextextendsRecord<string,any>|unknown=unknown, |
| 43 | +>={ |
| 44 | +inputSchema:TInputSchema; |
| 45 | +outputSchema:TOutputSchema; |
| 46 | +resolver:TResolver; |
| 47 | +type:TType; |
| 48 | +middleware:Middleware<TContext,TContext>[]; |
| 49 | +}; |
| 50 | + |
| 51 | +constinitialDef={ |
| 52 | +inputSchema:undefined, |
| 53 | +outputSchema:undefined, |
| 54 | +resolver:undefined, |
| 55 | +type:undefined, |
| 56 | +middleware:[]asMiddleware<any,any>[], |
| 57 | +}; |
| 58 | + |
| 59 | +exportfunctionaction< |
| 60 | +TContextextendsRecord<string,any>|unknown=unknown, |
| 61 | +>(){ |
| 62 | +functioncreateBuilder< |
| 63 | +TInputSchemaextendsZodTypeAny|undefined, |
| 64 | +TOutputSchemaextendsZodTypeAny|undefined, |
| 65 | +TTypeextends'mutation'|'query'|undefined, |
| 66 | +TContextOverrideextendsRecord<string,any>|unknown=unknown, |
| 67 | +>( |
| 68 | +def:ActionDef<any,TInputSchema,TOutputSchema,TType,TContextOverride> |
| 69 | +):ActionBuilder<TInputSchema,TOutputSchema,TType,TContextOverride>{ |
| 70 | +return{ |
| 71 | +input<TNewInputSchemaextendsZodSchemaOrRawShape>( |
| 72 | +schema:TNewInputSchema |
| 73 | +){ |
| 74 | +constinputSchema= |
| 75 | +schemainstanceofZodSchema ?schema :z.object(schema); |
| 76 | +returncreateBuilder({ |
| 77 | +...def, |
| 78 | +inputSchema:inputSchemaasInferZodSchemaOrRawShape<TNewInputSchema>,// handle zod object or raw shape |
| 79 | +}); |
| 80 | +}, |
| 81 | +output<TNewOutputextendsZodTypeAny>(schema:TNewOutput){ |
| 82 | +returncreateBuilder({ |
| 83 | +...def, |
| 84 | +outputSchema:schema, |
| 85 | +}); |
| 86 | +}, |
| 87 | + |
| 88 | +use<TNewContextextendsTContextOverride>( |
| 89 | +middleware:Middleware<TContextOverride,TNewContext> |
| 90 | +){ |
| 91 | +returncreateBuilder({ |
| 92 | +...def, |
| 93 | +//@ts-expect-error |
| 94 | +middleware:[...def.middleware,middleware], |
| 95 | +})asunknownasActionBuilder< |
| 96 | +TInputSchema, |
| 97 | +TOutputSchema, |
| 98 | +TType, |
| 99 | +TNewContext |
| 100 | +>; |
| 101 | +}, |
| 102 | +mutation< |
| 103 | +TResolverextendsResolver< |
| 104 | +TInputSchema, |
| 105 | +TOutputSchema, |
| 106 | +TContextOverride |
| 107 | +>, |
| 108 | +>(resolver:TResolver){ |
| 109 | +constnewDef:ActionDef< |
| 110 | +TResolver, |
| 111 | +TInputSchema, |
| 112 | +TOutputSchema, |
| 113 | +'mutation', |
| 114 | +TContextOverride |
| 115 | +>={ |
| 116 | +...def, |
| 117 | +resolver, |
| 118 | +type:'mutation', |
| 119 | +}; |
| 120 | +returncreateResolver(newDef)asunknownasAction< |
| 121 | +TResolver, |
| 122 | +TInputSchema, |
| 123 | +TOutputSchema, |
| 124 | +'mutation', |
| 125 | +TContextOverride |
| 126 | +>; |
| 127 | +}, |
| 128 | +query< |
| 129 | +TResolverextendsResolver< |
| 130 | +TInputSchema, |
| 131 | +TOutputSchema, |
| 132 | +TContextOverride |
| 133 | +>, |
| 134 | +>(resolver:TResolver){ |
| 135 | +constnewDef:ActionDef< |
| 136 | +TResolver, |
| 137 | +TInputSchema, |
| 138 | +TOutputSchema, |
| 139 | +'query', |
| 140 | +TContextOverride |
| 141 | +>={ |
| 142 | +...def, |
| 143 | +resolver, |
| 144 | +type:'query', |
| 145 | +}; |
| 146 | +returncreateResolver(newDef)asunknownasAction< |
| 147 | +TResolver, |
| 148 | +TInputSchema, |
| 149 | +TOutputSchema, |
| 150 | +'query', |
| 151 | +TContextOverride |
| 152 | +>; |
| 153 | +}, |
| 154 | +}; |
| 155 | +} |
| 156 | + |
| 157 | +returncreateBuilder<undefined,any,any,TContext>({ |
| 158 | +...initialDef, |
| 159 | +}); |
| 160 | +} |
| 161 | +exportinterfaceActionBuilder< |
| 162 | +TInputSchemaextendsZodTypeAny|undefined, |
| 163 | +TOutputSchemaextendsZodTypeAny|undefined, |
| 164 | +TTypeextends'mutation'|'query'|undefined, |
| 165 | +TContextextendsRecord<string,any>|unknown=unknown, |
| 166 | +>{ |
| 167 | +input:<TNewInputSchemaextendsZodSchemaOrRawShape>( |
| 168 | +schema:TNewInputSchema |
| 169 | +)=>ActionBuilder< |
| 170 | +InferZodSchemaOrRawShape<TNewInputSchema>, |
| 171 | +TOutputSchema, |
| 172 | +TType, |
| 173 | +TContext |
| 174 | +>; |
| 175 | +output:<TNewOutputextendsZodTypeAny>( |
| 176 | +schema:TNewOutput |
| 177 | +)=>ActionBuilder<TInputSchema,TNewOutput,TType,TContext>; |
| 178 | +use:<TNewContextextendsTContext>( |
| 179 | +middleware:Middleware<TContext,TNewContext> |
| 180 | +)=>ActionBuilder<TInputSchema,TOutputSchema,TType,TNewContext>; |
| 181 | + |
| 182 | +mutation:<TResolverextendsResolver<TInputSchema,TOutputSchema,TContext>>( |
| 183 | +resolver:TResolver |
| 184 | +)=>Action<TResolver,TInputSchema,TOutputSchema,'mutation',TContext>; |
| 185 | +query:<TResolverextendsResolver<TInputSchema,TOutputSchema,TContext>>( |
| 186 | +resolver:TResolver |
| 187 | +)=>Action<TResolver,TInputSchema,TOutputSchema,'query',TContext>; |
| 188 | +} |
| 189 | + |
| 190 | +exporttypeAction< |
| 191 | +TResolverextendsResolver<any,any,any>, |
| 192 | +TInputSchemaextendsZodTypeAny|undefined, |
| 193 | +TOutputSchemaextendsZodTypeAny|undefined|unknown, |
| 194 | +TTypeextends'mutation'|'query'|undefined, |
| 195 | +TContextextendsRecord<string,any>|unknown=unknown, |
| 196 | +>=ActionDef<TResolver,TInputSchema,TOutputSchema,TType,TContext>&{ |
| 197 | +callerWithoutParser:( |
| 198 | +ctx:TContext, |
| 199 | +input:TInputSchemaextendsZodTypeAny ?zInfer<TInputSchema> :void |
| 200 | +)=>ReturnType<TResolver>; |
| 201 | +}&{ |
| 202 | +( |
| 203 | +ctx:TContext, |
| 204 | +input:TInputSchemaextendsZodTypeAny ?zInfer<TInputSchema> :void |
| 205 | +):ReturnType<TResolver>; |
| 206 | +}; |
| 207 | +exportfunctioncreateResolver< |
| 208 | +TResolverextendsResolver<any,any,any>, |
| 209 | +TInputSchemaextendsZodTypeAny|undefined, |
| 210 | +TOutputSchemaextendsZodTypeAny|undefined, |
| 211 | +TTypeextends'mutation'|'query', |
| 212 | +TContextextendsRecord<string,any>|unknown, |
| 213 | +>(def:ActionDef<TResolver,TInputSchema,TOutputSchema,TType,TContext>){ |
| 214 | +/** |
| 215 | + * Invokes the resolver with middleware logic |
| 216 | + */ |
| 217 | +constcallerWithMiddleware=async( |
| 218 | +ctx:TContext, |
| 219 | +input:TInputSchemaextendsZodTypeAny ?zInfer<TInputSchema> :null, |
| 220 | +middlewares:Middleware<TContext,TContext>[]=def.middleware |
| 221 | +)=>{ |
| 222 | +letcurrentCtx=ctx; |
| 223 | + |
| 224 | +constexecuteMiddleware=async(index:number):Promise<any>=>{ |
| 225 | +if(index>=middlewares.length){ |
| 226 | +returndef.resolver({ input,ctx:currentCtx}); |
| 227 | +}else{ |
| 228 | +constcurrentMiddleware=middlewares[index]; |
| 229 | +returnawaitcurrentMiddleware({ |
| 230 | +ctx:currentCtx, |
| 231 | +next:async(newCtx?:TContext)=>{ |
| 232 | +currentCtx=newCtx||currentCtx; |
| 233 | +returnexecuteMiddleware(index+1); |
| 234 | +}, |
| 235 | +}); |
| 236 | +} |
| 237 | +}; |
| 238 | + |
| 239 | +returnexecuteMiddleware(0); |
| 240 | +}; |
| 241 | + |
| 242 | +/** |
| 243 | + * Calls the resolver function without parsing input/output |
| 244 | + * Useful for calling the resolver when the input/output is already parsed |
| 245 | + */ |
| 246 | +constcallerWithoutParser=async( |
| 247 | +ctx:TContext, |
| 248 | +input:TInputSchemaextendsZodTypeAny ?zInfer<TInputSchema> :null |
| 249 | +)=>{ |
| 250 | +returncallerWithMiddleware(ctx,input); |
| 251 | +}; |
| 252 | + |
| 253 | +/** |
| 254 | + * Invokes the resolver with parsing input/output and middleware logic |
| 255 | + * Useful for safe calling the resolver directly |
| 256 | + */ |
| 257 | +constcallerWithParser=async(ctx:TContext,input:any)=>{ |
| 258 | +constmaybeParsedInput=def.inputSchema |
| 259 | +?def.inputSchema.parse(input) |
| 260 | +:input; |
| 261 | +constresult=awaitcallerWithMiddleware(ctx,maybeParsedInput); |
| 262 | + |
| 263 | +constmaybeParsedOutput=def.outputSchema |
| 264 | +?def.outputSchema.parse(result) |
| 265 | +:result; |
| 266 | +returnmaybeParsedOutput; |
| 267 | +}; |
| 268 | + |
| 269 | +returnObject.assign(callerWithParser,def,{ callerWithoutParser}); |
| 270 | +} |