{"version":3,"file":"lazy-validator.mjs","names":[],"sources":["../../../../../../../@warlock.js/seal/src/validators/lazy-validator.ts"],"sourcesContent":["import type { JsonSchemaResult, JsonSchemaTarget } from \"../standard-schema/json-schema\";\nimport type { SchemaContext, ValidationResult } from \"../types\";\nimport { BaseValidator } from \"./base-validator\";\n\n/**\n * Lazy validator — defers resolution of the inner validator until validate-time.\n *\n * Solves the chicken-and-egg of self-referencing schemas. JavaScript evaluates\n * an object literal before the `const` binding completes, so this can't work:\n *\n * ```ts\n * const categorySchema = v.object({\n *   name: v.string(),\n *   children: v.array(categorySchema),  // ❌ ReferenceError\n * });\n * ```\n *\n * Wrap the recursive reference in `v.lazy(() => …)` — the thunk isn't invoked\n * during construction, only when `validate()` is called:\n *\n * ```ts\n * type Category = { name: string; children: Category[] };\n *\n * const categorySchema: ObjectValidator<...> = v.object({\n *   name: v.string(),\n *   children: v.array(v.lazy(() => categorySchema)),\n * });\n *\n * type T = Infer<typeof categorySchema>;\n * // { name: string; children: T[] }   ← recursive type\n * ```\n *\n * The thunk is memoized — it's invoked once on the first validate (or\n * `matchesType` / `toJsonSchema`) call and the result is cached. The thunk is\n * expected to return a stable validator; calling it on every validate would be\n * wasteful and could mask bugs where the user accidentally returns a fresh\n * validator each time.\n *\n * **JSON Schema caveat.** v1 uses simple resolve-and-delegate — recursive\n * schemas will infinite-loop in `toJsonSchema()`. If you need JSON Schema for\n * a recursive shape, generate it manually with `$defs` + `$ref` until v2 lands.\n *\n * @see `domains/seal/plans/2026-05-12-lazy-validator.md`\n */\nexport class LazyValidator<T extends BaseValidator = BaseValidator> extends BaseValidator {\n  private resolvedValidator: T | undefined;\n\n  public constructor(private thunk: () => T) {\n    super();\n    // Lazy itself defers required handling to the inner validator —\n    // mark the wrapper as optional so the required check doesn't fire here.\n    this.requiredRule = null;\n    this.isOptional = true;\n  }\n\n  /**\n   * Resolve the inner validator. Memoizes the result so subsequent calls\n   * don't re-execute the thunk.\n   */\n  private resolve(): T {\n    if (this.resolvedValidator === undefined) {\n      this.resolvedValidator = this.thunk();\n    }\n\n    return this.resolvedValidator;\n  }\n\n  public override async validate(data: any, context: SchemaContext): Promise<ValidationResult> {\n    return this.resolve().validate(data, context);\n  }\n\n  public override matchesType(value: any): boolean {\n    return this.resolve().matchesType(value);\n  }\n\n  public override clone(): this {\n    const cloned = super.clone();\n    // Share the thunk reference; reset the memo so the clone resolves\n    // independently on its first call (in case the thunk closure resolves\n    // differently in a different context — unlikely but cheap insurance).\n    cloned.thunk = this.thunk;\n    cloned.resolvedValidator = undefined;\n\n    return cloned;\n  }\n\n  /**\n   * JSON Schema generation — simple resolve-and-delegate.\n   *\n   * **Recursive schemas will infinite-loop.** Until v2 adds `$ref` + `$defs`\n   * generation, callers needing JSON Schema for recursive shapes must build\n   * the schema manually.\n   */\n  public override toJsonSchema(target: JsonSchemaTarget = \"draft-2020-12\"): JsonSchemaResult {\n    return this.resolve().toJsonSchema(target);\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,IAAa,gBAAb,cAA4E,cAAc;CAGxF,AAAO,YAAY,AAAQ,OAAgB;EACzC,MAAM;EADmB;EAIzB,KAAK,eAAe;EACpB,KAAK,aAAa;CACpB;;;;;CAMA,AAAQ,UAAa;EACnB,IAAI,KAAK,sBAAsB,QAC7B,KAAK,oBAAoB,KAAK,MAAM;EAGtC,OAAO,KAAK;CACd;CAEA,MAAsB,SAAS,MAAW,SAAmD;EAC3F,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,MAAM,OAAO;CAC9C;CAEA,AAAgB,YAAY,OAAqB;EAC/C,OAAO,KAAK,QAAQ,CAAC,CAAC,YAAY,KAAK;CACzC;CAEA,AAAgB,QAAc;EAC5B,MAAM,SAAS,MAAM,MAAM;EAI3B,OAAO,QAAQ,KAAK;EACpB,OAAO,oBAAoB;EAE3B,OAAO;CACT;;;;;;;;CASA,AAAgB,aAAa,SAA2B,iBAAmC;EACzF,OAAO,KAAK,QAAQ,CAAC,CAAC,aAAa,MAAM;CAC3C;AACF"}