@sanity-typed/groq
Version:
Infer GROQ Result Types from GROQ strings
920 lines (918 loc) • 63.7 kB
TypeScript
import { ClientConfig } from '@sanity/client';
import { GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Position } from 'geojson';
import { ExprNode, AccessAttributeNode, AccessElementNode, ArrayNode, ArrayElementNode, ArrayCoerceNode, AndNode, OrNode, SelectAlternativeNode, OpCallNode, ContextNode, DerefNode, EverythingNode, FilterNode, FuncCallNode, DateTime, Path, InRangeNode, MapNode, NegNode, NotNode, ObjectNode, ObjectAttributeNode, ObjectAttributeValueNode, ObjectSplatNode, ParameterNode, ParentNode, GroupNode, PipeFuncCallNode, PosNode, ProjectionNode, SelectNode, SelectorNode, SliceNode, ThisNode, ValueNode, GroqPipeFunction, AscNode, DescNode, GroqFunction } from 'groq-js';
import { IsNumericLiteral, SetOptional, IsNever, Join, IsUnknown, Split, Simplify as Simplify$1, UnionToIntersection } from 'type-fest';
import { PortableTextBlock } from '@portabletext-typed/types';
import { ReferenceValue, referenced } from '@sanity-typed/types';
type IsPlainObject<T> = T extends any[] ? false : T extends object ? true : false;
type TupleOfLength<T, Min extends number = number, Max extends number = number, Result extends T[] = []> = Result["length"] extends Min ? IsNumericLiteral<Max> extends false ? [...Result, ...T[]] : Result["length"] extends Max ? Result : Result | TupleOfLength<T, [
T,
...Result
]["length"] & number, Max, [
T,
...Result
]> : TupleOfLength<T, Min, Max, [T, ...Result]>;
type Simplify<AnyType> = Simplify$1<AnyType> extends AnyType ? Simplify$1<AnyType> : AnyType;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Query-context
*/
interface Context<Dataset extends any[], DeltaElement extends Dataset[number]> {
client: ClientConfig;
dataset: Dataset;
delta: {
after: DeltaElement | null;
before: DeltaElement | null;
};
identity: string;
parameters: {
[param: string]: any;
};
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Scope
*/
interface Scope<TContext extends Context<any[], any>> {
context: TContext;
parent: Scope<TContext> | null;
this: any;
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#NewNestedScope()
*/
interface NestedScope<Value, TScope extends Scope<Context<any[], any>>> {
context: TScope["context"];
parent: TScope;
this: Value;
}
type EscapedDoubleQuote = "__ESCAPED__DOUBLE__QUOTE___";
type EscapedSingleQuote = "__ESCAPED__SINGLE__QUOTE___";
type PrefixWithSpace<TString extends string> = `__PREFIX__WITH_SPACE__${TString}___`;
type SurroundWithSpace<TString extends string> = `__SURROUNDED_WITH_SPACES__${TString}___`;
type AddPlaceholders<TString extends string> = TString extends `${infer TLeft} in ${infer TRight}` ? `${AddPlaceholders<TLeft>}${SurroundWithSpace<"in">}${AddPlaceholders<TRight>}` : TString extends `${infer TLeft} match ${infer TRight}` ? `${AddPlaceholders<TLeft>}${SurroundWithSpace<"match">}${AddPlaceholders<TRight>}` : TString extends `${infer TLeft} asc${infer TRight}` ? `${AddPlaceholders<TLeft>}${PrefixWithSpace<"asc">}${AddPlaceholders<TRight>}` : TString extends `${infer TLeft} desc${infer TRight}` ? `${AddPlaceholders<TLeft>}${PrefixWithSpace<"desc">}${AddPlaceholders<TRight>}` : TString extends `${infer TLeft}\\${infer TRight}` ? `${AddPlaceholders<TLeft>}${TRight extends `${infer TRightHead}${infer TRightRest}` ? `${TRightHead extends '"' ? EscapedDoubleQuote : TRightHead extends "'" ? EscapedSingleQuote : `\\${TRightHead}`}${AddPlaceholders<TRightRest>}` : `\\${TRight}`}` : TString;
type RemovePlaceholders<TString extends string> = TString extends `${infer TLeft}${SurroundWithSpace<infer TOp>}${infer TRight}` ? `${RemovePlaceholders<TLeft>} ${TOp} ${RemovePlaceholders<TRight>}` : TString extends `${infer TLeft}${PrefixWithSpace<infer TOp>}${infer TRight}` ? `${RemovePlaceholders<TLeft>} ${TOp}${RemovePlaceholders<TRight>}` : TString extends `${infer TLeft}${EscapedDoubleQuote}${infer TRight}` ? `${RemovePlaceholders<TLeft>}\\"${RemovePlaceholders<TRight>}` : TString extends `${infer TLeft}${EscapedSingleQuote}${infer TRight}` ? `${RemovePlaceholders<TLeft>}\\'${RemovePlaceholders<TRight>}` : TString;
type RemoveWhitespace<TExpression extends string> = TExpression extends `${infer TLeft}${'"'}${infer TQuoted}${'"'}${infer TRight}` ? `${RemoveWhitespace<TLeft>}${'"'}${TQuoted}${'"'}${RemoveWhitespace<TRight>}` : TExpression extends `${infer TLeft}${"'"}${infer TQuoted}${"'"}${infer TRight}` ? `${RemoveWhitespace<TLeft>}${"'"}${TQuoted}${"'"}${RemoveWhitespace<TRight>}` : TExpression extends `${infer TLeft}${"\n"}${infer TRight}` ? `${RemoveWhitespace<TLeft>}${RemoveWhitespace<TRight>}` : TExpression extends `${infer TLeft}${"\t"}${infer TRight}` ? `${RemoveWhitespace<TLeft>}${RemoveWhitespace<TRight>}` : TExpression extends `${infer TLeft}${" "}${infer TRight}` ? `${RemoveWhitespace<TLeft>}${RemoveWhitespace<TRight>}` : TExpression extends `${infer TLeft}${" "}${infer TRight}` ? `${RemoveWhitespace<TLeft>}${RemoveWhitespace<TRight>}` : TExpression;
type CleanGROQ<TExpression extends string> = RemovePlaceholders<RemoveWhitespace<AddPlaceholders<TExpression>>>;
type ParseInner<TExpression extends string> = Expression<TExpression>;
type Parse<TExpression extends string> = ParseInner<CleanGROQ<TExpression>>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Evaluate()
*/
type Evaluate<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = EvaluateExpression<TNode, TScope>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Boolean
* @link https://spec.groq.dev/GROQ-1.revision1/#Null
* @link https://spec.groq.dev/GROQ-1.revision1/#Number
*/
type Primitives<TExpression extends string> = TExpression extends `+${number}` ? never : TExpression extends `-${number}` ? never : TExpression extends `.${string}` ? never : TExpression extends `${infer TValue extends boolean | number | null}` ? {
type: "Value";
value: TValue;
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#SingleEscapeSequence
*/
type SingleEscapeSequence = '"' | "'" | "/" | "\\" | "b" | "f" | "n" | "r" | "t";
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EscapeSequence
*/
type EscapeSequence = SingleEscapeSequence;
type ReplaceInString<TString extends string, TReplace extends string, TReplaceWith extends string = ""> = TString extends `${infer TLeft}${TReplace}${infer TRight}` ? `${TLeft}${TReplaceWith}${ReplaceInString<TRight, TReplace, TReplaceWith>}` : TString;
type IfStringHas<TString extends string, THas extends string> = TString extends `${string}${THas}${string}` ? true : false;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#String
*/
type StringType<TExpression extends string> = (TExpression extends `'${infer TString}'` ? IfStringHas<ReplaceInString<TString, `\\${EscapeSequence}`>, "'"> extends true ? never : {
type: "Value";
value: ReplaceInString<TString, `\\'`, // TODO https://github.com/saiichihashimoto/sanity-typed/issues/331
"'">;
} : never) | (TExpression extends `"${infer TString}"` ? IfStringHas<ReplaceInString<TString, `\\${EscapeSequence}`>, '"'> extends true ? never : {
type: "Value";
value: ReplaceInString<TString, `\\"`, // TODO https://github.com/saiichihashimoto/sanity-typed/issues/331
'"'>;
} : never);
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ArrayElement
*/
type ArrayElement<TArrayElement extends string> = TArrayElement extends `...${infer TExpression}` ? ParseInner<TExpression> extends never ? never : {
isSplat: true;
type: "ArrayElement";
value: ParseInner<TExpression>;
} : ParseInner<TArrayElement> extends never ? never : {
isSplat: false;
type: "ArrayElement";
value: ParseInner<TArrayElement>;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ArrayElements
*/
type ArrayElements<TArrayElements extends string, _Prefix extends string = ""> = `${_Prefix}${TArrayElements}` extends "" ? [] : (ArrayElement<`${_Prefix}${TArrayElements}`> extends never ? never : [ArrayElement<`${_Prefix}${TArrayElements}`>]) | (TArrayElements extends `${infer TArrayElement},${infer TRemainingElements}` ? ArrayElements<TRemainingElements, `${_Prefix}${TArrayElement},`> | (ArrayElement<`${_Prefix}${TArrayElement}`> extends never ? never : ArrayElements<TRemainingElements> extends never ? never : [
ArrayElement<`${_Prefix}${TArrayElement}`>,
...ArrayElements<TRemainingElements>
]) : never);
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Array
*/
type ArrayType<TExpression extends string> = TExpression extends `[${infer TArrayElements}]` ? ArrayElements<TArrayElements> extends never ? never : {
elements: ArrayElements<TArrayElements>;
type: "Array";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#DetermineName()
*/
type DetermineName<TNode extends ExprNode> = Extract<TNode, AccessAttributeNode>["name"] | (TNode extends AccessElementNode | ArrayCoerceNode | DerefNode | FilterNode | MapNode | ProjectionNode | SliceNode ? DetermineName<TNode["base"]> : never);
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ObjectAttribute
*/
type ObjectAttribute<TObjectAttribute extends string> = TObjectAttribute extends `...${infer TExpression}` ? TExpression extends "" ? {
type: "ObjectSplat";
value: {
type: "This";
};
} : ParseInner<TExpression> extends never ? never : {
type: "ObjectSplat";
value: ParseInner<TExpression>;
} : TObjectAttribute extends `${infer TName}:${infer TExpression}` ? StringType<TName> extends never ? never : ParseInner<TExpression> extends never ? never : {
name: StringType<TName>["value"];
type: "ObjectAttributeValue";
value: ParseInner<TExpression>;
} : ParseInner<TObjectAttribute> extends never ? never : DetermineName<ParseInner<TObjectAttribute>> extends never ? never : {
name: DetermineName<ParseInner<TObjectAttribute>>;
type: "ObjectAttributeValue";
value: ParseInner<TObjectAttribute>;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ObjectAttributes
*/
type ObjectAttributes<TObjectAttributes extends string, _Prefix extends string = ""> = `${_Prefix}${TObjectAttributes}` extends "" ? [] : (ObjectAttribute<`${_Prefix}${TObjectAttributes}`> extends never ? never : [ObjectAttribute<`${_Prefix}${TObjectAttributes}`>]) | (TObjectAttributes extends `${infer TObjectAttribute},${infer TRemainingAttributes}` ? ObjectAttributes<TRemainingAttributes, `${_Prefix}${TObjectAttribute},`> | (ObjectAttribute<`${_Prefix}${TObjectAttribute}`> extends never ? never : ObjectAttributes<TRemainingAttributes> extends never ? never : [
ObjectAttribute<`${_Prefix}${TObjectAttribute}`>,
...ObjectAttributes<TRemainingAttributes>
]) : never);
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Object
*/
type ObjectType<TExpression extends string> = TExpression extends `{${infer TObjectAttributes}}` ? ObjectAttributes<TObjectAttributes> extends never ? never : {
attributes: ObjectAttributes<TObjectAttributes>;
type: "Object";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Literal
*/
type Literal<TExpression extends string> = ArrayType<TExpression> | ObjectType<TExpression> | Primitives<TExpression> | StringType<TExpression>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#This
*/
type This<TExpression extends string> = TExpression extends "@" ? {
type: "This";
} : never;
type AlphaLower = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
type AlphaUpper = Uppercase<AlphaLower>;
type Alpha = AlphaLower | AlphaUpper;
type Numeric = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type IdentifierRest<TIdentifierRest extends string> = TIdentifierRest extends "" ? true : TIdentifierRest extends `${Alpha | Numeric | "_"}${infer TIdentifierRestInner}` ? IdentifierRest<TIdentifierRestInner> : false;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Identifier
*/
type Identifier<TIdentifier extends string> = TIdentifier extends `${Alpha | "_"}${infer TIdentifierRest}` ? IdentifierRest<TIdentifierRest> extends true ? TIdentifier : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ThisAttribute
*/
type ThisAttribute<TExpression extends string> = TExpression extends `${boolean | number | null}` ? never : Identifier<TExpression> extends never ? never : {
name: TExpression;
type: "AccessAttribute";
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Everything
*/
type Everything<TExpression extends string> = TExpression extends "*" ? {
type: "Everything";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Parent
*/
type Parent<TExpression extends string, Levels extends null[] = [null]> = TExpression extends "^" ? {
n: Levels["length"];
type: "Parent";
} : TExpression extends `^.${infer TParents}` ? Parent<TParents, [null, ...Levels]> : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-geo-type
*/
type Geo = GeometryCollection | LineString | MultiLineString | MultiPoint | MultiPolygon | Point | Polygon | Position;
declare const ArbitrarySelectorValue: unique symbol;
interface Functions<TArgs extends any[], TScope extends Scope<Context<any[], any>>> {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Array-namespace
*/
array: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#array_compact()
*/
compact: TArgs extends [infer TArr] ? TArr extends any[] ? TArr extends null[] | [] ? [] : TArr extends [infer THead, ...infer TTail] ? THead extends null ? Functions<[TTail], TScope>["array"]["compact"] : [THead, ...Functions<[TTail], TScope>["array"]["compact"]] : TArr extends (infer TElement)[] ? NonNullable<TElement>[] : never : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#array_join()
*/
join: TArgs extends [infer TArr, infer TSep] ? TArr extends any[] ? TSep extends string ? Functions<[TArr[number]], TScope>["global"]["string"] extends string ? Join<TArr, TSep> : null : null : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#array_unique()
*/
unique: TArgs extends [infer TArr] ? TArr extends any[] ? TArr extends null[] | [] ? [] : TArr extends [...infer TInitial, infer TLast] ? TLast extends boolean | number | string ? TLast extends Functions<[
TInitial
], TScope>["array"]["unique"][number] ? Functions<[TInitial], TScope>["array"]["unique"] : [...Functions<[TInitial], TScope>["array"]["unique"], TLast] : [...Functions<[TInitial], TScope>["array"]["unique"], TLast] : TArr : null : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Date-time-namespace
*/
dateTime: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#dateTime_now()
*/
now: TArgs extends [] ? DateTime : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Delta-namespace
*/
delta: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#delta_changedAny()
*/
changedAny: TArgs extends [infer TSelector] ? TSelector extends typeof ArbitrarySelectorValue ? TScope extends {
context: {
delta: {
after: infer TAfter;
before: infer TBefore;
};
};
} ? TBefore extends null ? never : TAfter extends null ? never : Functions<[
TBefore,
TAfter,
TSelector
], TScope>["diff"]["changedAny"] : never : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#delta_changedOnly()
*/
changedOnly: TArgs extends [infer TSelector] ? TSelector extends typeof ArbitrarySelectorValue ? TScope extends {
context: {
delta: {
after: infer TAfter;
before: infer TBefore;
};
};
} ? TBefore extends null ? never : TAfter extends null ? never : Functions<[
TBefore,
TAfter,
TSelector
], TScope>["diff"]["changedOnly"] : never : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#delta_operation()
*/
operation: TArgs extends [] ? TScope extends {
context: {
delta: {
after: infer TAfter;
before: infer TBefore;
};
};
} ? TBefore extends null ? TAfter extends null ? null : "create" : TAfter extends null ? "delete" : "update" : never : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Diff-namespace
*/
diff: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#diff_changedAny()
*/
changedAny: TArgs extends [any, any, infer TSelector] ? TSelector extends typeof ArbitrarySelectorValue ? boolean : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#diff_changedOnly()
*/
changedOnly: TArgs extends [any, any, infer TSelector] ? TSelector extends typeof ArbitrarySelectorValue ? boolean : never : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Geography-Extension
*/
geo: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#geo_contains()
*/
contains: TArgs extends [infer TFirst, infer TSecond] ? TFirst extends Geo ? TSecond extends Geo ? boolean : null : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#geo_distance()
*/
distance: TArgs extends [infer TFirst, infer TSecond] ? TFirst extends Point ? TSecond extends Point ? number : null : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#geo_intersects()
*/
intersects: TArgs extends [infer TFirst, infer TSecond] ? TFirst extends Geo ? TSecond extends Geo ? boolean : null : null : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Global-namespace
*/
global: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#boost()
*/
boost: never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_coalesce()
*/
coalesce: TArgs extends [] ? null : TArgs extends [infer THead, ...infer TTail] ? null extends THead ? Functions<TTail, TScope>["global"]["coalesce"] | NonNullable<THead> : THead : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_count()
*/
count: TArgs extends [infer TBase] ? TBase extends any[] ? TBase["length"] : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_dateTime()
*/
dateTime: TArgs extends [infer TBase] ? TBase extends DateTime | string ? DateTime : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_defined()
*/
defined: TArgs extends [infer TBase] ? TBase extends null ? false : true : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_geo()
*/
geo: TArgs extends [infer TBase] ? TBase extends Geo ? TBase : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-global-identity-
*/
identity: TArgs extends [] ? TScope extends {
context: {
identity: infer TIdentity;
};
} ? TIdentity : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_length()
*/
length: TArgs extends [infer TBase] ? TBase extends any[] | string ? TBase["length"] : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_lower()
*/
lower: TArgs extends [infer TValue] ? TValue extends string ? Lowercase<TValue> : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_now()
*/
now: TArgs extends [] ? string : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-global-path-
* @link https://www.sanity.io/docs/groq-functions#0ecd1b7eac78
*/
path: TArgs extends (infer TBase)[] ? TBase extends string ? Path : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_pt()
*/
pt: TArgs extends [infer TBase] ? TBase extends PortableTextBlock<any, any, any, any, any> | PortableTextBlock<any, any, any, any, any>[] ? TBase : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_references()
*/
references: TArgs extends (infer TElement)[] ? Extract<Exclude<TElement, []>, string[] | string> extends never ? false : boolean : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_round()
*/
round: TArgs extends [infer TNum, infer TPrecision] | [infer TNum] ? TNum extends number ? IsUnknown<TPrecision> extends true ? number : TPrecision extends number ? number : null : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_string()
*/
string: TArgs extends [infer TVal] ? TVal extends boolean | number | string ? `${TVal}` : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_upper()
*/
upper: TArgs extends [infer TValue] ? TValue extends string ? Uppercase<TValue> : null : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Math-namespace
*/
math: {
[mathFn in "avg" | "max" | "min" | "sum"]: TArgs extends [infer TArr] ? TArr extends null[] | [] ? mathFn extends "sum" ? 0 : null : TArr extends (number | null)[] ? mathFn extends "max" | "min" ? Exclude<TArr[number], null> : number : null : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-Portable-Text-Extension
*/
pt: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#pt_text()
*/
text: TArgs extends (infer TBase)[] ? TBase extends PortableTextBlock<any, any, any, any, any> | PortableTextBlock<any, any, any, any, any>[] ? string : null : never;
};
/**
* @link https://www.sanity.io/docs/groq-functions#61e2649fc0d8
*/
sanity: {
/**
* @link https://www.sanity.io/docs/groq-functions#48b1e793d6b9
*/
dataset: TArgs extends [] ? TScope["context"]["client"]["dataset"] : never;
/**
* @link https://www.sanity.io/docs/groq-functions#b89053823742
*/
projectId: TArgs extends [] ? TScope["context"]["client"]["projectId"] : never;
};
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#sec-String-namespace
*/
string: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#string_split()
*/
split: TArgs extends [infer TStr, infer TSep] ? TStr extends string ? TSep extends string ? Split<TStr, TSep> : null : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#string_startsWith()
*/
startsWith: TArgs extends [infer TStr, infer TPrefix] ? TStr extends string ? TPrefix extends string ? TStr extends `${TPrefix}${string}` ? true : false : null : null : never;
};
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Asc
*/
type Asc<TExpression extends string> = TExpression extends `${infer TBase} asc` ? ParseInner<TBase> extends never ? never : {
base: ParseInner<TBase>;
type: "Asc";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Desc
*/
type Desc<TExpression extends string> = TExpression extends `${infer TBase} desc` ? ParseInner<TBase> extends never ? never : {
base: ParseInner<TBase>;
type: "Desc";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Pair
*/
type Pair<TExpression extends string> = TExpression extends `${infer TCondition}=>${infer TValue}` ? ParseInner<TCondition> extends never ? never : ParseInner<TValue> extends never ? never : {
condition: ParseInner<TCondition>;
type: "SelectAlternative";
value: ParseInner<TValue>;
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ConstantEvaluate()
*/
type ConstantEvaluate<TNode extends ExprNode> = Evaluate<TNode, never>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#SelectorTuple
*/
type SelectorTupleInner<TExpression extends string> = TExpression extends `${infer TFirst},${infer TRest}` ? Selector<TFirst> extends never ? never : // eslint-disable-next-line @typescript-eslint/no-use-before-define -- Recursion
Selector<TRest> | SelectorTupleInner<TRest> : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Selector
*/
type Selector<TExpression extends string> = (TExpression extends `(${infer TInnerExpression})` ? Selector<TInnerExpression> | SelectorTupleInner<TInnerExpression> : never) | (TExpression extends `${infer TSelector}.${infer TIdentifier}` ? Selector<TSelector> extends never ? never : Identifier<TIdentifier> extends never ? TIdentifier extends `(${infer TInnerExpression})` ? Selector<TInnerExpression> | SelectorTupleInner<TInnerExpression> : never : {
type: "Selector";
} : never) | (TExpression extends `${infer TSelector}[${infer TBracketExpression}]` ? Selector<TSelector> extends never ? never : TBracketExpression extends "" ? {
type: "Selector";
} : ConstantEvaluate<ParseInner<TBracketExpression>> extends never ? never : ConstantEvaluate<ParseInner<TBracketExpression>> extends number ? never : {
type: "Selector";
} : never) | (ThisAttribute<TExpression> extends never ? never : {
type: "Selector";
});
interface FuncArgCustomParse<TExpression extends string, TFuncLastArg extends boolean> {
delta: {
changedAny: TFuncLastArg extends true ? Selector<TExpression> : ParseInner<TExpression>;
changedOnly: TFuncLastArg extends true ? Selector<TExpression> : ParseInner<TExpression>;
};
diff: {
changedAny: TFuncLastArg extends true ? Selector<TExpression> : ParseInner<TExpression>;
changedOnly: TFuncLastArg extends true ? Selector<TExpression> : ParseInner<TExpression>;
};
global: {
order: Asc<TExpression> | Desc<TExpression> | ParseInner<TExpression>;
select: Pair<TExpression> | (TFuncLastArg extends true ? ParseInner<TExpression> : never);
};
}
type FuncArgParse<TExpression extends string, TFuncNamespace extends string, TFuncName extends string, TFuncLastArg extends boolean = false> = TFuncNamespace extends keyof FuncArgCustomParse<TExpression, TFuncLastArg> ? TFuncName extends keyof FuncArgCustomParse<TExpression, TFuncLastArg>[TFuncNamespace] ? FuncArgCustomParse<TExpression, TFuncLastArg>[TFuncNamespace][TFuncName] : ParseInner<TExpression> : ParseInner<TExpression>;
type FuncArgs<TArgs extends string, TFuncNamespace extends string, TFuncName extends string, _Prefix extends string = ""> = `${_Prefix}${TArgs}` extends "" ? [] : (FuncArgParse<`${_Prefix}${TArgs}`, TFuncNamespace, TFuncName, true> extends never ? never : [
FuncArgParse<`${_Prefix}${TArgs}`, TFuncNamespace, TFuncName, true>
]) | (TArgs extends `${infer TFuncArg},${infer TFuncArgs}` ? FuncArgs<TFuncArgs, TFuncNamespace, TFuncName, `${_Prefix}${TFuncArg},`> | (FuncArgParse<`${_Prefix}${TFuncArg}`, TFuncNamespace, TFuncName> extends never ? never : FuncArgs<TFuncArgs, TFuncNamespace, TFuncName> extends never ? never : [
FuncArgParse<`${_Prefix}${TFuncArg}`, TFuncNamespace, TFuncName>,
...FuncArgs<TFuncArgs, TFuncNamespace, TFuncName>
]) : never);
type FunctionsToOtherNodes<TFuncName extends string, TFuncArgs extends any[]> = TFuncName extends "after" | "before" ? {
key: TFuncName;
type: "Context";
} : TFuncName extends "select" ? TFuncArgs extends [
...infer TAlternatives extends SelectAlternativeNode[],
infer TFallback extends ExprNode
] ? {
alternatives: TAlternatives;
fallback: TFallback;
type: "Select";
} : TFuncArgs extends infer TAlternatives extends SelectAlternativeNode[] ? {
alternatives: TAlternatives;
type: "Select";
} : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#FuncCall
*/
type FuncCall<TExpression extends string> = TExpression extends `${infer TFuncFullName}(${infer TFuncCallArgs})` ? TFuncFullName extends `${infer TFuncNamespace}::${infer TFuncName}` ? TFuncNamespace extends keyof Functions<any, any> ? FuncArgs<TFuncCallArgs, TFuncNamespace, TFuncName> extends never ? never : TFuncName extends keyof Functions<any, any>[TFuncNamespace] ? {
args: Simplify<FuncArgs<TFuncCallArgs, TFuncNamespace, TFuncName>>;
func: GroqFunction;
name: TFuncName;
namespace: TFuncNamespace;
type: "FuncCall";
} : FunctionsToOtherNodes<TFuncName, Simplify<FuncArgs<TFuncCallArgs, TFuncNamespace, TFuncName>>> : never : FuncArgs<TFuncCallArgs, "global", TFuncFullName> extends never ? never : TFuncFullName extends keyof Functions<any, any>["global"] ? {
args: Simplify<FuncArgs<TFuncCallArgs, "global", TFuncFullName>>;
func: GroqFunction;
name: TFuncFullName;
namespace: "global";
type: "FuncCall";
} : FunctionsToOtherNodes<TFuncFullName, Simplify<FuncArgs<TFuncCallArgs, "global", TFuncFullName>>> : never;
/**
* @link https://www.sanity.io/docs/groq-parameters
*/
type Parameter<TExpression extends string> = TExpression extends `$${infer TIdentifier}` ? Identifier<TIdentifier> extends never ? never : {
name: TIdentifier;
type: "Parameter";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#SimpleExpression
*/
type SimpleExpression<TExpression extends string> = Everything<TExpression> | FuncCall<TExpression> | Parameter<TExpression> | Parent<TExpression> | This<TExpression> | ThisAttribute<TExpression>;
type Level1 = SelectAlternativeNode;
type Level2 = Level1 | OrNode;
type Level3 = AndNode | Level2;
type Level4 = AscNode | DescNode | Level3 | (OpCallNode & {
op: "!=" | "<" | "<=" | "==" | ">" | ">=" | "in" | "match";
});
type Level5 = Level4;
type Level6 = Level5 | (OpCallNode & {
op: "-" | "+";
});
type Level7 = Level6 | (OpCallNode & {
op: "*" | "/" | "%";
});
type Level8 = Level7 | NegNode;
type Level9 = Level8 | (OpCallNode & {
op: "**";
});
type Level10 = Level9 | NotNode | PosNode;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Parenthesis
*/
type Parenthesis<TExpression extends string> = TExpression extends `(${infer TInnerExpression})` ? ParseInner<TInnerExpression> extends never ? never : {
base: ParseInner<TInnerExpression>;
type: "Group";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#ArrayPostfix
*/
type ArrayPostfix<TExpression extends string> = TExpression extends `${infer TBase}[]` ? Exclude<ParseInner<TBase>, Level10> extends never ? never : {
base: Exclude<ParseInner<TBase>, Level10>;
type: "ArrayCoerce";
} : never;
type KnownArrayNode = ArrayCoerceNode | ArrayNode | EverythingNode | FilterNode | MapNode | PipeFuncCallNode | SliceNode;
type MaybeMapBase<TBase extends ExprNode> = TBase extends never ? never : TBase extends KnownArrayNode ? {
type: "This";
} : TBase;
type MaybeMap<TBase extends ExprNode, TNode extends ExprNode> = TBase extends never ? never : TNode extends never ? never : TBase extends KnownArrayNode ? {
base: TBase;
expr: TNode;
type: "Map";
} : TNode;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Range
*/
type Range<TExpression extends string> = {
[TOp in "..." | ".."]: TExpression extends `${infer TStart}${TOp}${infer TEnd}` ? ParseInner<TStart> extends never ? never : ParseInner<TEnd> extends never ? never : {
isInclusive: TOp extends ".." ? true : false;
left: ParseInner<TStart>;
right: ParseInner<TEnd>;
type: "Range";
} : never;
}["..." | ".."];
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#SquareBracketTraversal
* @link https://spec.groq.dev/GROQ-1.revision1/#AttributeAccess
* @link https://spec.groq.dev/GROQ-1.revision1/#ElementAccess
* @link https://spec.groq.dev/GROQ-1.revision1/#Filter
*/
type SquareBracketTraversal<TExpression extends string, _Prefix extends string = ""> = TExpression extends `${infer TBase}[${infer TBracketExpression}]` ? SquareBracketTraversal<`${TBracketExpression}]`, `${_Prefix}${TBase}[`> | (Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10> extends never ? never : (ConstantEvaluate<ParseInner<TBracketExpression>> extends never ? never : ConstantEvaluate<ParseInner<TBracketExpression>> extends string ? MaybeMap<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>, {
base: MaybeMapBase<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>>;
name: ConstantEvaluate<ParseInner<TBracketExpression>>;
type: "AccessAttribute";
}> : ConstantEvaluate<ParseInner<TBracketExpression>> extends number ? {
base: Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>;
index: ConstantEvaluate<ParseInner<TBracketExpression>>;
type: "AccessElement";
} : {
base: Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>;
expr: ParseInner<TBracketExpression>;
type: "Filter";
}) | (Range<TBracketExpression> extends never ? never : ConstantEvaluate<Range<TBracketExpression>["left"]> extends number ? ConstantEvaluate<Range<TBracketExpression>["right"]> extends number ? {
base: Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>;
isInclusive: Range<TBracketExpression>["isInclusive"];
left: ConstantEvaluate<Range<TBracketExpression>["left"]>;
right: ConstantEvaluate<Range<TBracketExpression>["right"]>;
type: "Slice";
} : never : never)) : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#AttributeAccess
*/
type AttributeAccess<TExpression extends string, _Prefix extends string = ""> = TExpression extends `${infer TBase}.${infer TIdentifier}` ? AttributeAccess<TIdentifier, `${_Prefix}${TBase}.`> | (Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10> extends never ? never : Identifier<TIdentifier> extends never ? never : MaybeMap<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>, {
base: MaybeMapBase<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>>;
name: TIdentifier;
type: "AccessAttribute";
}>) : never;
type ProjectionInner<TBase extends string, TProjection extends string> = Exclude<ParseInner<TBase>, Level10> extends never ? never : ObjectType<`{${TProjection}}`> extends never ? never : MaybeMap<Exclude<ParseInner<TBase>, Level10>, {
base: MaybeMapBase<Exclude<ParseInner<TBase>, Level10>>;
expr: ObjectType<`{${TProjection}}`>;
type: "Projection";
}>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Projection
*/
type Projection<TExpression extends string, _Prefix extends string = ""> = TExpression extends `${infer TBase}|{${infer TProjection}}` ? Projection<`${TProjection}}`, `${_Prefix}${TBase}|{`> | ProjectionInner<`${_Prefix}${TBase}`, TProjection> : TExpression extends `${infer TBase}{${infer TProjection}}` ? Projection<`${TProjection}}`, `${_Prefix}${TBase}{`> | ProjectionInner<`${_Prefix}${TBase}`, TProjection> : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Dereference
*/
type Dereference<TExpression extends string, _Prefix extends string = ""> = TExpression extends `${infer TBase}->${infer TIdentifier}` ? Dereference<TIdentifier, `${_Prefix}${TBase}->`> | (Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10> extends never ? never : TIdentifier extends "" ? MaybeMap<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>, {
base: MaybeMapBase<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>>;
type: "Deref";
}> : Identifier<TIdentifier> extends never ? never : MaybeMap<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>, {
base: {
base: MaybeMapBase<Exclude<ParseInner<`${_Prefix}${TBase}`>, Level10>>;
type: "Deref";
};
name: TIdentifier;
type: "AccessAttribute";
}>) : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#TraversalExpression
*/
type TraversalExpression<TExpression extends string> = ArrayPostfix<TExpression> | AttributeAccess<TExpression> | Dereference<TExpression> | Projection<TExpression> | SquareBracketTraversal<TExpression>;
/**
* Whenever a tuple is reordered, we can't be certain what the types are.
* So each member is a union of all members.
* We also map instead of TArray[number][] to ensure the length of the tuple is preserved.
*/
type TupleToUnionArray<TArray extends any[]> = {
[Index in keyof TArray]: TArray[number];
};
interface PipeFunctions<TBase extends any[], TArgs extends any[]> {
global: {
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#order()
*/
order: TArgs extends [] ? never : TupleToUnionArray<TBase>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#score()
*/
score: TArgs extends [] ? never : TBase extends (infer Element)[] ? (IsPlainObject<Element> extends false ? never : Element & {
_score: number;
})[] : never;
};
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#PipeFuncCall
*/
type PipeFuncCall<TExpression extends string> = TExpression extends `${infer TBase}|${infer TFuncFullName}(${infer TFuncCallArgs})` ? Parse<TBase> extends never ? never : TFuncFullName extends `${infer TFuncNamespace}::${infer TFuncName}` ? TFuncNamespace extends keyof PipeFunctions<any, any> ? FuncArgs<TFuncCallArgs, TFuncNamespace, TFuncName> extends never ? never : TFuncName extends keyof PipeFunctions<any, any>[TFuncNamespace] ? {
args: Simplify<FuncArgs<TFuncCallArgs, TFuncNamespace, TFuncName>>;
base: Parse<TBase>;
func: GroqPipeFunction;
name: TFuncNamespace extends "global" ? TFuncName : TFuncFullName;
type: "PipeFuncCall";
} : never : never : FuncArgs<TFuncCallArgs, "global", TFuncFullName> extends never ? never : TFuncFullName extends keyof PipeFunctions<any, any>["global"] ? {
args: Simplify<FuncArgs<TFuncCallArgs, "global", TFuncFullName>>;
base: Parse<TBase>;
func: GroqPipeFunction;
name: TFuncFullName;
type: "PipeFuncCall";
} : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#CompoundExpression
*/
type CompoundExpression<TExpression extends string> = Parenthesis<TExpression> | PipeFuncCall<TExpression> | TraversalExpression<TExpression>;
interface BooleanOperators {
"&&": {
leftLevel: Level2;
rightLevel: Level3;
stronger: false;
type: "And";
weaker: true;
};
"||": {
leftLevel: Level1;
rightLevel: Level2;
stronger: true;
type: "Or";
weaker: false;
};
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#And
* @link https://spec.groq.dev/GROQ-1.revision1/#Or
*/
type BooleanOperator<TExpression extends string, TOp extends keyof BooleanOperators | null = null, _Prefix extends string = ""> = TOp extends null ? {
[TOp in keyof BooleanOperators]: BooleanOperator<TExpression, TOp>;
}[keyof BooleanOperators] : TExpression extends `${infer TLeft}${TOp}${infer TRight}` ? BooleanOperator<TRight, TOp, `${_Prefix}${TLeft}${TOp}`> | (Exclude<ParseInner<`${_Prefix}${TLeft}`>, BooleanOperators[NonNullable<TOp>]["leftLevel"]> extends never ? never : Exclude<ParseInner<TRight>, BooleanOperators[NonNullable<TOp>]["rightLevel"]> extends never ? never : {
left: Exclude<ParseInner<`${_Prefix}${TLeft}`>, BooleanOperators[NonNullable<TOp>]["leftLevel"]>;
right: Exclude<ParseInner<TRight>, BooleanOperators[NonNullable<TOp>]["rightLevel"]>;
type: BooleanOperators[NonNullable<TOp>]["type"];
}) : never;
interface PrefixOperators {
"!": {
level: Exclude<Level9, NegNode>;
type: "Not";
};
"+": {
level: Exclude<Level9, NegNode>;
type: "Pos";
};
"-": {
level: Level7;
type: "Neg";
};
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Not
* @link https://spec.groq.dev/GROQ-1.revision1/#UnaryPlus
* @link https://spec.groq.dev/GROQ-1.revision1/#UnaryMinus
*/
type PrefixOperator<TExpression extends string, TOp extends keyof PrefixOperators | null = null> = TOp extends null ? {
[TOp in keyof PrefixOperators]: PrefixOperator<TExpression, TOp>;
}[keyof PrefixOperators] : TExpression extends `${TOp}${infer TBase}` ? Exclude<ParseInner<TBase>, PrefixOperators[NonNullable<TOp>]["level"]> extends never ? never : {
base: Exclude<ParseInner<TBase>, PrefixOperators[NonNullable<TOp>]["level"]>;
type: PrefixOperators[NonNullable<TOp>]["type"];
} : never;
interface Operators {
"!=": {
leftLevel: Level4;
rightLevel: Level4;
};
"%": {
leftLevel: Level6;
rightLevel: Level7;
};
"*": {
leftLevel: Level6;
rightLevel: // HACK https://github.com/sanity-io/GROQ/issues/112
EverythingNode | Level7;
};
"**": {
leftLevel: Level9;
rightLevel: Level7;
};
"+": {
leftLevel: Level5;
rightLevel: Level6;
};
"-": {
leftLevel: Level5;
rightLevel: Level6;
};
"/": {
leftLevel: Level6;
rightLevel: Level7;
};
"<": {
leftLevel: Level4;
rightLevel: Level4;
};
"<=": {
leftLevel: Level4;
rightLevel: Level4;
};
"==": {
leftLevel: Level4;
rightLevel: Level4;
};
">": {
leftLevel: Level4;
rightLevel: Level4;
};
">=": {
leftLevel: Level4;
rightLevel: Level4;
};
"match": {
leftLevel: Level4;
rightLevel: Level4;
withSpaces: true;
};
}
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Equality
* @link https://spec.groq.dev/GROQ-1.revision1/#Comparison
* @link https://spec.groq.dev/GROQ-1.revision1/#Match
* @link https://spec.groq.dev/GROQ-1.revision1/#Plus
* @link https://spec.groq.dev/GROQ-1.revision1/#Minus
* @link https://spec.groq.dev/GROQ-1.revision1/#Star
* @link https://spec.groq.dev/GROQ-1.revision1/#Slash
* @link https://spec.groq.dev/GROQ-1.revision1/#Percent
* @link https://spec.groq.dev/GROQ-1.revision1/#StarStar
*/
type OpCall<TExpression extends string, TOp extends keyof Operators | null = null, _Prefix extends string = ""> = TOp extends null ? {
[TOp in keyof Operators]: OpCall<TExpression, TOp>;
}[keyof Operators] : TExpression extends `${infer TLeft}${Operators[NonNullable<TOp>] extends {
withSpaces: true;
} ? ` ${TOp} ` : TOp}${infer TRight}` ? OpCall<TRight, TOp, `${_Prefix}${TLeft}${Operators[NonNullable<TOp>] extends {
withSpaces: true;
} ? ` ${TOp} ` : TOp}`> | (Exclude<ParseInner<`${_Prefix}${TLeft}`>, Operators[NonNullable<TOp>]["leftLevel"]> extends never ? never : Exclude<ParseInner<TRight>, Operators[NonNullable<TOp>]["rightLevel"]> extends never ? never : {
left: Exclude<ParseInner<`${_Prefix}${TLeft}`>, Operators[NonNullable<TOp>]["leftLevel"]>;
op: TOp;
right: Exclude<ParseInner<TRight>, Operators[NonNullable<TOp>]["rightLevel"]>;
type: "OpCall";
}) : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#In
*/
type InOperator<TExpression extends string, _Prefix extends string = ""> = TExpression extends `${infer TLeft} in ${infer TRight}` ? Exclude<ParseInner<`${_Prefix}${TLeft}`>, Level4> extends never ? never : Exclude<ParseInner<TRight>, Level4> extends never ? Range<TRight> extends never ? never : {
base: Exclude<ParseInner<`${_Prefix}${TLeft}`>, Level4>;
isInclusive: Range<TRight>["isInclusive"];
left: Range<TRight>["left"];
right: Range<TRight>["right"];
type: "InRange";
} : {
left: Exclude<ParseInner<`${_Prefix}${TLeft}`>, Level4>;
op: "in";
right: Exclude<ParseInner<TRight>, Level4>;
type: "OpCall";
} : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#OperatorCall
*/
type OperatorCall<TExpression extends string> = BooleanOperator<TExpression> | InOperator<TExpression> | OpCall<TExpression> | PrefixOperator<TExpression>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#Expression
*/
type Expression<TExpression extends string> = CompoundExpression<TExpression> | Literal<TExpression> | OperatorCall<TExpression> | SimpleExpression<TExpression>;
type EvaluateBaseOrThis<TNode extends AccessAttributeNode, TScope extends Scope<Context<any[], any>>> = TNode extends {
base: infer TBase extends ExprNode;
} ? Evaluate<TBase, TScope> : TScope["this"];
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateAttributeAccess()
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateThisAttribute()
*/
type EvaluateAccessAttribute<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends AccessAttributeNode ? EvaluateBaseOrThis<TNode, TScope> extends object ? EvaluateBaseOrThis<TNode, TScope> extends {
[name in TNode["name"]]: infer TValue;
} ? TValue : EvaluateBaseOrThis<TNode, TScope> extends {
[name in TNode["name"]]?: infer TValue;
} ? TValue | undefined : null : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateElementAccess()
*/
type EvaluateAccessElement<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends AccessElementNode ? Evaluate<TNode["base"], TScope> extends any[] ? TNode["index"] extends keyof Evaluate<TNode["base"], TScope> ? Evaluate<TNode["base"], TScope>[TNode["index"]] | (Evaluate<TNode["base"], TScope> extends [any, ...any] ? never : null) : null : null : never;
type FlattenDoubleArray<TArray extends any[][]> = TArray extends [] ? [] : TArray extends [infer THead extends any[], ...infer TTail extends any[][]] ? [...THead, ...FlattenDoubleArray<TTail>] : TArray extends (infer TElement extends any[])[] ? TElement[number][] : never;
type EvaluateArrayElement<TElement extends ArrayElementNode, TScope extends Scope<Context<any[], any>>> = TElement["isSplat"] extends true ? Evaluate<TElement["value"], TScope> extends any[] ? Evaluate<TElement["value"], TScope> : [Evaluate<TElement["value"], TScope>] : [Evaluate<TElement["value"], TScope>];
type EvaluateArrayElements<TElements extends ArrayElementNode[], TScope extends Scope<Context<any[], any>>> = FlattenDoubleArray<{
[Index in keyof TElements]: EvaluateArrayElement<TElements[Index], TScope>;
}>;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateArray()
*/
type EvaluateArray<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends ArrayNode ? EvaluateArrayElements<TNode["elements"], TScope> : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateArrayPostfix()
*/
type EvaluateArrayPostfix<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends ArrayCoerceNode ? Evaluate<TNode["base"], TScope> extends any[] ? Evaluate<TNode["base"], TScope> : null : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateAnd()
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateOr()
*/
type EvaluateBooleanOperator<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends AndNode | OrNode ? TNode extends {
left: infer TLeft extends ExprNode;
right: infer TRight extends ExprNode;
type: infer TType;
} ? Extract<BooleanOperators[keyof BooleanOperators], {
type: TType;
}> extends {
stronger: infer TStronger;
weaker: infer TWeaker;
} ? boolean extends Evaluate<TLeft, TScope> ? Evaluate<TRight, TScope> : boolean extends Evaluate<TRight, TScope> ? Evaluate<TLeft, TScope> : Evaluate<TLeft, TScope> extends TStronger ? TStronger : Evaluate<TRight, TScope> extends TStronger ? TStronger : Evaluate<TLeft, TScope> extends TWeaker ? Evaluate<TRight, TScope> extends TWeaker ? TWeaker : null : null : never : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateComparison()
*/
type EvaluateComparison<TNode extends ExprNode> = TNode extends OpCallNode & {
op: "<" | "<=" | ">" | ">=";
} ? boolean : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#global_after()
* @link https://spec.groq.dev/GROQ-1.revision1/#global_before()
*/
type EvaluateContext<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends ContextNode ? TNode extends {
key: infer TKey extends "after" | "before";
} ? TScope extends {
context: {
delta: {
[key in TKey]: infer TValue;
};
};
} ? TValue : null : never : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateDereference()
*/
type EvaluateDereference<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends DerefNode ? Evaluate<TNode["base"], TScope> extends SetOptional<ReferenceValue<infer TReferenced>, typeof referenced> & {
_ref: infer TRef;
} ? TScope["context"]["dataset"] extends (infer TDataset)[] ? IsNever<Extract<TDataset, {
_id: TRef;
_type: TReferenced;
}>> extends true ? null : Extract<TDataset, {
_id: TRef;
_type: TReferenced;
}> : null : null : never;
type Not<TBoolean, Enabled extends boolean = true> = TBoolean extends boolean ? Enabled extends false ? TBoolean : TBoolean extends true ? false : true : null;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateEquality()
*/
type EvaluateEquality<TNode extends ExprNode, TScope extends Scope<Context<any[], any>>> = TNode extends OpCallNode & {
op: "!=" | "==";
} ? Not<Evaluate<TNode["left"], TScope> extends Evaluate<TNode["right"], TScope> ? true : Evaluate<TNode["right"], TScope> extends Evaluate<TNode["left"], TScope> ? true : false, TNode["op"] extends "!=" ? true : false> : never;
/**
* @link https://spec.groq.dev/GROQ-1.revision1/#EvaluateEverything()
*/
type EvaluateEverything<TNode extends ExprNo