UNPKG

prostgles-client

Version:

Reactive client for Postgres

259 lines 11 kB
import type { FieldFilter, WALItem, AnyObject, ClientSyncHandles, SyncBatchParams, TableHandler, EqualityFilter, NormalizedRow } from "prostgles-types"; import { WAL } from "prostgles-types"; import type { DBHandlerClient } from "../prostgles"; export declare const debug: any; type OmittedSyncProps = "onDebug" | "name" | "filter" | "db" | "onError"; export type SyncOptions = Partial<Omit<SyncedTableOptions, OmittedSyncProps>> & { select?: FieldFilter; handlesOnData?: boolean; }; export type SyncOneOptions = Partial<Omit<SyncedTableOptions, OmittedSyncProps>> & { handlesOnData?: boolean; }; type SyncDebugEvent = { type: "sync"; tableName: string; command: keyof ClientSyncHandles | "notifySubscribers"; data: AnyObject; info?: string; }; type OnErrorHandler = (error: any) => void; /** * Creates a local synchronized table */ type OnChange<T extends Record<string, unknown>> = (data: SyncDataItem<NormalizedRow<T>>[], delta?: Partial<T>[]) => any; type SyncHandler<T> = { $unsync: () => void; $upsert: (newData: T[]) => void | Promise<void>; getItems: () => T[]; }; export type Sync<T extends AnyObject> = <TD extends T>(basicFilter: EqualityFilter<TD>, options: SyncOptions, onChange: OnChange<TD>, onError?: OnErrorHandler) => Promise<SyncHandler<TD>>; type OnchangeOne<T extends Record<string, unknown>> = (data: SyncDataItem<NormalizedRow<T>>, delta?: Partial<NormalizedRow<T>>) => void | Promise<void>; /** * Creates a local synchronized record */ export type SyncOne<T extends AnyObject = AnyObject> = <TD extends T>(basicFilter: Partial<TD>, options: SyncOneOptions, onChange: OnchangeOne<TD>, onError?: OnErrorHandler) => Promise<SingleSyncHandles<TD>>; export type SyncBatchRequest = { from_synced?: string | number; to_synced?: string | number; offset: number; limit: number; }; export type ItemUpdate = { idObj: AnyObject; delta: AnyObject; opts?: $UpdateOpts; }; export type ItemUpdated = ItemUpdate & { oldItem: any; newItem: any; status: "inserted" | "updated" | "deleted" | "unchanged"; from_server: boolean; }; export type CloneSync<T extends AnyObject, Full extends boolean> = (onChange: SingleChangeListener<T, Full>, onError?: (error: any) => void) => SingleSyncHandles<T, Full>; export type CloneMultiSync<T extends AnyObject> = (onChange: MultiChangeListener<T>, onError?: (error: any) => void) => MultiSyncHandles<T>; export type $UpdateOpts = { deepMerge: boolean; }; type DeepPartial<T> = T extends Array<any> ? T : T extends object ? { [P in keyof T]?: DeepPartial<T[P]>; } : T; /** * CRUD handles added if initialised with handlesOnData = true */ export type SingleSyncHandles<T extends AnyObject = AnyObject, Full extends boolean = false> = { $get: () => NormalizedRow<T> | undefined; $find: (idObj: Partial<NormalizedRow<T>>) => NormalizedRow<T> | undefined; $unsync: () => any; $delete: () => void; $update: <OPTS extends $UpdateOpts>(newData: OPTS extends { deepMerge: true; } ? DeepPartial<T> : Partial<T>, opts?: OPTS) => any; $cloneSync: CloneSync<T, Full>; $cloneMultiSync: CloneMultiSync<T>; }; export type SyncDataItem<T extends AnyObject = AnyObject, Full extends boolean = false> = NormalizedRow<T> & (Full extends true ? SingleSyncHandles<NormalizedRow<T>, Full> : Partial<SingleSyncHandles<NormalizedRow<T>, Full>>); export type MultiSyncHandles<T extends AnyObject> = { $unsync: () => void; $upsert: (newData: NormalizedRow<T>[]) => any; getItems: () => AnyObject[]; }; export type SubscriptionSingle<T extends AnyObject = AnyObject, Full extends boolean = false> = { _onChange: SingleChangeListener<T, Full>; notify: (data: T, delta?: DeepPartial<T>) => T; idObj: Partial<T>; handlesOnData?: boolean; handles?: SingleSyncHandles<T, Full>; }; export type SubscriptionMulti<T extends AnyObject = AnyObject> = { _onChange: MultiChangeListener<T>; notify: (data: T[], delta: DeepPartial<T>[]) => T[]; idObj?: Partial<T>; handlesOnData?: boolean; handles?: MultiSyncHandles<T>; }; declare const STORAGE_TYPES: { readonly map: "map"; readonly localStorage: "localStorage"; }; export type MultiChangeListener<T extends AnyObject = AnyObject> = (items: SyncDataItem<T>[], delta: DeepPartial<T>[]) => any; export type SingleChangeListener<T extends AnyObject = AnyObject, Full extends boolean = false> = (item: SyncDataItem<T, Full>, delta?: DeepPartial<T>) => any; type StorageType = keyof typeof STORAGE_TYPES; export type SyncedTableOptions = { /** * Table name */ name: string; /** * Basic filter */ filter?: EqualityFilter<AnyObject>; /** * Data change listener. * Called on first sync and every time the data changes */ onChange?: MultiChangeListener; onError?: OnErrorHandler; db: DBHandlerClient | Partial<DBHandlerClient>; /** * If true then the first onChange trigger is skipped */ skipFirstTrigger?: boolean; select?: "*" | AnyObject; /** * Default is "object". * "localStorage" will persist the data */ storageType?: StorageType; /** * If true then only the delta of the text field is sent to server. * Full text is sent if an error occurs */ patchText?: boolean; patchJSON?: boolean; onReady: () => void; onDebug?: (event: SyncDebugEvent, tbl: SyncedTable) => Promise<void>; }; export type DbTableSync = { unsync: () => void; syncData: (data?: AnyObject[], deleted?: AnyObject[], cb?: (err?: any) => void) => void; }; export declare class SyncedTable { db: DBHandlerClient | Partial<DBHandlerClient>; name: string; select?: "*" | AnyObject; filter?: AnyObject; onChange?: MultiChangeListener; id_fields: string[]; synced_field: string; throttle: number; batch_size: number; skipFirstTrigger: boolean; columns: { name: string; data_type: string; }[]; wal?: WAL; notifyWal?: WAL; _multiSubscriptions: SubscriptionMulti[]; _singleSubscriptions: SubscriptionSingle[]; /** * add debug mode to fix sudden no data and sync listeners bug */ set multiSubscriptions(mSubs: SubscriptionMulti[]); get multiSubscriptions(): SubscriptionMulti[]; set singleSubscriptions(sSubs: SubscriptionSingle[]); get singleSubscriptions(): SubscriptionSingle[]; dbSync?: DbTableSync; storageType?: StorageType; itemsMap: Map<string, AnyObject>; patchText: boolean; patchJSON: boolean; isSynced: boolean; onError: SyncedTableOptions["onError"]; onDebug?: (evt: Omit<SyncDebugEvent, "type" | "tableName" | "channelName">) => Promise<void>; constructor({ name, filter, onChange, onReady, onDebug, db, skipFirstTrigger, select, storageType, patchText, patchJSON, onError, }: SyncedTableOptions); /** * Will update text/json fields through patching method * This will send less data to server * @param walData */ updatePatches: (walData: WALItem[]) => Promise<any[]>; static create(opts: Omit<SyncedTableOptions, "onReady">): Promise<SyncedTable>; /** * Returns a sync handler to all records within the SyncedTable instance * @param onChange change listener <(items: object[], delta: object[]) => any > * @param handlesOnData If true then $upsert and $unsync handles will be added on each data item. True by default; */ sync<T extends AnyObject = AnyObject>(onChange: MultiChangeListener<T>, handlesOnData?: boolean): MultiSyncHandles<T>; makeSingleSyncHandles<T extends AnyObject = AnyObject, Full extends boolean = false>(idObj: Partial<T>, onChange: SingleChangeListener<T, Full> | MultiChangeListener<T>): SingleSyncHandles<T, Full>; /** * Returns a sync handler to a specific record within the SyncedTable instance * @param idObj object containing the target id_fields properties * @param onChange change listener <(item: object, delta: object) => any > * @param handlesOnData If true then $update, $delete and $unsync handles will be added on the data item. True by default; */ syncOne<T extends AnyObject = AnyObject, Full extends boolean = false>(idObj: Partial<T>, onChange: SingleChangeListener<T, Full>, handlesOnData?: boolean): SingleSyncHandles<T, Full>; /** * Notifies multi subs with ALL data + deltas. Attaches handles on data if required * @param newData -> updates. Must include id_fields + updates */ _notifySubscribers: (changes?: Pick<ItemUpdated, "idObj" | "newItem" | "delta">[]) => void; unsubscribe: (onChange: SingleChangeListener | MultiChangeListener) => string; getIdStr(d: AnyObject): string; getIdObj(d: AnyObject): AnyObject; getRowSyncObj(d: AnyObject): AnyObject; unsync: () => void; destroy: () => void; matchesFilter(item: AnyObject | undefined): boolean; matchesIdObj(a: AnyObject | undefined, b: AnyObject | undefined): boolean; /** * Returns properties that are present in {n} and are different to {o} * @param o current full data item * @param n new data item */ getDelta(o: AnyObject, n: AnyObject): AnyObject; deleteAll(): void; get tableHandler(): Pick<TableHandler, "update" | "updateBatch" | "delete"> | undefined; delete: (item: AnyObject, from_server?: boolean) => Promise<boolean>; /** * Ensures that all object keys match valid column names */ checkItemCols: (item: AnyObject) => void; /** * Upserts data locally -> notify subs -> sends to server if required * synced_field is populated if data is not from server * @param items <{ idObj: object, delta: object }[]> Data items that changed * @param from_server : <boolean> If false then updates will be sent to server */ upsert: (items: ItemUpdate[], from_server?: boolean) => Promise<any>; getItem<T = AnyObject>(idObj: Partial<T>): T | undefined; /** * * @param item data to be inserted/updated/deleted. Must include id_fields * @param index (optional) index within array * @param isFullData * @param deleteItem */ setItem(_item: AnyObject, isFullData?: boolean, deleteItem?: boolean): void; /** * Sets the current data */ setItems: (_items: AnyObject[]) => void; /** * Returns the current data ordered by synced_field ASC and matching the main filter; */ getItems: <T extends AnyObject = AnyObject>() => T[]; /** * Sync data request */ getBatch: ({ from_synced, to_synced, offset, limit }?: SyncBatchParams) => { [x: string]: any; }[]; } export declare const mergeDeep: (_target: Record<string, unknown> | undefined, _source: Record<string, unknown> | undefined) => { [x: string]: unknown; }; export declare const quickClone: <T>(obj: T) => T; export {}; //# sourceMappingURL=SyncedTable.d.ts.map