UNPKG

groq-builder

Version:

A **schema-aware**, strongly-typed GROQ query builder. It enables you to build GROQ queries using **auto-completion**, **type-checking**, and **runtime validation**.

54 lines (53 loc) 4.21 kB
import { GroqBuilder } from "../groq-builder"; import { Empty, IsAny, LiteralUnion, Simplify, SimplifyDeep, StringKeys, TypeMismatchError, UndefinedToNull, ValueOf } from "../types/utils"; import { FragmentInputTypeTag, IGroqBuilder, Parser, ParserWithWidenedInput } from "../types/public-types"; import { Path, PathEntries, PathValue } from "../types/path-types"; import { DeepRequired } from "../types/deep-required"; import { QueryConfig } from "../types/schema-types"; import { ConditionalKey, ExtractConditionalProjectionTypes } from "./conditional-types"; export type ProjectionKey<TResultItem> = IsAny<TResultItem> extends true ? string : ProjectionKeyImpl<Simplify<PathEntries<DeepRequired<TResultItem>>>>; type ProjectionKeyImpl<Entries> = ValueOf<{ [Key in keyof Entries]: Entries[Key] extends Array<any> ? `${StringKeys<Key>}[]` | Key : Key; }>; export type ProjectionKeyValue<TResultItem, TKey> = UndefinedToNull<PathValue<TResultItem, Extract<TKey extends `${infer TPath}[]` ? TPath : TKey, Path<TResultItem>>>>; export type ProjectionMap<TResultItem> = { [P in LiteralUnion<keyof TResultItem, string>]?: ProjectionFieldConfig<TResultItem, P extends keyof TResultItem ? UndefinedToNull<TResultItem[P]> : any>; } & { "..."?: true | Parser; }; export type ProjectionMapOrCallback<TResultItem, TQueryConfig extends QueryConfig> = ProjectionMap<TResultItem> | ((q: GroqBuilder<TResultItem, TQueryConfig>) => ProjectionMap<TResultItem>); export type ProjectionFieldConfig<TResultItem, TFieldType> = true | ProjectionKey<TResultItem> | ParserWithWidenedInput<TFieldType> | readonly [ProjectionKey<TResultItem>, ParserWithWidenedInput<TFieldType>] | IGroqBuilder; export type ExtractProjectionResult<TResultItem, TProjectionMap> = (TProjectionMap extends { "...": true; } ? TResultItem : Empty) & (TProjectionMap extends { "...": Parser<TResultItem, infer TOutput>; } ? TOutput : Empty) & ExtractConditionalProjectionTypes<TProjectionMap> & ExtractProjectionResultFields<TResultItem, Omit<TProjectionMap, "..." | typeof FragmentInputTypeTag | ConditionalKey<string>>>; type ExtractProjectionResultFields<TResultItem, TProjectionMap> = { [P in keyof TProjectionMap]: TProjectionMap[P] extends IGroqBuilder<infer TValue> ? TValue : TProjectionMap[P] extends boolean ? P extends keyof TResultItem ? UndefinedToNull<TResultItem[P]> : TypeMismatchError<{ error: `⛔️ 'true' can only be used for known properties ⛔️`; expected: keyof TResultItem; actual: P; }> : TProjectionMap[P] extends string ? TProjectionMap[P] extends ProjectionKey<TResultItem> ? ProjectionKeyValue<TResultItem, TProjectionMap[P]> : TypeMismatchError<{ error: `⛔️ Naked projections must be known properties ⛔️`; expected: SimplifyDeep<ProjectionKey<TResultItem>>; actual: TProjectionMap[P]; }> : TProjectionMap[P] extends readonly [infer TKey, infer TParser] ? TKey extends ProjectionKey<TResultItem> ? TParser extends Parser<infer TParserInput, infer TParserOutput> ? ValidateParserInput<ProjectionKeyValue<TResultItem, TKey>, TParserInput, TParserOutput> : TypeMismatchError<{ error: `⛔️ Naked projections must be known properties ⛔️`; expected: SimplifyDeep<ProjectionKey<TResultItem>>; actual: TKey; }> : TypeMismatchError<{ error: `⛔️ Naked projections must be known properties ⛔️`; expected: SimplifyDeep<ProjectionKey<TResultItem>>; actual: TKey; }> : TProjectionMap[P] extends Parser<infer TParserInput, infer TParserOutput> ? P extends keyof TResultItem ? ValidateParserInput<UndefinedToNull<TResultItem[P]>, TParserInput, TParserOutput> : TypeMismatchError<{ error: `⛔️ Parser can only be used with known properties ⛔️`; expected: keyof TResultItem; actual: P; }> : never; }; export type ValidateParserInput<TIncomingValue, TParserInput, TParserOutput> = TIncomingValue extends TParserInput ? TParserOutput : IsAny<TIncomingValue> extends true ? TParserOutput : TypeMismatchError<{ error: `⛔️ Parser expects a different input type ⛔️`; expected: TParserInput; actual: TIncomingValue; }>; export {};