/* eslint-disable @typescript-eslint/no-explicit-any */ import type { Effect, Option, PubSub, S } from "effect-app" import type { InvalidStateError, NotFoundError, OptimisticConcurrencyException } from "effect-app/client/errors" import type { NonNegativeInt } from "effect-app/Schema/numbers" import type { FieldValues, IsNever, ResolveFirstLevel } from "../filter/types.js" import type { QAll, Query, QueryProjection, RawQuery } from "../query.js" import type { Mapped } from "./legacy.js" import type { ValidationResult } from "./validation.js" export interface Repository< T, Encoded extends FieldValues, Evt, ItemType extends string, IdKey extends keyof T, RSchema, RPublish, RProvided = never > { readonly itemType: ItemType readonly idKey: IdKey readonly find: (id: T[IdKey]) => Effect.Effect, never, RSchema> readonly all: Effect.Effect readonly saveAndPublish: ( items: Iterable, events?: Iterable ) => Effect.Effect readonly changeFeed: PubSub.PubSub<[T[], "save" | "remove"]> readonly removeAndPublish: ( items: Iterable, events?: Iterable ) => Effect.Effect readonly removeById: ( idOrIds: T[IdKey] | ReadonlyArray ) => Effect.Effect readonly queryRaw: ( schema: S.Codec, raw: RawQuery ) => Effect.Effect /** * Explicitly seed a namespace. Primary is seeded eagerly on initialization. * Non-primary namespaces must be seeded explicitly before use. */ readonly seedNamespace: (namespace: string) => Effect.Effect readonly query: { // ending with projection < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", E extends boolean = false >( q: ( initial: Query ) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: ( _: $A ) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: ( _: $B ) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: ( _: $C ) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, $D = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: ( _: $D ) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, $D = never, $E = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, $G = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => $G, q8: (_: $G) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, $G = never, $H = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => $G, q8: (_: $G) => $H, q9: (_: $H) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > < A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many", $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, $G = never, $H = never, $I = never, E extends boolean = false >( q1: ( initial: Query ) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => $G, q8: (_: $G) => $H, q9: (_: $H) => $I, q10: (_: $I) => QueryProjection ): Effect.Effect< TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A, | (TType extends "many" ? never : NotFoundError) | (TType extends "count" ? never : S.SchemaError), Exclude | RSchema > // ending with generic query < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, E extends boolean = false >( q: (initial: Query) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: ( _: $A ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: ( _: $A ) => $B, q3: ( _: $B ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: ( _: $C ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, $D = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: ( _: $D ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, $D = never, $E = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: ( _: $E ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: ( _: $F ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, $G = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => $G, q8: ( _: $G ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, $G = never, $H = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => $G, q8: (_: $G) => $H, q9: ( _: $H ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > < R = never, TType extends "one" | "many" = "many", EncodedRefined extends Encoded = Encoded, $A = never, $B = never, $C = never, $D = never, $E = never, $F = never, $G = never, $H = never, $I = never, E extends boolean = false >( q1: (initial: Query) => $A, q2: (_: $A) => $B, q3: (_: $B) => $C, q4: (_: $C) => $D, q5: (_: $D) => $E, q6: (_: $E) => $F, q7: (_: $F) => $G, q8: (_: $G) => $H, q9: (_: $H) => $I, q10: ( _: $I ) => QAll, R, TType, E> ): Effect.Effect< TType extends "many" ? DistributeQueryIfExclusiveOnArray : RefineTHelper, TType extends "many" ? never : NotFoundError, Exclude | RSchema > } /** @deprecated use query */ readonly mapped: Mapped /** * Validates a random sample of repository items by applying jitM and schema decode. * Useful for testing that migrations and schema changes work correctly on existing data. */ readonly validateSample: (options?: { /** percentage of items to sample (0.0-1.0), default 0.1 (10%) */ percentage?: number /** optional maximum number of items to sample */ maxItems?: number }) => Effect.Effect } type DistributeQueryIfExclusiveOnArray = [Exclusive] extends [true] ? T extends any ? RefineTHelper extends infer R ? IsNever extends true ? never : readonly R[] : never : never : readonly RefineTHelper[] type NullableRefined = { // EncodedRefined may be a union, so if you just keyof you'll get just common keys // p.s. NullableRefined is homomorphic in T so it distributes itself over T [k in keyof T]: [null] extends [T[k]] ? [null] extends [Extract[k]] ? T[k] : Exclude : T[k] } // for DX purposes type ShouldRecursiveExtractTagged = true extends { [k in keyof T]: "_tag" extends keyof T[k] ? k extends keyof EncodedRefined ? "_tag" extends keyof EncodedRefined[k] ? true : false : false : false }[keyof T] ? true : false // support is not 100% but we have to make compromises type RecursiveExtractTagged = ShouldRecursiveExtractTagged extends true ? { [k in keyof T]: "_tag" extends keyof T[k] ? k extends keyof EncodedRefined ? "_tag" extends keyof EncodedRefined[k] ? ExtractTagged : T[k] : T[k] : T[k] } : T type ExtractTagged_ = EncodedRefined extends { _tag: string } ? T extends { _tag: string } ? Extract : T : T type ExtractTagged = ExtractTagged_ extends infer R ? RecursiveExtractTagged, EncodedRefined> : never type ShouldRecursiveExtractIded = true extends { [k in keyof T]: "id" extends keyof T[k] ? k extends keyof EncodedRefined ? "id" extends keyof EncodedRefined[k] ? true : false : false : false }[keyof T] ? true : false type RecusiveExtractIded = ShouldRecursiveExtractIded extends true ? { [k in keyof T]: "id" extends keyof T[k] ? k extends keyof EncodedRefined ? "id" extends keyof EncodedRefined[k] ? ExtractIded : T[k] : T[k] : T[k] } : T type ExtractIded_ = EncodedRefined extends { id: string } ? T extends { id: string } ? Extract : T : T type ExtractIded = ExtractIded_ extends infer R ? RecusiveExtractIded, EncodedRefined> : never export type RefineTHelper = ResolveFirstLevel< NullableRefined< ExtractIded, EncodedRefined>, EncodedRefined > >