import { ZodObject, ZodDefault, z } from 'zod'; type DefaultMaxDepth = 8; type HasDefaults = S extends { _zod: { def: { defaultValue: unknown; }; }; } ? true : S extends ZodObject ? { [K in keyof Shape]: HasDefaults; } extends Record ? true : false : false; type UnwrapSchema = T extends ZodDefault ? U : T; type AllFieldsHaveDefaults = Schema extends { _zod: { def: { defaultValue: unknown; }; }; } ? true : HasDefaults>; interface AppScopeConfig | undefined = undefined, FactSchema extends ZodObject | 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 = Stack['length'] extends MaxDepth ? never : T extends object ? { [K in keyof T]-?: K extends string | number ? `${K}` | `${K}.${ObjectPaths}` : never; }[keyof T] : never; type ObjectPathValue = P extends keyof T ? T[P] : P extends `${infer K}.${infer Rest}` ? K extends keyof T ? ObjectPathValue : 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 * * // Custom depth for deeper nesting (impacts performance) * type DeepPaths = DotPaths */ type DotPaths, MaxDepth extends number = DefaultMaxDepth> = { [NS in keyof T['shape']]: (string & NS) | { [P in ObjectPaths>, [ ], MaxDepth>]: `${string & NS}.${P}`; }[ObjectPaths>, [], MaxDepth>]; }[keyof T['shape']]; type PathValue, P extends string> = P extends `${infer NS}.${infer Rest}` ? NS extends keyof T['shape'] ? ObjectPathValue>, Rest> : never : P extends keyof T['shape'] ? z.output> : never; type DotNotationFlagFunction | undefined> = FS extends ZodObject ?

>(path: P) => PathValue : never; type FactFunction | undefined> = SC extends ZodObject ?

& string>(name: P, value: PathValue) => void : never; type OverrideFlagsFunction | undefined> = FS extends ZodObject ? (partial: { [K in DotPaths]?: PathValue; }) => void : (partial: Record) => void; type WithFlagsFunction | undefined> = FS extends ZodObject ? (overrides: { [K in DotPaths]?: PathValue; }, fn: () => T) => T : (overrides: Record, fn: () => T) => T; type PickFlagsFunction | undefined> = FS extends ZodObject ? { & string>>(...paths: K): K; & string>>(paths: K): K; } : never; interface AppScope | undefined, SC extends ZodObject | undefined> { flag: DotNotationFlagFunction; fact: FactFunction; overrideFlags: OverrideFlagsFunction; withFlags: WithFlagsFunction; pickFlags: PickFlagsFunction; getAllDefaultFlags: () => Record; } /** * 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, FactSchema extends ZodObject | undefined = undefined>(config: AllFieldsHaveDefaults extends true ? AppScopeConfig : { flagSchema: FlagSchema; factSchema?: FactSchema; __error__: 'createAppScope: flagSchema must have .default() for all leaf fields'; }): AppScope; export { createAppScope as c };