import { Transaction, CollectionReference } from "@firebase/firestore-types"; import { GetAllFilters } from "./core/interfaces"; import { TypeConstructor, SchemaField, ListField, LookUpField, NumberField, SchemaFieldConstructor } from "./types/interfaces"; import { FirestoreWrapper } from "./firebase/interfaces"; export interface Record { id: string; updated_at: Date; created_at: Date; [key: string]: any; } export declare type QueryObject = { [key: string]: boolean | QueryObject; }; export declare type SnapshotUnsubscribe = () => void; export declare type SnapshotSubscribe = (onNext?: (r: T & Record) => void, error?: (r: Error) => void, completed?: () => void) => SnapshotUnsubscribe; export declare type CreateOptions = { skipValidations?: boolean; skipEvents?: boolean; }; export declare type DeleteOptions = { skipEvents?: boolean; }; export declare type UpdateOptions = { skipValidations?: boolean; skipEvents?: boolean; }; export declare type CreateEvent = (newRecord: T & Record, transaction?: Transaction) => void | Promise; export declare type DeleteEvent = (recordId: string, transaction?: Transaction) => void | Promise; export declare type UpdateEvent = (getOldRecord: () => Promise, fieldsUpdated: Partial, transaction?: Transaction) => void | Promise; interface SchemaEvents { onCreate?: CreateEvent; onDelete?: DeleteEvent; onUpdate?: UpdateEvent; } export interface SchemaEventList { onCreate?: CreateEvent[]; onDelete?: DeleteEvent[]; onUpdate?: UpdateEvent[]; } export interface SchemaFieldsDefinition { [name: string]: SchemaFieldConstructor | TypeConstructor; } export interface SchemaFieldsMap { [name: string]: SchemaField; } interface ISchema { /** * Name of the schema */ name: string; /** * Map of constructed fields */ fields: SchemaFieldsMap; /** * Firestore reference to the collection that this schema is using */ collectionRef: CollectionReference; /** * Creates a new document. * @param record An object representing the document to be created. The object can only have the keys that you defined on the schema. * * If you want the document to have an specific ID, you can add an `id` key inside the object, otherwise, dont use the `id` key to let firestore choose the value. * * @param options An object to skip some events that occur when you call this method. */ create(record: T & { id?: string; }, options?: CreateOptions): Promise; /** * Updates an existing document. * @param recordId Id of the document to be updated. * @param newValues An object containing partially (or all) the keys defined on the schema. * @param options An object to skip some events that occur when you call this method. */ update(recordId: string, newValues: Partial, options?: UpdateOptions): Promise; /** * Deletes a document. * @param recordId Id of the document to be deleted. * @param options An object to skip some events that occur when you call this method. */ delete(recordId: string, options?: DeleteOptions): Promise; /** * Retrieves data from firestore using as starting node a document from this collection. * * @param id Id of a document * @param query Object that will explain which fields will be retrieved and resolved * * The object should only contain keys that are on the schema definition. * Each key can have as value `false` / `true` / `QueryObject` * * - If the key has value of `false`, it means that field wont be resolved and the raw value will be returned. * - If the key has value of `true`, it means that field will be resolved and the result will be returned. * - If the key has a `QueryObject` (**the field should be of type LookUp**), the query will be executed and the resulting object will be returned. * * You can have as many `QueryObjects` nested as you want. * * Example: * ```javascript * UserSchema.query('SOME_DOCUMENT_ID', { * name: false, * comments: { * post: { * author: { * name: false, * picture: true * } * }, * content: true, * created_at: true * } * }) * ``` * * `comments` is of type List and `post` is of type LookUp */ query(id: string, query?: QueryObject, transaction?: Transaction): Promise; /** * Retrieves a document in the same state as it is stored on firestore. * * This means fields wont be resolved. * * *eg: LookUp fields wont be replaced by the referenced document and instead you will have the id* * @param id Id of a document */ getRaw(id: string, transaction?: Transaction): Promise; /** * Retrieves a document with all its fields resolved. * * *eg: LookUp fields will be replaced by the referenced document* * @param id Id of a document * @param fields List of field names that you want to retrieve. * * If you omit this argument, all the fields of the document will be resolved and returned. */ get(id: string, fields?: string[], transaction?: Transaction): Promise; /** * Retrieves multiple documents from this collection * @param filters Filter object to avoid retrieving the entire collection. You should probably always use this argument. */ getAll(filters?: GetAllFilters): Promise<(T & Record)[]>; /** * Subscribes to document updates. * @param id Id of a document * @param query Query to be executed on every event */ onRecordChange(id: string, query?: QueryObject): { subscribe: SnapshotSubscribe; }; } declare type SaveSchemaInstance = (schema: ISchema) => void; interface IStore { firebaseInstance: FirestoreWrapper; isDefined(name: string): boolean; define(name: string, specs: SchemaFieldsMap, events: SchemaEvents): SaveSchemaInstance; getSchema(name: string): ISchema; getSchemaFieldMap(schemaName: string): SchemaFieldsMap; getSchemaEvents(schemaName: string): SchemaEventList; setSchemaEvents(schemaName: string, events: SchemaEvents): void; } export interface CreateRelation { (): [SchemaFieldConstructor, SchemaFieldConstructor]; } export interface CreateCountRelation { (listFieldName: string): SchemaFieldConstructor; } export interface CreateSumRelation { (schemaName: string, parentKeyInsideSchema: keyof T, fieldNameToSumUp: keyof T): NumberField; } interface IDictionary { [key: string]: T; } export { ISchema, SchemaEvents, IStore, IDictionary as Dictionary };