UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

82 lines (81 loc) 5.77 kB
import { CollectionImpl } from '../../collection.js'; import { Aggregate, BasicExpression } from '../ir.js'; import { QueryBuilder } from './index.js'; export interface Context { baseSchema: ContextSchema; schema: ContextSchema; fromSourceName: string; hasJoins?: boolean; joinTypes?: Record<string, `inner` | `left` | `right` | `full` | `outer` | `cross`>; result?: any; } export type ContextSchema = Record<string, unknown>; export type Source = { [alias: string]: CollectionImpl<any, any> | QueryBuilder<Context>; }; export type InferCollectionType<T> = T extends CollectionImpl<infer U> ? U : never; export type SchemaFromSource<T extends Source> = Prettify<{ [K in keyof T]: T[K] extends CollectionImpl<infer U> ? U : T[K] extends QueryBuilder<infer TContext> ? GetResult<TContext> : never; }>; export type GetAliases<TContext extends Context> = keyof TContext[`schema`]; export type WhereCallback<TContext extends Context> = (refs: RefProxyForContext<TContext>) => any; export type SelectObject<T extends Record<string, BasicExpression | Aggregate | RefProxy | RefProxyFor<any>> = Record<string, BasicExpression | Aggregate | RefProxy | RefProxyFor<any>>> = T; export type ResultTypeFromSelect<TSelectObject> = { [K in keyof TSelectObject]: TSelectObject[K] extends RefProxy<infer T> ? T : TSelectObject[K] extends BasicExpression<infer T> ? T : TSelectObject[K] extends Aggregate<infer T> ? T : TSelectObject[K] extends RefProxyFor<infer T> ? T : never; }; export type OrderByCallback<TContext extends Context> = (refs: RefProxyForContext<TContext>) => any; export type GroupByCallback<TContext extends Context> = (refs: RefProxyForContext<TContext>) => any; export type JoinOnCallback<TContext extends Context> = (refs: RefProxyForContext<TContext>) => any; export type RefProxyForContext<TContext extends Context> = { [K in keyof TContext[`schema`]]: RefProxyFor<TContext[`schema`][K]>; }; type IsExactlyUndefined<T> = [T] extends [undefined] ? true : false; type IsOptional<T> = undefined extends T ? true : false; type NonUndefined<T> = T extends undefined ? never : T; export type RefProxyFor<T> = OmitRefProxy<IsExactlyUndefined<T> extends true ? RefProxy<T> : IsOptional<T> extends true ? NonUndefined<T> extends Record<string, any> ? { [K in keyof NonUndefined<T>]: NonUndefined<T>[K] extends Record<string, any> ? RefProxyFor<NonUndefined<T>[K] | undefined> & RefProxy<NonUndefined<T>[K] | undefined> : RefProxy<NonUndefined<T>[K] | undefined>; } & RefProxy<T> : RefProxy<T> : T extends Record<string, any> ? { [K in keyof T]: T[K] extends Record<string, any> ? RefProxyFor<T[K]> & RefProxy<T[K]> : RefProxy<T[K]>; } & RefProxy<T> : RefProxy<T>>; export type Ref<T> = RefProxyFor<T>; type OmitRefProxy<T> = Omit<T, `__refProxy` | `__path` | `__type`>; export interface RefProxy<T = any> { /** @internal */ readonly __refProxy: true; /** @internal */ readonly __path: Array<string>; /** @internal */ readonly __type: T; } export type MergeContextWithJoinType<TContext extends Context, TNewSchema extends ContextSchema, TJoinType extends `inner` | `left` | `right` | `full` | `outer` | `cross`> = { baseSchema: TContext[`baseSchema`]; schema: ApplyJoinOptionalityToMergedSchema<TContext[`schema`], TNewSchema, TJoinType, TContext[`fromSourceName`]>; fromSourceName: TContext[`fromSourceName`]; hasJoins: true; joinTypes: (TContext[`joinTypes`] extends Record<string, any> ? TContext[`joinTypes`] : {}) & { [K in keyof TNewSchema & string]: TJoinType; }; result: TContext[`result`]; }; export type ApplyJoinOptionalityToMergedSchema<TExistingSchema extends ContextSchema, TNewSchema extends ContextSchema, TJoinType extends `inner` | `left` | `right` | `full` | `outer` | `cross`, TFromSourceName extends string> = { [K in keyof TExistingSchema]: K extends TFromSourceName ? TJoinType extends `right` | `full` ? TExistingSchema[K] | undefined : TExistingSchema[K] : TExistingSchema[K]; } & { [K in keyof TNewSchema]: TJoinType extends `left` | `full` ? // New table becomes optional for left and full joins TNewSchema[K] | undefined : TNewSchema[K]; }; export type GetResult<TContext extends Context> = Prettify<TContext[`result`] extends object ? TContext[`result`] : TContext[`hasJoins`] extends true ? TContext[`schema`] : TContext[`schema`][TContext[`fromSourceName`]]>; export type ApplyJoinOptionalityToSchema<TSchema extends ContextSchema, TJoinTypes extends Record<string, string>, TFromSourceName extends string> = { [K in keyof TSchema]: K extends TFromSourceName ? HasJoinType<TJoinTypes, `right` | `full`> extends true ? TSchema[K] | undefined : TSchema[K] : K extends keyof TJoinTypes ? TJoinTypes[K] extends `left` | `full` ? TSchema[K] | undefined : IsTableMadeOptionalBySubsequentJoins<K, TJoinTypes, TFromSourceName> extends true ? TSchema[K] | undefined : TSchema[K] : TSchema[K]; }; type IsTableMadeOptionalBySubsequentJoins<TTableAlias extends string | number | symbol, TJoinTypes extends Record<string, string>, TFromSourceName extends string> = TTableAlias extends TFromSourceName ? HasJoinType<TJoinTypes, `right` | `full`> : false; export type HasJoinType<TJoinTypes extends Record<string, string>, TTargetTypes extends string> = true extends { [K in keyof TJoinTypes]: TJoinTypes[K] extends TTargetTypes ? true : false; }[keyof TJoinTypes] ? true : false; export type MergeContext<TContext extends Context, TNewSchema extends ContextSchema> = MergeContextWithJoinType<TContext, TNewSchema, `left`>; export type WithResult<TContext extends Context, TResult> = Prettify<Omit<TContext, `result`> & { result: Prettify<TResult>; }>; export type Prettify<T> = { [K in keyof T]: T[K]; } & {}; export {};