import { Atom } from 'tlstate'; import { Computed } from 'tlstate'; /** * Get the type of all records in a record store. * @public */ export declare type AllRecords> = ExtractR>; /** * Assert whether an id correspond to a record type. * * @example * assertIdType(myId, ID) * * @param id The id to check. * @param type The type of the record. * * @public */ export declare function assertIdType(id: string | undefined, type: RecordType): asserts id is ID; declare interface BaseMigrationsInfo { firstVersion: number; currentVersion: number; migrators: { [version: number]: Migration; }; } /** * The base record that all records must extend. * @public */ export declare interface BaseRecord { readonly id: ID; readonly typeName: TypeName; } /** * A diff describing the changes to a collection. * @public */ export declare type CollectionDiff = { added?: Set; removed?: Set; }; /** @public */ export declare function compareRecordVersions(a: RecordVersion, b: RecordVersion): 0 | 1 | -1; /** @public */ export declare const compareSchemas: (a: SerializedSchema, b: SerializedSchema) => number; /** * A record store is a collection of records of different types. * @public */ export declare type ComputedCache = { get(id: ID): Data | undefined; }; /** * Create a record type. * * @example * const Book = createRecordType('book') * * @param typeName The name of the type to create. * * @public */ export declare function createRecordType(typeName: R['typeName'], config?: Omit[1]>, 'defaultProperties' | 'onLoad'>): RecordType>; declare type Decrement = n extends 0 ? never : n extends 1 ? 0 : n extends 2 ? 1 : n extends 3 ? 2 : n extends 4 ? 3 : n extends 5 ? 4 : n extends 6 ? 5 : n extends 7 ? 6 : n extends 8 ? 7 : n extends 9 ? 8 : n extends 10 ? 9 : n extends 11 ? 10 : n extends 12 ? 11 : n extends 13 ? 12 : n extends 14 ? 13 : n extends 15 ? 14 : n extends 16 ? 15 : n extends 17 ? 16 : n extends 18 ? 17 : n extends 19 ? 18 : n extends 20 ? 19 : n extends 21 ? 20 : n extends 22 ? 21 : n extends 23 ? 22 : n extends 24 ? 23 : n extends 25 ? 24 : n extends 26 ? 25 : n extends 27 ? 26 : n extends 28 ? 27 : n extends 29 ? 28 : n extends 30 ? 29 : n extends 31 ? 30 : n extends 32 ? 31 : n extends 33 ? 32 : n extends 34 ? 33 : n extends 35 ? 34 : n extends 36 ? 35 : n extends 37 ? 36 : n extends 38 ? 37 : n extends 39 ? 38 : n extends 40 ? 39 : n extends 41 ? 40 : n extends 42 ? 41 : n extends 43 ? 42 : n extends 44 ? 43 : n extends 45 ? 44 : n extends 46 ? 45 : n extends 47 ? 46 : n extends 48 ? 47 : n extends 49 ? 48 : n extends 50 ? 49 : n extends 51 ? 50 : never; /** @public */ export declare function defineMigrations({ firstVersion, currentVersion, migrators, subTypeKey, subTypeMigrations, }: { firstVersion: FirstVersion; currentVersion: CurrentVersion; migrators: { [version in Exclude, FirstVersion>]: Migration; }; subTypeKey?: string; subTypeMigrations?: Record; }): Migrations; /** * Freeze an object when in development mode. * Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze * * @example * const frozen = devFreeze({ a: 1 }) * * @param object The object to freeze. * * @returns The frozen object when in development mode, or else the object when in other modes. * * @public */ export declare function devFreeze(object: T): T; declare type ExtractR> = T extends RecordType ? S : never; declare type ExtractRecordType> = T extends Store ? R : never; /** @public */ export declare function getRecordVersion(record: BaseRecord, serializedSchema: SerializedSchema): RecordVersion; /** * An entry containing changes that originated either by user actions or remote changes. * @public */ export declare type HistoryEntry = { changes: RecordsDiff; source: 'user' | 'remote'; }; /** @public */ export declare type ID = string & { __type__: R; }; /* Excluded from this release type: IncrementalSetConstructor */ /** @public */ export declare function migrate({ value, migrations, fromVersion, toVersion, }: { value: unknown; migrations: Migrations; fromVersion: number; toVersion: number; }): MigrationResult; /** @public */ export declare function migrateRecord({ record, migrations, fromVersion, toVersion, }: { record: unknown; migrations: Migrations; fromVersion: number; toVersion: number; }): MigrationResult; /** @public */ export declare type Migration = { up: (oldState: T) => T; down: (newState: T) => T; }; /** @public */ export declare enum MigrationFailureReason { IncompatibleSubtype = "incompatible-subtype", UnknownType = "unknown-type", TargetVersionTooNew = "target-version-too-new", TargetVersionTooOld = "target-version-too-old", MigrationError = "migration-error", UnrecognizedSubtype = "unrecognized-subtype" } /** @public */ export declare type MigrationResult = { type: 'success'; value: T; } | { type: 'error'; reason: MigrationFailureReason; }; /** @public */ export declare interface Migrations extends BaseMigrationsInfo { subTypeKey?: string; subTypeMigrations?: Record; } declare type OmitMeta = R extends R ? Omit : R; declare type QueryExpression = { [k in keyof R & string]?: ValueMatcher; }; declare type Range_2 = To extends From ? From : To | Range_2>; declare type RecFromId = K extends ID ? R : never; /** * A diff describing the changes to a record. * @public */ export declare type RecordsDiff = { added: Record; updated: Record; removed: Record; }; /** * A record type is a type that can be stored in a record store. It is created with * `createRecordType`. * * @public */ export declare class RecordType> { /** * The unique type associated with this record. * * @public * @readonly */ readonly typeName: R['typeName']; readonly config: { readonly createDefaultProperties: () => Exclude, RequiredProperties>; readonly migrations: Migrations; }; constructor( /** * The unique type associated with this record. * * @public * @readonly */ typeName: R['typeName'], config: { readonly createDefaultProperties: () => Exclude, RequiredProperties>; readonly migrations: Migrations; }); /** * Create a new record of this type. * * @param properties The properties of the record. * * @returns The new record. */ create(properties: Pick & Omit, RequiredProperties>): R; /** * Clone a record of this type. * * @param record The record to clone. * @public * @returns The cloned record. */ clone(record: R): R; /** * Create a new ID for this record type. * * @example * const id = recordType.createId() * * @public * @returns The new ID. */ createId(): ID; /** * Create a new ID for this record type based on the given ID. * * @example * const id = recordType.createCustomId("myId") * * @param id The ID to base the new ID on. * @returns The new ID. */ createCustomId(id: string): ID; /** * Check whether a record is an instance of this record type. * * @example * const result = recordType.isInstance(someRecord) * * @param record The record to check. * @returns Whether the record is an instance of this record type. */ isInstance: (record?: BaseRecord) => record is R; /** * Check whether an id is an id of this type. * * @example * const result = recordType.isIn("someId") * * @param id The id to check. * @returns Whether the id is an id of this type. */ isId(id?: string): id is ID; /** * Create a new RecordType that has the same type name as this RecordType and includes the given default properties. * * @example * const authorType = createRecordType('author', () => ({ living: true })) * const deadAuthorType = authorType.withDefaultProperties({ living: false }) * * @param fn A function that returns the default properties of the new RecordType. * * @returns The new RecordType. */ withDefaultProperties, 'typeName' | 'id'>>(createDefaultProperties: () => DefaultProps): RecordType>; } /** @public */ export declare type RecordVersion = { rootVersion: number; subTypeVersion?: number; }; /** @public */ export declare function reverseRecordsDiff(diff: RecordsDiff): RecordsDiff; declare type RSIndex = Computed>>, RSIndexDiff>; declare type RSIndexDiff = Map>>; /** @public */ export declare interface SerializedSchema { /** * Schema version is the version for this type you're looking at right now */ schemaVersion: number; /** * Store version is the version for the structure of the store. e.g. higher level * structure like removing or renaming a record type. */ storeVersion: number; /** * Record versions are the versions for each record type. e.g. adding a new field to a record */ recordVersions: Record; subTypeKey: string; }>; } /** * Squash a collection of diffs into a single diff. * * @param diffs An array of diffs to squash. * @returns A single diff that represents the squashed diffs. * @public */ export declare function squashRecordDiffs(diffs: RecordsDiff[]): RecordsDiff; /** * A store of records. * @public */ export declare class Store { /** * An atom containing the store's atoms. * * @private * @readonly */ private readonly atoms; /** * An atom containing the store's history. * * @public * @readonly */ readonly history: Atom>; /** * A StoreQueries instance for this store. * * @public * @readonly */ readonly query: StoreQueries; /** * A set containing listeners that have been added to this store. * * @private */ private listeners; /** * An array of history entries that have not yet been flushed. * * @private */ private historyAccumulator; /** * A reactor that responds to changes to the history by squashing the * accumulated history and notifying listeners of the changes. * * @private */ private historyReactor; readonly onError?: (error: StoreError) => void; validators: StoreValidators; constructor(config: { /** * The store's initial data. */ initialData?: StoreSnapshot; /** * A map of validators for each record type. A record's validator will be * called when the record is created or updated. It should throw an error if the record is invalid. */ validators: StoreValidators; UNSAFE_SKIP_INITIAL_VALIDATION?: boolean; onError?: (error: StoreError) => void; }); _flushHistory(): void; private _validateRecord; private validateRecord; /** * Update the history with a diff of changes. * * @param changes The changes to add to the history. */ private updateHistory; validate(phase: 'initialize' | 'createRecord' | 'updateRecord' | 'tests'): void; /** * A callback fired after a record is created. Use this to perform * related updates to other records in the store. * * @param record The record to be created */ onAfterCreate?: (record: R) => void; /** * A callback fired after each record's change. * * @param prev The previous value, if any. * @param next The next value. */ onAfterChange?: (prev: R, next: R) => void; /** * A callback fired before a record is deleted. * * @param prev The record that will be deleted. */ onBeforeDelete?: (prev: R) => void; /** * A callback fired after a record is deleted. * * @param prev The record that will be deleted. */ onAfterDelete?: (prev: R) => void; private _runCallbacks; /** * Add some records to the store. It's an error if they already exist. * * @param records The records to add. * @public */ put: (records: R[], phaseOverride?: 'initialize') => void; /** * Remove some records from the store via their ids. * * @param ids The ids of the records to remove. * @public */ remove: (ids: ID[]) => void; /** * Get the value of a store record by its id. * * @param id The id of the record to get. * @public */ get: >(id: K) => RecFromId | undefined; /** * Opposite of `deserialize`. Creates a JSON payload from the record store. * * @param filter (optional) A function to filter structs that do not satisfy the predicate. * @returns The record store snapshot as a JSON payload. */ serialize: (filter?: ((record: R) => boolean) | undefined) => StoreSnapshot; /** * Opposite of `serialize`. Replace the store's current records with records as defined by a simple JSON structure into the stores. * * @param snapshot The JSON snapshot to deserialize. * @public */ deserialize: (snapshot: StoreSnapshot) => void; /** * Get an array of all values in the store. * * @public * @returns An array of all values in the store. */ allRecords: () => R[]; /** * Removes all records from the store. * * @public */ clear: () => void; /** * Update a record. To update multiple records at once, use the `update` method of the `TypedStore` class. * * @param id The id of the record to update. * @param updater A function that updates the record. */ update: >(id: K, updater: (record: RecFromId) => RecFromId) => void; /** * Get whether the record store has a id. * * @param id The id of the record to check. * @public */ has: >(id: K) => boolean; /** * Add a new listener to the store. * * @param listener The listener to call when the store updates. * @returns A function to remove the listener. */ listen: (listener: StoreListener) => () => void; private isMergingRemoteChanges; /** * Merge changes from a remote source without triggering listeners. * * @param fn A function that merges the external changes. * @public */ mergeRemoteChanges: (fn: () => void) => void; extractingChanges(fn: () => void): RecordsDiff; applyDiff(diff: RecordsDiff, runCallbacks?: boolean): void; /** * Create a computed cache. * * @param name The name of the derivation cache. * @param derive A function used to derive the value of the cache. * @public */ createComputedCache: (name: string, derive: (record: V) => T | undefined) => ComputedCache; /** * Create a computed cache from a selector * * @param name The name of the derivation cache. * @param selector A function that returns a subset of the original shape * @param derive A function used to derive the value of the cache. * @public */ createSelectedComputedCache: (name: string, selector: (record: V) => T | undefined, derive: (input: T) => J | undefined) => ComputedCache; } /** @public */ export declare type StoreError = { error: Error; phase: 'initialize' | 'createRecord' | 'updateRecord' | 'tests'; recordBefore?: unknown; recordAfter: unknown; isExistingValidationIssue: boolean; }; /** * A function that will be called when the history changes. * @public */ export declare type StoreListener = (entry: HistoryEntry) => void; /** * A class that provides a 'namespace' for the various kinds of indexes * one may wish to derive from the record store. */ declare class StoreQueries { private readonly atoms; private readonly history; constructor(atoms: Atom, Atom>>, history: Atom>); /** * A cache of derivations (indexes). * * @private */ private indexCache; /** * A cache of derivations (filtered histories). * * @private */ private historyCache; /** * Create a derivation that contains the hisotry for a given type * * @param typeName The name of the type to filter by. * * @returns A derivation that returns the ids of all records of the given type. * @public */ filterHistory(typeName: TypeName): Computed>>; /** * Create a derivation that returns an index on a property for the given type. * * @param typeName The name of the type. * @param property The name of the property. * * @public */ index>(typeName: TypeName, property: Property): RSIndex, Property>; /** * Create a derivation that returns an index on a property for the given type. * * @param typeName The name of the type?. * @param property The name of the property?. * * @private */ __uncached_createIndex>(typeName: TypeName, property: Property): RSIndex, Property>; /** * Create a derivation that will return a signle record matching the given query. * * It will return undefined if there is no matching record * * @param typeName The name of the type? * @param queryCreator A function that returns the query expression. * @param name (optinal) The name of the query. */ record(typeName: TypeName, queryCreator?: () => QueryExpression>, name?: string): Computed | undefined>; /** * Create a derivation that will return an array of records matching the given query * * @param typeName The name of the type? * @param queryCreator A function that returns the query expression. * @param name (optinal) The name of the query. */ records(typeName: TypeName, queryCreator?: () => QueryExpression>, name?: string): Computed>>; /** * Create a derivation that will return the ids of all records of the given type. * * @param typeName The name of the type. * @param queryCreator A function that returns the query expression. * @param name (optinal) The name of the query. */ ids(typeName: TypeName, queryCreator?: () => QueryExpression>, name?: string): Computed>>, CollectionDiff>>>; exec(typeName: TypeName, query: QueryExpression>): Array>; } /** @public */ export declare class StoreSchema { readonly typeArray: RecordType[]; readonly storeMigrations: Migrations; types: Record>; constructor(typeArray: RecordType[], storeMigrations: Migrations); migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'up' | 'down'): MigrationResult; migrateStore(store: Store, persistedSchema: SerializedSchema): MigrationResult; serialize(): SerializedSchema; serializeEarliestVersion(): SerializedSchema; } /** * A serialized snapshot of the record store's values. * @public */ export declare type StoreSnapshot = { [id: string]: R; }; /** @public */ declare type StoreValidator = { validate: (record: unknown) => R; }; /** @public */ export declare type StoreValidators = { [K in R['typeName']]: StoreValidator>; }; declare type ValueMatcher = { eq: T; } | { neq: T; }; export { }