ts-apicalypse
Version:
A Typescript client and request builder for Apicalypse
918 lines (890 loc) • 32.5 kB
text/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,
NUMBER = 1,
STRING = 2,
STARTSWITH = 6,
ENDSWITH = 10,
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 { AllAutoPath, AllowedValues, AutoPath, Builder, BuilderOperator, BuilderOperatorNarrow, ChosenPaths, CountBuilder, DeepPick, Executor, ExecutorMulti, FallbackIfUnknown, FlatPath, GetOp, NamedBuilder, NamedBuilderOperator, NarrowBuilder, NonEmptyStringList, NumbersOperatos, Options, Path, Pipe, PipeSub, ResultMultiMono, StandardOperators, StringOperators, Stringifiable, WhereFlags, WhereInFlags, and, exclude, fields, isNamed, limit, multi, offset, or, request, search, sort, where, whereIn };