@phalcode/ts-apicalypse
Version:
A Typescript client and request builder for Apicalypse
918 lines (890 loc) • 32.7 kB
TypeScript
import { AxiosRequestConfig, AxiosPromise } from 'axios';
/**
* Check whether `A1` is equal to `A2` or not.
* @param A1
* @param A2
* @returns [[Boolean]]
* @example
* ```ts
* import {A} from 'ts-toolbelt'
*
* type test0 = A.Equals<42 | 0, 42 | 0> // true
* type test1 = A.Equals<{a: string}, {b: string}> // false
* type test3 = A.Equals<{a: string}, {readonly a: string}> // false
* ```
*/
declare type Equals<A1 extends any, A2 extends any> = (<A>() => A extends A2 ? 1 : 0) extends (<A>() => A extends A1 ? 1 : 0) ? 1 : 0;
/**
* Describes index keys for any type
*/
declare type Key = string | number | symbol;
/**
* A [[List]]
* @param A its type
* @returns [[List]]
* @example
* ```ts
* type list0 = [1, 2, 3]
* type list1 = number[]
* ```
*/
declare type List<A = any> = ReadonlyArray<A>;
/**
* Get in `O` the type of a field of key `K`
* @param O to extract from
* @param K to extract at
* @returns [[Any]]
* @example
* ```ts
* import {O} from 'ts-toolbelt'
*
* type User = {
* info: {
* name: string
* age: number
* payment: {}
* }
* id: number
* }
*
* type test0 = O.At<User, 'id'> // number
* ```
*/
declare type At<A extends any, K extends Key> = A extends List ? number extends A['length'] ? K extends number | `${number}` ? A[never] | undefined : undefined : K extends keyof A ? A[K] : undefined : unknown extends A ? unknown : K extends keyof A ? A[K] : undefined;
/**
* Ask TS to re-check that `A1` extends `A2`.
* And if it fails, `A2` will be enforced anyway.
* Can also be used to add constraints on parameters.
* @param A1 to check against
* @param A2 to cast to
* @returns `A1 | A2`
* @example
* ```ts
* import {A} from 'ts-toolbelt'
*
* type test0 = A.Cast<'42', string> // '42'
* type test1 = A.Cast<'42', number> // number
* ```
*/
declare type Cast<A1 extends any, A2 extends any> = A1 extends A2 ? A1 : A2;
/**
* Check whether `A1` is part of `A2` or not. The difference with
* `extends` is that it forces a [[Boolean]] return.
* @param A1
* @param A2
* @returns [[Boolean]]
* @example
* ```ts
* import {A} from 'ts-toolbelt'
*
* type test0 = A.Extends<'a' | 'b', 'b'> // Boolean
* type test1 = A.Extends<'a', 'a' | 'b'> // True
*
* type test2 = A.Extends<{a: string}, {a: any}> // True
* type test3 = A.Extends<{a: any}, {a: any, b: any}> // False
*
* type test4 = A.Extends<never, never> // False
* /// Nothing cannot extend nothing, use `A.Equals`
* ```
*/
declare type Extends<A1 extends any, A2 extends any> = [
A1
] extends [never] ? 0 : A1 extends A2 ? 1 : 0;
/**
* Check whether `A1` is part of `A2` or not. It works like
* [[Extends]] but [[Boolean]] results are narrowed to [[False]].
* @param A1
* @param A2
* @returns [[Boolean]]
* @example
* ```ts
* type test0 = A.Contains<'a' | 'b', 'b'> // False
* type test1 = A.Contains<'a', 'a' | 'b'> // True
*
* type test2 = A.Contains<{a: string}, {a: string, b: number}> // False
* type test3 = A.Contains<{a: string, b: number}, {a: string}> // True
*
* type test4 = A.Contains<never, never> // False
* /// Nothing cannot contain nothing, use `A.Equals`
* ```
*/
declare type Contains<A1 extends any, A2 extends any> = Extends<A1, A2> extends 1 ? 1 : 0;
/**
* Describes the match strategy when matching types
* * `default` : `extends->`
* * `contains->` : X contains Y ([[Contains]]<X, Y>)
* * `extends->` : X extends Y ([[Extends]]<X, Y>)
* * `<-contains` : Y contains X ([[Contains]]<Y, X>)
* * `<-extends` : Y extends X ([[Extends]]<Y, X>)
* * `equals` : X equals Y (([[Equals]]<X, Y>))
*/
declare type Match = 'default' | 'contains->' | 'extends->' | '<-contains' | '<-extends' | 'equals';
/**
* Check whether `A` is similar to `A1` or not. In other words, it is a compact
* type that bundles [[Equals]], [[Extends]], [[Contains]], comparison types.
* @param A to be compared
* @param A1 to compare to
* @param match (?=`'default'`) to change precision
* @returns [[Boolean]]
* @example
* ```ts
* import {A} from 'ts-toolbelt'
*
* type test0 = A.Is<'a', 'a' | 'b', 'extends->'> // True
* type test1 = A.Is<'a' | 'b', 'a', 'extends->'> // Boolean
*
* type test2 = A.Is<'a', 'a' | 'b', '<-extends'> // Boolean
* type test3 = A.Is<'a' | 'b', 'a', '<-extends'> // True
*
* type test4 = A.Is<'a', 'a' | 'b', 'contains->'> // True
* type test5 = A.Is<'a' | 'b', 'a', 'contains->'> // False
*
* type test6 = A.Is<'a', 'a' | 'b', '<-contains'> // False
* type test7 = A.Is<'a' | 'b', 'a', '<-contains'> // True
*
* type test8 = A.Is<'a', 'a' | 'b', 'equals'> // False
* type test9 = A.Is<'b' |'a', 'a' | 'b', 'equals'> // True
* ```
*/
declare type Is<A extends any, A1 extends any, match extends Match = 'default'> = {
'default': Extends<A, A1>;
'contains->': Contains<A, A1>;
'extends->': Extends<A, A1>;
'<-contains': Contains<A1, A>;
'<-extends': Extends<A1, A>;
'equals': Equals<A1, A>;
}[match];
/**
* @hidden
*/
declare type _UnionOf<O extends object> = O[keyof O];
/**
* Transform an [[Object]] into an [[Union]]
* @param O to transform
* @returns [[Any]]
* @example
* ```ts
* ```
*/
declare type UnionOf<O extends object> = O extends unknown ? _UnionOf<O> : never;
/**
* An entry of `IterationMap`
*/
declare type Iteration = [
value: number,
sign: '-' | '0' | '+',
prev: keyof IterationMap,
next: keyof IterationMap,
oppo: keyof IterationMap
];
declare type IterationMap = {
'__': [number, '-' | '0' | '+', '__', '__', '__'];
'-100': [-100, '-', '__', '-99', '100'];
'-99': [-99, '-', '-100', '-98', '99'];
'-98': [-98, '-', '-99', '-97', '98'];
'-97': [-97, '-', '-98', '-96', '97'];
'-96': [-96, '-', '-97', '-95', '96'];
'-95': [-95, '-', '-96', '-94', '95'];
'-94': [-94, '-', '-95', '-93', '94'];
'-93': [-93, '-', '-94', '-92', '93'];
'-92': [-92, '-', '-93', '-91', '92'];
'-91': [-91, '-', '-92', '-90', '91'];
'-90': [-90, '-', '-91', '-89', '90'];
'-89': [-89, '-', '-90', '-88', '89'];
'-88': [-88, '-', '-89', '-87', '88'];
'-87': [-87, '-', '-88', '-86', '87'];
'-86': [-86, '-', '-87', '-85', '86'];
'-85': [-85, '-', '-86', '-84', '85'];
'-84': [-84, '-', '-85', '-83', '84'];
'-83': [-83, '-', '-84', '-82', '83'];
'-82': [-82, '-', '-83', '-81', '82'];
'-81': [-81, '-', '-82', '-80', '81'];
'-80': [-80, '-', '-81', '-79', '80'];
'-79': [-79, '-', '-80', '-78', '79'];
'-78': [-78, '-', '-79', '-77', '78'];
'-77': [-77, '-', '-78', '-76', '77'];
'-76': [-76, '-', '-77', '-75', '76'];
'-75': [-75, '-', '-76', '-74', '75'];
'-74': [-74, '-', '-75', '-73', '74'];
'-73': [-73, '-', '-74', '-72', '73'];
'-72': [-72, '-', '-73', '-71', '72'];
'-71': [-71, '-', '-72', '-70', '71'];
'-70': [-70, '-', '-71', '-69', '70'];
'-69': [-69, '-', '-70', '-68', '69'];
'-68': [-68, '-', '-69', '-67', '68'];
'-67': [-67, '-', '-68', '-66', '67'];
'-66': [-66, '-', '-67', '-65', '66'];
'-65': [-65, '-', '-66', '-64', '65'];
'-64': [-64, '-', '-65', '-63', '64'];
'-63': [-63, '-', '-64', '-62', '63'];
'-62': [-62, '-', '-63', '-61', '62'];
'-61': [-61, '-', '-62', '-60', '61'];
'-60': [-60, '-', '-61', '-59', '60'];
'-59': [-59, '-', '-60', '-58', '59'];
'-58': [-58, '-', '-59', '-57', '58'];
'-57': [-57, '-', '-58', '-56', '57'];
'-56': [-56, '-', '-57', '-55', '56'];
'-55': [-55, '-', '-56', '-54', '55'];
'-54': [-54, '-', '-55', '-53', '54'];
'-53': [-53, '-', '-54', '-52', '53'];
'-52': [-52, '-', '-53', '-51', '52'];
'-51': [-51, '-', '-52', '-50', '51'];
'-50': [-50, '-', '-51', '-49', '50'];
'-49': [-49, '-', '-50', '-48', '49'];
'-48': [-48, '-', '-49', '-47', '48'];
'-47': [-47, '-', '-48', '-46', '47'];
'-46': [-46, '-', '-47', '-45', '46'];
'-45': [-45, '-', '-46', '-44', '45'];
'-44': [-44, '-', '-45', '-43', '44'];
'-43': [-43, '-', '-44', '-42', '43'];
'-42': [-42, '-', '-43', '-41', '42'];
'-41': [-41, '-', '-42', '-40', '41'];
'-40': [-40, '-', '-41', '-39', '40'];
'-39': [-39, '-', '-40', '-38', '39'];
'-38': [-38, '-', '-39', '-37', '38'];
'-37': [-37, '-', '-38', '-36', '37'];
'-36': [-36, '-', '-37', '-35', '36'];
'-35': [-35, '-', '-36', '-34', '35'];
'-34': [-34, '-', '-35', '-33', '34'];
'-33': [-33, '-', '-34', '-32', '33'];
'-32': [-32, '-', '-33', '-31', '32'];
'-31': [-31, '-', '-32', '-30', '31'];
'-30': [-30, '-', '-31', '-29', '30'];
'-29': [-29, '-', '-30', '-28', '29'];
'-28': [-28, '-', '-29', '-27', '28'];
'-27': [-27, '-', '-28', '-26', '27'];
'-26': [-26, '-', '-27', '-25', '26'];
'-25': [-25, '-', '-26', '-24', '25'];
'-24': [-24, '-', '-25', '-23', '24'];
'-23': [-23, '-', '-24', '-22', '23'];
'-22': [-22, '-', '-23', '-21', '22'];
'-21': [-21, '-', '-22', '-20', '21'];
'-20': [-20, '-', '-21', '-19', '20'];
'-19': [-19, '-', '-20', '-18', '19'];
'-18': [-18, '-', '-19', '-17', '18'];
'-17': [-17, '-', '-18', '-16', '17'];
'-16': [-16, '-', '-17', '-15', '16'];
'-15': [-15, '-', '-16', '-14', '15'];
'-14': [-14, '-', '-15', '-13', '14'];
'-13': [-13, '-', '-14', '-12', '13'];
'-12': [-12, '-', '-13', '-11', '12'];
'-11': [-11, '-', '-12', '-10', '11'];
'-10': [-10, '-', '-11', '-9', '10'];
'-9': [-9, '-', '-10', '-8', '9'];
'-8': [-8, '-', '-9', '-7', '8'];
'-7': [-7, '-', '-8', '-6', '7'];
'-6': [-6, '-', '-7', '-5', '6'];
'-5': [-5, '-', '-6', '-4', '5'];
'-4': [-4, '-', '-5', '-3', '4'];
'-3': [-3, '-', '-4', '-2', '3'];
'-2': [-2, '-', '-3', '-1', '2'];
'-1': [-1, '-', '-2', '0', '1'];
'0': [0, '0', '-1', '1', '0'];
'1': [1, '+', '0', '2', '-1'];
'2': [2, '+', '1', '3', '-2'];
'3': [3, '+', '2', '4', '-3'];
'4': [4, '+', '3', '5', '-4'];
'5': [5, '+', '4', '6', '-5'];
'6': [6, '+', '5', '7', '-6'];
'7': [7, '+', '6', '8', '-7'];
'8': [8, '+', '7', '9', '-8'];
'9': [9, '+', '8', '10', '-9'];
'10': [10, '+', '9', '11', '-10'];
'11': [11, '+', '10', '12', '-11'];
'12': [12, '+', '11', '13', '-12'];
'13': [13, '+', '12', '14', '-13'];
'14': [14, '+', '13', '15', '-14'];
'15': [15, '+', '14', '16', '-15'];
'16': [16, '+', '15', '17', '-16'];
'17': [17, '+', '16', '18', '-17'];
'18': [18, '+', '17', '19', '-18'];
'19': [19, '+', '18', '20', '-19'];
'20': [20, '+', '19', '21', '-20'];
'21': [21, '+', '20', '22', '-21'];
'22': [22, '+', '21', '23', '-22'];
'23': [23, '+', '22', '24', '-23'];
'24': [24, '+', '23', '25', '-24'];
'25': [25, '+', '24', '26', '-25'];
'26': [26, '+', '25', '27', '-26'];
'27': [27, '+', '26', '28', '-27'];
'28': [28, '+', '27', '29', '-28'];
'29': [29, '+', '28', '30', '-29'];
'30': [30, '+', '29', '31', '-30'];
'31': [31, '+', '30', '32', '-31'];
'32': [32, '+', '31', '33', '-32'];
'33': [33, '+', '32', '34', '-33'];
'34': [34, '+', '33', '35', '-34'];
'35': [35, '+', '34', '36', '-35'];
'36': [36, '+', '35', '37', '-36'];
'37': [37, '+', '36', '38', '-37'];
'38': [38, '+', '37', '39', '-38'];
'39': [39, '+', '38', '40', '-39'];
'40': [40, '+', '39', '41', '-40'];
'41': [41, '+', '40', '42', '-41'];
'42': [42, '+', '41', '43', '-42'];
'43': [43, '+', '42', '44', '-43'];
'44': [44, '+', '43', '45', '-44'];
'45': [45, '+', '44', '46', '-45'];
'46': [46, '+', '45', '47', '-46'];
'47': [47, '+', '46', '48', '-47'];
'48': [48, '+', '47', '49', '-48'];
'49': [49, '+', '48', '50', '-49'];
'50': [50, '+', '49', '51', '-50'];
'51': [51, '+', '50', '52', '-51'];
'52': [52, '+', '51', '53', '-52'];
'53': [53, '+', '52', '54', '-53'];
'54': [54, '+', '53', '55', '-54'];
'55': [55, '+', '54', '56', '-55'];
'56': [56, '+', '55', '57', '-56'];
'57': [57, '+', '56', '58', '-57'];
'58': [58, '+', '57', '59', '-58'];
'59': [59, '+', '58', '60', '-59'];
'60': [60, '+', '59', '61', '-60'];
'61': [61, '+', '60', '62', '-61'];
'62': [62, '+', '61', '63', '-62'];
'63': [63, '+', '62', '64', '-63'];
'64': [64, '+', '63', '65', '-64'];
'65': [65, '+', '64', '66', '-65'];
'66': [66, '+', '65', '67', '-66'];
'67': [67, '+', '66', '68', '-67'];
'68': [68, '+', '67', '69', '-68'];
'69': [69, '+', '68', '70', '-69'];
'70': [70, '+', '69', '71', '-70'];
'71': [71, '+', '70', '72', '-71'];
'72': [72, '+', '71', '73', '-72'];
'73': [73, '+', '72', '74', '-73'];
'74': [74, '+', '73', '75', '-74'];
'75': [75, '+', '74', '76', '-75'];
'76': [76, '+', '75', '77', '-76'];
'77': [77, '+', '76', '78', '-77'];
'78': [78, '+', '77', '79', '-78'];
'79': [79, '+', '78', '80', '-79'];
'80': [80, '+', '79', '81', '-80'];
'81': [81, '+', '80', '82', '-81'];
'82': [82, '+', '81', '83', '-82'];
'83': [83, '+', '82', '84', '-83'];
'84': [84, '+', '83', '85', '-84'];
'85': [85, '+', '84', '86', '-85'];
'86': [86, '+', '85', '87', '-86'];
'87': [87, '+', '86', '88', '-87'];
'88': [88, '+', '87', '89', '-88'];
'89': [89, '+', '88', '90', '-89'];
'90': [90, '+', '89', '91', '-90'];
'91': [91, '+', '90', '92', '-91'];
'92': [92, '+', '91', '93', '-92'];
'93': [93, '+', '92', '94', '-93'];
'94': [94, '+', '93', '95', '-94'];
'95': [95, '+', '94', '96', '-95'];
'96': [96, '+', '95', '97', '-96'];
'97': [97, '+', '96', '98', '-97'];
'98': [98, '+', '97', '99', '-98'];
'99': [99, '+', '98', '100', '-99'];
'100': [100, '+', '99', '__', '-100'];
};
/**
* Move `I`'s position forward
* @param I to move
* @returns [[Iteration]]
* @example
* ```ts
* import {I} from 'ts-toolbelt'
*
* type i = I.IterationOf<'20'>
*
* type test0 = I.Pos<i> // 20
* type test1 = I.Pos<I.Next<i>> // 21
* ```
*/
declare type Next<I extends Iteration> = IterationMap[I[3]];
/**
* Transform a number into an [[Iteration]]
* (to use [[Prev]], [[Next]], & [[Pos]])
* @param N to transform
* @returns [[Iteration]]
* @example
* ```ts
* import {I} from 'ts-toolbelt'
*
* type i = I.IterationOf<0> // ["-1", "1", "0", 0, "0"]
*
* type next = I.Next<i> // ["0", "2", "1", 1, "+"]
* type prev = I.Prev<i> // ["-2", "0", "-1", -1, "-"]
*
* type nnext = I.Pos<next> // +1
* type nprev = I.Pos<prev> // -1
* ```
*/
declare type IterationOf<N extends number> = `${N}` extends keyof IterationMap ? IterationMap[`${N}`] : IterationMap['__'];
/**
* Get the position of `I` (**number**)
* @param I to query
* @returns `number`
* @example
* ```ts
* import {I} from 'ts-toolbelt'
*
* type i = I.IterationOf<'20'>
*
* type test0 = I.Pos<i> // 20
* type test1 = I.Pos<I.Next<i>> // 21
* ```
*/
declare type Pos<I extends Iteration> = I[0];
/**
* Get the length of `L`
* @param L to get length
* @returns [[String]] or `number`
* @example
* ```ts
* ```
*/
declare type Length<L extends List> = L['length'];
/**
* Get the first entry of `L`
* @param L to extract from
* @returns [[Any]]
* @example
* ```ts
* ```
*/
declare type Head<L extends List> = Length<L> extends 0 ? never : L[0];
/**
* Remove the last element out of `L`
* @param L to remove from
* @returns [[List]]
* @example
* ```ts
* ```
*/
declare type Pop<L extends List> = L extends (readonly [...infer LBody, any] | readonly [...infer LBody, any?]) ? LBody : L;
/**
* Remove the first item out of a [[List]]
* @param L
* @returns [[List]]
* @example
* ```ts
* ```
*/
declare type Tail<L extends List> = L extends readonly [] ? L : L extends readonly [any?, ...infer LTail] ? LTail : L;
/**
* Extract the part of `U` that matches `M`
* @param U to extract from
* @param M to select with
* @returns [[Union]]
* @example
* ```ts
* ```
*/
declare type Select<U extends any, M extends any, match extends Match = 'default'> = U extends unknown ? {
1: U & M;
0: never;
}[Is<U, M, match>] : never;
declare type Literal = string | number | bigint | boolean;
/**
* @hidden
*/
declare type _Join<T extends List, D extends string> = T extends [] ? '' : T extends [Literal] ? `${T[0]}` : T extends [Literal, ...infer R] ? `${T[0]}${D}${_Join<R, D>}` : string;
/**
* Concat many literals together
* @param T to concat
* @param D to delimit
*/
declare type Join<T extends List<Literal>, D extends string = ''> = _Join<T, D> extends infer X ? Cast<X, string> : never;
/**
* @ignore
*/
declare type __Split<S extends string, D extends string, T extends string[] = []> = S extends `${infer BS}${D}${infer AS}` ? __Split<AS, D, [...T, BS]> : [...T, S];
/**
* @hidden
*/
declare type _Split<S extends string, D extends string = ''> = D extends '' ? Pop<__Split<S, D>> : __Split<S, D>;
/**
* Split `S` by `D` into a [[List]]
* @param S to split up
* @param D to split at
*/
declare type Split<S extends string, D extends string = ''> = _Split<S, D> extends infer X ? Cast<X, string[]> : never;
/**
* All primitive types
*/
declare type Primitive = boolean | string | number | bigint | symbol | undefined | null;
interface Options extends AxiosRequestConfig {
queryMethod?: 'url' | 'body';
}
interface Stringifiable {
toApicalypseString(): string;
}
interface Builder<T = any> extends Stringifiable {
queryFields: {
fields?: string;
exclude?: string;
sort?: string;
limit?: string;
offset?: string;
search?: string;
where: string[];
};
queryEndpoint?: string;
queryName?: string;
}
interface NamedBuilder<T, N extends string> extends Omit<Builder<T>, 'queryEndpoint' | 'queryName'> {
queryEndpoint: string;
queryName: N;
}
interface NarrowBuilder<T> extends Builder<T> {
__narrow: true;
}
interface CountBuilder<T> extends Builder<T> {
__count: true;
}
type PickWith<T, K extends keyof T, X> = X extends keyof T ? Pick<T, K | X> : Pick<T, K>;
interface Pipe<T extends object, mode extends 'result' | 'count' = 'result'> {
<A>(...steps: (BuilderOperator<T, T> | BuilderOperatorNarrow<T, A>)[]): Stringifiable & Executor<FallbackIfUnknown<A, PickWith<T, never, 'id'>>, mode>;
}
type PipeSub<T extends object, Ret extends string, mode extends 'result' | 'count' = 'result'> = {
<A>(...steps: (BuilderOperator<T, T> | BuilderOperatorNarrow<T, A>)[]): NamedBuilder<FallbackIfUnknown<A, PickWith<T, never, 'id'>>, Ret> & (mode extends 'count' ? CountBuilder<any> : {});
};
interface Executor<T, mode extends 'result' | 'count' = 'result'> {
execute(url: string, options?: Options): AxiosPromise<{
result: T[];
count: {
count: number;
};
}[mode]>;
}
type ResultMultiMono<T extends NamedBuilder<any, any>> = {
name: T["queryName"];
} & (T extends CountBuilder<any> ? {
count: number;
} : {
result: T extends NamedBuilder<infer S, any> ? S[] : never;
});
interface ExecutorMulti<T extends Builder<any>[]> {
execute(url: string, options?: Options): AxiosPromise<T extends (infer S)[] ? ResultMultiMono<S extends NamedBuilder<any, any> ? S : never>[] : never>;
}
interface BuilderOperator<T, R> {
(builder: Builder<T>): Builder<R>;
}
interface BuilderOperatorNarrow<T, R> {
(builder: Builder<T>): NarrowBuilder<R>;
}
interface NamedBuilderOperator<T, N extends string> {
(builder: Builder<T>): NamedBuilder<T, N>;
}
type StandardOperators = '=' | '!=';
type StringOperators = StandardOperators | '~';
type NumbersOperatos = StandardOperators | '>=' | '>' | '<=' | '<';
type AllowedValues = true | false | null;
type GetOp<T> = T extends number ? NumbersOperatos : T extends string ? StringOperators : StandardOperators;
declare enum WhereFlags {
RAW = 1,// x = n
NUMBER = 1,// x = n
STRING = 2,// x = "n"
STARTSWITH = 6,// x = "n"*
ENDSWITH = 10,// x = *"n"
CONTAINS = 14
}
declare enum WhereInFlags {
AND = 32,// [...]
NAND = 48,// ![...]
OR = 64,// (...)
NOR = 80,// !(...)
EXACT = 128
}
type FallbackIfUnknown<T, F> = unknown extends T ? F : T;
type OuterKeyCast<T, K extends string> = PickOuterKey<K> & UnionKeyOf<T>;
type UnionKeyOf<T> = T extends Array<infer T> ? keyof T : T extends infer T ? keyof T : never;
type DeepPick<T, P extends string> = T extends Primitive ? T : T extends Array<infer I> ? DeepPick<I, P>[] : T extends object ? string extends P ? number : PickWith<InnerPick<T, P>, OuterKeyCast<T, P>, 'id'> : never;
type InnerPick<T, K extends string> = {
[key in keyof T]: DeepPick<T[key], InnerKey<Extract<key, string>, K>>;
};
type FlatPath<O extends any, P extends List<Key>, X = Path<O, P>> = X extends object ? number : X;
type PickOuterKey<K extends string> = K extends '*' ? string : KeyHead<K>;
type KeyHead<K extends string> = K extends `${infer K}.${string}` ? K : K;
type InnerKey<key extends string, K> = [
Extract<K, `${key}.${string}`>
] extends [`${key}.${infer K}`] ? K : never;
type FlatKey<O, K extends keyof O> = Exclude<O[K], null | undefined> extends Array<infer I> ? I : O[K];
type Flat<O> = Exclude<O, null | undefined> extends Array<infer I> ? I : O;
type _ExcludePrimitiveKeys<O> = O extends Primitive ? Omit<O, keyof O> : O;
type _Path<O, P extends List<Key>, It extends Iteration = IterationOf<0>> = {
0: _Path<Flat<At<_ExcludePrimitiveKeys<O>, P[Pos<It>]>>, P, Next<It>>;
1: O;
}[Extends<Pos<It>, Length<P>>];
type Path<O extends any, P extends List<Key>> = _Path<O, P> extends infer X ? Cast<X, any> : never;
type Index = number | string;
type KeyToIndex<K extends Key, SP extends List<Index>> = number extends K ? Head<SP> : K & Index;
type MetaPath<O, D extends string, St extends string, SP extends List<Index> = [], P extends List<Index> = []> = {
[K in keyof Required<O>]: Exclude<MetaPath<FlatKey<O, K>, D, St, Tail<SP>, [...P, KeyToIndex<K, SP>]>, string> | Join<[...P, KeyToIndex<K, SP>], D> | ([St] extends [never] ? never : Join<[...P, St], D>);
};
type NextPath<OP> = Select<UnionOf<Exclude<OP, string> & {}>, string>;
type CurrentPath<OP> = Select<Exclude<OP, object>, string>;
type ExecPath<A, SP extends List<Index>, D extends string, St extends string> = NextPath<Path<MetaPath<A, D, St, SP>, SP>>;
type HintPath<A, P extends string, SP extends List<Index>, Exec extends string, D extends string, St extends string> = [Exec] extends [never] ? CurrentPath<Path<MetaPath<A, D, St, SP>, SP>> extends never ? ExecPath<A, Pop<SP>, D, St> : CurrentPath<Path<MetaPath<A, D, St, SP>, SP>> : Exec | P;
type _AutoPath<A, P extends string, D extends string, St extends string, SP extends List<Index> = Split<P, D>> = HintPath<A, P, SP, ExecPath<A, SP, D, St>, D, St>;
type AutoPath<O extends any, P extends string, D extends string = '.', St extends string = '*'> = _AutoPath<O, P, D, St>;
type AllAutoPath<O extends object, P extends List<string>> = {
[K in keyof P]: AutoPath<O, P[K] & string>;
};
type NonEmptyStringList = [string, ...string[]];
type ChosenPaths<P extends NonEmptyStringList> = [string] extends P ? '*' : P[number];
/**
* Select only given fields.
* Resulting response type is narrowed to only include specified fields (including nested ones).
*
* @example
* ```ts
* request().pipe(
* fields('*'), // select all fields
* fields(["name", "genres.id"]), // select specific fields, incuding sub-type
* fields(["name", "genres.*"]), // select specific fields, incuding all fields of sub-type
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#fields}
* @param f
*/
declare function fields<T extends Record<any, any>, P extends NonEmptyStringList>(f: AllAutoPath<T, P> | '*'): BuilderOperatorNarrow<T, DeepPick<T, ChosenPaths<P>>>;
/**
* Exclude given fields from selection.
* Resulting response type is narrowed to exclude specified fields (not compatible with nested fields).
*
* @example
* ```ts
* request().pipe(
* fields('*'),
* exclude(["name", "created_at"]), // exclude specific fields
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#exclude}
* @param exclude
*/
declare function exclude<T extends Record<any, any>, K extends keyof T>(exclude: K[]): BuilderOperatorNarrow<T, Omit<T, K>>;
/**
* Sort results by specified field.
*
* @example
* ```ts
* request().pipe(
* sort('name'), // defaults to 'asc' when direction is not specified
* sort('name', 'desc'), // manually specify direction
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#sorting}
* @param field
* @param direction
*/
declare function sort<T extends Record<any, any>>(field: keyof T, direction?: 'asc' | 'desc'): BuilderOperator<T, T>;
/**
* Limit the number of results returned by the query.
*
* @example
* ```ts
* request().pipe(
* limit(42), // Only retrieve 42 elements
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#pagination}
* @param limit
*/
declare function limit<T extends Record<any, any>>(limit: number): BuilderOperator<T, T>;
/**
* Start results at a given offset.
*
* @example
* ```ts
* request().pipe(
* offset(50), // Start he results at position 50...
* limit(42), // ...and limit the number of results to 42
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#pagination}
* @param offset
*/
declare function offset<T extends Record<any, any>>(offset: number): BuilderOperator<T, T>;
/**
* Search based on name, results are sorted by similarity to the given search string.
*
* @example
* ```ts
* request().pipe(
* search('zelda'),
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#search-1}
* @param search
*/
declare function search<T extends Record<any, any>>(search: string): BuilderOperator<T, T>;
/**
* Filters results based on given parameters. All parameters are type validated if `request` is given a type.
* Also see {@link whereIn}.
*
* @example
* ```ts
* request<MyType>().pipe(
* where('ratings', '>', 4), // ratings greater than 4
* where('ratings', '>=', 4), // ratings greater than or equal 4
* where('ratings', '<', 4), // ratings less than 4
* where('ratings', '<=', 4), // ratings less than or equal 4
* where('name', '=', 'zelda'), // name is zelda (case sensitive)
* where('name', '~', 'zelda'), // name is zelda (case insensitive)
* where('name', '!=', 'zelda'), // name is not zelda
* where('name', '=', 'zelda', WhereFlags.STARTSWITH), // name starts with zelda (also works with ~)
* where('name', '=', 'zelda', WhereFlags.ENDSWITH), // name ends with zelda (also works with ~)
* where('name', '=', 'zelda', WhereFlags.CONTAINS), // name contains zelda (also works with ~)
* where('release_date', '=', null) // no release date
* where('release_date', '!=', null) // release date has any value
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#filters}
* @param key
* @param op
* @param value
* @param flag
*/
declare function where<T extends Record<any, any>, P extends string>(key: AutoPath<T, P, '.', never>, op: GetOp<Path<T, Split<P, '.'>>>, value: FlatPath<T, Split<P, '.'>> | AllowedValues, flag?: WhereFlags): BuilderOperator<T, T>;
/**
* Filters results based on given parameters. All parameters are type validated if `request` is given a type.
* Also see {@link where}.
*
* @example
* ```ts
* request<MyType>().pipe(
* whereIn('genres', [1, 2], WhereInFlags.AND), // Results whose genres includes 1 and 2
* whereIn('genres', [1, 2], WhereInFlags.OR), // Results whose genres includes 1 or 2
* whereIn('genres', [1, 2], WhereInFlags.NAND), // Results whose genres does not contain both 1 and 2, but can be 1 or 2
* whereIn('genres', [1, 2], WhereInFlags.NOR), // Results whose genres does not contain 1 or does not contain 2
* whereIn('genres', [1, 2], WhereInFlags.EXACT), // Results whose exclusive genres are 1 and 2
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#filters}
* @param key
* @param values
* @param flag
*/
declare function whereIn<T extends Record<any, any>, P extends string>(key: AutoPath<T, P, '.', never>, values: FlatPath<T, Split<P, '.'>>[], flag?: WhereInFlags | WhereFlags): BuilderOperator<T, T>;
/**
* Combine multiple {@link where} and {@link whereIn} conditions.
*
* @example
* ```ts
* // Select results that are on platform 1 and 2, and whose name are either 'zelda' or 'link'
* request<MyType>().pipe(
* and(
* whereIn('platforms', [1, 2], WhereInFlags.AND),
* or(
* where('name', '=', 'zelda'),
* where('name', '=', 'link'),
* )
* )
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#filters}
* @param operators
*/
declare function and<T extends Record<any, any>>(...operators: BuilderOperator<T, T>[]): BuilderOperator<T, T>;
/**
* Combine multiple {@link where} and {@link whereIn} conditions.
*
* @example
* ```ts
* // Select results that are on platform 1 and 2, and whose name are either 'zelda' or 'link'
* request<MyType>().pipe(
* and(
* whereIn('platforms', [1, 2], WhereInFlags.AND),
* or(
* where('name', '=', 'zelda'),
* where('name', '=', 'link'),
* )
* )
* )
* ```
* @see {@link https://api-docs.igdb.com/?shell#filters}
* @param operators
*/
declare function or<T extends Record<any, any>, R>(...operators: BuilderOperator<T, R>[]): BuilderOperator<T, R>;
/**
* Prepare a request to an apicalypse endpoint.
*
* @example
* ```ts
* // MyType is optional but recommended, so that results are properly typed
* request<MyType>().pipe(
* fields(["name"]),
* sort("created_at", "asc"),
* where("created_at", ">", now),
* )
* .execute('http:...')
* .then(results => ...);
* ```
*/
declare function request<T extends Record<any, any>, mode extends 'result' | 'count' = 'result'>(): {
pipe: Pipe<T, mode>;
sub: <S extends string>(queryEndpoint: string, queryName: S) => {
pipe: PipeSub<T, S, mode>;
};
};
/**
* Prepare a multi-query request to an apicalypse endpoint.
*
* @example
* ```ts
* multi(
* // MyType is optional but recommended, so that results are properly typed
* request<MyType>()
* .sub('endpoint', 'alias') // mandatory for multi requests
* .pipe(
* fields(["name"]),
* sort("created_at", "asc"),
* where("created_at", ">", now),
* ),
* request<MyType>()
* .sub('endpoint', 'alias2') // mandatory for multi requests
* .pipe(
* fields(["name"]),
* sort("created_at", "asc"),
* where("created_at", "<", now),
* )
* )
* .execute('http:...')
* .then(response => ...);
* ```
* @see {@link https://api-docs.igdb.com/?shell#multi-query}
* @param builders
*/
declare function multi<T extends Record<any, any>, B extends Builder<T>[]>(...builders: B): Stringifiable & ExecutorMulti<B>;
/**
* Narrow multi-query results types.
*
* @example
* ```ts
* interface MyType {
* name: string,
* created_at: number
* }
*
* multi(
* request<MyType>().sub("games", "latest-games").pipe(
* fields(["name"]),
* sort("created_at", "desc"),
* where("created_at", "<", now),
* ),
* request<MyType>().sub("games", "coming-soon").pipe(
* fields(["created_at"]),
* sort("created_at", "desc"),
* where("created_at", ">", now),
* )
* ).execute('http:...').then(response => {
* for (const result of response.data) {
* if (isNamed(result, 'latest-games')) {
* result.result.name // result is of type `{ name: string }`
* } else {
* result.result.created_at // result is of type `{ created_at: number }`
* }
* }
* });
* ```
* @param builder
* @param name
*/
declare function isNamed<T extends NamedBuilder<any, string>, S extends string>(builder: ResultMultiMono<T>, name: S): builder is ResultMultiMono<Extract<T, NamedBuilder<any, S>>>;
export { type AllAutoPath, type AllowedValues, type AutoPath, type Builder, type BuilderOperator, type BuilderOperatorNarrow, type ChosenPaths, type CountBuilder, type DeepPick, type Executor, type ExecutorMulti, type FallbackIfUnknown, type FlatPath, type GetOp, type NamedBuilder, type NamedBuilderOperator, type NarrowBuilder, type NonEmptyStringList, type NumbersOperatos, type Options, type Path, type Pipe, type PipeSub, type ResultMultiMono, type StandardOperators, type StringOperators, type Stringifiable, WhereFlags, WhereInFlags, and, exclude, fields, isNamed, limit, multi, offset, or, request, search, sort, where, whereIn };