UNPKG

axiom

Version:

Axiom AI SDK provides - an API to wrap your AI calls with observability instrumentation. - offline evals

208 lines (203 loc) 6.91 kB
import { ZodObject, ZodDefault, z } from 'zod'; type ValidChars = | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-' | '_'; type ValidateName<T extends string, Original extends string = T> = // For widened strings, don't attempt validation – let them flow through unchanged string extends T // string is not wider than T, ie T is string ? T : T extends '' ? Original extends '' ? '❌ Name cannot be empty' : Original : T extends `${infer First}${infer Rest}` ? First extends ValidChars ? ValidateName<Rest, Original> : `❌ Invalid character in "${Original}". Only A-Z, a-z, 0-9, -, _ allowed` : never; type DefaultMaxDepth = 8; type HasDefaults<S> = S extends { _zod: { def: { defaultValue: unknown; }; }; } ? true : S extends ZodObject<infer Shape> ? { [K in keyof Shape]: HasDefaults<Shape[K]>; } extends Record<keyof Shape, true> ? true : false : false; type UnwrapSchema<T> = T extends ZodDefault<infer U> ? U : T; type AllFieldsHaveDefaults<Schema> = Schema extends { _zod: { def: { defaultValue: unknown; }; }; } ? true : HasDefaults<UnwrapSchema<Schema>>; interface AppScopeConfig<FlagSchema extends ZodObject<any> | undefined = undefined, FactSchema extends ZodObject<any> | undefined = undefined> { flagSchema: FlagSchema; factSchema?: FactSchema; } /** * Recursive type to extract all possible paths from an object type. * Uses stack-based depth limiting for better performance. * * @template T - The object type to extract paths from * @template Stack - Internal stack counter (do not set manually) * @template MaxDepth - Maximum recursion depth (default: 8 for good balance) */ type ObjectPaths<T, Stack extends unknown[] = [], MaxDepth extends number = DefaultMaxDepth> = Stack['length'] extends MaxDepth ? never : T extends object ? { [K in keyof T]-?: K extends string | number ? `${K}` | `${K}.${ObjectPaths<T[K], [1, ...Stack], MaxDepth>}` : never; }[keyof T] : never; type ObjectPathValue<T, P extends string> = P extends keyof T ? T[P] : P extends `${infer K}.${infer Rest}` ? K extends keyof T ? ObjectPathValue<T[K], Rest> : never : never; /** * Generate deep nested paths from flag schema. * * @template T - ZodObject to extract paths from * @template MaxDepth - Maximum recursion depth (default: 8, override for deeper nesting) * @example * // Default 8-level depth * type Paths = DotPaths<MySchema> * * // Custom depth for deeper nesting (impacts performance) * type DeepPaths = DotPaths<MySchema, 12> */ type DotPaths<T extends ZodObject<any>, MaxDepth extends number = DefaultMaxDepth> = { [NS in keyof T['shape']]: (string & NS) | { [P in ObjectPaths<z.output<UnwrapSchema<T['shape'][NS]>>, [ ], MaxDepth>]: `${string & NS}.${P}`; }[ObjectPaths<z.output<UnwrapSchema<T['shape'][NS]>>, [], MaxDepth>]; }[keyof T['shape']]; type PathValue<T extends ZodObject<any>, P extends string> = P extends `${infer NS}.${infer Rest}` ? NS extends keyof T['shape'] ? ObjectPathValue<z.output<UnwrapSchema<T['shape'][NS]>>, Rest> : never : P extends keyof T['shape'] ? z.output<UnwrapSchema<T['shape'][P]>> : never; type DotNotationFlagFunction<FS extends ZodObject<any> | undefined> = FS extends ZodObject<any> ? <P extends DotPaths<FS>>(path: P) => PathValue<FS, P> : never; type FactFunction<SC extends ZodObject<any> | undefined> = SC extends ZodObject<any> ? <P extends DotPaths<SC> & string>(name: P, value: PathValue<SC, P>) => void : never; type OverrideFlagsFunction<FS extends ZodObject<any> | undefined> = FS extends ZodObject<any> ? (partial: { [K in DotPaths<FS>]?: PathValue<FS, K>; }) => void : (partial: Record<string, any>) => void; type WithFlagsFunction<FS extends ZodObject<any> | undefined> = FS extends ZodObject<any> ? <T>(overrides: { [K in DotPaths<FS>]?: PathValue<FS, K>; }, fn: () => T) => T : <T>(overrides: Record<string, any>, fn: () => T) => T; type PickFlagsFunction<FS extends ZodObject<any> | undefined> = FS extends ZodObject<any> ? { <K extends ReadonlyArray<DotPaths<FS> & string>>(...paths: K): K; <K extends ReadonlyArray<DotPaths<FS> & string>>(paths: K): K; } : never; interface AppScope<FS extends ZodObject<any> | undefined, SC extends ZodObject<any> | undefined> { flag: DotNotationFlagFunction<FS>; fact: FactFunction<SC>; overrideFlags: OverrideFlagsFunction<FS>; withFlags: WithFlagsFunction<FS>; pickFlags: PickFlagsFunction<FS>; getAllDefaultFlags: () => Record<string, any>; } /** * Create a new application-level evaluation scope. * * @param config.flagSchema A zod object describing the schema for flags **(required)** * @param config.factSchema A zod object describing the schema for facts (optional) * * @example * import { z } from 'zod'; * * const { flag, fact, withFlags, pickFlags, overrideFlags } = createAppScope({ * flagSchema: z.object({ * ui: z.object({ * darkMode: z.boolean().default(false), * theme: z.object({ * primary: z.string().default('#00f'), * }), * }), * api: z.object({ endpoint: z.string().default('/api') }), * }), * factSchema: z.object({ * userAction: z.string(), * timing: z.number(), * }), * }); * * // Typed flag access * const dark = flag('ui.darkMode'); // inferred boolean * const theme = flag('ui.theme'); // entire object * const primary = flag('ui.theme.primary'); // '#00f' * const endpoint = flag('api.endpoint'); // uses schema default * * // Typed fact recording * fact('userAction', 'clicked_button'); * fact('timing', 1250); * * // Temporarily override flags for a block of code * withFlags({ 'ui.darkMode': true }, () => { * // code here, `ui.darkMode` will be true in this block and reset after * }); * * // Override flags globally for the current evaluation run * overrideFlags({ 'api.endpoint': '/custom' }); */ declare function createAppScope<FlagSchema extends ZodObject<any>, FactSchema extends ZodObject<any> | undefined = undefined>(config: AllFieldsHaveDefaults<FlagSchema> extends true ? AppScopeConfig<FlagSchema, FactSchema> : { flagSchema: FlagSchema; factSchema?: FactSchema; __error__: 'createAppScope: flagSchema must have .default() for all leaf fields'; }): AppScope<FlagSchema, FactSchema>; export { type ValidateName as V, createAppScope as c };