import type { Field } from './Field';
import type { FiltersMap, OptionalFiltersMap } from '../model';
import type { OffsetQuery, OffsetQueryResult, CursorQuery, CursorQueryResult, FetchTotalFn } from '../hooks/paginationModeConfig';
/** Field-management permissions. Absent when the schema's fields cannot be edited. */
export interface SchemaPermissions {
    createField: boolean;
    updateField: boolean;
    deleteField: boolean;
}
/** Item-level CRUD permissions. */
export interface ItemPermissions {
    createItem: boolean;
    updateItem: boolean;
    deleteItem: boolean;
}
/**
 * A source-neutral description of a collection — data only, no behavior.
 * Item access is in `CollectionBackend`, field mutations in `FieldActions`.
 */
export interface Schema {
    id: string;
    fields: Record<string, Field | undefined>;
    /** The field that best represents the entity (titles/selections). */
    displayField: string;
    /** The identifier field. */
    idField: string;
    /** Absent when the schema's fields cannot be edited. */
    schemaPermissions?: SchemaPermissions;
    itemPermissions?: ItemPermissions;
}
export interface BackupConfig {
    create: () => Promise<{
        backupId: string;
    }>;
    waitForCompletion: (backupId: string, options?: {
        signal?: AbortSignal;
    }) => Promise<void>;
    cancel?: (backupId: string) => Promise<void>;
    restore?: (backupId: string) => Promise<{
        restorationId: string;
    }>;
    waitForRestoration?: (restorationId: string, options?: {
        signal?: AbortSignal;
    }) => Promise<void>;
}
export interface BulkInsertError {
    rowIndex: number;
    message?: string;
    code?: string;
}
export interface BulkInsertResult {
    succeeded?: number;
    failed?: number;
    errors?: BulkInsertError[];
}
/** Item data access shared by both pagination modes. */
export interface CollectionBackendBase<T = Record<string, unknown>> {
    get: (entityId: string) => Promise<T>;
    create: (entity: Partial<T>) => Promise<T>;
    update: (entity: T) => Promise<T>;
    delete: (entityId: string) => Promise<void>;
    bulkDelete: (entityIds: string[]) => Promise<void>;
    move?: (id: string, params: {
        moveAfterId: string | null | undefined;
    }) => Promise<void>;
    backup?: BackupConfig;
    bulkInsert?: (entities: Partial<T>[]) => Promise<BulkInsertResult>;
}
/** Per-call search scope the query layer passes to a backend's `find`. */
export interface FindOptions {
    searchableFieldIds?: string[];
}
/**
 * The query-layer fetch-data fns plus the optional `find` options the runtime
 * already accepts. Kept separate so the shared `OffsetFetchDataFn`/
 * `CursorFetchDataFn` used by `fetchData` stay unchanged.
 */
type OffsetFindFn<T, F extends FiltersMap> = (query: OffsetQuery<F>, options?: FindOptions) => Promise<OffsetQueryResult<T>>;
type CursorFindFn<T, F extends FiltersMap> = (query: CursorQuery<F>, options?: FindOptions) => Promise<CursorQueryResult<T>>;
/**
 * A source's item data access. The source declares its `paginationMode`
 * (offset by default) together with the matching `find`, same as core's
 * `PaginationModeConfig`.
 */
export type CollectionBackend<T = Record<string, unknown>, F extends FiltersMap = OptionalFiltersMap> = CollectionBackendBase<T> & ({
    paginationMode?: 'offset';
    find: OffsetFindFn<T, F>;
} | {
    paginationMode: 'cursor';
    find: CursorFindFn<T, F>;
    fetchTotal?: FetchTotalFn;
});
/** Field-management actions. All optional — a read-only source provides none. */
export interface FieldActions {
    /**
     * Field-mutating actions return the collection's updated fields map so the
     * caller can merge its local state from the response, without reloading the
     * schema. (`renameField` is the exception — nothing consumes its result yet.)
     */
    addField?: (field: Field) => Promise<Schema['fields']>;
    /**
     * Adds several fields in a single mutation, each under its `field.id` key
     * (callers decide the keys up front — e.g. CSV import uploads values under
     * them), unlike `addField`, which derives a fresh key from the display name.
     */
    addFields?: (fields: Field[]) => Promise<Schema['fields']>;
    editField?: (fieldId: string, updates: Partial<Field>) => Promise<Schema['fields']>;
    deleteField?: (fieldId: string) => Promise<Schema['fields']>;
    renameField?: (fieldId: string, newName: string) => Promise<void>;
    makePrimary?: (fieldId: string) => Promise<Schema['fields']>;
    duplicateField?: (fieldId: string) => Promise<Schema['fields']>;
    duplicateFieldWithContent?: (fieldId: string) => Promise<Schema['fields']>;
}
/** Everything a source provides for a collection. */
export interface LoadedSchema<T = Record<string, unknown>> {
    schema: Schema;
    backend: CollectionBackend<T>;
    fieldActions?: FieldActions;
}
/**
 * Loads a collection's `LoadedSchema`. Sources that need dependencies expose a
 * factory that returns this type.
 */
export type SchemaLoader<T extends Record<string, unknown> = Record<string, unknown>> = (collectionId: string) => Promise<LoadedSchema<T>>;
export {};
//# sourceMappingURL=Schema.d.ts.map