export declare type AnyArray<T = any> = T[] | readonly T[]

export declare type AnyEmptyArray = [] | readonly []

export declare type AnyOp = SetOp<unknown> | SetIfMissingOp<unknown> | UnsetOp

export declare function append<const Items extends AnyArray<unknown>>(
  items: Items | ArrayElement<Items>,
): InsertOp<NormalizeReadOnlyArray<Items>, 'after', -1>

export declare type ArrayElement<A> = A extends readonly (infer T)[] ? T : never

export declare type ArrayOp =
  | InsertOp<AnyArray, RelativePosition, Index | KeyedPathElement>
  | UpsertOp<AnyArray, RelativePosition, Index | KeyedPathElement>
  | ReplaceOp<AnyArray, Index | KeyedPathElement>
  | TruncateOp

export declare type Arrify<T> = (T extends (infer E)[] ? E : T)[]

export declare const assign: <
  const T extends {
    [x: string]: unknown
  },
>(
  value: T,
) => AssignOp<T>

declare type AssignMutation = [
  'patch',
  'assign',
  Id,
  CompactPath,
  [object],
  RevisionLock?,
]

export declare type AssignOp<T extends object = object> = {
  type: 'assign'
  value: T
}

export declare function at<const P extends Path, O extends Operation>(
  path: P,
  operation: O,
): NodePatch<NormalizeReadOnlyArray<P>, O>

export declare function at<const P extends string, O extends Operation>(
  path: P,
  operation: O,
): NodePatch<SafePath<P>, O>

export declare function autoKeys<Item>(generateKey: (item: Item) => string): {
  insert: <Pos extends RelativePosition, Ref extends number | KeyedPathElement>(
    position: Pos,
    referenceItem: Ref,
    items: Item[],
  ) => InsertOp<Item[], Pos, Ref>
  upsert: <
    Pos_1 extends RelativePosition,
    ReferenceItem extends number | KeyedPathElement,
  >(
    items: Item[],
    position: Pos_1,
    referenceItem: ReferenceItem,
  ) => UpsertOp<Item[], Pos_1, ReferenceItem>
  replace: <
    Pos_2 extends RelativePosition,
    ReferenceItem_1 extends number | KeyedPathElement,
  >(
    items: Item[],
    position: Pos_2,
    referenceItem: ReferenceItem_1,
  ) => ReplaceOp<Item[], ReferenceItem_1>
  insertBefore: <Ref_1 extends number | KeyedPathElement>(
    ref: Ref_1,
    items: Item[],
  ) => InsertOp<Item[], 'before', Ref_1>
  prepend: (items: Item[]) => InsertOp<Item[], 'before', 0>
  insertAfter: <Ref_2 extends number | KeyedPathElement>(
    ref: Ref_2,
    items: Item[],
  ) => InsertOp<Item[], 'after', Ref_2>
  append: (items: Item[]) => InsertOp<Item[], 'after', -1>
}

export declare type ByIndex<P extends number, T extends AnyArray> = T[P]

declare namespace CompactEncoder {
  export {
    decode,
    encode,
    Id,
    RevisionLock,
    CompactPath,
    ItemRef,
    DeleteMutation_2 as DeleteMutation,
    CreateMutation_2 as CreateMutation,
    CreateIfNotExistsMutation_2 as CreateIfNotExistsMutation,
    CreateOrReplaceMutation_2 as CreateOrReplaceMutation,
    UnsetMutation,
    InsertMutation,
    UpsertMutation,
    TruncateMutation,
    IncMutation,
    DecMutation,
    AssignMutation,
    UnassignMutation,
    ReplaceMutation,
    SetMutation,
    SetIfMissingMutation,
    DiffMatchPatchMutation,
    CompactPatchMutation,
    CompactMutation,
  }
}
export {CompactEncoder}

declare namespace CompactFormatter {
  export {format, ItemRef_2 as ItemRef}
}
export {CompactFormatter}

declare type CompactMutation<Doc> =
  | DeleteMutation_2
  | CreateMutation_2<Doc>
  | CreateIfNotExistsMutation_2<Doc>
  | CreateOrReplaceMutation_2<Doc>
  | CompactPatchMutation

declare type CompactPatchMutation =
  | UnsetMutation
  | InsertMutation
  | UpsertMutation
  | TruncateMutation
  | IncMutation
  | DecMutation
  | SetMutation
  | SetIfMissingMutation
  | DiffMatchPatchMutation
  | AssignMutation
  | UnassignMutation
  | ReplaceMutation

declare type CompactPath = string

export declare type Concat<
  R extends Result<any, any>,
  Arr extends any[],
> = R[1] extends any[] ? Ok<[...R[1], ...Arr]> : R

export declare type ConcatInner<
  R extends Result<any, any>,
  R2 extends Result<any, any>,
> = R2[1] extends any[] ? Concat<R, R2[1]> : R2

export declare function create<Doc extends Optional<SanityDocumentBase, '_id'>>(
  document: Doc,
): CreateMutation<Doc>

export declare function createIfNotExists<Doc extends SanityDocumentBase>(
  document: Doc,
): CreateIfNotExistsMutation<Doc>

export declare type CreateIfNotExistsMutation<Doc extends SanityDocumentBase> =
  {
    type: 'createIfNotExists'
    document: Doc
  }

declare type CreateIfNotExistsMutation_2<Doc> = ['createIfNotExists', Doc]

export declare type CreateMutation<
  Doc extends Optional<SanityDocumentBase, '_id'>,
> = {
  type: 'create'
  document: Doc
}

declare type CreateMutation_2<Doc> = ['create', Doc]

export declare function createOrReplace<Doc extends SanityDocumentBase>(
  document: Doc,
): CreateOrReplaceMutation<Doc>

export declare type CreateOrReplaceMutation<Doc extends SanityDocumentBase> = {
  type: 'createOrReplace'
  document: Doc
}

declare type CreateOrReplaceMutation_2<Doc> = ['createOrReplace', Doc]

export declare const dec: <const N extends number = 1>(amount?: N) => DecOp<N>

declare type DecMutation = [
  'patch',
  'dec',
  Id,
  CompactPath,
  [number],
  RevisionLock?,
]

declare function decode<Doc extends SanityDocumentBase>(
  mutations: CompactMutation<Doc>[],
): Mutation[]

declare function decode_2<Doc extends SanityDocumentBase>(
  encodedMutation: SanityMutation<Doc>,
): Mutation

declare function decodeAll<Doc extends SanityDocumentBase>(
  sanityMutations: SanityMutation<Doc>[],
): Mutation[]

export declare type DecOp<Amount extends number> = {
  type: 'dec'
  amount: Amount
}

export declare const del: typeof delete_

export declare function delete_(id: string): DeleteMutation

export declare type DeleteMutation = {
  type: 'delete'
  id: string
}

declare type DeleteMutation_2 = ['delete', Id]

export declare const destroy: typeof delete_

export declare const diffMatchPatch: (value: string) => DiffMatchPatchOp

declare type DiffMatchPatchMutation = [
  'patch',
  'diffMatchPatch',
  Id,
  CompactPath,
  [string],
  RevisionLock?,
]

export declare type DiffMatchPatchOp = {
  type: 'diffMatchPatch'
  value: string
}

export declare type Digit =
  | '0'
  | '1'
  | '2'
  | '3'
  | '4'
  | '5'
  | '6'
  | '7'
  | '8'
  | '9'

export declare type ElementType<T extends AnyArray> =
  T extends AnyArray<infer E> ? E : unknown

declare function encode<Doc extends SanityDocumentBase>(
  mutations: Mutation[],
): CompactMutation<Doc>[]

declare function encode_2(mutation: Mutation):
  | {
      patch:
        | {
            unset: string[]
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            insert: {
              [x: string]: string | readonly any[]
              items: AnyArray
              replace?: undefined
            }
            unset?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            diffMatchPatch: {
              [x: string]: string
            }
            unset?: undefined
            insert?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            inc: {
              [x: string]: number
            }
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            dec: {
              [x: string]: number
            }
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            unset: string[]
            insert: {
              [x: string]: string | readonly any[]
              items: AnyArray
              replace?: undefined
            }
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            set: {
              [k: string]: never
            }
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            insert: {
              replace: string
              items: AnyArray
            }
            unset?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
    }[]
  | {
      [x: string]: any
      delete?: undefined
    }
  | {
      delete: {
        id: string
      }
    }

declare function encodeAll(mutations: Mutation[]): any[]

declare function encodeMutation(mutation: Mutation):
  | {
      patch:
        | {
            unset: string[]
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            insert: {
              [x: string]: string | readonly any[]
              items: AnyArray
              replace?: undefined
            }
            unset?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            diffMatchPatch: {
              [x: string]: string
            }
            unset?: undefined
            insert?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            inc: {
              [x: string]: number
            }
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            dec: {
              [x: string]: number
            }
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            unset: string[]
            insert: {
              [x: string]: string | readonly any[]
              items: AnyArray
              replace?: undefined
            }
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            set: {
              [k: string]: never
            }
            unset?: undefined
            insert?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
        | {
            insert: {
              replace: string
              items: AnyArray
            }
            unset?: undefined
            diffMatchPatch?: undefined
            inc?: undefined
            dec?: undefined
            set?: undefined
            ifRevisionID?: string | undefined
            id: string
          }
    }[]
  | {
      [x: string]: any
      delete?: undefined
    }
  | {
      delete: {
        id: string
      }
    }

declare function encodeTransaction(transaction: Transaction): {
  transactionId: string | undefined
  mutations: any[]
}

export declare type Err<E> = Result<E, null>

export declare type FindBy<P, T extends AnyArray> = T extends AnyEmptyArray
  ? undefined
  : T[0] extends P
    ? T[0]
    : T extends [any, ...infer Tail] | readonly [any, ...infer Tail]
      ? FindBy<P, Tail>
      : ElementType<T>

export declare type FindInArray<
  P extends KeyedPathElement | number,
  T extends AnyArray,
> = P extends KeyedPathElement
  ? FindBy<P, T>
  : P extends number
    ? ByIndex<P, T>
    : never

declare function format<Doc extends SanityDocumentBase>(
  mutations: Mutation[],
): string

declare type Id = string

export declare const inc: <const N extends number = 1>(amount?: N) => IncOp<N>

declare type IncMutation = [
  'patch',
  'inc',
  Id,
  CompactPath,
  [number],
  RevisionLock?,
]

export declare type IncOp<Amount extends number> = {
  type: 'inc'
  amount: Amount
}

export declare type Index = number

declare type Insert = {
  before?: string
  after?: string
  replace?: string
  items: any[]
}

export declare function insert<
  const Items extends AnyArray<unknown>,
  const Pos extends RelativePosition,
  const ReferenceItem extends Index | KeyedPathElement,
>(
  items: Items | ArrayElement<Items>,
  position: Pos,
  indexOrReferenceItem: ReferenceItem,
): InsertOp<NormalizeReadOnlyArray<Items>, Pos, ReferenceItem>

export declare const insertAfter: <
  const Items extends AnyArray<unknown>,
  const ReferenceItem extends number | KeyedPathElement,
>(
  items: Items | ArrayElement<Items>,
  indexOrReferenceItem: ReferenceItem,
) => InsertOp<NormalizeReadOnlyArray<Items>, 'after', ReferenceItem>

export declare function insertBefore<
  const Items extends AnyArray<unknown>,
  const ReferenceItem extends Index | KeyedPathElement,
>(
  items: Items | ArrayElement<Items>,
  indexOrReferenceItem: ReferenceItem,
): InsertOp<NormalizeReadOnlyArray<Items>, 'before', ReferenceItem>

declare type InsertMutation = [
  'patch',
  'insert',
  Id,
  CompactPath,
  [RelativePosition, ItemRef, AnyArray],
  RevisionLock?,
]

export declare type InsertOp<
  Items extends AnyArray,
  Pos extends RelativePosition,
  ReferenceItem extends Index | KeyedPathElement,
> = {
  type: 'insert'
  referenceItem: ReferenceItem
  position: Pos
  items: Items
}

declare type ItemRef = string | number

declare type ItemRef_2 = string | number

export declare type KeyedPathElement = {
  _key: string
}

export declare type Merge<R extends Result<any, any>, E> = R[0] extends null
  ? Ok<R[1] & E>
  : R

export declare type MergeInner<
  R extends Result<any, any>,
  R2 extends Result<any, any>,
> = R2[0] extends null ? Merge<R, R2[1]> : R

export declare type Mutation<Doc extends SanityDocumentBase = any> =
  | CreateMutation<Doc>
  | CreateIfNotExistsMutation<Doc>
  | CreateOrReplaceMutation<Doc>
  | DeleteMutation
  | PatchMutation

export declare type NodePatch<
  P extends Path = Path,
  O extends Operation = Operation,
> = {
  path: P
  op: O
}

export declare type NodePatchList =
  | [NodePatch, ...NodePatch[]]
  | NodePatch[]
  | readonly NodePatch[]
  | readonly [NodePatch, ...NodePatch[]]

export declare type NormalizeReadOnlyArray<T> = T extends readonly [
  infer NP,
  ...infer Rest,
]
  ? [NP, ...Rest]
  : T extends readonly (infer NP)[]
    ? NP[]
    : T

export declare type NumberOp = IncOp<number> | DecOp<number>

export declare type ObjectOp = AssignOp | UnassignOp

export declare type Ok<V> = Result<null, V>

export declare type OnlyDigits<S> = S extends `${infer Head}${infer Tail}`
  ? Head extends Digit
    ? Tail extends ''
      ? true
      : OnlyDigits<Tail> extends true
        ? true
        : false
    : false
  : false

export declare type Operation = PrimitiveOp | ArrayOp | ObjectOp

export declare type Optional<T, K extends keyof T> = Omit<T, K> &
  Partial<Pick<T, K>>

export declare type ParseAllProps<Props extends string[]> = Props extends [
  `${infer Head}`,
  ...infer Tail,
]
  ? Tail extends string[]
    ? ConcatInner<ParseProperty<Trim<Head>>, ParseAllProps<Tail>>
    : ParseProperty<Trim<Head>>
  : Ok<[]>

export declare type ParseError<T extends string = 'unknown'> = T & {
  error: true
}

export declare type ParseExpressions<S extends string> =
  S extends `[${infer Expr}]${infer Remainder}`
    ? Trim<Remainder> extends ''
      ? ToArray<ParseInnerExpression<Trim<Expr>>>
      : ConcatInner<
          ToArray<ParseInnerExpression<Trim<Expr>>>,
          ParseExpressions<Remainder>
        >
    : Err<ParseError<`Cannot parse object from "${S}"`>>

export declare type ParseInnerExpression<S extends string> = S extends ''
  ? Err<ParseError<'Saw an empty expression'>>
  : Try<ParseNumber<S>, ParseObject<S>>

export declare type ParseKVPair<S extends string> =
  Split<S, '=='> extends [`${infer LHS}`, `${infer RHS}`]
    ? ParseValue<Trim<RHS>> extends infer Res
      ? Res extends [null, infer Value]
        ? Ok<{
            [P in Trim<LHS>]: Value
          }>
        : Err<
            ParseError<`Can't parse right hand side as a value in "${S}" (Invalid value ${RHS})`>
          >
      : never
    : Err<ParseError<`Can't parse key value pair from ${S}`>>

export declare type ParseNumber<S extends string> =
  S extends `${infer Head}${infer Tail}`
    ? Head extends '-'
      ? OnlyDigits<Tail> extends true
        ? Ok<ToNumber<S>>
        : Err<ParseError<`Invalid integer value "${S}"`>>
      : OnlyDigits<S> extends true
        ? Ok<ToNumber<S>>
        : Err<ParseError<`Invalid integer value "${S}"`>>
    : Err<ParseError<`Invalid integer value "${S}"`>>

export declare type ParseObject<S extends string> =
  S extends `${infer Pair},${infer Remainder}`
    ? Trim<Remainder> extends ''
      ? Ok<Record<never, never>>
      : MergeInner<ParseKVPair<Pair>, ParseObject<Remainder>>
    : ParseKVPair<S>

export declare type ParseProperty<S extends string> =
  Trim<S> extends ''
    ? Err<ParseError<'Empty property'>>
    : Split<Trim<S>, '[', true> extends [`${infer Prop}`, `${infer Expression}`]
      ? Trim<Prop> extends ''
        ? ParseExpressions<Trim<Expression>>
        : ConcatInner<Ok<[Trim<Prop>]>, ParseExpressions<Trim<Expression>>>
      : Ok<[Trim<S>]>

export declare type ParseValue<S extends string> = string extends S
  ? Err<ParseError<'ParseValue got generic string type'>>
  : S extends 'null'
    ? Ok<null>
    : S extends 'true'
      ? Ok<true>
      : S extends 'false'
        ? Ok<false>
        : S extends `"${infer Value}"`
          ? Ok<Value>
          : Try<
              ParseNumber<S>,
              Err<
                ParseError<`ParseValue failed. Can't parse "${S}" as a value.`>
              >
            >

export declare function patch<P extends NodePatchList | NodePatch>(
  id: string,
  patches: P,
  options?: PatchOptions,
): PatchMutation<NormalizeReadOnlyArray<Tuplify<P>>>

export declare type PatchMutation<
  Patches extends NodePatchList = NodePatchList,
> = {
  type: 'patch'
  id: string
  patches: Patches
  options?: PatchOptions
}

export declare type PatchOptions = {
  ifRevision?: string
}

export declare type Path = PathElement[] | readonly PathElement[]

export declare type PathElement = PropertyName | Index | KeyedPathElement

export declare function prepend<const Items extends AnyArray<unknown>>(
  items: Items | ArrayElement<Items>,
): InsertOp<NormalizeReadOnlyArray<Items>, 'before', 0>

export declare type PrimitiveOp = AnyOp | StringOp | NumberOp

export declare type PropertyName = string

export declare type RelativePosition = 'before' | 'after'

export declare function replace<
  Items extends any[],
  ReferenceItem extends Index | KeyedPathElement,
>(
  items: Items | ArrayElement<Items>,
  referenceItem: ReferenceItem,
): ReplaceOp<Items, ReferenceItem>

declare type ReplaceMutation = [
  'patch',
  'replace',
  Id,
  CompactPath,
  [ItemRef, AnyArray],
  RevisionLock?,
]

export declare type ReplaceOp<
  Items extends AnyArray,
  ReferenceItem extends Index | KeyedPathElement,
> = {
  type: 'replace'
  referenceItem: ReferenceItem
  items: Items
}

export declare type Result<E, V> = [E, V]

declare type RevisionLock = string

export declare type SafePath<S extends string> = StripError<StringToPath<S>>

declare type SanityCreateIfNotExistsMutation<Doc extends SanityDocumentBase> = {
  createIfNotExists: Doc
}

declare type SanityCreateMutation<Doc extends SanityDocumentBase> = {
  create: Doc
}

declare type SanityCreateOrReplaceMutation<Doc extends SanityDocumentBase> = {
  createOrReplace: Doc
}

declare type SanityDecPatch = {
  id: string
  dec: {
    [path: string]: number
  }
}

declare type SanityDeleteMutation = {
  delete: {
    id: string
  }
}

declare type SanityDiffMatchPatch = {
  id: string
  diffMatchPatch: {
    [path: string]: string
  }
}

export declare type SanityDocumentBase = {
  _id?: string
  _type: string
  _createdAt?: string
  _updatedAt?: string
  _rev?: string
}

declare namespace SanityEncoder {
  export {
    decodeAll,
    decode_2 as decode,
    Mutation,
    SanityDocumentBase,
    SanityDiffMatchPatch,
    SanitySetPatch,
    Insert,
    SanityInsertPatch,
    SanityUnsetPatch,
    SanityIncPatch,
    SanityDecPatch,
    SanitySetIfMissingPatch,
    SanityPatch,
    SanityCreateIfNotExistsMutation,
    SanityCreateOrReplaceMutation,
    SanityCreateMutation,
    SanityDeleteMutation,
    SanityPatchMutation,
    SanityMutation,
    encode_2 as encode,
    encodeAll,
    encodeTransaction,
    encodeMutation,
  }
}
export {SanityEncoder}

declare type SanityIncPatch = {
  id: string
  inc: {
    [path: string]: number
  }
}

declare type SanityInsertPatch = {
  id: string
  insert: Insert
}

declare type SanityMutation<
  Doc extends SanityDocumentBase = SanityDocumentBase,
> =
  | SanityCreateMutation<Doc>
  | SanityCreateIfNotExistsMutation<Doc>
  | SanityCreateOrReplaceMutation<Doc>
  | SanityDeleteMutation
  | SanityPatchMutation

declare type SanityPatch =
  | SanitySetPatch
  | SanityUnsetPatch
  | SanityInsertPatch
  | SanitySetIfMissingPatch
  | SanityDiffMatchPatch
  | SanityIncPatch
  | SanityDecPatch

declare type SanityPatchMutation = {
  patch:
    | SanitySetPatch
    | SanitySetIfMissingPatch
    | SanityDiffMatchPatch
    | SanityInsertPatch
    | SanityUnsetPatch
}

declare type SanitySetIfMissingPatch = {
  id: string
  setIfMissing: {
    [path: string]: any
  }
}

declare type SanitySetPatch = {
  id: string
  set: {
    [path: string]: any
  }
}

declare type SanityUnsetPatch = {
  id: string
  unset: string[]
}

export declare const set: <const T>(value: T) => SetOp<T>

export declare const setIfMissing: <const T>(value: T) => SetIfMissingOp<T>

declare type SetIfMissingMutation = [
  'patch',
  'setIfMissing',
  Id,
  CompactPath,
  [unknown],
  RevisionLock?,
]

export declare type SetIfMissingOp<T> = {
  type: 'setIfMissing'
  value: T
}

declare type SetMutation = ['patch', 'set', Id, CompactPath, any, RevisionLock?]

export declare type SetOp<T> = {
  type: 'set'
  value: T
}

export declare type Split<
  S extends string,
  Char extends string,
  IncludeSeparator extends boolean = false,
> = S extends `${infer First}${Char}${infer Remainder}`
  ? [First, `${IncludeSeparator extends true ? Char : ''}${Remainder}`]
  : [S]

export declare type SplitAll<
  S extends string,
  Char extends string,
> = S extends `${infer First}${Char}${infer Remainder}`
  ? [First, ...SplitAll<Remainder, Char>]
  : [S]

export declare type StringOp = DiffMatchPatchOp

export declare type StringToPath<S extends string> = Unwrap<
  ParseAllProps<SplitAll<Trim<S>, '.'>>
>

export declare type StripError<
  S extends StringToPath<string> | ParseError<string>,
> = S extends ParseError<string> ? never : S

export declare type ToArray<R extends Result<any, any>> = R extends [
  infer E,
  infer V,
]
  ? E extends null
    ? V extends any[]
      ? R
      : Ok<[R[1]]>
    : R
  : R

export declare type ToNumber<T extends string> =
  T extends `${infer N extends number}` ? N : never

export declare interface Transaction {
  id?: string
  mutations: Mutation[]
}

export declare type Trim<
  S extends string,
  Char extends string = ' ',
> = TrimRight<TrimLeft<S, Char>, Char>

export declare type TrimLeft<
  Str extends string,
  Char extends string = ' ',
> = string extends Str
  ? Str
  : Str extends `${Char}${infer Trimmed}`
    ? TrimLeft<Trimmed, Char>
    : Str

export declare type TrimRight<
  Str extends string,
  Char extends string = ' ',
> = string extends Str
  ? Str
  : Str extends `${infer Trimmed}${Char}`
    ? TrimRight<Trimmed, Char>
    : Str

export declare function truncate(
  startIndex: number,
  endIndex?: number,
): TruncateOp

declare type TruncateMutation = [
  'patch',
  'truncate',
  Id,
  CompactPath,
  [startIndex: number, endIndex: number | undefined],
  RevisionLock?,
]

export declare type TruncateOp = {
  type: 'truncate'
  startIndex: number
  endIndex?: number
}

export declare type Try<R extends Result<any, any>, Handled> = R[1] extends null
  ? Handled
  : R

export declare type Tuplify<T> = T extends readonly [infer NP, ...infer Rest]
  ? [NP, ...Rest]
  : T extends readonly (infer NP)[]
    ? NP[]
    : [T]

export declare const unassign: <const K extends readonly string[]>(
  keys: K,
) => UnassignOp<K>

declare type UnassignMutation = [
  'patch',
  'assign',
  Id,
  CompactPath,
  [string[]],
  RevisionLock?,
]

export declare type UnassignOp<
  K extends readonly string[] = readonly string[],
> = {
  type: 'unassign'
  keys: K
}

export declare const unset: () => UnsetOp

declare type UnsetMutation = [
  'patch',
  'unset',
  Id,
  CompactPath,
  [],
  RevisionLock?,
]

export declare type UnsetOp = {
  type: 'unset'
}

export declare type Unwrap<R extends Result<any, any>> = R extends [
  infer E,
  infer V,
]
  ? E extends null
    ? V
    : E
  : never

export declare function upsert<
  const Items extends AnyArray<unknown>,
  const Pos extends RelativePosition,
  const ReferenceItem extends Index | KeyedPathElement,
>(
  items: Items | ArrayElement<Items>,
  position: Pos,
  referenceItem: ReferenceItem,
): UpsertOp<Items, Pos, ReferenceItem>

declare type UpsertMutation = [
  'patch',
  'upsert',
  Id,
  CompactPath,
  [RelativePosition, ItemRef, AnyArray],
  RevisionLock?,
]

export declare type UpsertOp<
  Items extends AnyArray,
  Pos extends RelativePosition,
  ReferenceItem extends Index | KeyedPathElement,
> = {
  type: 'upsert'
  items: Items
  referenceItem: ReferenceItem
  position: Pos
}

export {}
