import type { O } from "ts-toolbelt" import type { AnyDataModel } from "../dataModel/BaseDataModel" import type { AnyModel } from "../model/BaseModel" import type { ModelClass } from "../modelShared/BaseModelShared" import type { SnapshotInOf, SnapshotOutOf } from "../snapshot/SnapshotOf" import type { IsOptionalValue } from "../utils/types" // type schemas // infer is there just to cache type generation export interface Type { /** @ignore */ $$type: Name /** @ignore */ $$data: Data } export interface IdentityType extends Type<"identity", Data> {} export interface ModelType extends Type<"model", Model> {} export interface CodecType< Runtime, SnapshotIn = Runtime, SnapshotOut = SnapshotIn, StoredData = Runtime, > extends Type<"codec", Runtime> { /** @ignore */ $$snapshotIn: SnapshotIn /** @ignore */ $$snapshotOut: SnapshotOut /** @ignore */ $$storedData: StoredData } type ArrayData = number extends S["length"] ? Array extends infer R ? R : never> : { [k in keyof S]: TypeToData extends infer R ? R : never } type ArraySnapshotInData = number extends S["length"] ? Array extends infer R ? R : never> : { [k in keyof S]: TypeToSnapshotIn extends infer R ? R : never } type ArraySnapshotOutData = number extends S["length"] ? Array extends infer R ? R : never> : { [k in keyof S]: TypeToSnapshotOut extends infer R ? R : never } export interface ArrayType extends Type<"array", ArrayData> {} export interface ObjectOfTypes { /** @ignore */ [k: string]: AnyType } /** * Name of the properties of an object that can be set to undefined, any or unknown. * @internal */ export type UndefinablePropsNames = { [K in keyof T]: IsOptionalValue }[keyof T] /** * Computes the optional keys for an object type schema. * @internal */ export type ObjectOptionalKeys = UndefinablePropsNames<{ [k in keyof S]: TypeToDataOpt extends infer R ? R : never }> type ObjectData = O.Optional< { [k in keyof S]: TypeToData extends infer R ? R : never }, ObjectOptionalKeys > type ObjectSnapshotInData = O.Optional< { [k in keyof S]: TypeToSnapshotIn extends infer R ? R : never }, ObjectOptionalKeys > type ObjectSnapshotOutData = O.Optional< { [k in keyof S]: TypeToSnapshotOut extends infer R ? R : never }, ObjectOptionalKeys > type RecordData = { [k: string]: TypeToData extends infer R ? R : never } type RecordSnapshotInData = { [k: string]: TypeToSnapshotIn extends infer D ? D : never } type RecordSnapshotOutData = { [k: string]: TypeToSnapshotOut extends infer D ? D : never } export interface ObjectType extends Type<"object", ObjectData> {} export interface ObjectTypeFunction { // biome-ignore lint/style/useShorthandFunctionType: make the type recursive (): ObjectOfTypes } export interface RecordType extends Type<"record", RecordData> {} export type AnyStandardType = | IdentityType | ModelType | CodecType | ArrayType | ObjectType | RecordType | ObjectTypeFunction export type AnyType = null | undefined | AnyNonValueType export type AnyNonValueType = | ModelClass | ModelClass | StringConstructor | NumberConstructor | BooleanConstructor | BigIntConstructor | AnyStandardType // type schemas to actual types type ConstructorToType = S extends StringConstructor ? string : S extends NumberConstructor ? number : S extends BooleanConstructor ? boolean : S extends BigIntConstructor ? BigIntMapping : S extends null ? null : S extends undefined ? undefined : never type ConstructorToData = ConstructorToType type ConstructorToSnapshotData = ConstructorToType type TypeToDataLeaf = S extends ModelClass ? M : S extends { $$data: infer D } ? D : ConstructorToData type TypeToSnapshotLeaf = S extends ModelClass ? Dir extends "in" ? SnapshotInOf : SnapshotOutOf : S extends { $$data: infer D } ? D : ConstructorToSnapshotData export type TypeToData = S extends ObjectTypeFunction ? ObjectType>["$$data"] extends infer R ? R : never : TypeToDataLeaf export type TypeToSnapshotIn = S extends ObjectTypeFunction ? ObjectSnapshotInData> extends infer R ? R : never : S extends CodecType ? D : S extends ArrayType ? ArraySnapshotInData : S extends ObjectType ? ObjectSnapshotInData : S extends RecordType ? RecordSnapshotInData : S extends ModelType ? SnapshotInOf : TypeToSnapshotLeaf export type TypeToSnapshotOut = S extends ObjectTypeFunction ? ObjectSnapshotOutData> extends infer R ? R : never : S extends CodecType ? D : S extends ArrayType ? ArraySnapshotOutData : S extends ObjectType ? ObjectSnapshotOutData : S extends RecordType ? RecordSnapshotOutData : S extends ModelType ? SnapshotOutOf : TypeToSnapshotLeaf /** @ignore */ export type TypeToDataOpt = S extends { $$data: infer D } ? D & undefined : never