{"version":3,"file":"schema-registry.mjs","sources":["../../../../src/lib/data/normalization/schema-registry.ts"],"sourcesContent":["/**\n * @file Schema Registry\n * @description Central registry for managing entity schemas with relationship\n * tracking, validation, and schema versioning support.\n *\n * Features:\n * - Centralized schema management\n * - Automatic relationship inference\n * - Schema versioning and migration\n * - Schema validation and integrity checks\n * - Lazy schema resolution for circular references\n *\n * @example\n * ```typescript\n * import { createSchemaRegistry, schema } from '@/lib/data/normalization';\n *\n * const registry = createSchemaRegistry();\n *\n * registry.register('users', {\n *   relations: {\n *     posts: schema.array('posts'),\n *     profile: 'profiles',\n *   },\n * });\n *\n * registry.register('posts', {\n *   relations: {\n *     author: 'users',\n *     comments: schema.array('comments'),\n *   },\n * });\n *\n * const { entities, result } = registry.normalize(data, 'posts');\n * ```\n */\n\nimport {\n  ArraySchema,\n  type Entity,\n  EntitySchema,\n  type NormalizationResult,\n  normalize as baseNormalize,\n  type NormalizedEntities,\n  ObjectSchema,\n  type Schema,\n  UnionSchema,\n  ValueSchema,\n} from './normalizer';\nimport { denormalize as baseDenormalize, type DenormalizeOptions } from './denormalizer';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Schema definition for registry\n */\nexport interface SchemaDefinition {\n  /** ID attribute name or function */\n  idAttribute?: string | ((entity: Entity) => string);\n  /** Relationship definitions (can reference other schemas by name) */\n  relations?: Record<string, string | Schema | RelationDefinition>;\n  /** Process entity after extraction */\n  processStrategy?: (entity: Entity) => Entity;\n  /** Merge strategy for duplicate entities */\n  mergeStrategy?: (existing: Entity, incoming: Entity) => Entity;\n  /** Fields to exclude from normalization */\n  excludeFields?: string[];\n  /** Schema version */\n  version?: number;\n  /** Migration function from previous version */\n  migrate?: (entity: Entity, fromVersion: number) => Entity;\n}\n\n/**\n * Relation definition\n */\nexport interface RelationDefinition {\n  /** Schema name or schema instance */\n  schema: string | Schema;\n  /** Relation type */\n  type: 'entity' | 'array' | 'union';\n  /** For union types, the discriminator */\n  schemaAttribute?: string | ((entity: Entity) => string);\n  /** Union schema mappings */\n  schemas?: Record<string, string>;\n}\n\n/**\n * Registered schema entry\n */\ninterface RegisteredSchema {\n  name: string;\n  definition: SchemaDefinition;\n  schema: EntitySchema | null;\n  version: number;\n  createdAt: number;\n  updatedAt: number;\n}\n\n/**\n * Schema registry configuration\n */\nexport interface SchemaRegistryConfig {\n  /** Enable strict mode (throw on undefined schemas) */\n  strict?: boolean;\n  /** Enable automatic reverse relationship inference */\n  inferReverseRelations?: boolean;\n  /** Default ID attribute */\n  defaultIdAttribute?: string;\n  /** Schema version storage key */\n  versionStorageKey?: string;\n  /** Enable schema caching */\n  enableCaching?: boolean;\n}\n\n/**\n * Schema registry interface\n */\nexport interface SchemaRegistry {\n  /** Register a schema */\n  register: (name: string, definition?: SchemaDefinition) => EntitySchema;\n  /** Get a schema by name */\n  get: (name: string) => EntitySchema | undefined;\n  /** Check if schema exists */\n  has: (name: string) => boolean;\n  /** Get all registered schema names */\n  getNames: () => string[];\n  /** Get all schemas */\n  getAll: () => Map<string, EntitySchema>;\n  /** Unregister a schema */\n  unregister: (name: string) => boolean;\n  /** Clear all schemas */\n  clear: () => void;\n  /** Normalize data using registry */\n  normalize: <T = string | string[]>(data: unknown, schemaName: string) => NormalizationResult<T>;\n  /** Denormalize data using registry */\n  denormalize: <T = unknown>(\n    input: unknown,\n    schemaName: string,\n    entities: NormalizedEntities,\n    options?: DenormalizeOptions\n  ) => T | null;\n  /** Validate schema integrity */\n  validate: () => SchemaValidationResult;\n  /** Get schema dependencies */\n  getDependencies: (name: string) => string[];\n  /** Get reverse dependencies */\n  getReverseDependencies: (name: string) => string[];\n  /** Export schemas for serialization */\n  export: () => ExportedSchemas;\n  /** Import schemas from serialization */\n  import: (schemas: ExportedSchemas) => void;\n  /** Get schema version */\n  getVersion: (name: string) => number;\n  /** Migrate entity to latest schema version */\n  migrateEntity: (name: string, entity: Entity, fromVersion: number) => Entity;\n}\n\n/**\n * Schema validation result\n */\nexport interface SchemaValidationResult {\n  valid: boolean;\n  errors: SchemaValidationError[];\n  warnings: SchemaValidationWarning[];\n}\n\n/**\n * Schema validation error\n */\nexport interface SchemaValidationError {\n  schema: string;\n  type: 'missing_relation' | 'circular_dependency' | 'invalid_definition';\n  message: string;\n  details?: unknown;\n}\n\n/**\n * Schema validation warning\n */\nexport interface SchemaValidationWarning {\n  schema: string;\n  type: 'unused_schema' | 'missing_reverse_relation' | 'potential_issue';\n  message: string;\n  details?: unknown;\n}\n\n/**\n * Exported schemas format\n */\nexport interface ExportedSchemas {\n  version: string;\n  schemas: Record<string, SchemaDefinition & { name: string }>;\n  exportedAt: string;\n}\n\n// =============================================================================\n// DEFAULT CONFIG\n// =============================================================================\n\nconst DEFAULT_CONFIG: Required<SchemaRegistryConfig> = {\n  strict: false,\n  inferReverseRelations: false,\n  defaultIdAttribute: 'id',\n  versionStorageKey: 'schema_versions',\n  enableCaching: true,\n};\n\n// =============================================================================\n// SCHEMA REGISTRY FACTORY\n// =============================================================================\n\n/**\n * Create a schema registry\n *\n * @param config - Registry configuration\n * @returns Schema registry instance\n *\n * @example\n * ```typescript\n * const registry = createSchemaRegistry({ strict: true });\n *\n * // Register schemas\n * registry.register('users', {\n *   relations: {\n *     posts: { schema: 'posts', type: 'array' },\n *   },\n * });\n *\n * registry.register('posts', {\n *   relations: {\n *     author: 'users',\n *   },\n * });\n *\n * // Use registry\n * const { entities, result } = registry.normalize(apiData, 'posts');\n * const post = registry.denormalize('101', 'posts', entities);\n * ```\n */\nexport function createSchemaRegistry(config: SchemaRegistryConfig = {}): SchemaRegistry {\n  const options: Required<SchemaRegistryConfig> = { ...DEFAULT_CONFIG, ...config };\n\n  // Internal storage\n  const registeredSchemas = new Map<string, RegisteredSchema>();\n  const resolvedSchemas = new Map<string, EntitySchema>();\n  const schemaCache = new Map<string, Schema>();\n\n  /**\n   * Resolve a relation definition to a Schema\n   */\n  function resolveRelation(relation: string | Schema | RelationDefinition): Schema {\n    // String reference\n    if (typeof relation === 'string') {\n      return getOrCreateSchema(relation);\n    }\n\n    // Already a schema\n    if (\n      relation instanceof EntitySchema ||\n      relation instanceof ArraySchema ||\n      relation instanceof ObjectSchema ||\n      relation instanceof UnionSchema ||\n      relation instanceof ValueSchema\n    ) {\n      return relation;\n    }\n\n    // Relation definition\n    const def = relation;\n    const baseSchema = typeof def.schema === 'string' ? getOrCreateSchema(def.schema) : def.schema;\n\n    switch (def.type) {\n      case 'array':\n        return new ArraySchema(baseSchema);\n\n      case 'union': {\n        if (!def.schemas) {\n          throw new Error('Union relation requires schemas mapping');\n        }\n        const unionSchemas: Record<string, EntitySchema> = {};\n        for (const [key, schemaName] of Object.entries(def.schemas)) {\n          unionSchemas[key] = getOrCreateSchema(schemaName);\n        }\n        return new UnionSchema(unionSchemas, def.schemaAttribute);\n      }\n\n      case 'entity':\n      default:\n        return baseSchema;\n    }\n  }\n\n  /**\n   * Get or create a schema by name\n   */\n  function getOrCreateSchema(name: string): EntitySchema {\n    // Check resolved cache\n    const cachedSchema = resolvedSchemas.get(name);\n    if (cachedSchema != null) {\n      return cachedSchema;\n    }\n\n    // Check if registered\n    const registered = registeredSchemas.get(name);\n    if (registered?.schema) {\n      return registered.schema;\n    }\n\n    // Create placeholder for forward reference\n    if (options.strict && !registeredSchemas.has(name)) {\n      throw new Error(`[SchemaRegistry] Schema \"${name}\" is not registered`);\n    }\n\n    // Create new schema\n    const schema = new EntitySchema(name, {\n      idAttribute: options.defaultIdAttribute,\n    });\n\n    resolvedSchemas.set(name, schema);\n    return schema;\n  }\n\n  /**\n   * Build full schema from definition\n   */\n  function buildSchema(name: string, definition: SchemaDefinition): EntitySchema {\n    const relations: Record<string, Schema> = {};\n\n    // Resolve all relations\n    if (definition.relations) {\n      for (const [key, value] of Object.entries(definition.relations)) {\n        relations[key] = resolveRelation(value);\n      }\n    }\n\n    // Create entity schema\n\n    return new EntitySchema(name, {\n      idAttribute: definition.idAttribute ?? options.defaultIdAttribute,\n      relations: relations as Record<string, EntitySchema | ArraySchema | UnionSchema>,\n      processStrategy: definition.processStrategy,\n      mergeStrategy: definition.mergeStrategy,\n      excludeFields: definition.excludeFields,\n    });\n  }\n\n  /**\n   * Resolve all pending schema references\n   */\n  function resolveAllSchemas(): void {\n    // First pass: build all schemas\n    for (const [name, registered] of registeredSchemas) {\n      if (!registered.schema) {\n        registered.schema = buildSchema(name, registered.definition);\n        resolvedSchemas.set(name, registered.schema);\n      }\n    }\n\n    // Second pass: update references for circular dependencies\n    for (const [name, registered] of registeredSchemas) {\n      if (registered.definition.relations) {\n        // const schema = registered.schema!;\n        const newRelations: Record<string, Schema> = {};\n\n        for (const [key, value] of Object.entries(registered.definition.relations)) {\n          newRelations[key] = resolveRelation(value);\n        }\n\n        // Replace schema with updated relations\n        const updatedSchema = new EntitySchema(name, {\n          idAttribute: registered.definition.idAttribute ?? options.defaultIdAttribute,\n          relations: newRelations as Record<string, EntitySchema | ArraySchema | UnionSchema>,\n          processStrategy: registered.definition.processStrategy,\n          mergeStrategy: registered.definition.mergeStrategy,\n          excludeFields: registered.definition.excludeFields,\n        });\n\n        registered.schema = updatedSchema;\n        resolvedSchemas.set(name, updatedSchema);\n      }\n    }\n  }\n\n  /**\n   * Register a schema\n   */\n  function register(name: string, definition: SchemaDefinition = {}): EntitySchema {\n    const now = Date.now();\n    const existing = registeredSchemas.get(name);\n\n    registeredSchemas.set(name, {\n      name,\n      definition,\n      schema: null,\n      version:\n        definition.version !== undefined && definition.version !== 0 ? definition.version : 1,\n      createdAt: existing?.createdAt ?? now,\n      updatedAt: now,\n    });\n\n    // Clear resolved cache to force rebuild\n    resolvedSchemas.delete(name);\n    schemaCache.clear();\n\n    // Resolve all schemas\n    resolveAllSchemas();\n\n    const resolved = resolvedSchemas.get(name);\n    if (resolved === undefined) {\n      throw new Error(`Failed to resolve schema: ${name}`);\n    }\n    return resolved;\n  }\n\n  /**\n   * Get a schema by name\n   */\n  function get(name: string): EntitySchema | undefined {\n    return resolvedSchemas.get(name);\n  }\n\n  /**\n   * Check if schema exists\n   */\n  function has(name: string): boolean {\n    return registeredSchemas.has(name);\n  }\n\n  /**\n   * Get all registered schema names\n   */\n  function getNames(): string[] {\n    return Array.from(registeredSchemas.keys());\n  }\n\n  /**\n   * Get all schemas\n   */\n  function getAll(): Map<string, EntitySchema> {\n    return new Map(resolvedSchemas);\n  }\n\n  /**\n   * Unregister a schema\n   */\n  function unregister(name: string): boolean {\n    const existed = registeredSchemas.delete(name);\n    resolvedSchemas.delete(name);\n    schemaCache.clear();\n    return existed;\n  }\n\n  /**\n   * Clear all schemas\n   */\n  function clear(): void {\n    registeredSchemas.clear();\n    resolvedSchemas.clear();\n    schemaCache.clear();\n  }\n\n  /**\n   * Normalize data using registry\n   */\n  function normalize<T = string | string[]>(\n    data: unknown,\n    schemaName: string\n  ): NormalizationResult<T> {\n    const entitySchema = resolvedSchemas.get(schemaName);\n    if (!entitySchema) {\n      if (options.strict) {\n        throw new Error(`[SchemaRegistry] Schema \"${schemaName}\" is not registered`);\n      }\n      // Auto-register\n      register(schemaName);\n    }\n\n    const schema = resolvedSchemas.get(schemaName);\n    if (schema === undefined) {\n      throw new Error(`Failed to resolve schema: ${schemaName}`);\n    }\n    return baseNormalize<T>(data, schema);\n  }\n\n  /**\n   * Denormalize data using registry\n   */\n  function denormalize<T = unknown>(\n    input: unknown,\n    schemaName: string,\n    entities: NormalizedEntities,\n    denormOptions: DenormalizeOptions = {}\n  ): T | null {\n    const entitySchema = resolvedSchemas.get(schemaName);\n    if (!entitySchema) {\n      if (options.strict) {\n        throw new Error(`[SchemaRegistry] Schema \"${schemaName}\" is not registered`);\n      }\n      return null;\n    }\n\n    return baseDenormalize<T>(input, entitySchema, entities, denormOptions);\n  }\n\n  /**\n   * Validate schema integrity\n   */\n  function validate(): SchemaValidationResult {\n    const errors: SchemaValidationError[] = [];\n    const warnings: SchemaValidationWarning[] = [];\n    const usedSchemas = new Set<string>();\n\n    for (const [name, registered] of registeredSchemas) {\n      const { definition } = registered;\n\n      // Check relations\n      if (definition.relations) {\n        for (const [relationKey, relation] of Object.entries(definition.relations)) {\n          let targetName: string | null = null;\n\n          if (typeof relation === 'string') {\n            targetName = relation;\n          } else if (typeof relation === 'object' && 'schema' in relation) {\n            if (typeof relation.schema === 'string') {\n              targetName = relation.schema;\n            }\n          }\n\n          if (targetName !== null && targetName !== '') {\n            usedSchemas.add(targetName);\n\n            if (!registeredSchemas.has(targetName)) {\n              errors.push({\n                schema: name,\n                type: 'missing_relation',\n                message: `Relation \"${relationKey}\" references undefined schema \"${targetName}\"`,\n                details: { relation: relationKey, target: targetName },\n              });\n            }\n\n            // Check for reverse relation\n            if (options.inferReverseRelations) {\n              const targetDef = registeredSchemas.get(targetName)?.definition;\n              if (targetDef?.relations) {\n                const hasReverse = Object.values(targetDef.relations).some((rel) => {\n                  if (typeof rel === 'string') return rel === name;\n                  if (typeof rel === 'object' && 'schema' in rel) {\n                    return rel.schema === name;\n                  }\n                  return false;\n                });\n\n                if (!hasReverse) {\n                  warnings.push({\n                    schema: targetName,\n                    type: 'missing_reverse_relation',\n                    message: `Schema \"${targetName}\" has no reverse relation to \"${name}\"`,\n                    details: { from: name, relation: relationKey },\n                  });\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n\n    // Check for unused schemas\n    for (const name of registeredSchemas.keys()) {\n      if (!usedSchemas.has(name)) {\n        // Check if it's a root schema (not referenced by others)\n        const isReferenced = Array.from(registeredSchemas.values()).some((reg) => {\n          if (!reg.definition.relations) return false;\n          return Object.values(reg.definition.relations).some((rel) => {\n            if (typeof rel === 'string') return rel === name;\n            if (typeof rel === 'object' && 'schema' in rel) {\n              return rel.schema === name;\n            }\n            return false;\n          });\n        });\n\n        if (!isReferenced && registeredSchemas.size > 1) {\n          warnings.push({\n            schema: name,\n            type: 'unused_schema',\n            message: `Schema \"${name}\" is not referenced by any other schema`,\n          });\n        }\n      }\n    }\n\n    return {\n      valid: errors.length === 0,\n      errors,\n      warnings,\n    };\n  }\n\n  /**\n   * Get schema dependencies\n   */\n  function getDependencies(name: string): string[] {\n    const registered = registeredSchemas.get(name);\n    if (!registered?.definition.relations) {\n      return [];\n    }\n\n    const deps = new Set<string>();\n\n    for (const relation of Object.values(registered.definition.relations)) {\n      if (typeof relation === 'string') {\n        deps.add(relation);\n      } else if (typeof relation === 'object' && 'schema' in relation) {\n        if (typeof relation.schema === 'string') {\n          deps.add(relation.schema);\n        }\n        if (\n          'schema' in relation &&\n          relation.schema !== undefined &&\n          relation.schema !== null &&\n          relation.schema !== ''\n        ) {\n          const schemas = typeof relation.schema === 'object' ? Object.values(relation.schema) : [];\n          schemas.forEach((s) => {\n            if (typeof s === 'string') deps.add(s);\n          });\n        }\n      }\n    }\n\n    return Array.from(deps);\n  }\n\n  /**\n   * Get reverse dependencies\n   */\n  function getReverseDependencies(name: string): string[] {\n    const deps: string[] = [];\n\n    for (const [schemaName, registered] of registeredSchemas) {\n      if (schemaName === name) continue;\n      if (!registered.definition.relations) continue;\n\n      for (const relation of Object.values(registered.definition.relations)) {\n        let matches = false;\n\n        if (typeof relation === 'string') {\n          matches = relation === name;\n        } else if (typeof relation === 'object' && 'schema' in relation) {\n          if (typeof relation.schema === 'string') {\n            matches = relation.schema === name;\n          }\n          if ('schemas' in relation && relation.schemas) {\n            matches = matches || Object.values(relation.schemas).includes(name);\n          }\n        }\n\n        if (matches) {\n          deps.push(schemaName);\n          break;\n        }\n      }\n    }\n\n    return deps;\n  }\n\n  /**\n   * Export schemas for serialization\n   */\n  function exportSchemas(): ExportedSchemas {\n    const schemas: Record<string, SchemaDefinition & { name: string }> = {};\n\n    for (const [name, registered] of registeredSchemas) {\n      // Convert relations to serializable format\n      const relations: Record<string, string | RelationDefinition> = {};\n\n      if (registered.definition.relations) {\n        for (const [key, relation] of Object.entries(registered.definition.relations)) {\n          if (typeof relation === 'string') {\n            relations[key] = relation;\n          } else if (relation instanceof EntitySchema) {\n            relations[key] = relation.name;\n          } else if (relation instanceof ArraySchema) {\n            const innerSchema = relation.schema;\n            if (innerSchema instanceof EntitySchema) {\n              relations[key] = { schema: innerSchema.name, type: 'array' };\n            }\n          } else if (typeof relation === 'object' && 'schema' in relation) {\n            relations[key] = relation as RelationDefinition;\n          }\n        }\n      }\n\n      schemas[name] = {\n        name,\n        ...registered.definition,\n        relations: Object.keys(relations).length > 0 ? relations : undefined,\n        // Omit non-serializable functions\n        processStrategy: undefined,\n        mergeStrategy: undefined,\n        migrate: undefined,\n      };\n    }\n\n    return {\n      version: '1.0.0',\n      schemas,\n      exportedAt: new Date().toISOString(),\n    };\n  }\n\n  /**\n   * Import schemas from serialization\n   */\n  function importSchemas(exported: ExportedSchemas): void {\n    clear();\n\n    for (const [name, schema] of Object.entries(exported.schemas)) {\n      register(name, {\n        idAttribute: schema.idAttribute,\n        relations: schema.relations,\n        excludeFields: schema.excludeFields,\n        version: schema.version,\n      });\n    }\n  }\n\n  /**\n   * Get schema version\n   */\n  function getVersion(name: string): number {\n    const version = registeredSchemas.get(name)?.version;\n    return version !== undefined && version !== 0 ? version : 0;\n  }\n\n  /**\n   * Migrate entity to latest schema version\n   */\n  function migrateEntity(name: string, entity: Entity, fromVersion: number): Entity {\n    const registered = registeredSchemas.get(name);\n    if (!registered) {\n      return entity;\n    }\n\n    const currentVersion = registered.version;\n    if (fromVersion >= currentVersion) {\n      return entity;\n    }\n\n    // Apply migrations\n    let migratedEntity = { ...entity };\n    const { migrate } = registered.definition;\n\n    if (migrate) {\n      for (let v = fromVersion; v < currentVersion; v++) {\n        migratedEntity = migrate(migratedEntity, v);\n      }\n    }\n\n    return migratedEntity;\n  }\n\n  return {\n    register,\n    get,\n    has,\n    getNames,\n    getAll,\n    unregister,\n    clear,\n    normalize,\n    denormalize,\n    validate,\n    getDependencies,\n    getReverseDependencies,\n    export: exportSchemas,\n    import: importSchemas,\n    getVersion,\n    migrateEntity,\n  };\n}\n\n// =============================================================================\n// SINGLETON REGISTRY\n// =============================================================================\n\n/**\n * Default global schema registry\n */\nlet globalRegistry: SchemaRegistry | null = null;\n\n/**\n * Get or create global schema registry\n */\nexport function getGlobalRegistry(): SchemaRegistry {\n  globalRegistry ??= createSchemaRegistry();\n  return globalRegistry;\n}\n\n/**\n * Reset global schema registry\n */\nexport function resetGlobalRegistry(): void {\n  globalRegistry?.clear();\n  globalRegistry = null;\n}\n\n// =============================================================================\n// CONVENIENCE FUNCTIONS\n// =============================================================================\n\n/**\n * Register a schema in global registry\n */\nexport function registerSchema(name: string, definition?: SchemaDefinition): EntitySchema {\n  return getGlobalRegistry().register(name, definition);\n}\n\n/**\n * Get schema from global registry\n */\nexport function getSchema(name: string): EntitySchema | undefined {\n  return getGlobalRegistry().get(name);\n}\n\n/**\n * Normalize using global registry\n */\nexport function normalizeWithRegistry<T = string | string[]>(\n  data: unknown,\n  schemaName: string\n): NormalizationResult<T> {\n  return getGlobalRegistry().normalize<T>(data, schemaName);\n}\n\n/**\n * Denormalize using global registry\n */\nexport function denormalizeWithRegistry<T = unknown>(\n  input: unknown,\n  schemaName: string,\n  entities: NormalizedEntities,\n  options?: DenormalizeOptions\n): T | null {\n  return getGlobalRegistry().denormalize<T>(input, schemaName, entities, options);\n}\n\n// =============================================================================\n// SCHEMA BUILDER\n// =============================================================================\n\n/**\n * Fluent schema builder\n */\nexport class SchemaBuilder {\n  private readonly name: string;\n  private readonly definition: SchemaDefinition;\n  private registry: SchemaRegistry;\n\n  constructor(name: string, registry?: SchemaRegistry) {\n    this.name = name;\n    this.definition = {};\n    this.registry = registry ?? getGlobalRegistry();\n  }\n\n  /**\n   * Set ID attribute\n   */\n  id(attribute: string | ((entity: Entity) => string)): this {\n    this.definition.idAttribute = attribute;\n    return this;\n  }\n\n  /**\n   * Add entity relation\n   */\n  belongsTo(field: string, schemaName: string): this {\n    this.definition.relations ??= {};\n    this.definition.relations[field] = schemaName;\n    return this;\n  }\n\n  /**\n   * Add array relation\n   */\n  hasMany(field: string, schemaName: string): this {\n    this.definition.relations ??= {};\n    this.definition.relations[field] = { schema: schemaName, type: 'array' };\n    return this;\n  }\n\n  /**\n   * Add union relation\n   */\n  union(\n    field: string,\n    schemas: Record<string, string>,\n    discriminator: string | ((entity: Entity) => string) = '__typename'\n  ): this {\n    this.definition.relations ??= {};\n    const schemaValues = Object.values(schemas);\n    const [firstSchema] = schemaValues;\n    if (firstSchema === undefined || firstSchema === '') {\n      throw new Error(`Union must have at least one schema for field ${field}`);\n    }\n    this.definition.relations[field] = {\n      schema: firstSchema,\n      type: 'union',\n      schemas,\n      schemaAttribute: discriminator,\n    };\n    return this;\n  }\n\n  /**\n   * Set process strategy\n   */\n  process(fn: (entity: Entity) => Entity): this {\n    this.definition.processStrategy = fn;\n    return this;\n  }\n\n  /**\n   * Set merge strategy\n   */\n  merge(fn: (existing: Entity, incoming: Entity) => Entity): this {\n    this.definition.mergeStrategy = fn;\n    return this;\n  }\n\n  /**\n   * Set excluded fields\n   */\n  exclude(...fields: string[]): this {\n    this.definition.excludeFields = fields;\n    return this;\n  }\n\n  /**\n   * Set version\n   */\n  version(v: number, migrate?: (entity: Entity, fromVersion: number) => Entity): this {\n    this.definition.version = v;\n    this.definition.migrate = migrate;\n    return this;\n  }\n\n  /**\n   * Build and register schema\n   */\n  build(): EntitySchema {\n    return this.registry.register(this.name, this.definition);\n  }\n}\n\n/**\n * Create a schema builder\n */\nexport function defineSchema(name: string, registry?: SchemaRegistry): SchemaBuilder {\n  return new SchemaBuilder(name, registry);\n}\n"],"names":["DEFAULT_CONFIG","createSchemaRegistry","config","options","registeredSchemas","resolvedSchemas","schemaCache","resolveRelation","relation","getOrCreateSchema","EntitySchema","ArraySchema","ObjectSchema","UnionSchema","ValueSchema","def","baseSchema","unionSchemas","key","schemaName","name","cachedSchema","registered","schema","buildSchema","definition","relations","value","resolveAllSchemas","newRelations","updatedSchema","register","now","existing","resolved","get","has","getNames","getAll","unregister","existed","clear","normalize","data","baseNormalize","denormalize","input","entities","denormOptions","entitySchema","baseDenormalize","validate","errors","warnings","usedSchemas","relationKey","targetName","targetDef","rel","reg","getDependencies","deps","s","getReverseDependencies","matches","exportSchemas","schemas","innerSchema","importSchemas","exported","getVersion","version","migrateEntity","entity","fromVersion","currentVersion","migratedEntity","migrate","v","globalRegistry","getGlobalRegistry","resetGlobalRegistry","registerSchema","getSchema","normalizeWithRegistry","denormalizeWithRegistry","SchemaBuilder","registry","attribute","field","discriminator","schemaValues","firstSchema","fn","fields","defineSchema"],"mappings":"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"}