a48a55d3de
The new version of the sync engine is gonna be calling `ensureStoreIsUsable` on every sync message, so I took some time to make it scale better. At the moment it operates on a serialized version of the store, which is expensive and unnecessary. Here I changed it to use reactive queries for the data it needs, so it only operates on small bits of data and should not become more expensive as the number of shapes grows. ### Change Type <!-- 💡 Indicate the type of change your pull request is. --> <!-- 🤷♀️ If you're not sure, don't select anything --> <!-- ✂️ Feel free to delete unselected options --> <!-- To select one, put an x in the box: [x] --> - [x] `patch` — Bug Fix - [ ] `minor` — New Feature - [ ] `major` — Breaking Change - [ ] `dependencies` — Dependency Update (publishes a `patch` release, for devDependencies use `internal`) - [ ] `documentation` — Changes to the documentation only (will not publish a new version) - [ ] `tests` — Changes to any testing-related code only (will not publish a new version) - [ ] `internal` — Any other changes that don't affect the published package (will not publish a new version) ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
332 lines
10 KiB
Markdown
332 lines
10 KiB
Markdown
## API Report File for "@tldraw/tlstore"
|
|
|
|
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
|
|
```ts
|
|
|
|
import { Atom } from 'signia';
|
|
import { Computed } from 'signia';
|
|
import { Signal } from 'signia';
|
|
|
|
// @public
|
|
export type AllRecords<T extends Store<any>> = ExtractR<ExtractRecordType<T>>;
|
|
|
|
// @public
|
|
export function assertIdType<R extends BaseRecord>(id: string | undefined, type: RecordType<R, any>): asserts id is ID<R>;
|
|
|
|
// @public
|
|
export interface BaseRecord<TypeName extends string = string> {
|
|
// (undocumented)
|
|
readonly id: ID<this>;
|
|
// (undocumented)
|
|
readonly typeName: TypeName;
|
|
}
|
|
|
|
// @public
|
|
export type CollectionDiff<T> = {
|
|
added?: Set<T>;
|
|
removed?: Set<T>;
|
|
};
|
|
|
|
// @public (undocumented)
|
|
export function compareRecordVersions(a: RecordVersion, b: RecordVersion): -1 | 0 | 1;
|
|
|
|
// @public (undocumented)
|
|
export const compareSchemas: (a: SerializedSchema, b: SerializedSchema) => -1 | 0 | 1;
|
|
|
|
// @public
|
|
export type ComputedCache<Data, R extends BaseRecord> = {
|
|
get(id: ID<R>): Data | undefined;
|
|
};
|
|
|
|
// @public
|
|
export function createRecordType<R extends BaseRecord>(typeName: R['typeName'], config: {
|
|
migrations?: Migrations;
|
|
validator: StoreValidator<R>;
|
|
scope: Scope;
|
|
}): RecordType<R, keyof Omit<R, 'id' | 'typeName'>>;
|
|
|
|
// @public (undocumented)
|
|
export function defineMigrations<FirstVersion extends number, CurrentVersion extends number>({ firstVersion, currentVersion, migrators, subTypeKey, subTypeMigrations, }: {
|
|
firstVersion: FirstVersion;
|
|
currentVersion: CurrentVersion;
|
|
migrators: {
|
|
[version in Exclude<Range_2<FirstVersion, CurrentVersion>, FirstVersion>]: Migration;
|
|
};
|
|
subTypeKey?: string;
|
|
subTypeMigrations?: Record<string, BaseMigrationsInfo>;
|
|
}): Migrations;
|
|
|
|
// @public
|
|
export function devFreeze<T>(object: T): T;
|
|
|
|
// @public (undocumented)
|
|
export function getRecordVersion(record: BaseRecord, serializedSchema: SerializedSchema): RecordVersion;
|
|
|
|
// @public
|
|
export type HistoryEntry<R extends BaseRecord = BaseRecord> = {
|
|
changes: RecordsDiff<R>;
|
|
source: 'remote' | 'user';
|
|
};
|
|
|
|
// @public (undocumented)
|
|
export type ID<R extends BaseRecord = BaseRecord> = string & {
|
|
__type__: R;
|
|
};
|
|
|
|
// @internal
|
|
export class IncrementalSetConstructor<T> {
|
|
constructor(
|
|
previousValue: Set<T>);
|
|
// @public
|
|
add(item: T): void;
|
|
// @public
|
|
get(): {
|
|
value: Set<T>;
|
|
diff: CollectionDiff<T>;
|
|
} | undefined;
|
|
// @public
|
|
remove(item: T): void;
|
|
}
|
|
|
|
// @public (undocumented)
|
|
export function migrate<T>({ value, migrations, fromVersion, toVersion, }: {
|
|
value: unknown;
|
|
migrations: Migrations;
|
|
fromVersion: number;
|
|
toVersion: number;
|
|
}): MigrationResult<T>;
|
|
|
|
// @public (undocumented)
|
|
export function migrateRecord<R extends BaseRecord>({ record, migrations, fromVersion, toVersion, }: {
|
|
record: unknown;
|
|
migrations: Migrations;
|
|
fromVersion: number;
|
|
toVersion: number;
|
|
}): MigrationResult<R>;
|
|
|
|
// @public (undocumented)
|
|
export type Migration<T = any> = {
|
|
up: (oldState: T) => T;
|
|
down: (newState: T) => T;
|
|
};
|
|
|
|
// @public (undocumented)
|
|
export enum MigrationFailureReason {
|
|
// (undocumented)
|
|
IncompatibleSubtype = "incompatible-subtype",
|
|
// (undocumented)
|
|
MigrationError = "migration-error",
|
|
// (undocumented)
|
|
TargetVersionTooNew = "target-version-too-new",
|
|
// (undocumented)
|
|
TargetVersionTooOld = "target-version-too-old",
|
|
// (undocumented)
|
|
UnknownType = "unknown-type",
|
|
// (undocumented)
|
|
UnrecognizedSubtype = "unrecognized-subtype"
|
|
}
|
|
|
|
// @public (undocumented)
|
|
export type MigrationResult<T> = {
|
|
type: 'error';
|
|
reason: MigrationFailureReason;
|
|
} | {
|
|
type: 'success';
|
|
value: T;
|
|
};
|
|
|
|
// @public (undocumented)
|
|
export interface Migrations extends BaseMigrationsInfo {
|
|
// (undocumented)
|
|
subTypeKey?: string;
|
|
// (undocumented)
|
|
subTypeMigrations?: Record<string, BaseMigrationsInfo>;
|
|
}
|
|
|
|
// @public
|
|
export type RecordsDiff<R extends BaseRecord> = {
|
|
added: Record<string, R>;
|
|
updated: Record<string, [from: R, to: R]>;
|
|
removed: Record<string, R>;
|
|
};
|
|
|
|
// @public
|
|
export class RecordType<R extends BaseRecord, RequiredProperties extends keyof Omit<R, 'id' | 'typeName'>> {
|
|
constructor(
|
|
typeName: R['typeName'], config: {
|
|
readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>;
|
|
readonly migrations: Migrations;
|
|
readonly validator?: {
|
|
validate: (r: unknown) => R;
|
|
} | StoreValidator<R>;
|
|
readonly scope?: Scope;
|
|
});
|
|
clone(record: R): R;
|
|
create(properties: Pick<R, RequiredProperties> & Omit<Partial<R>, RequiredProperties>): R;
|
|
createCustomId(id: string): ID<R>;
|
|
// (undocumented)
|
|
readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>;
|
|
createId(): ID<R>;
|
|
isId(id?: string): id is ID<R>;
|
|
isInstance: (record?: BaseRecord) => record is R;
|
|
// (undocumented)
|
|
readonly migrations: Migrations;
|
|
parseId(id: string): ID<R>;
|
|
// (undocumented)
|
|
readonly scope: Scope;
|
|
readonly typeName: R['typeName'];
|
|
validate(record: unknown): R;
|
|
// (undocumented)
|
|
readonly validator: {
|
|
validate: (r: unknown) => R;
|
|
} | StoreValidator<R>;
|
|
withDefaultProperties<DefaultProps extends Omit<Partial<R>, 'id' | 'typeName'>>(createDefaultProperties: () => DefaultProps): RecordType<R, Exclude<RequiredProperties, keyof DefaultProps>>;
|
|
}
|
|
|
|
// @public (undocumented)
|
|
export type RecordVersion = {
|
|
rootVersion: number;
|
|
subTypeVersion?: number;
|
|
};
|
|
|
|
// @public (undocumented)
|
|
export function reverseRecordsDiff(diff: RecordsDiff<any>): RecordsDiff<any>;
|
|
|
|
// @public (undocumented)
|
|
export interface SerializedSchema {
|
|
recordVersions: Record<string, {
|
|
version: number;
|
|
subTypeVersions: Record<string, number>;
|
|
subTypeKey: string;
|
|
} | {
|
|
version: number;
|
|
}>;
|
|
schemaVersion: number;
|
|
storeVersion: number;
|
|
}
|
|
|
|
// @public
|
|
export function squashRecordDiffs<T extends BaseRecord>(diffs: RecordsDiff<T>[]): RecordsDiff<T>;
|
|
|
|
// @public
|
|
export class Store<R extends BaseRecord = BaseRecord, Props = unknown> {
|
|
constructor(config: {
|
|
initialData?: StoreSnapshot<R>;
|
|
schema: StoreSchema<R, Props>;
|
|
props: Props;
|
|
});
|
|
allRecords: () => R[];
|
|
// (undocumented)
|
|
applyDiff(diff: RecordsDiff<R>, runCallbacks?: boolean): void;
|
|
clear: () => void;
|
|
createComputedCache: <T, V extends R = R>(name: string, derive: (record: V) => T | undefined) => ComputedCache<T, V>;
|
|
createSelectedComputedCache: <T, J, V extends R = R>(name: string, selector: (record: V) => T | undefined, derive: (input: T) => J | undefined) => ComputedCache<J, V>;
|
|
deserialize: (snapshot: StoreSnapshot<R>) => void;
|
|
// @internal (undocumented)
|
|
ensureStoreIsUsable(): void;
|
|
// (undocumented)
|
|
extractingChanges(fn: () => void): RecordsDiff<R>;
|
|
// (undocumented)
|
|
_flushHistory(): void;
|
|
get: <K extends ID<R>>(id: K) => RecFromId<K> | undefined;
|
|
has: <K extends ID<R>>(id: K) => boolean;
|
|
readonly history: Atom<number, RecordsDiff<R>>;
|
|
// @internal (undocumented)
|
|
isPossiblyCorrupted(): boolean;
|
|
listen: (listener: StoreListener<R>) => () => void;
|
|
// @internal (undocumented)
|
|
markAsPossiblyCorrupted(): void;
|
|
mergeRemoteChanges: (fn: () => void) => void;
|
|
onAfterChange?: (prev: R, next: R) => void;
|
|
onAfterCreate?: (record: R) => void;
|
|
onAfterDelete?: (prev: R) => void;
|
|
onBeforeDelete?: (prev: R) => void;
|
|
// (undocumented)
|
|
readonly props: Props;
|
|
put: (records: R[], phaseOverride?: 'initialize') => void;
|
|
readonly query: StoreQueries<R>;
|
|
remove: (ids: ID<R>[]) => void;
|
|
// (undocumented)
|
|
readonly schema: StoreSchema<R, Props>;
|
|
serialize: (filter?: ((record: R) => boolean) | undefined) => StoreSnapshot<R>;
|
|
unsafeGetWithoutCapture: <K extends ID<R>>(id: K) => RecFromId<K> | undefined;
|
|
update: <K extends ID<R>>(id: K, updater: (record: RecFromId<K>) => RecFromId<K>) => void;
|
|
// (undocumented)
|
|
validate(phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord'): void;
|
|
}
|
|
|
|
// @public (undocumented)
|
|
export type StoreError = {
|
|
error: Error;
|
|
phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord';
|
|
recordBefore?: unknown;
|
|
recordAfter: unknown;
|
|
isExistingValidationIssue: boolean;
|
|
};
|
|
|
|
// @public
|
|
export type StoreListener<R extends BaseRecord> = (entry: HistoryEntry<R>) => void;
|
|
|
|
// @public (undocumented)
|
|
export class StoreSchema<R extends BaseRecord, P = unknown> {
|
|
// (undocumented)
|
|
static create<R extends BaseRecord, P = unknown>(types: {
|
|
[TypeName in R['typeName']]: {
|
|
createId: any;
|
|
};
|
|
}, options?: StoreSchemaOptions<R, P>): StoreSchema<R, P>;
|
|
// @internal (undocumented)
|
|
createIntegrityChecker(store: Store<R, P>): (() => void) | undefined;
|
|
// (undocumented)
|
|
get currentStoreVersion(): number;
|
|
// @internal (undocumented)
|
|
derivePresenceState(store: Store<R, P>): Signal<null | R> | undefined;
|
|
// (undocumented)
|
|
migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'down' | 'up'): MigrationResult<R>;
|
|
// (undocumented)
|
|
migrateStoreSnapshot(storeSnapshot: StoreSnapshot<R>, persistedSchema: SerializedSchema): MigrationResult<StoreSnapshot<R>>;
|
|
// (undocumented)
|
|
serialize(): SerializedSchema;
|
|
// (undocumented)
|
|
serializeEarliestVersion(): SerializedSchema;
|
|
// (undocumented)
|
|
readonly types: {
|
|
[Record in R as Record['typeName']]: RecordType<R, any>;
|
|
};
|
|
// (undocumented)
|
|
validateRecord(store: Store<R>, record: R, phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord', recordBefore: null | R): R;
|
|
}
|
|
|
|
// @public (undocumented)
|
|
export type StoreSchemaOptions<R extends BaseRecord, P> = {
|
|
snapshotMigrations?: Migrations;
|
|
onValidationFailure?: (data: {
|
|
error: unknown;
|
|
store: Store<R>;
|
|
record: R;
|
|
phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord';
|
|
recordBefore: null | R;
|
|
}) => R;
|
|
createIntegrityChecker?: (store: Store<R, P>) => void;
|
|
derivePresenceState?: (store: Store<R, P>) => Signal<null | R>;
|
|
};
|
|
|
|
// @public
|
|
export type StoreSnapshot<R extends BaseRecord> = Record<string, R>;
|
|
|
|
// @public (undocumented)
|
|
export type StoreValidator<R extends BaseRecord> = {
|
|
validate: (record: unknown) => R;
|
|
};
|
|
|
|
// @public (undocumented)
|
|
export type StoreValidators<R extends BaseRecord> = {
|
|
[K in R['typeName']]: StoreValidator<Extract<R, {
|
|
typeName: K;
|
|
}>>;
|
|
};
|
|
|
|
// (No @packageDocumentation comment for this package)
|
|
|
|
```
|