UNPKG

loro-mirror

Version:

Type-safe state management synchronized with Loro CRDT via a declarative schema and bidirectional mirroring.

257 lines 9.37 kB
/** * Types for the schema definition system */ import { ContainerType } from "loro-crdt"; /** * Options for schema definitions */ export interface SchemaOptions { /** Whether the field is required */ required?: boolean; /** Default value for the field */ defaultValue?: unknown; /** Description of the field */ description?: string; /** Additional validation function */ validate?: (value: unknown) => boolean | string; [key: string]: unknown; } /** * Base interface for all schema types */ export interface BaseSchemaType { type: string; options: SchemaOptions; getContainerType(): ContainerType | null; } /** * String schema type */ export interface StringSchemaType<T extends string = string> extends BaseSchemaType { type: "string"; _t: T; } /** * Number schema type */ export interface NumberSchemaType extends BaseSchemaType { type: "number"; } /** * Boolean schema type */ export interface BooleanSchemaType extends BaseSchemaType { type: "boolean"; } /** * Ignored field schema type */ export interface IgnoreSchemaType extends BaseSchemaType { type: "ignore"; } /** * Loro Map schema type */ export interface LoroMapSchema<T extends Record<string, SchemaType>> extends BaseSchemaType { type: "loro-map"; definition: SchemaDefinition<T>; } /** * Enhanced LoroMapSchema with catchall support */ export interface LoroMapSchemaWithCatchall<T extends Record<string, SchemaType>, C extends SchemaType> extends BaseSchemaType { type: "loro-map"; definition: SchemaDefinition<T>; catchallType: C; catchall<NewC extends SchemaType>(catchallSchema: NewC): LoroMapSchemaWithCatchall<T, NewC>; } /** * Loro List schema type */ export interface LoroListSchema<T extends SchemaType> extends BaseSchemaType { type: "loro-list"; itemSchema: T; idSelector?: (item: unknown) => string; } /** * Loro Movable List schema type */ export interface LoroMovableListSchema<T extends SchemaType> extends BaseSchemaType { type: "loro-movable-list"; itemSchema: T; idSelector?: (item: unknown) => string; } /** * Loro Text schema type */ export interface LoroTextSchemaType extends BaseSchemaType { type: "loro-text"; } /** * Loro Tree schema type * * Represents a tree where each node has a `data` map described by `nodeSchema`. */ export interface LoroTreeSchema<T extends Record<string, SchemaType>> extends BaseSchemaType { type: "loro-tree"; nodeSchema: LoroMapSchema<T>; } /** * Root schema type */ export interface RootSchemaType<T extends Record<string, ContainerSchemaType>> extends BaseSchemaType { type: "schema"; definition: RootSchemaDefinition<T>; } /** * Union of all schema types */ export type SchemaType = StringSchemaType | NumberSchemaType | BooleanSchemaType | IgnoreSchemaType | LoroMapSchema<Record<string, SchemaType>> | LoroMapSchemaWithCatchall<Record<string, SchemaType>, SchemaType> | LoroListSchema<SchemaType> | LoroMovableListSchema<SchemaType> | LoroTextSchemaType | LoroTreeSchema<Record<string, SchemaType>> | RootSchemaType<Record<string, ContainerSchemaType>>; export type ContainerSchemaType = LoroMapSchema<Record<string, SchemaType>> | LoroMapSchemaWithCatchall<Record<string, SchemaType>, SchemaType> | LoroListSchema<SchemaType> | LoroMovableListSchema<SchemaType> | LoroTextSchemaType | LoroTreeSchema<Record<string, SchemaType>>; /** * Schema definition type */ export type RootSchemaDefinition<T extends Record<string, ContainerSchemaType>> = { [K in keyof T]: T[K]; }; /** * Schema definition type */ export type SchemaDefinition<T extends Record<string, SchemaType>> = { [K in keyof T]: T[K]; }; /** * Check if a schema type is required * * true is default */ type IsSchemaRequired<S extends SchemaType> = S extends { options: { required: true; }; } ? true : S extends { options: { required: false; }; } ? false : S extends { options: { required?: undefined; }; } ? true : S extends { options: {}; } ? true : true; /** * Infer the JavaScript type from a schema type */ export type InferType<S extends SchemaType> = IsSchemaRequired<S> extends false ? (S extends StringSchemaType<infer T> ? T | undefined : S extends NumberSchemaType ? number | undefined : S extends BooleanSchemaType ? boolean | undefined : S extends IgnoreSchemaType ? unknown : S extends LoroTextSchemaType ? string | undefined : S extends LoroMapSchemaWithCatchall<infer M, infer C> ? (keyof M extends never ? ({ [key: string]: InferType<C>; } & { $cid: string; }) | undefined : (({ [K in keyof M]: InferType<M[K]>; } & { [K in Exclude<string, keyof M>]: InferType<C>; }) & { $cid: string; }) | undefined) : S extends LoroMapSchema<infer M> ? ({ [K in keyof M]: InferType<M[K]>; } & { $cid: string; }) | undefined : S extends LoroListSchema<infer I> ? Array<InferType<I>> | undefined : S extends LoroMovableListSchema<infer I> ? Array<InferType<I>> | undefined : S extends LoroTreeSchema<infer M> ? Array<InferTreeNodeTypeWithCid<M>> | undefined : S extends RootSchemaType<infer R> ? { [K in keyof R]: InferType<R[K]>; } | undefined : never) : (S extends StringSchemaType<infer T> ? T : S extends NumberSchemaType ? number : S extends BooleanSchemaType ? boolean : S extends IgnoreSchemaType ? unknown : S extends LoroTextSchemaType ? string : S extends LoroMapSchemaWithCatchall<infer M, infer C> ? keyof M extends never ? ({ [key: string]: InferType<C>; } & { $cid: string; }) : (({ [K in keyof M]: InferType<M[K]>; } & { [K in Exclude<string, keyof M>]: InferType<C>; }) & { $cid: string; }) : S extends LoroMapSchema<infer M> ? ({ [K in keyof M]: InferType<M[K]>; } & { $cid: string; }) : S extends LoroListSchema<infer I> ? Array<InferType<I>> : S extends LoroMovableListSchema<infer I> ? Array<InferType<I>> : S extends LoroTreeSchema<infer M> ? Array<InferTreeNodeTypeWithCid<M>> : S extends RootSchemaType<infer R> ? { [K in keyof R]: InferType<R[K]>; } : never); /** * Infer the JavaScript type from a schema definition */ export type InferSchemaType<T extends Record<string, SchemaType>> = { [K in keyof T]: InferType<T[K]>; }; /** * Infer the input (write) type for setState updates. * Identical to InferType<S> except that for any LoroMap shape, the `$cid` field is optional. */ export type InferInputType<S extends SchemaType> = IsSchemaRequired<S> extends false ? (S extends StringSchemaType<infer T> ? T | undefined : S extends NumberSchemaType ? number | undefined : S extends BooleanSchemaType ? boolean | undefined : S extends IgnoreSchemaType ? unknown : S extends LoroTextSchemaType ? string | undefined : S extends LoroMapSchemaWithCatchall<infer M, infer C> ? (keyof M extends never ? ({ [key: string]: InferInputType<C>; } & { $cid?: string; }) | undefined : (({ [K in keyof M]: InferInputType<M[K]>; } & { [K in Exclude<string, keyof M>]: InferInputType<C>; }) & { $cid?: string; }) | undefined) : S extends LoroMapSchema<infer M> ? ({ [K in keyof M]: InferInputType<M[K]>; } & { $cid?: string; }) | undefined : S extends LoroListSchema<infer I> ? Array<InferInputType<I>> | undefined : S extends LoroMovableListSchema<infer I> ? Array<InferInputType<I>> | undefined : S extends LoroTreeSchema<infer M> ? Array<InferInputTreeNodeType<M>> | undefined : S extends RootSchemaType<infer R> ? { [K in keyof R]: InferInputType<R[K]>; } | undefined : never) : (S extends StringSchemaType<infer T> ? T : S extends NumberSchemaType ? number : S extends BooleanSchemaType ? boolean : S extends IgnoreSchemaType ? unknown : S extends LoroTextSchemaType ? string : S extends LoroMapSchemaWithCatchall<infer M, infer C> ? keyof M extends never ? ({ [key: string]: InferInputType<C>; } & { $cid?: string; }) : (({ [K in keyof M]: InferInputType<M[K]>; } & { [K in Exclude<string, keyof M>]: InferInputType<C>; }) & { $cid?: string; }) : S extends LoroMapSchema<infer M> ? ({ [K in keyof M]: InferInputType<M[K]>; } & { $cid?: string; }) : S extends LoroListSchema<infer I> ? Array<InferInputType<I>> : S extends LoroMovableListSchema<infer I> ? Array<InferInputType<I>> : S extends LoroTreeSchema<infer M> ? Array<InferInputTreeNodeType<M>> : S extends RootSchemaType<infer R> ? { [K in keyof R]: InferInputType<R[K]>; } : never); /** * Helper: Infer the node type for a tree schema */ export type InferTreeNodeType<M extends Record<string, SchemaType>> = { id: string; data: { [K in keyof M]: InferType<M[K]>; }; children: Array<InferTreeNodeType<M>>; }; /** * Helper: Infer the node type for a tree schema whose node.data map includes $cid */ export type InferTreeNodeTypeWithCid<M extends Record<string, SchemaType>> = { id: string; data: ({ [K in keyof M]: InferType<M[K]>; } & { $cid: string; }); children: Array<InferTreeNodeTypeWithCid<M>>; }; /** * Helper: Input node type for a tree schema (node.data has optional $cid) */ export type InferInputTreeNodeType<M extends Record<string, SchemaType>> = { id: string; data: ({ [K in keyof M]: InferInputType<M[K]>; } & { $cid?: string; }); children: Array<InferInputTreeNodeType<M>>; }; export {}; //# sourceMappingURL=types.d.ts.map