wizard-ql
Version:
WizardQL is a natural-language-like query language for constructing data queries for resources that meet conditions.
177 lines (176 loc) • 6.71 kB
TypeScript
/** All available operation aliases (alias -> operation) */
export declare const OPERATION_ALIAS_DICTIONARY: {
readonly AND: "AND";
readonly '&&': "AND";
readonly '&': "AND";
readonly '^': "AND";
readonly OR: "OR";
readonly '||': "OR";
readonly '|': "OR";
readonly V: "OR";
readonly GEQ: "GEQ";
readonly '>=': "GEQ";
readonly '=>': "GEQ";
readonly LEQ: "LEQ";
readonly '<=': "LEQ";
readonly '=<': "LEQ";
readonly NOTEQUALS: "NOTEQUAL";
readonly NOTEQUAL: "NOTEQUAL";
readonly NEQ: "NOTEQUAL";
readonly ISNT: "NOTEQUAL";
readonly '!==': "NOTEQUAL";
readonly '!=': "NOTEQUAL";
readonly EQUALS: "EQUAL";
readonly EQUAL: "EQUAL";
readonly EQ: "EQUAL";
readonly IS: "EQUAL";
readonly '==': "EQUAL";
readonly '=': "EQUAL";
readonly LESS: "LESS";
readonly '<': "LESS";
readonly GREATER: "GREATER";
readonly '>': "GREATER";
readonly MORE: "GREATER";
readonly NOTIN: "NOTIN";
readonly '!:': "NOTIN";
readonly IN: "IN";
readonly ':': "IN";
readonly NOTMATCHES: "NOTMATCH";
readonly NOTMATCH: "NOTMATCH";
readonly '!~': "NOTMATCH";
readonly MATCHES: "MATCH";
readonly MATCH: "MATCH";
readonly '~': "MATCH";
};
export interface Token {
/** The text content of the token */
content: string;
/** The index in the original expression this token originates from */
index: number;
}
export type Operation = (typeof OPERATION_ALIAS_DICTIONARY)[keyof typeof OPERATION_ALIAS_DICTIONARY];
export declare const ALIASES: string[];
/** All base operations and their type */
export declare const OPERATION_PURPOSE_DICTIONARY: {
readonly AND: "junction";
readonly OR: "junction";
readonly EQUAL: "comparison";
readonly NOTEQUAL: "comparison";
readonly LESS: "comparison";
readonly GREATER: "comparison";
readonly GEQ: "comparison";
readonly LEQ: "comparison";
readonly IN: "comparison";
readonly NOTIN: "comparison";
readonly MATCH: "comparison";
readonly NOTMATCH: "comparison";
};
type KeysWhereValue<T, V> = Exclude<{
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T], never>;
export type JunctionOperation = KeysWhereValue<typeof OPERATION_PURPOSE_DICTIONARY, 'junction'>;
export type ComparisonOperation = KeysWhereValue<typeof OPERATION_PURPOSE_DICTIONARY, 'comparison'>;
/** All comparison operations and their types */
export declare const COMPARISON_TYPE_DICTIONARY: {
readonly EQUAL: "primitive";
readonly NOTEQUAL: "primitive";
readonly GEQ: "numeric";
readonly GREATER: "numeric";
readonly LEQ: "numeric";
readonly LESS: "numeric";
readonly IN: "array";
readonly NOTIN: "array";
readonly MATCH: "string";
readonly NOTMATCH: "string";
};
/** Convert an operation's comparison type to a language server type */
export type ComparisonTypeToTSType<T extends keyof typeof COMPARISON_TYPE_DICTIONARY> = {
primitive: Primitive;
boolean: boolean;
string: string;
number: number;
date: Date;
numeric: number | Date;
array: Primitive[];
}[typeof COMPARISON_TYPE_DICTIONARY[T]];
export type FieldType = 'boolean' | 'string' | 'number' | 'date';
export type TypeRecord = Record<string, FieldType | FieldType[]>;
/** Convert a field type string to a language server type */
export type FieldTypeToTSType<T extends FieldType> = {
boolean: boolean;
string: string;
number: number;
date: Date;
}[T];
/** Primitive values that can be used in comparisons */
export type Primitive = FieldTypeToTSType<FieldType>;
/** Convert input type record to language server type record */
export type ConvertTypeRecord<T extends TypeRecord> = {
[K in keyof T]: T[K] extends FieldType[] ? FieldTypeToTSType<T[K][number]> : T[K] extends FieldType ? FieldTypeToTSType<T[K]> : Primitive;
};
export declare const TYPE_PRIORITY: ["boolean", "date", "number", "string"];
/**
* A group of conditions joined by a junction operator
* @template R A record mapping field names to values
*/
export interface Group<R extends Record<string, unknown> = Record<string, Primitive>, V extends boolean = false> {
type: 'group';
/** The junction operator */
operation: JunctionOperation;
/** The members of the group */
constituents: Array<Expression<R, V>>;
}
/**
* A query on a field, validated by type constraints
* @template R A record mapping field names to values
* @template F The name of the field being queried
*/
export interface Condition<R extends Record<string, unknown>, F extends keyof R, O extends ComparisonOperation> {
type: 'condition';
/** The operation */
operation: O;
/** The name of the field */
field: F;
/** The value being checked */
value: typeof COMPARISON_TYPE_DICTIONARY[O] extends 'array' ? Array<R[F]> : Extract<ComparisonTypeToTSType<O>, R[F]>;
/** Was this condition validated by the constraints or is its type unknown? */
validated: true;
}
/**
* A query on a field
*/
export interface UncheckedCondition<O extends ComparisonOperation = ComparisonOperation> {
type: 'condition';
/** The operation */
operation: O;
/** The name of the field */
field: string;
/** The value being checked */
value: Exclude<ComparisonTypeToTSType<O>, Date>;
/** Was this condition validated by the constraints or is its type unknown? */
validated: false;
}
/**
* Reverse the keys and values of a type and aggregate by common value
*/
type ReverseAggregate<T extends Record<any, any>> = {
[V in T[keyof T]]: {
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T];
};
type ReverseAggregatedTypes = ReverseAggregate<typeof COMPARISON_TYPE_DICTIONARY>;
/** Create a union of conditions; an intersection of the operation type validation and constraint type validation */
export type CheckedConditionSpread<R extends Record<string, unknown>> = {
[K in keyof R]: {
[O in keyof ReverseAggregatedTypes]: Condition<R, K, ReverseAggregatedTypes[O]>;
}[keyof ReverseAggregatedTypes];
}[keyof R];
/** Create a union of conditions that are operation type validated */
export type UncheckedConditionSpread = {
[O in keyof ReverseAggregatedTypes]: UncheckedCondition<ReverseAggregatedTypes[O]>;
}[keyof ReverseAggregatedTypes];
export type Expression<R extends Record<string, unknown> = Record<string, Primitive>, V extends boolean = false> = Group<R, V> | (V extends true ? CheckedConditionSpread<R> : CheckedConditionSpread<R> | UncheckedConditionSpread);
export type UncheckedExpression = (Omit<Group, 'constituents'> & {
constituents: UncheckedExpression[];
}) | UncheckedConditionSpread;
export {};