import DataPack from "./datapack.js"; import { DatabaseError } from "olmdb/lowlevel"; import { Model } from "./models.js"; import type { AnyModelClass, ModelBase as ModelInstanceBase } from "./models.js"; /** * @internal Abstract base class for all type wrappers in the Edinburgh ORM system. * * This is an implementation detail and should not be referenced directly in user code. * Type wrappers define how values are serialized to/from the database and how they are validated. * Each type wrapper must implement serialization, deserialization, and validation logic. * * @template T - The TypeScript type this wrapper represents. */ export declare abstract class TypeWrapper { /** @internal Used for TypeScript type inference - this field is required for the type system */ _T: T; /** A string identifier for this type, used during serialization */ abstract kind: string; constructor(); /** * Serialize a value from an object property to a Pack. * @param value The value to serialize. * @param pack The Pack instance to write to. */ abstract serialize(value: T, pack: DataPack): void; /** * Deserialize a value from a Pack into an object property. * @param pack The Pack instance to read from. */ abstract deserialize(pack: DataPack): T; /** * Validate a value. * @param value The value to validate. * @returns - A DatabaseError if validation fails. */ abstract getError(value: T): DatabaseError | void; /** * Serialize type metadata to a Pack (for schema serialization). * @param pack The Pack instance to write to. */ serializeType(pack: DataPack): void; /** * Check if indexing should be skipped for this field value. * @param obj The object containing the value. * @param prop The property name or index. * @returns true if indexing should be skipped. */ containsNull(value: T): boolean; toString(): string; clone(value: T): T; equals(value1: T, value2: T): boolean; getLinkedModel(): undefined | AnyModelClass; } export interface TypeWrapper { /** * Generate a default value for this type. * @param model The model instance. * @returns The default value. */ default?(model: any): T; } export declare const QUERY_ARG: unique symbol; export type LinkTargetPKArgs = T extends { get(...args: infer PKA): any; } ? PKA : never; export type LinkPrimaryKeyInput = PKA extends readonly [infer ONLY] ? ONLY | PKA : PKA; export type FieldValue> = TYPE extends TypeWrapper ? T : never; export type FieldQueryArg = T extends ModelInstanceBase ? T | LinkPrimaryKeyInput> : T extends { readonly [QUERY_ARG]?: infer QUERY; } ? Exclude : T; /** * @internal Type wrapper for array values with optional length constraints. * @template T - The type of array elements. */ export declare class SetType extends TypeWrapper> { inner: TypeWrapper; opts: { min?: number; max?: number; }; kind: string; /** * Create a new SetType. * @param inner Type wrapper for set elements. */ constructor(inner: TypeWrapper, opts?: { min?: number; max?: number; }); serialize(value: Set, pack: DataPack): void; deserialize(pack: DataPack): Set; getError(value: Set): DatabaseError | undefined; serializeType(pack: DataPack): void; static deserializeType(pack: DataPack, featureFlags: number): SetType; default(): Set; clone(value: Set): Set; equals(a: Set, b: Set): boolean; toString(): string; getLinkedModel(): AnyModelClass | undefined; } /** * @internal Type wrapper for model relationships (foreign keys). * @template T - The target model class type. */ export declare class LinkType Model> extends TypeWrapper> { kind: string; private TargetModel; /** * Create a new LinkType. * @param TargetModel The model class this link points to, or a thunk for forward references. */ constructor(TargetModel: T | (() => T)); getLinkedModel(): AnyModelClass; serialize(model: InstanceType, pack: DataPack): void; deserialize(pack: DataPack): InstanceType; getError(value: InstanceType): DatabaseError | undefined; serializeType(pack: DataPack): void; static deserializeType(pack: DataPack, featureFlags: number): LinkType; toString(): string; } /** Type wrapper instance for the string type. */ export declare const string: TypeWrapper; /** Type wrapper instance for the ordered string type, which is just like a string * except that it sorts lexicographically in the database (instead of by incrementing * length first), making it suitable for index fields that want lexicographic range * scans. Ordered strings are implemented as null-terminated UTF-8 strings, so they * may not contain null characters. */ export declare const orderedString: TypeWrapper; /** Type wrapper instance for the number type. */ export declare const number: TypeWrapper; /** Type wrapper instance for the date/time type. Stored without timezone info, rounded to whole seconds. */ export declare const dateTime: TypeWrapper; /** Type wrapper instance for the boolean type. */ export declare const boolean: TypeWrapper; /** Type wrapper instance for the identifier type. */ export declare const identifier: TypeWrapper; /** Type wrapper instance for the 'undefined' type. */ export declare const undef: TypeWrapper; /** * Create a literal type wrapper for a constant value. * @template T - The literal type. * @param value The literal value. * @returns A literal type instance. * * @example * ```typescript * const statusType = E.literal("active"); * const countType = E.literal(42); * ``` */ export declare function literal(value: T): TypeWrapper; /** * Create a union type wrapper from multiple type choices. * @template T - Array of type wrapper or basic types. * @param choices The type choices for the union. * @returns A union type instance. * * @example * ```typescript * const stringOrNumber = E.or(E.string, E.number); * const status = E.or("active", "inactive", "pending"); * ``` */ export declare function or | BasicType)[]>(...choices: T): TypeWrapper>; /** * Create an optional type wrapper (allows undefined). * @template T - Type wrapper or basic type to make optional. * @param inner The inner type to make optional. * @returns A union type that accepts the inner type or undefined. * * @example * ```typescript * const optionalString = E.opt(E.string); * const optionalNumber = E.opt(E.number); * ``` */ export declare function opt | BasicType>(inner: T): TypeWrapper>; /** * Create an array type wrapper with optional length constraints. * @template T - The element type. * @param inner Type wrapper for array elements. * @param opts Optional constraints (min/max length). * @returns An array type instance. * * @example * ```typescript * const stringArray = E.array(E.string); * const boundedArray = E.array(E.number, {min: 1, max: 10}); * ``` */ export declare function array(inner: TypeWrapper, opts?: { min?: number; max?: number; }): TypeWrapper; /** * Create a Set type wrapper with optional length constraints. * @template T - The element type. * @param inner Type wrapper for set elements. * @param opts Optional constraints (min/max length). * @returns A set type instance. * * @example * ```typescript * const stringSet = E.set(E.string); * const boundedSet = E.set(E.number, {min: 1, max: 10}); * ``` */ export declare function set(inner: TypeWrapper, opts?: { min?: number; max?: number; }): TypeWrapper>; /** * Create a Record type wrapper for key-value objects with string or number keys. * @template T - The value type. * @param inner Type wrapper for record values. * @returns A record type instance. * * @example * ```typescript * const scores = E.record(E.number); // Record * ``` */ export declare function record(inner: TypeWrapper): TypeWrapper>; /** @internal Flatten an intersection into a single, readable object type. */ type Prettify = { [K in keyof T]: T[K]; } & {}; /** @internal The TS value type a shape entry (type wrapper or literal) represents. */ type UnwrapField = X extends TypeWrapper ? U : X; /** A shape for {@link object}: a map of property name → field type (or literal). */ export type ObjectShape = Record | BasicType>; /** * The value type produced by {@link object} for a given shape. Keys whose field * type permits `undefined` (e.g. wrapped in {@link opt}) become optional; all * others are required. */ export type ObjectValue = Prettify<{ [K in keyof S as undefined extends UnwrapField ? never : K]: UnwrapField; } & { [K in keyof S as undefined extends UnwrapField ? K : never]?: UnwrapField; }>; /** * Create a fixed-shape object (struct) type wrapper. Unlike {@link record}, the * keys are part of the schema, so values are stored compactly in key order * without repeating the keys per record. Optional (`E.opt`) fields become * optional properties in the resulting type. * * @param shape A map of property name → field type wrapper (or literal value). * @returns An object type instance. * * @example * ```typescript * const point = E.object({ x: E.number, y: E.number }); // { x: number; y: number } * const entry = E.object({ * at: E.number, * what: E.or(E.string, point), // string | { x: number; y: number } * note: E.opt(E.string), // note?: string * }); * ``` */ export declare function object(shape: S): TypeWrapper>; /** * Create a link type wrapper for model relationships. * @template T - The target model class. * @param TargetModel The model class this link points to. * @returns A link type instance. * * @example * ```typescript * const Author = E.defineModel("Author", class { * id = E.field(E.identifier); * posts = E.field(E.array(E.link(() => Book))); * }, { pk: "id" }); * * const Book = E.defineModel("Book", class { * id = E.field(E.identifier); * author = E.field(E.link(Author)); * }, { pk: "id" }); * ``` */ export declare function link Model>(TargetModel: T): TypeWrapper>; export declare function link Model>(TargetModel: () => T): TypeWrapper>; export type BasicType = string | number | boolean | undefined | null; export type UnwrapTypes | BasicType)[]> = { [K in keyof T]: T[K] extends TypeWrapper ? U : T[K]; }[number]; /** * Serialize a type wrapper to a Pack for schema persistence. * @param arg The type wrapper to serialize. * @param pack The Pack instance to write to. */ export declare function serializeType(arg: TypeWrapper, pack: DataPack): void; /** * Deserialize a type wrapper from a Pack. * @param pack The Pack instance to read from. * @param featureFlags Feature flags for version compatibility. * @returns The deserialized type wrapper. */ export declare function deserializeType(pack: DataPack, featureFlags: number): TypeWrapper; export {};