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**.
39 lines (38 loc) • 2.35 kB
TypeScript
import { QueryConfig } from "./schema-types";
import type { IsLiteral, LiteralUnion } from "type-fest";
import { StringKeys, UndefinedToNull, ValueOf } from "./utils";
import { Path, PathValue } from "./path-types";
export declare namespace Expressions {
/**
* This type allows any string, but provides
* TypeScript suggestions for common expressions,
* like '_type == "product"' or 'slug.current == $slug'.
*/
export type AnyConditional<TResultItem, TQueryConfig extends QueryConfig> = LiteralUnion<Conditional<TResultItem, TQueryConfig>, string>;
/**
* A strongly-typed conditional Groq conditional expression.
* Currently, this only supports simple "equality" expressions,
* like '_type == "product"' or 'slug.current == $slug'.
* */
export type Conditional<TResultItem, TQueryConfig extends QueryConfig> = Equality<TResultItem, TQueryConfig>;
export type Equality<TResultItem, TQueryConfig extends QueryConfig,
/** (local use only) Calculate our Parameter entries once, and reuse across suggestions */
_ParameterEntries = ParameterEntries<TQueryConfig["parameters"]>> = ValueOf<{
[Key in SuggestedKeys<TResultItem>]: `${Key} == ${SuggestedValues<_ParameterEntries, SuggestedKeysValue<TResultItem, Key>>}`;
}>;
type LiteralValue<TValue> = TValue extends string ? `"${TValue}"` : TValue extends number | boolean | null ? TValue : never;
type LiteralSuggestion<TValue> = IsLiteral<TValue> extends true ? never : TValue extends string ? "(string)" : TValue extends number ? "(number)" : never;
type SuggestedKeys<TResultItem> = Path<TResultItem>;
type SuggestedKeysValue<TResultItem, TKey extends SuggestedKeys<TResultItem>> = UndefinedToNull<PathValue<TResultItem, TKey>>;
type SuggestedValues<TParameterEntries, TValue> = StringKeysWithType<TParameterEntries, TValue> | LiteralSuggestion<TValue> | LiteralValue<TValue>;
export type ParameterEntries<TParameters> = {
[P in Path<TParameters> as `$${P}`]: PathValue<TParameters, P>;
};
/**
* Finds all (string) keys of TObject where the value matches the given TType
*/
export type StringKeysWithType<TObject, TType> = StringKeys<ValueOf<{
[P in keyof TObject]: TObject[P] extends TType ? P : TType extends TObject[P] ? P : never;
}>>;
export {};
}