tldraw/packages/store/api-report.md
alex 91903c9761
Move arrow helpers from editor to tldraw (#3721)
With the new work on bindings, we no longer need to keep any arrows
stuff hard-coded in `editor`, so let's move it to `tldraw` with the rest
of the shapes.

Couple other changes as part of this:
- We had two different types of `WeakMap` backed cache, but we now only
have one
- There's a new free-standing version of `createComputedCache` that
doesn't need access to the editor/store in order to create the cache.
instead, it returns a `{get(editor, id)}` object and instantiates the
cache on a per-editor basis for each call.
- Fixed a bug in `createSelectedComputedCache` where the selector
derivation would get re-created on every call to `get`

### Change Type

- [x] `sdk` — Changes the tldraw SDK
- [x] `improvement` — Improving existing features

### Release Notes

#### Breaking changes
- `editor.getArrowInfo(shape)` has been replaced with
`getArrowInfo(editor, shape)`
- `editor.getArrowsBoundTo(shape)` has been removed. Instead, use
`editor.getBindingsToShape(shape, 'arrow')` and follow the `fromId` of
each binding to the corresponding arrow shape
- These types have moved from `@tldraw/editor` to `tldraw`:
    - `TLArcInfo`
    - `TLArrowInfo`
    - `TLArrowPoint`
- `WeakMapCache` has been removed
2024-05-09 09:48:01 +00:00

14 KiB

API Report File for "@tldraw/store"

Do not edit this file. It is a report generated by API Extractor.


import { Atom } from '@tldraw/state';
import { Computed } from '@tldraw/state';
import { Result } from '@tldraw/utils';

// @public
export type AllRecords<T extends Store<any>> = ExtractR<ExtractRecordType<T>>;

// @public
export function assertIdType<R extends UnknownRecord>(id: string | undefined, type: RecordType<R, any>): asserts id is IdOf<R>;

// @public
export interface BaseRecord<TypeName extends string, Id extends RecordId<UnknownRecord>> {
    // (undocumented)
    readonly id: Id;
    // (undocumented)
    readonly typeName: TypeName;
}

// @public
export type CollectionDiff<T> = {
    added?: Set<T>;
    removed?: Set<T>;
};

// @public
export type ComputedCache<Data, R extends UnknownRecord> = {
    get(id: IdOf<R>): Data | undefined;
};

// @public
export function createComputedCache<Context extends StoreContext<any>, Result, Record extends ContextRecordType<Context> = ContextRecordType<Context>>(name: string, derive: (context: Context, record: Record) => Result | undefined, isEqual?: (a: Record, b: Record) => boolean): {
    get(context: Context, id: IdOf<Record>): Result | undefined;
};

// @internal (undocumented)
export function createEmptyRecordsDiff<R extends UnknownRecord>(): RecordsDiff<R>;

// @public
export function createMigrationIds<const ID extends string, const Versions extends Record<string, number>>(sequenceId: ID, versions: Versions): {
    [K in keyof Versions]: `${ID}/${Versions[K]}`;
};

// @public
export function createMigrationSequence({ sequence, sequenceId, retroactive, }: {
    retroactive?: boolean;
    sequence: Array<Migration | StandaloneDependsOn>;
    sequenceId: string;
}): MigrationSequence;

// @internal (undocumented)
export function createRecordMigrationSequence(opts: {
    filter?: (record: UnknownRecord) => boolean;
    recordType: string;
    retroactive?: boolean;
    sequence: Omit<Extract<Migration, {
        scope: 'record';
    }>, 'scope'>[];
    sequenceId: string;
}): MigrationSequence;

// @public
export function createRecordType<R extends UnknownRecord>(typeName: R['typeName'], config: {
    ephemeralKeys?: {
        readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean;
    };
    scope: RecordScope;
    validator?: StoreValidator<R>;
}): RecordType<R, keyof Omit<R, 'id' | 'typeName'>>;

// @public @deprecated (undocumented)
export function defineMigrations(opts: {
    currentVersion?: number;
    firstVersion?: number;
    migrators?: Record<number, LegacyMigration>;
    subTypeKey?: string;
    subTypeMigrations?: Record<string, LegacyBaseMigrationsInfo>;
}): LegacyMigrations;

// @public
export function devFreeze<T>(object: T): T;

// @public
export type HistoryEntry<R extends UnknownRecord = UnknownRecord> = {
    changes: RecordsDiff<R>;
    source: ChangeSource;
};

// @public (undocumented)
export type IdOf<R extends UnknownRecord> = R['id'];

// @internal
export class IncrementalSetConstructor<T> {
    constructor(
    previousValue: Set<T>);
    // @public
    add(item: T): void;
    // @public
    get(): {
        diff: CollectionDiff<T>;
        value: Set<T>;
    } | undefined;
    // @public
    remove(item: T): void;
}

// @internal
export function isRecordsDiffEmpty<T extends UnknownRecord>(diff: RecordsDiff<T>): boolean;

// @public (undocumented)
export type LegacyMigration<Before = any, After = any> = {
    down: (newState: After) => Before;
    up: (oldState: Before) => After;
};

// @public (undocumented)
export interface LegacyMigrations extends LegacyBaseMigrationsInfo {
    // (undocumented)
    subTypeKey?: string;
    // (undocumented)
    subTypeMigrations?: Record<string, LegacyBaseMigrationsInfo>;
}

// @public (undocumented)
export type Migration = {
    readonly dependsOn?: readonly MigrationId[] | undefined;
    readonly id: MigrationId;
} & ({
    readonly down?: (newState: SerializedStore<UnknownRecord>) => SerializedStore<UnknownRecord> | void;
    readonly scope: 'store';
    readonly up: (oldState: SerializedStore<UnknownRecord>) => SerializedStore<UnknownRecord> | void;
} | {
    readonly down?: (newState: UnknownRecord) => UnknownRecord | void;
    readonly filter?: (record: UnknownRecord) => boolean;
    readonly scope: 'record';
    readonly up: (oldState: UnknownRecord) => UnknownRecord | void;
});

// @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 MigrationId = `${string}/${number}`;

// @public (undocumented)
export type MigrationResult<T> = {
    reason: MigrationFailureReason;
    type: 'error';
} | {
    type: 'success';
    value: T;
};

// @public (undocumented)
export interface MigrationSequence {
    retroactive: boolean;
    // (undocumented)
    sequence: Migration[];
    // (undocumented)
    sequenceId: string;
}

// @internal (undocumented)
export function parseMigrationId(id: MigrationId): {
    sequenceId: string;
    version: number;
};

// @public (undocumented)
export type RecordId<R extends UnknownRecord> = string & {
    __type__: R;
};

// @public
export type RecordsDiff<R extends UnknownRecord> = {
    added: Record<IdOf<R>, R>;
    removed: Record<IdOf<R>, R>;
    updated: Record<IdOf<R>, [from: R, to: R]>;
};

// @public
export class RecordType<R extends UnknownRecord, RequiredProperties extends keyof Omit<R, 'id' | 'typeName'>> {
    constructor(
    typeName: R['typeName'], config: {
        readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>;
        readonly ephemeralKeys?: {
            readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean;
        };
        readonly scope?: RecordScope;
        readonly validator?: StoreValidator<R>;
    });
    clone(record: R): R;
    create(properties: Pick<R, RequiredProperties> & Omit<Partial<R>, RequiredProperties>): R;
    // @deprecated
    createCustomId(id: string): IdOf<R>;
    // (undocumented)
    readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>;
    createId(customUniquePart?: string): IdOf<R>;
    // (undocumented)
    readonly ephemeralKeys?: {
        readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean;
    };
    // (undocumented)
    readonly ephemeralKeySet: ReadonlySet<string>;
    isId(id?: string): id is IdOf<R>;
    isInstance: (record?: UnknownRecord) => record is R;
    parseId(id: IdOf<R>): string;
    // (undocumented)
    readonly scope: RecordScope;
    readonly typeName: R['typeName'];
    validate(record: unknown, recordBefore?: R): R;
    // (undocumented)
    readonly validator: StoreValidator<R>;
    withDefaultProperties<DefaultProps extends Omit<Partial<R>, 'id' | 'typeName'>>(createDefaultProperties: () => DefaultProps): RecordType<R, Exclude<RequiredProperties, keyof DefaultProps>>;
}

// @public (undocumented)
export function reverseRecordsDiff(diff: RecordsDiff<any>): RecordsDiff<any>;

// @public (undocumented)
export type SerializedSchema = SerializedSchemaV1 | SerializedSchemaV2;

// @public (undocumented)
export interface SerializedSchemaV1 {
    recordVersions: Record<string, {
        subTypeKey: string;
        subTypeVersions: Record<string, number>;
        version: number;
    } | {
        version: number;
    }>;
    schemaVersion: 1;
    storeVersion: number;
}

// @public (undocumented)
export interface SerializedSchemaV2 {
    // (undocumented)
    schemaVersion: 2;
    // (undocumented)
    sequences: {
        [sequenceId: string]: number;
    };
}

// @public
export type SerializedStore<R extends UnknownRecord> = Record<IdOf<R>, R>;

// @public
export function squashRecordDiffs<T extends UnknownRecord>(diffs: RecordsDiff<T>[]): RecordsDiff<T>;

// @internal
export function squashRecordDiffsMutable<T extends UnknownRecord>(target: RecordsDiff<T>, diffs: RecordsDiff<T>[]): void;

// @public (undocumented)
export type StandaloneDependsOn = {
    readonly dependsOn: readonly MigrationId[];
};

// @public
export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
    constructor(config: {
        schema: StoreSchema<R, Props>;
        initialData?: SerializedStore<R>;
        id?: string;
        props: Props;
    });
    // @internal (undocumented)
    addHistoryInterceptor(fn: (entry: HistoryEntry<R>, source: ChangeSource) => void): () => void;
    allRecords: () => R[];
    // (undocumented)
    applyDiff(diff: RecordsDiff<R>, { runCallbacks, ignoreEphemeralKeys, }?: {
        ignoreEphemeralKeys?: boolean;
        runCallbacks?: boolean;
    }): void;
    // @internal (undocumented)
    atomic<T>(fn: () => T, runCallbacks?: boolean): T;
    clear: () => void;
    createComputedCache: <Result, Record extends R = R>(name: string, derive: (record: Record) => Result | undefined, isEqual?: ((a: Record, b: Record) => boolean) | undefined) => ComputedCache<Result, Record>;
    createSelectedComputedCache: <Selection, Result, Record extends R = R>(name: string, selector: (record: Record) => Selection | undefined, derive: (input: Selection) => Result | undefined) => ComputedCache<Result, Record>;
    // @internal (undocumented)
    ensureStoreIsUsable(): void;
    extractingChanges(fn: () => void): RecordsDiff<R>;
    filterChangesByScope(change: RecordsDiff<R>, scope: RecordScope): {
        added: { [K in IdOf<R>]: R; };
        removed: { [K in IdOf<R>]: R; };
        updated: { [K_1 in IdOf<R>]: [from: R, to: R]; };
    } | null;
    // (undocumented)
    _flushHistory(): void;
    get: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
    getSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>;
    has: <K extends IdOf<R>>(id: K) => boolean;
    readonly history: Atom<number, RecordsDiff<R>>;
    readonly id: string;
    // @internal (undocumented)
    isPossiblyCorrupted(): boolean;
    listen: (onHistory: StoreListener<R>, filters?: Partial<StoreListenerFilters>) => () => void;
    loadSnapshot(snapshot: StoreSnapshot<R>): void;
    // @internal (undocumented)
    markAsPossiblyCorrupted(): void;
    mergeRemoteChanges: (fn: () => void) => void;
    migrateSnapshot(snapshot: StoreSnapshot<R>): StoreSnapshot<R>;
    onAfterChange?: (prev: R, next: R, source: 'remote' | 'user') => void;
    onAfterCreate?: (record: R, source: 'remote' | 'user') => void;
    onAfterDelete?: (prev: R, source: 'remote' | 'user') => void;
    onBeforeChange?: (prev: R, next: R, source: 'remote' | 'user') => R;
    onBeforeCreate?: (next: R, source: 'remote' | 'user') => R;
    onBeforeDelete?: (prev: R, source: 'remote' | 'user') => false | void;
    // (undocumented)
    readonly props: Props;
    put: (records: R[], phaseOverride?: 'initialize') => void;
    readonly query: StoreQueries<R>;
    remove: (ids: IdOf<R>[]) => void;
    // (undocumented)
    readonly schema: StoreSchema<R, Props>;
    // (undocumented)
    readonly scopedTypes: {
        readonly [K in RecordScope]: ReadonlySet<R['typeName']>;
    };
    serialize: (scope?: 'all' | RecordScope) => SerializedStore<R>;
    unsafeGetWithoutCapture: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
    update: <K extends IdOf<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;
    isExistingValidationIssue: boolean;
    phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord';
    recordAfter: unknown;
    recordBefore?: unknown;
};

// @public
export type StoreListener<R extends UnknownRecord> = (entry: HistoryEntry<R>) => void;

// @public (undocumented)
export class StoreSchema<R extends UnknownRecord, P = unknown> {
    // (undocumented)
    static create<R extends UnknownRecord, 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)
    getMigrationsSince(persistedSchema: SerializedSchema): Result<Migration[], string>;
    // @internal (undocumented)
    getType(typeName: string): RecordType<R, any>;
    // (undocumented)
    migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'down' | 'up'): MigrationResult<R>;
    // (undocumented)
    migrateStoreSnapshot(snapshot: StoreSnapshot<R>): MigrationResult<SerializedStore<R>>;
    // (undocumented)
    readonly migrations: Record<string, MigrationSequence>;
    // (undocumented)
    serialize(): SerializedSchemaV2;
    // @deprecated (undocumented)
    serializeEarliestVersion(): SerializedSchema;
    // (undocumented)
    readonly sortedMigrations: readonly Migration[];
    // (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 UnknownRecord, P> = {
    createIntegrityChecker?: (store: Store<R, P>) => void;
    onValidationFailure?: (data: {
        error: unknown;
        phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord';
        record: R;
        recordBefore: null | R;
        store: Store<R>;
    }) => R;
    migrations?: MigrationSequence[];
};

// @public (undocumented)
export type StoreSnapshot<R extends UnknownRecord> = {
    schema: SerializedSchema;
    store: SerializedStore<R>;
};

// @public (undocumented)
export type StoreValidator<R extends UnknownRecord> = {
    validate: (record: unknown) => R;
    validateUsingKnownGoodVersion?: (knownGoodVersion: R, record: unknown) => R;
};

// @public (undocumented)
export type StoreValidators<R extends UnknownRecord> = {
    [K in R['typeName']]: StoreValidator<Extract<R, {
        typeName: K;
    }>>;
};

// @public (undocumented)
export type UnknownRecord = BaseRecord<string, RecordId<UnknownRecord>>;

// (No @packageDocumentation comment for this package)