import { ULID } from 'ulid';
import { Patch } from 'immer';
import { PersistentModel, PersistentModelConstructor, PredicateObject, PredicatesGroup, RelationshipType, RelationType, ModelKeys, ModelAttributes, SchemaNamespace, SortPredicatesGroup, NonModelTypeConstructor, PaginationInput, DeferredCallbackResolverOptions, SchemaModel, ModelAttribute, IndexesType } from './types';
export declare const ID = "id";
/**
 * Used by the Async Storage Adapter to concatenate key values
 * for a record. For instance, if a model has the following keys:
 * `customId: ID! @primaryKey(sortKeyFields: ["createdAt"])`,
 * we concatenate the `customId` and `createdAt` as:
 * `12-234-5#2022-09-28T00:00:00.000Z`
 */
export declare const DEFAULT_PRIMARY_KEY_VALUE_SEPARATOR = "#";
/**
 * Used for generating spinal-cased index name from an array of
 * key field names.
 * E.g. for keys `[id, title]` => 'id-title'
 */
export declare const IDENTIFIER_KEY_SEPARATOR = "-";
export declare const errorMessages: {
    idEmptyString: string;
    queryByPkWithCompositeKeyPresent: string;
    deleteByPkWithCompositeKeyPresent: string;
    observeWithObjectLiteral: string;
};
export declare enum NAMESPACES {
    DATASTORE = "datastore",
    USER = "user",
    SYNC = "sync",
    STORAGE = "storage"
}
declare const DATASTORE = NAMESPACES.DATASTORE;
declare const USER = NAMESPACES.USER;
declare const SYNC = NAMESPACES.SYNC;
declare const STORAGE = NAMESPACES.STORAGE;
export { USER, SYNC, STORAGE, DATASTORE };
export declare const USER_AGENT_SUFFIX_DATASTORE = "/DataStore";
export declare const exhaustiveCheck: (obj: never, throwOnError?: boolean) => void;
export declare const isNullOrUndefined: (val: any) => boolean;
export declare const validatePredicate: <T extends Readonly<Record<string, any>>>(model: T, groupType: "and" | "or" | "not", predicatesOrGroups: (PredicateObject<T> | PredicatesGroup<T>)[]) => any;
export declare const validatePredicateField: <T>(value: T, operator: "eq" | "ne" | "gt" | "lt" | "ge" | "le" | "contains" | "notContains" | "beginsWith" | "between", operand: T | [T, T]) => boolean;
export declare const isModelConstructor: <T extends Readonly<Record<string, any>>>(obj: any) => obj is PersistentModelConstructor<T>;
export declare function registerNonModelClass(clazz: NonModelTypeConstructor<any>): void;
export declare const isNonModelConstructor: (obj: any) => obj is NonModelTypeConstructor<any>;
export declare const traverseModel: <T extends Readonly<Record<string, any>>>(srcModelName: string, instance: T, namespace: SchemaNamespace, modelInstanceCreator: <T_1 extends Readonly<Record<string, any>>>(modelConstructor: PersistentModelConstructor<T_1>, init: Partial<T_1>) => T_1, getModelConstructorByModelName: (namsespaceName: NAMESPACES, modelName: string) => PersistentModelConstructor<any>) => {
    modelName: string;
    item: T;
    instance: T;
}[];
export declare const isPrivateMode: () => Promise<unknown>;
/**
 * Whether the browser's implementation of IndexedDB breaks on array lookups
 * against composite indexes whose keypath contains a single column.
 *
 * E.g., Whether `store.createIndex(indexName, ['id'])` followed by
 * `store.index(indexName).get([1])` will *ever* return records.
 *
 * In all known, modern Safari browsers as of Q4 2022, the query against an index like
 * this will *always* return `undefined`. So, the index needs to be created as a scalar.
 */
export declare const isSafariCompatabilityMode: () => Promise<boolean>;
export declare function monotonicUlidFactory(seed?: number): ULID;
/**
 * Uses performance.now() if available, otherwise, uses Date.now() (e.g. react native without a polyfill)
 *
 * The values returned by performance.now() always increase at a constant rate,
 * independent of the system clock (which might be adjusted manually or skewed
 * by software like NTP).
 *
 * Otherwise, performance.timing.navigationStart + performance.now() will be
 * approximately equal to Date.now()
 *
 * See: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now#Example
 */
export declare function getNow(): number;
export declare function sortCompareFunction<T extends PersistentModel>(sortPredicates: SortPredicatesGroup<T>): (a: any, b: any) => number;
export declare function valuesEqual(valA: any, valB: any, nullish?: boolean): boolean;
/**
 * Statelessly extracts the specified page from an array.
 *
 * @param records - The source array to extract a page from.
 * @param pagination - A definition of the page to extract.
 * @returns This items from `records` matching the `pagination` definition.
 */
export declare function inMemoryPagination<T extends PersistentModel>(records: T[], pagination?: PaginationInput<T>): T[];
/**
 * An `aysnc` implementation of `Array.some()`. Returns as soon as a match is found.
 * @param items The items to check.
 * @param matches The async matcher function, expected to
 * return Promise<boolean>: `true` for a matching item, `false` otherwise.
 * @returns A `Promise<boolean>`, `true` if "some" items match; `false` otherwise.
 */
export declare function asyncSome(items: Record<string, any>[], matches: (item: Record<string, any>) => Promise<boolean>): Promise<boolean>;
/**
 * An `aysnc` implementation of `Array.every()`. Returns as soon as a non-match is found.
 * @param items The items to check.
 * @param matches The async matcher function, expected to
 * return Promise<boolean>: `true` for a matching item, `false` otherwise.
 * @returns A `Promise<boolean>`, `true` if every item matches; `false` otherwise.
 */
export declare function asyncEvery(items: Record<string, any>[], matches: (item: Record<string, any>) => Promise<boolean>): Promise<boolean>;
/**
 * An `async` implementation of `Array.filter()`. Returns after all items have been filtered.
 * TODO: Return AsyncIterable.
 * @param items The items to filter.
 * @param matches The `async` matcher function, expected to
 * return Promise<boolean>: `true` for a matching item, `false` otherwise.
 * @returns A `Promise<T>` of matching items.
 */
export declare function asyncFilter<T>(items: T[], matches: (item: T) => Promise<boolean>): Promise<T[]>;
export declare const isAWSDate: (val: string) => boolean;
export declare const isAWSTime: (val: string) => boolean;
export declare const isAWSDateTime: (val: string) => boolean;
export declare const isAWSTimestamp: (val: number) => boolean;
export declare const isAWSEmail: (val: string) => boolean;
export declare const isAWSJSON: (val: string) => boolean;
export declare const isAWSURL: (val: string) => boolean;
export declare const isAWSPhone: (val: string) => boolean;
export declare const isAWSIPAddress: (val: string) => boolean;
export declare class DeferredPromise {
    promise: Promise<string>;
    resolve: (value: string | PromiseLike<string>) => void;
    reject: () => void;
    constructor();
}
export declare class DeferredCallbackResolver {
    private limitPromise;
    private timerPromise;
    private maxInterval;
    private timer;
    private raceInFlight;
    private callback;
    private errorHandler;
    private defaultErrorHandler;
    constructor(options: DeferredCallbackResolverOptions);
    private startTimer;
    private racePromises;
    start(): void;
    clear(): void;
    resolve(): void;
}
/**
 * merge two sets of patches created by immer produce.
 * newPatches take precedent over oldPatches for patches modifying the same path.
 * In the case many consecutive pathces are merged the original model should
 * always be the root model.
 *
 * Example:
 * A -> B, patches1
 * B -> C, patches2
 *
 * mergePatches(A, patches1, patches2) to get patches for A -> C
 *
 * @param originalSource the original Model the patches should be applied to
 * @param oldPatches immer produce patch list
 * @param newPatches immer produce patch list (will take precedence)
 * @return merged patches
 */
export declare function mergePatches<T>(originalSource: T, oldPatches: Patch[], newPatches: Patch[]): Patch[];
export declare const getStorename: (namespace: string, modelName: string) => string;
export declare const processCompositeKeys: (attributes: ModelAttributes) => Set<string>[];
export declare const extractKeyIfExists: (modelDefinition: SchemaModel) => ModelAttribute;
export declare const extractPrimaryKeyFieldNames: (modelDefinition: SchemaModel) => string[];
export declare const extractPrimaryKeyValues: <T extends Readonly<Record<string, any>>>(model: T, keyFields: string[]) => string[];
export declare const extractPrimaryKeysAndValues: <T extends Readonly<Record<string, any>>>(model: T, keyFields: string[]) => any;
export declare const isIdManaged: (modelDefinition: SchemaModel) => boolean;
export declare const isIdOptionallyManaged: (modelDefinition: SchemaModel) => boolean;
export declare const establishRelationAndKeys: (namespace: SchemaNamespace) => [RelationshipType, ModelKeys];
export declare const getIndex: (rel: RelationType[], src: string) => string;
export declare const getIndexFromAssociation: (indexes: IndexesType, src: string | string[]) => string;
/**
 * Backwards-compatability for schema generated prior to custom primary key support:
the single field `targetName` has been replaced with an array of `targetNames`.
`targetName` and `targetNames` are exclusive (will never exist on the same schema)
 * @param src {RelationType | ModelAssociation | undefined}
 * @returns array of targetNames, or `undefined`
 */
export declare const extractTargetNamesFromSrc: (src: {
    connectionType: "HAS_MANY" | "HAS_ONE";
    associatedWith: string | string[];
    targetName?: string;
    targetNames?: string[];
} | {
    connectionType: "BELONGS_TO";
    targetName?: string;
    targetNames?: string[];
} | RelationType) => string[];
export declare const indexNameFromKeys: (keys: string[]) => string;
export declare const keysEqual: (keysA: any, keysB: any) => boolean;
export declare const getIndexKeys: (namespace: SchemaNamespace, modelName: string) => string[];
/**
 * Determine what the managed timestamp field names are for the given model definition
 * and return the mapping.
 *
 * All timestamp fields are included in the mapping, regardless of whether the final field
 * names are the defaults or customized in the `@model` directive.
 *
 * @see https://docs.amplify.aws/cli/graphql/data-modeling/#customize-creation-and-update-timestamps
 *
 * @param definition modelDefinition to inspect.
 * @returns An object mapping `createdAt` and `updatedAt` to their field names.
 */
export declare const getTimestampFields: (definition: SchemaModel) => {
    createdAt: string;
    updatedAt: string;
};
