import { Prisma } from '@prisma/client/extension';
import { StandardSchemaV1 } from '@standard-schema/spec';

declare type Narrowable = string | number | bigint | boolean | [];
declare type Exact<A, W> = (A extends unknown ? (W extends A ? {
    [K in keyof A]: Exact<A[K], W[K]>;
} : W) : never) | (A extends Narrowable ? A : never);
type CoerceAnyToNever<T> = unknown extends T ? never : T;
type CoerceNeverToValue<T, V> = [T] extends [never] ? V : T;
type ModelKeys<T> = {
    [K in keyof T]: K extends `$${string}` ? never : K;
}[keyof T];
type Rules<C, Ctx extends StandardSchemaV1, AllModelKeys extends ModelKeys<C> = ModelKeys<C>> = {
    [K in AllModelKeys]?: {
        read?: OpRuleShape<ReadOperation, C, K, Ctx>;
        create?: OpRuleShape<CreateOperation, C, K, Ctx>;
        delete?: OpRuleShape<DeleteOperation, C, K, Ctx>;
        update?: OpRuleShape<UpdateOperation, C, K, Ctx>;
        $allOperations?: OpRuleShape<Operation, C, K, Ctx>;
    } | boolean;
} & {
    $transaction?: boolean;
    $allModels?: {
        read?: AnyOpRuleShape<ReadOperation, Ctx>;
        create?: AnyOpRuleShape<CreateOperation, Ctx>;
        delete?: AnyOpRuleShape<DeleteOperation, Ctx>;
        update?: AnyOpRuleShape<UpdateOperation, Ctx>;
        $allOperations?: AnyOpRuleShape<Operation, Ctx>;
    } | boolean;
};
/** <Operation> */
type DeleteOperation = "delete" | "deleteMany";
type UpdateOperation = "update" | "updateMany" | "updateManyAndReturn" | "upsert";
type CreateOperation = "create" | "upsert" | "createMany" | "createManyAndReturn";
type ReadOperation = "aggregate" | "count" | "findFirst" | "findFirstOrThrow" | "findMany" | "findUnique" | "findUniqueOrThrow" | "groupBy";
type Operation = CreateOperation | DeleteOperation | UpdateOperation | ReadOperation;
/** <Operation:Model> */
type OpRuleShape<O extends Operation, C, K extends keyof C, Ctx extends StandardSchemaV1> = boolean | OpRuleShapeWhere<O, C, K> | OpRuleShapeCallback<O, C, K, Ctx> | OpRuleShapeVerbose<O, C, K, Ctx>;
type OpRuleShapeWhere<O extends Operation, C, K extends keyof C> = Prisma.Args<C[K], O> extends {
    where?: infer W;
} ? {
    $where: W;
    $rule?: never;
} : never;
type OpCtx<O extends Operation, C, K extends keyof C, Ctx extends StandardSchemaV1> = K extends unknown ? O extends unknown ? {
    model: K;
    operation: O;
    args: readonly [CoerceAnyToNever<Prisma.Args<C[K], O>>];
    context: StandardSchemaV1.InferOutput<Ctx> | undefined;
    uuid?: string;
} : never : never;
type OpRuleShapeCallback<O extends Operation, C, K extends keyof C, Ctx extends StandardSchemaV1> = {
    (ctx: OpCtx<O, C, K, Ctx>): MaybePromise<boolean | OpRuleShapeWhere<O, C, K>>;
};
type OpRuleShapeBefore<O extends Operation, C, K extends keyof C, Ctx extends StandardSchemaV1> = {
    (ctx: OpCtx<O, C, K, Ctx>): MaybePromise<void>;
};
type OpRuleShapeAfter<O extends Operation, C, K extends keyof C, Ctx extends StandardSchemaV1> = {
    (ctx: OpCtx<O, C, K, Ctx> & {
        result: unknown;
    }): MaybePromise<void>;
};
type OpRuleShapeVerbose<O extends Operation, C, K extends keyof C, Ctx extends StandardSchemaV1> = {
    $rule: boolean | OpRuleShapeWhere<O, C, K> | OpRuleShapeCallback<O, C, K, Ctx>;
    $after?: OpRuleShapeAfter<O, C, K, Ctx>;
    $before?: OpRuleShapeBefore<O, C, K, Ctx>;
    $blockedFields?: FieldsOf<O, C, K>[];
    $where?: never;
};
/** </Operation:Model> */
/** <Operation:Any> */
type AnyOpRuleShape<O extends Operation, Ctx extends StandardSchemaV1> = boolean | AnyOpRuleShapeCallback<O, Ctx> | AnyOpRuleShapeVerbose<O, Ctx>;
type AnyOpRuleShapeWhere = object;
type AnyOpCtx<O extends Operation, Ctx extends StandardSchemaV1> = {
    model: string;
    operation: O;
    args: object;
    context: StandardSchemaV1.InferOutput<Ctx>;
    uuid?: string;
};
type AnyOpRuleShapeCallback<O extends Operation, Ctx extends StandardSchemaV1> = {
    (ctx: AnyOpCtx<O, Ctx>): MaybePromise<boolean | AnyOpRuleShapeWhere>;
};
type AnyOpRuleShapeBefore<O extends Operation, Ctx extends StandardSchemaV1> = {
    (ctx: AnyOpCtx<O, Ctx>): MaybePromise<void>;
};
type AnyOpRuleShapeAfter<O extends Operation, Ctx extends StandardSchemaV1> = {
    (ctx: AnyOpCtx<O, Ctx> & {
        result: unknown;
    }): MaybePromise<void>;
};
type AnyOpRuleShapeVerbose<O extends Operation, Ctx extends StandardSchemaV1> = {
    $rule: boolean | AnyOpRuleShapeCallback<O, Ctx>;
    $after?: AnyOpRuleShapeAfter<O, Ctx>;
    $before?: AnyOpRuleShapeBefore<O, Ctx>;
    $blockedFields?: string[];
};
/** </Operation:Any> */
/** </Operation> */
type MaybePromise<T> = T | Promise<T>;
type FieldsOf<O extends Operation, C, K extends keyof C, P extends Record<string, unknown> = Prisma.Payload<C[K], O>> = CoerceNeverToValue<keyof P["scalars"] | keyof P["objects"] | keyof P["composites"], string>;
declare function defineRules<C extends object, R, CtxSchema extends StandardSchemaV1 = StandardSchemaV1>(args: {
    prisma: C;
    contextSchema?: CtxSchema;
    rules: Exact<R, Rules<C, CtxSchema>>;
}): C & {
    $rules: {
        setGlobalContext(ctx: StandardSchemaV1.InferInput<CtxSchema>): void;
        contextSchema: unknown;
        rules: Exact<R, Rules<C, CtxSchema, ModelKeys<C>>>;
    };
};

/**
 * Allow only accessing the models on the client object.
 */
type KeepObjectsOnly<T> = {
    [K in keyof T as K extends `$${string}` ? (K extends "$transaction" | "$rules" ? K : never) : K]: T[K];
};
type AuthorizedClient<T> = KeepObjectsOnly<T>;
declare const AuthorizedClient: new <T>(args: {
    url?: string;
    publicKey: string;
}) => AuthorizedClient<T>;

export { AuthorizedClient, defineRules };
