UNPKG

@magnetarjs/types

Version:
223 lines (222 loc) 9.07 kB
import { DocInstance } from '../Doc.js'; import { StoreName } from './core.js'; import { EventNameFnMap } from './events.js'; import { ModifyPayloadFnMap } from './modifyPayload.js'; import { ModifyReadResponseFnMap } from './modifyReadResponse.js'; import { PartialDeep } from './utils/PartialDeep.js'; import { OPathsWithOptional } from './utils/Paths.js'; /** * these are all the actions that Magnetar streamlines, whichever plugin is used * these actions are executable from a `MagnetarModule` and handled by each plugin individually */ export type ActionName = 'fetch' | 'fetchCount' | 'fetchSum' | 'fetchAverage' | 'stream' | 'insert' | 'merge' | 'assign' | 'replace' | 'deleteProp' | 'delete'; /** * You can pass options to this action specifically; * This is what the dev can provide as second param when executing any action in addition to the payload. * @example * // first update the server and await that before updating the local cache store: * { executionOrder: ['remote', 'cache'] } * @example * // don't throw errors for this action, wherever it might fail * { onError: 'continue' } */ export type ActionConfig<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = { executionOrder?: StoreName[]; onError?: 'revert' | 'continue' | 'stop'; modifyPayloadOn?: ModifyPayloadFnMap<DocDataType>; modifyReadResponseOn?: ModifyReadResponseFnMap<DocDataType>; on?: EventNameFnMap; /** * An option for remote stores like Firestore to delay a sync to the server and batch any additional actions made during the `syncDebounceMs`. */ syncDebounceMs?: number; }; /** * Opens a continuous stream to a document or collection. * @returns the open stream promise. This will never resolve as long as the stream is open. * @param payload - Optional payload. For remote stores like Firestore, can include `onFirstData` callback to detect when initial snapshot arrives. It will be executed even on first Data OR on when it was determined there was no data on the server. * @example * // Basic stream * collection('pokedex').stream() * @example * // With onFirstData callback (Firestore plugins) * let isLoading = true * collection('pokedex').stream({ onFirstData: () => isLoading = false }) * @example * // Insert initial doc * collection('pokedex').stream({ onFirstData: ({ empty }) => { * if (empty) { * collection('pokedex').insert({ name: 'Bulbasaur' }) * } * }}) */ export type MagnetarStreamAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = (payload?: { onFirstData?: (params: { empty?: boolean; existingStream?: boolean; }) => void; } | undefined, /** * TODO * @deprecated — should deprecated this "general" action config and replace with one specific for this action */ actionConfig?: ActionConfig<DocDataType>) => Promise<void>; /** * Fetches document(s) and adds the data to your local cache store's state. * Fetch is optimistic by default — if it can find the doc's data in your local cache state, it will return that and prevent any remote fetches. * You can force a re-fetch by passing `{ force: true }` * @returns the document(s) data that was fetched. If you need to access other metadata that was retrieved during fetching, you can use `modifyReadResponse.added`. * @example * const bulbasaur = magnetar.collection('pokedex').doc('001') * bulbasaur.fetch() // does nothing if already fetched once * @example * const bulbasaur = magnetar.collection('pokedex').doc('001') * bulbasaur.fetch({ force: true }) // makes API call to remote store * @example * const pokedex = magnetar.collection('pokedex') * pokedex.fetch() // does nothing if already fetched once * @example * const pokedex = magnetar.collection('pokedex') * pokedex.fetch({ force: true }) // makes API call to remote store */ export type MagnetarFetchAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }, calledFrom extends 'collection' | 'doc' = 'collection' | 'doc'> = (payload?: { force?: boolean; } | { [key: string]: any; } | undefined, /** * TODO * @deprecated — should deprecated this "general" action config and replace with one specific for this action */ actionConfig?: ActionConfig<DocDataType>) => Promise<calledFrom extends 'collection' ? Map<string, DocDataType> : DocDataType | undefined>; /** * Fetches a collection's document count and caches this count to your local cache store's state. * @returns the document count that was fetched. * @example * magnetar.collection('pokedex').count // 0 * * const count = await magnetar.collection('pokedex').fetchCount() * count // 151 * magnetar.collection('pokedex').count // 151 */ export type MagnetarFetchCountAction = () => Promise<number>; /** * Fetches a collection's document sum for a the passed fieldPath and caches this sum to your local cache store's state. * @returns the document sum that was fetched. * @example * magnetar.collection('pokedex').sum // {} * * const sum = await magnetar.collection('pokedex').fetchSum('base.HP') * sum // 10_000 * magnetar.collection('pokedex').sum // { base: { HP: 10_000 } } */ export type MagnetarFetchSumAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = (fieldPath: OPathsWithOptional<DocDataType>) => Promise<number>; /** * Fetches a collection's document average for a the passed fieldPath and caches this average to your local cache store's state. * @returns the document average that was fetched. * @example * magnetar.collection('pokedex').average // 0 * * const average = await magnetar.collection('pokedex').fetchAverage('base.HP') * average // 88 * magnetar.collection('pokedex').average // { base: { HP: 88 } } */ export type MagnetarFetchAverageAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = (fieldPath: OPathsWithOptional<DocDataType>) => Promise<number>; /** * @returns The new `doc()` instance after inserting. You can access the inserted `id` by checking this returned instance. * @example * const newDoc = collection('myDocs').insert({ some: 'payload' }) * newDoc.id // the generated id * newDoc.data // { some: 'payload' } */ export type MagnetarInsertAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = (payload: DocDataType, /** * TODO * @deprecated — should deprecated this "general" action config and replace with one specific for this action */ actionConfig?: ActionConfig<DocDataType>) => Promise<DocInstance<DocDataType>>; /** * @returns the new document data after applying the changes to the cached document (including any modifications from modifyPayloadOn) */ export type MagnetarWriteAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = (payload: PartialDeep<DocDataType>, /** * TODO * @deprecated — should deprecated this "general" action config and replace with one specific for this action */ actionConfig?: ActionConfig<DocDataType>) => Promise<DocDataType>; /** * @returns the new document data after applying the changes to the cached document (including any modifications from modifyPayloadOn) */ export type MagnetarDeletePropAction<DocDataType extends { [key: string]: any; } = { [key: string]: any; }> = (payload: keyof DocDataType | string | (keyof DocDataType | string)[], /** * TODO * @deprecated — should deprecated this "general" action config and replace with one specific for this action */ actionConfig?: ActionConfig<DocDataType>) => Promise<Partial<DocDataType>>; /** * @param {*} [payload] When executing on a doc: no payload needed. When executing on a collection: you need to pass the document ID you want to delete. * @param {ActionConfig} [actionConfig] * @example collection('pokedex').delete('001') * @example doc('pokedex/001').delete() */ export type MagnetarDeleteAction = (payload?: any, /** * TODO * @deprecated — should deprecated this "general" action config and replace with one specific for this action */ actionConfig?: ActionConfig) => Promise<void>; /** * All fetch promises with the payload passed to `fetch(payload)` as key (JSON.stringify) and the "fetch promise" as value. In case `fetch()` had no payload, use `undefined` */ export type FetchPromises = { [key in 'fetch' | 'fetchCount' | 'fetchSum' | 'fetchAverage']: Map<string, Promise<any>>; }; /** * Meta data on the last fetch call for a collection(). * - easily fetch more data with: * ```js * dbMyCollection.startAfter(dbMyCollection.fetched.cursor).fetch()` * ``` * - easily know if you fetched everything when using `startAfter` fetches: * ```js * if (dbMyCollection.fetched.reachedEnd) alert('fetched everything already') * ``` */ export type FetchMetaDataCollection = { /** Wether or not the end was reached, in case there is no `limit` this is always true */ reachedEnd: boolean; /** The last fetched doc, in a format defined by the Plugin */ cursor: unknown; };