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**.
55 lines (54 loc) • 3.4 kB
TypeScript
import { ExtractProjectionResult, ProjectionMap, ProjectionMapOrCallback } from "./projection-types";
import { Empty, IntersectionOfValues, Simplify, ValueOf } from "../types/utils";
import { ExtractDocumentTypes, QueryConfig } from "../types/schema-types";
import { GroqBuilder } from "../groq-builder";
import { IGroqBuilder, InferResultType } from "../types/public-types";
import { Expressions } from "../types/groq-expressions";
export type ConditionalProjectionMap<TResultItem, TQueryConfig extends QueryConfig> = Partial<Record<Expressions.AnyConditional<TResultItem, TQueryConfig>, ProjectionMap<TResultItem> | ((q: GroqBuilder<TResultItem, TQueryConfig>) => ProjectionMap<TResultItem>)>>;
export type ExtractConditionalProjectionResults<TResultItem, TConditionalProjectionMap extends ConditionalProjectionMap<any, any>, TConfig extends ConditionalConfig> = SpreadableConditionals<TConfig["key"], (TConfig["isExhaustive"] extends true ? never : Empty) | ValueOf<{
[P in keyof TConditionalProjectionMap]: ExtractProjectionResult<TResultItem, TConditionalProjectionMap[P]>;
}>>;
export type ExtractConditionalProjectionTypes<TProjectionMap> = Simplify<IntersectionOfValues<{
[P in Extract<keyof TProjectionMap, ConditionalKey<string>>]: InferResultType<Extract<TProjectionMap[P], IGroqBuilder>>;
}>>;
export type ConditionalByTypeProjectionMap<TResultItem, TQueryConfig extends QueryConfig> = {
[_type in ExtractDocumentTypes<TResultItem>]?: ProjectionMapOrCallback<Extract<TResultItem, {
_type: _type;
}>, TQueryConfig>;
};
export type ExtractConditionalByTypeProjectionResults<TResultItem, TConditionalByTypeProjectionMap extends ConditionalByTypeProjectionMap<any, any>, TConfig extends ConditionalConfig> = SpreadableConditionals<TConfig["key"], (TConfig["isExhaustive"] extends true ? never : {
/**
* When using conditionalByType,
* this _type is automatically added to the query.
*/
_type: Exclude<ExtractDocumentTypes<TResultItem>, keyof TConditionalByTypeProjectionMap>;
}) | ValueOf<{
[_type in keyof TConditionalByTypeProjectionMap]: {
/**
* When using conditionalByType,
* this _type is automatically added to the query.
*/
_type: _type;
} & ExtractProjectionResult<Extract<TResultItem, {
_type: _type;
}>, TConditionalByTypeProjectionMap[_type] extends (q: any) => infer TProjectionMap ? TProjectionMap : TConditionalByTypeProjectionMap[_type]>;
}>>;
export type ConditionalKey<TKey extends string> = `[CONDITIONAL] ${TKey}`;
export declare function isConditional(key: string): key is ConditionalKey<string>;
export type SpreadableConditionals<TKey extends string, ConditionalResultType> = {
[UniqueConditionalKey in ConditionalKey<TKey>]: IGroqBuilder<ConditionalResultType>;
};
export type ConditionalConfig<TKey extends string = string, TIsExhaustive extends boolean = boolean> = {
/**
* If using multiple conditions in a single projection,
* each condition must have a unique key.
* This key is not used in the resulting query, and can be anything.
*/
key: TKey;
/**
* If the conditional statements cover all possible scenarios,
* then setting `isExhaustive` to `true` will ensure stronger types,
* and will throw runtime errors if none of the conditions are satisfied.
*/
isExhaustive: TIsExhaustive;
};