UNPKG

flipper-plugin

Version:

Flipper Desktop plugin SDK and components

314 lines 10.1 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ type AppendEvent<T> = { type: 'append'; entry: Entry<T>; }; type UpdateEvent<T> = { type: 'update'; entry: Entry<T>; oldValue: T; oldVisible: { [viewId: string]: boolean; }; index: number; }; type RemoveEvent<T> = { type: 'remove'; entry: Entry<T>; index: number; }; type ShiftEvent<T> = { type: 'shift'; entries: Entry<T>[]; amount: number; }; type SINewIndexValueEvent<T> = { type: 'siNewIndexValue'; indexKey: string; value: T; firstOfKind: boolean; }; type ClearEvent = { type: 'clear'; }; type DataEvent<T> = AppendEvent<T> | UpdateEvent<T> | RemoveEvent<T> | ShiftEvent<T> | SINewIndexValueEvent<T> | ClearEvent; type Entry<T> = { value: T; id: number; visible: { [viewId: string]: boolean; }; approxIndex: { [viewId: string]: number; }; }; type Primitive = number | string | boolean | null | undefined; type OutputChange = { type: 'shift'; index: number; location: 'before' | 'in' | 'after'; delta: number; newCount: number; } | { type: 'update'; index: number; } | { type: 'reset'; newCount: number; } | { type: 'windowChange'; newStart: number; newEnd: number; }; export type DataSourceOptionKey<K extends PropertyKey> = { /** * If a key is set, the given field of the records is assumed to be unique, * and it's value can be used to perform lookups and upserts. */ key?: K; }; export type DataSourceOptions<T> = { /** * The maximum amount of records that this DataSource will store. * If the limit is exceeded, the oldest records will automatically be dropped to make place for the new ones */ limit?: number; /** * Secondary indices, that can be used to perform O(1) lookups on specific keys later on. * A combination of keys is allowed. * * For example: * indices: [["title"], ["id", "title"]] * * Enables: * dataSource.getAllRecordsByIndex({ * id: 123, * title: "Test" * }) */ indices?: IndexDefinition<T>[]; }; type IndexDefinition<T> = Array<keyof T>; type IndexQuery<T> = Partial<T>; export declare function createDataSource<T, Key extends keyof T>(initialSet: readonly T[], options: DataSourceOptions<T> & DataSourceOptionKey<Key>): DataSource<T, T[Key] extends string | number ? T[Key] : never>; export declare function createDataSource<T>(initialSet?: readonly T[], options?: DataSourceOptions<T>): DataSource<T, never>; export declare class DataSource<T extends any, KeyType = never> { private nextId; private _records; private _recordsById; private _secondaryIndices; private _recordsBySecondaryIndex; /** * @readonly */ keyAttribute: keyof T | undefined; private idToIndex; private shiftOffset; /** * The maximum amount of records this DataSource can have */ limit: number; /** * The default view on this data source. A view applies * sorting, filtering and windowing to get more constrained output. * * Additional views can created through the fork method. */ readonly view: DataSourceView<T, KeyType>; readonly additionalViews: { [viewId: string]: DataSourceView<T, KeyType>; }; private readonly outputEventEmitter; constructor(keyAttribute: keyof T | undefined, secondaryIndices?: IndexDefinition<T>[]); get size(): number; /** * Returns a defensive copy of the stored records. * This is a O(n) operation! Prefer using .size and .get instead if only a subset is needed. */ records(): readonly T[]; get(index: number): T; has(key: KeyType): boolean; getById(key: KeyType): T | undefined; keys(): IterableIterator<KeyType>; entries(): IterableIterator<[KeyType, T]>; [Symbol.iterator](): IterableIterator<T>; secondaryIndicesKeys(): string[]; /** * Returns the index of a specific key in the *records* set. * Returns -1 if the record wansn't found */ getIndexOfKey(key: KeyType): number; append(value: T): void; /** * Updates or adds a record. Returns `true` if the record already existed. * Can only be used if a key is used. */ upsert(value: T): boolean; /** * Replaces an item in the base data collection. * Note that the index is based on the insertion order, and not based on the current view */ update(index: number, value: T): void; /** * @param index * * Warning: this operation can be O(n) if a key is set */ delete(index: number): void; /** * Removes the item with the given key from this dataSource. * Returns false if no record with the given key was found * * Warning: this operation can be O(n) if a key is set */ deleteByKey(keyValue: KeyType): boolean; /** * Removes the first N entries. * @param amount */ shift(amount: number): void; /** * The clear operation removes any records stored, but will keep the current view preferences such as sorting and filtering */ clear(): void; /** * The rebuild function that would support rebuilding multiple views all at once */ rebuild(): void; /** * Returns a fork of this dataSource, that shares the source data with this dataSource, * but has it's own FSRW pipeline, to allow multiple views on the same data */ private fork; /** * Returns a new view of the `DataSource` if there doesn't exist a `DataSourceView` with the `viewId` passed in. * The view will allow different filters and sortings on the `DataSource` which can be helpful in cases * where multiple tables/views are needed. * @param viewId id for the `DataSourceView` * @returns `DataSourceView` that corresponds to the `viewId` */ getAdditionalView(viewId: string): DataSourceView<T, KeyType>; deleteView(viewId: string): void; addDataListener<E extends DataEvent<T>['type']>(event: E, cb: (data: Extract<DataEvent<T>, { type: E; }>) => void): () => void; private assertKeySet; private getKey; private storeIndexOfKey; private emitDataEvent; private storeSecondaryIndices; private removeSecondaryIndices; /** * Returns all items matching the specified index query. * * Note that the results are unordered, unless * records have not been updated using upsert / update, in that case * insertion order is maintained. * * Example: * `ds.getAllRecordsByIndex({title: 'subit a bug', done: false})` * * If no index has been specified for this exact keyset in the indexQuery (see options.indices), this method will throw * * @param indexQuery * @returns */ getAllRecordsByIndex(indexQuery: IndexQuery<T>): readonly T[]; /** * Like getAllRecords, but returns the first match only. * @param indexQuery * @returns */ getFirstRecordByIndex(indexQuery: IndexQuery<T>): T | undefined; getAllIndexValues(index: IndexDefinition<T>): string[] | undefined; private getSecondaryIndexValueFromRecord; /** * @private */ serialize(): readonly T[]; /** * @private */ deserialize(value: any[]): void; } export declare class DataSourceView<T, KeyType> { readonly datasource: DataSource<T, KeyType>; private sortBy; private reverse; private filter?; private filterExceptions?; /** * @readonly */ windowStart: number; /** * @readonly */ windowEnd: number; private viewId; private outputChangeListeners; /** * This is the base view data, that is filtered and sorted, but not reversed or windowed */ private _output; constructor(datasource: DataSource<T, KeyType>, viewId: string); get size(): number; get isSorted(): boolean; get isFiltered(): boolean; get isReversed(): boolean; /** * Returns a defensive copy of the current output. * Sort, filter, reverse and are applied. * Start and end behave like slice, and default to the currently active window. */ output(start?: number, end?: number): readonly T[]; getViewIndex(entry: T): number; setWindow(start: number, end: number): void; addListener(listener: (change: OutputChange) => void): () => void; setSortBy(sortBy: undefined | keyof T | ((a: T) => Primitive)): void; setFilter(filter: undefined | ((value: T) => boolean)): void; /** * Granular control over filters to add one-off exceptions to them. * They allow us to add singular items to table views. * Extremely useful for Bloks Debugger where we have to jump between multiple types of rows that could be filtered out */ setFilterExpections(ids: KeyType[] | undefined): void; toggleReversed(): void; setReversed(reverse: boolean): void; /** * The reset operation resets any view preferences such as sorting and filtering, but keeps the current set of records. */ reset(): void; private normalizeIndex; get(viewIndex: number): T; getEntry(viewIndex: number): Entry<T>; getViewIndexOfEntry(entry: Entry<T>): number; [Symbol.iterator](): IterableIterator<T>; private notifyAllListeners; private notifyItemUpdated; private notifyItemShift; private notifyReset; /** * @private */ processEvent(event: DataEvent<T>): void; private processRemoveEvent; /** * Rebuilds the entire view. Typically there should be no need to call this manually * @private */ rebuild(): void; private sortHelper; private getSortedIndex; private insertSorted; private applyFilterExceptions; } export {}; //# sourceMappingURL=DataSource.d.ts.map