UNPKG

@miuiu/postgrest

Version:
272 lines 13.3 kB
import { GenericSchema, Prettify } from "./types"; declare type Whitespace = " " | "\n" | "\t"; declare type LowerAlphabet = "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"; declare type Alphabet = LowerAlphabet | Uppercase<LowerAlphabet>; declare type Digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0"; declare type Letter = Alphabet | Digit | "_"; declare type Json = string | number | boolean | null | { [key: string]: Json; } | Json[]; /** * Parser errors. */ declare type ParserError<Message extends string> = { error: true; } & Message; declare type GenericStringError = ParserError<"Received a generic string">; /** * Trims whitespace from the left of the input. */ declare type EatWhitespace<Input extends string> = string extends Input ? GenericStringError : Input extends `${Whitespace}${infer Remainder}` ? EatWhitespace<Remainder> : Input; /** * Constructs a type definition for a single field of an object. * * @param Definitions Record of definitions, possibly generated from PostgREST's OpenAPI spec. * @param Name Name of the table being queried. * @param Field Single field parsed by `ParseQuery`. */ declare type ConstructFieldDefinition<Schema extends GenericSchema, Row extends Record<string, unknown>, Field> = Field extends { star: true; } ? Row : Field extends { name: string; original: string; children: unknown[]; } ? { [_ in Field["name"]]: GetResultHelper<Schema, (Schema["Tables"] & Schema["Views"])[Field["original"]]["Row"], Field["children"], unknown> extends infer Child ? Child | Child[] | null : never; } : Field extends { name: string; original: string; } ? { [K in Field["name"]]: Row[Field["original"]]; } : Field extends { name: string; type: infer T; } ? { [K in Field["name"]]: T; } : Record<string, unknown>; /** * Notes: all `Parse*` types assume that their input strings have their whitespace * removed. They return tuples of ["Return Value", "Remainder of text"] or * a `ParserError`. */ /** * Reads a consecutive sequence of more than 1 letter, * where letters are `[0-9a-zA-Z_]`. */ declare type ReadLetters<Input extends string> = string extends Input ? GenericStringError : ReadLettersHelper<Input, ""> extends [ `${infer Letters}`, `${infer Remainder}` ] ? Letters extends "" ? ParserError<`Expected letter at \`${Input}\``> : [Letters, Remainder] : ReadLettersHelper<Input, "">; declare type ReadLettersHelper<Input extends string, Acc extends string> = string extends Input ? GenericStringError : Input extends `${infer L}${infer Remainder}` ? L extends Letter ? ReadLettersHelper<Remainder, `${Acc}${L}`> : [Acc, Input] : [Acc, ""]; /** * Reads a consecutive sequence of more than 1 double-quoted letters, * where letters are `[^"]`. */ declare type ReadQuotedLetters<Input extends string> = string extends Input ? GenericStringError : Input extends `"${infer Remainder}` ? ReadQuotedLettersHelper<Remainder, ""> extends [ `${infer Letters}`, `${infer Remainder}` ] ? Letters extends "" ? ParserError<`Expected string at \`${Remainder}\``> : [Letters, Remainder] : ReadQuotedLettersHelper<Remainder, ""> : ParserError<`Not a double-quoted string at \`${Input}\``>; declare type ReadQuotedLettersHelper<Input extends string, Acc extends string> = string extends Input ? GenericStringError : Input extends `${infer L}${infer Remainder}` ? L extends '"' ? [Acc, Remainder] : ReadQuotedLettersHelper<Remainder, `${Acc}${L}`> : ParserError<`Missing closing double-quote in \`"${Acc}${Input}\``>; /** * Parses a (possibly double-quoted) identifier. * For now, identifiers are just sequences of more than 1 letter. */ declare type ParseIdentifier<Input extends string> = ReadLetters<Input> extends [ infer Name, `${infer Remainder}` ] ? [Name, `${Remainder}`] : ReadQuotedLetters<Input> extends [infer Name, `${infer Remainder}`] ? [Name, `${Remainder}`] : ParserError<`No (possibly double-quoted) identifier at \`${Input}\``>; /** * Parses a node. * A node is one of the following: * - `*` * - `field` * - `field->json...` * - `field(nodes)` * - `field!hint(nodes)` * - `field!inner(nodes)` * - `field!hint!inner(nodes)` * - `renamed_field:field` * - `renamed_field:field->json...` * - `renamed_field:field(nodes)` * - `renamed_field:field!hint(nodes)` * - `renamed_field:field!inner(nodes)` * - `renamed_field:field!hint!inner(nodes)` * * TODO: casting operators `::text`, more support for JSON operators `->`, `->>`. */ declare type ParseNode<Input extends string> = Input extends "" ? ParserError<"Empty string"> : Input extends `*${infer Remainder}` ? [{ star: true; }, EatWhitespace<Remainder>] : ParseIdentifier<Input> extends [infer Name, `${infer Remainder}`] ? EatWhitespace<Remainder> extends `!inner${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: Name; children: Fields; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<"Expected embedded resource after `!inner`"> : EatWhitespace<Remainder> extends `!${infer Remainder}` ? ParseIdentifier<EatWhitespace<Remainder>> extends [ infer _Hint, `${infer Remainder}` ] ? EatWhitespace<Remainder> extends `!inner${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: Name; children: Fields; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<"Expected embedded resource after `!inner`"> : ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: Name; children: Fields; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<"Expected embedded resource after `!hint`"> : ParserError<"Expected identifier after `!`"> : EatWhitespace<Remainder> extends `:${infer Remainder}` ? ParseIdentifier<EatWhitespace<Remainder>> extends [ infer OriginalName, `${infer Remainder}` ] ? EatWhitespace<Remainder> extends `!inner${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: OriginalName; children: Fields; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<"Expected embedded resource after `!inner`"> : EatWhitespace<Remainder> extends `!${infer Remainder}` ? ParseIdentifier<EatWhitespace<Remainder>> extends [ infer _Hint, `${infer Remainder}` ] ? EatWhitespace<Remainder> extends `!inner${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: OriginalName; children: Fields; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<"Expected embedded resource after `!inner`"> : ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: OriginalName; children: Fields; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<"Expected embedded resource after `!hint`"> : ParserError<"Expected identifier after `!`"> : ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: OriginalName; children: Fields; }, EatWhitespace<Remainder> ] : ParseJsonAccessor<EatWhitespace<Remainder>> extends [ infer _PropertyName, infer PropertyType, `${infer Remainder}` ] ? [ { name: Name; type: PropertyType; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : [ { name: Name; original: OriginalName; }, EatWhitespace<Remainder> ] : ParseIdentifier<EatWhitespace<Remainder>> : ParseEmbeddedResource<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: Name; children: Fields; }, EatWhitespace<Remainder> ] : ParseJsonAccessor<EatWhitespace<Remainder>> extends [ infer PropertyName, infer PropertyType, `${infer Remainder}` ] ? [ { name: PropertyName; type: PropertyType; }, EatWhitespace<Remainder> ] : ParseEmbeddedResource<EatWhitespace<Remainder>> extends ParserError<string> ? ParseEmbeddedResource<EatWhitespace<Remainder>> : [ { name: Name; original: Name; }, EatWhitespace<Remainder> ] : ParserError<`Expected identifier at \`${Input}\``>; /** * Parses a JSON property accessor of the shape `->a->b->c`. The last accessor in * the series may convert to text by using the ->> operator instead of ->. * * Returns a tuple of ["Last property name", "Last property type", "Remainder of text"] * or the original string input indicating that no opening `->` was found. */ declare type ParseJsonAccessor<Input extends string> = Input extends `->${infer Remainder}` ? Remainder extends `>${infer Remainder}` ? ParseIdentifier<Remainder> extends [infer Name, `${infer Remainder}`] ? [Name, string, EatWhitespace<Remainder>] : ParserError<"Expected property name after `->>`"> : ParseIdentifier<Remainder> extends [infer Name, `${infer Remainder}`] ? ParseJsonAccessor<Remainder> extends [ infer PropertyName, infer PropertyType, `${infer Remainder}` ] ? [PropertyName, PropertyType, EatWhitespace<Remainder>] : [Name, Json, EatWhitespace<Remainder>] : ParserError<"Expected property name after `->`"> : Input; /** * Parses an embedded resource, which is an opening `(`, followed by a sequence of * nodes, separated by `,`, then a closing `)`. * * Returns a tuple of ["Parsed fields", "Remainder of text"], an error, * or the original string input indicating that no opening `(` was found. */ declare type ParseEmbeddedResource<Input extends string> = Input extends `(${infer Remainder}` ? ParseNodes<EatWhitespace<Remainder>> extends [ infer Fields, `${infer Remainder}` ] ? EatWhitespace<Remainder> extends `)${infer Remainder}` ? Fields extends [] ? ParserError<"Expected fields after `(`"> : [Fields, EatWhitespace<Remainder>] : ParserError<`Expected ")"`> : ParseNodes<EatWhitespace<Remainder>> : Input; /** * Parses a sequence of nodes, separated by `,`. * * Returns a tuple of ["Parsed fields", "Remainder of text"] or an error. */ declare type ParseNodes<Input extends string> = string extends Input ? GenericStringError : ParseNodesHelper<Input, []>; declare type ParseNodesHelper<Input extends string, Fields extends unknown[]> = ParseNode<Input> extends [infer Field, `${infer Remainder}`] ? EatWhitespace<Remainder> extends `,${infer Remainder}` ? ParseNodesHelper<EatWhitespace<Remainder>, [Field, ...Fields]> : [[Field, ...Fields], EatWhitespace<Remainder>] : ParseNode<Input>; /** * Parses a query. * A query is a sequence of nodes, separated by `,`, ensuring that there is * no remaining input after all nodes have been parsed. * * Returns an array of parsed nodes, or an error. */ declare type ParseQuery<Query extends string> = string extends Query ? GenericStringError : ParseNodes<EatWhitespace<Query>> extends [ infer Fields, `${infer Remainder}` ] ? EatWhitespace<Remainder> extends "" ? Fields : ParserError<`Unexpected input: ${Remainder}`> : ParseNodes<EatWhitespace<Query>>; declare type GetResultHelper<Schema extends GenericSchema, Row extends Record<string, unknown>, Fields extends unknown[], Acc> = Fields extends [infer R] ? GetResultHelper<Schema, Row, [ ], ConstructFieldDefinition<Schema, Row, R> & Acc> : Fields extends [infer R, ...infer Rest] ? GetResultHelper<Schema, Row, Rest, ConstructFieldDefinition<Schema, Row, R> & Acc> : Prettify<Acc>; /** * Constructs a type definition for an object based on a given PostgREST query. * * @param Row Record<string, unknown>. * @param Query Select query string literal to parse. */ export declare type GetResult<Schema extends GenericSchema, Row extends Record<string, unknown>, Query extends string> = ParseQuery<Query> extends unknown[] ? GetResultHelper<Schema, Row, ParseQuery<Query>, unknown> : ParseQuery<Query>; export {}; //# sourceMappingURL=select-query-parser.d.ts.map