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; 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[]; declare type SingleValuePostgreSQLTypes = 'bool' | 'int2' | 'int4' | 'int8' | 'float4' | 'float8' | 'numeric' | 'bytea' | 'bpchar' | 'varchar' | 'date' | 'text' | 'citext' | 'time' | 'timetz' | 'timestamp' | 'timestamptz' | 'uuid' | 'vector' | 'json' | 'jsonb' | 'void' | 'record' | string; declare type ArrayPostgreSQLTypes = `_${SingleValuePostgreSQLTypes}`; declare type PostgreSQLTypes = SingleValuePostgreSQLTypes | ArrayPostgreSQLTypes; declare type TypeScriptSingleValueTypes = T extends 'bool' ? boolean : T extends 'int2' | 'int4' | 'int8' | 'float4' | 'float8' | 'numeric' ? number : T extends 'bytea' | 'bpchar' | 'varchar' | 'date' | 'text' | 'citext' | 'time' | 'timetz' | 'timestamp' | 'timestamptz' | 'uuid' | 'vector' ? string : T extends 'json' | 'jsonb' ? Json : T extends 'void' ? undefined : T extends 'record' ? Record : unknown; declare type AggregateFunctions = 'count' | 'sum' | 'avg' | 'min' | 'max'; declare type StripUnderscore = T extends `_${infer U}` ? U : T; declare type TypeScriptTypes = T extends ArrayPostgreSQLTypes ? TypeScriptSingleValueTypes>>[] : TypeScriptSingleValueTypes; /** * Parser errors. */ declare type ParserError = { error: true; } & Message; declare type GenericStringError = ParserError<'Received a generic string'>; export declare type SelectQueryError = { error: true; } & Message; /** * Creates a new {@link ParserError} if the given input is not already a parser error. */ declare type CreateParserErrorIfRequired = Input extends ParserError ? Input : ParserError; /** * Trims whitespace from the left of the input. */ declare type EatWhitespace = string extends Input ? GenericStringError : Input extends `${Whitespace}${infer Remainder}` ? EatWhitespace : Input; /** * Returns a boolean representing whether there is a foreign key with the given name. */ declare type HasFKey = Relationships extends [infer R] ? R extends { foreignKeyName: FKeyName; } ? true : false : Relationships extends [infer R, ...infer Rest] ? HasFKey extends true ? true : HasFKey : false; /** * Returns a boolean representing whether there the foreign key has a unique constraint. */ declare type HasUniqueFKey = Relationships extends [infer R] ? R extends { foreignKeyName: FKeyName; isOneToOne: true; } ? true : false : Relationships extends [infer R, ...infer Rest] ? HasUniqueFKey extends true ? true : HasUniqueFKey : false; /** * Returns a boolean representing whether there is a foreign key referencing * a given relation. */ declare type HasFKeyToFRel = Relationships extends [infer R] ? R extends { referencedRelation: FRelName; } ? true : false : Relationships extends [infer R, ...infer Rest] ? HasFKeyToFRel extends true ? true : HasFKeyToFRel : false; declare type HasUniqueFKeyToFRel = Relationships extends [infer R] ? R extends { referencedRelation: FRelName; isOneToOne: true; } ? true : false : Relationships extends [infer R, ...infer Rest] ? HasUniqueFKeyToFRel extends true ? true : HasUniqueFKeyToFRel : false; /** * Constructs a type definition for a single field of an object. * * @param Schema Database schema. * @param Row Type of a row in the given table. * @param Relationships Relationships between different tables in the database. * @param Field Single field parsed by `ParseQuery`. */ declare type ConstructFieldDefinition, RelationName, Relationships, Field> = Field extends { star: true; } ? Row : Field extends { spread: true; original: string; children: unknown[]; } ? GetResultHelper : Field extends { children: []; } ? {} : Field extends { name: string; original: string; hint: string; children: unknown[]; } ? { [_ in Field['name']]: GetResultHelper extends infer Child ? HasUniqueFKey extends true ? Child | null : Relationships extends unknown[] ? HasFKey extends true ? Field extends { inner: true; } ? Child : Child | null : Child[] : Child[] : never; } : Field extends { name: string; original: string; children: unknown[]; } ? { [_ in Field['name']]: GetResultHelper extends infer Child ? HasUniqueFKeyToFRel extends true ? Child | null : Relationships extends unknown[] ? HasFKeyToFRel extends true ? Field extends { inner: true; } ? Child : Child | null : Child[] : Child[] : never; } : Field extends { name: string; type: infer T; } ? { [K in Field['name']]: T; } : Field extends { name: string; original: string; } ? Field['original'] extends keyof Row ? { [K in Field['name']]: Row[Field['original']]; } : Field['original'] extends 'count' ? { count: number; } : SelectQueryError<`Referencing missing column \`${Field['original']}\``> : Record; /** * 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 1 or more letter, where letters are `[0-9a-zA-Z_]`. */ declare type ReadLetters = string extends Input ? GenericStringError : ReadLettersHelper extends [`${infer Letters}`, `${infer Remainder}`] ? Letters extends '' ? ParserError<`Expected letter at \`${Input}\``> : [Letters, Remainder] : ReadLettersHelper; declare type ReadLettersHelper = string extends Input ? GenericStringError : Input extends `${infer L}${infer Remainder}` ? L extends Letter ? ReadLettersHelper : [Acc, Input] : [Acc, '']; /** * Reads a consecutive sequence of 1 or more double-quoted letters, * where letters are `[^"]`. */ declare type ReadQuotedLetters = string extends Input ? GenericStringError : Input extends `"${infer Remainder}` ? ReadQuotedLettersHelper extends [`${infer Letters}`, `${infer Remainder}`] ? Letters extends '' ? ParserError<`Expected string at \`${Remainder}\``> : [Letters, Remainder] : ReadQuotedLettersHelper : ParserError<`Not a double-quoted string at \`${Input}\``>; declare type ReadQuotedLettersHelper = string extends Input ? GenericStringError : Input extends `${infer L}${infer Remainder}` ? L extends '"' ? [Acc, Remainder] : ReadQuotedLettersHelper : ParserError<`Missing closing double-quote in \`"${Acc}${Input}\``>; /** * Parses a (possibly double-quoted) identifier. * Identifiers are sequences of 1 or more letters. */ declare type ParseIdentifier = ReadLetters extends [ infer Name, `${infer Remainder}` ] ? [Name, `${Remainder}`] : ReadQuotedLetters extends [infer Name, `${infer Remainder}`] ? [Name, `${Remainder}`] : ParserError<`No (possibly double-quoted) identifier at \`${Input}\``>; /** * Parses a field without preceding field renaming. * A field is one of the following: * - a field with an embedded resource * - `field(nodes)` * - `field!hint(nodes)` * - `field!inner(nodes)` * - `field!hint!inner(nodes)` * - a field without an embedded resource (see {@link ParseFieldWithoutEmbeddedResource}) */ declare type ParseField = Input extends '' ? ParserError<'Empty string'> : ParseIdentifier extends [infer Name, `${infer Remainder}`] ? EatWhitespace extends `!inner${infer Remainder}` ? ParseEmbeddedResource> extends [infer Fields, `${infer Remainder}`] ? [ { name: Name; original: Name; children: Fields; inner: true; }, EatWhitespace ] : CreateParserErrorIfRequired>, 'Expected embedded resource after `!inner`'> : EatWhitespace extends `!${infer Remainder}` ? ParseIdentifier> extends [infer Hint, `${infer Remainder}`] ? EatWhitespace extends `!inner${infer Remainder}` ? ParseEmbeddedResource> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: Name; hint: Hint; children: Fields; inner: true; }, EatWhitespace ] : CreateParserErrorIfRequired>, 'Expected embedded resource after `!inner`'> : ParseEmbeddedResource> extends [ infer Fields, `${infer Remainder}` ] ? [ { name: Name; original: Name; hint: Hint; children: Fields; }, EatWhitespace ] : CreateParserErrorIfRequired>, 'Expected embedded resource after `!hint`'> : ParserError<'Expected identifier after `!`'> : ParseEmbeddedResource> extends [infer Fields, `${infer Remainder}`] ? [ { name: Name; original: Name; children: Fields; }, EatWhitespace ] : ParseEmbeddedResource> extends ParserError ? ParseEmbeddedResource> : ParseFieldWithoutEmbeddedResource : ParserError<`Expected identifier at \`${Input}\``>; /** * Parses a field excluding embedded resources, without preceding field renaming. * This is one of the following: * - `field` * - `field.aggregate()` * - `field.aggregate()::type` * - `field::type` * - `field::type.aggregate()` * - `field::type.aggregate()::type` * - `field->json...` * - `field->json.aggregate()` * - `field->json.aggregate()::type` * - `field->json::type` * - `field->json::type.aggregate()` * - `field->json::type.aggregate()::type` */ declare type ParseFieldWithoutEmbeddedResource = ParseFieldWithoutEmbeddedResourceAndAggregation extends [infer Field, `${infer Remainder}`] ? ParseFieldAggregation> extends [ `${infer AggregateFunction}`, `${infer Remainder}` ] ? ParseFieldTypeCast> extends [infer Type, `${infer Remainder}`] ? [ Omit & { name: AggregateFunction; original: AggregateFunction; type: Type; }, EatWhitespace ] : ParseFieldTypeCast> extends ParserError ? ParseFieldTypeCast> : [ Omit & { name: AggregateFunction; original: AggregateFunction; }, EatWhitespace ] : ParseFieldAggregation> extends ParserError ? ParseFieldAggregation> : [ Field, EatWhitespace ] : CreateParserErrorIfRequired, `Expected field at \`${Input}\``>; /** * Parses a field excluding embedded resources or aggregation, without preceding field renaming. * This is one of the following: * - `field` * - `field::type` * - `field->json...` * - `field->json...::type` */ declare type ParseFieldWithoutEmbeddedResourceAndAggregation = ParseFieldWithoutEmbeddedResourceAndTypeCast extends [infer Field, `${infer Remainder}`] ? ParseFieldTypeCast> extends [infer Type, `${infer Remainder}`] ? [ Omit & { type: Type; }, EatWhitespace ] : ParseFieldTypeCast> extends ParserError ? ParseFieldTypeCast> : [ Field, EatWhitespace ] : CreateParserErrorIfRequired, `Expected field at \`${Input}\``>; /** * Parses a field excluding embedded resources or typecasting, without preceding field renaming. * This is one of the following: * - `field` * - `field->json...` */ declare type ParseFieldWithoutEmbeddedResourceAndTypeCast = ParseIdentifier extends [infer Name, `${infer Remainder}`] ? ParseJsonAccessor> extends [ infer PropertyName, infer PropertyType, `${infer Remainder}` ] ? [ { name: PropertyName; original: PropertyName; type: PropertyType; }, EatWhitespace ] : [ { name: Name; original: Name; }, EatWhitespace ] : ParserError<`Expected field at \`${Input}\``>; /** * Parses a field typecast (`::type`), returning a tuple of ["Type", "Remainder of text"] * or the original string input indicating that no typecast was found. */ declare type ParseFieldTypeCast = EatWhitespace extends `::${infer Remainder}` ? ParseIdentifier> extends [`${infer CastType}`, `${infer Remainder}`] ? CastType extends PostgreSQLTypes ? [TypeScriptTypes, EatWhitespace] : ParserError<`Invalid type for \`::\` operator \`${CastType}\``> : ParserError<`Invalid type for \`::\` operator at \`${Remainder}\``> : Input; /** * Parses a field aggregation (`.max()`), returning a tuple of ["Aggregate function", "Remainder of text"] * or the original string input indicating that no aggregation was found. */ declare type ParseFieldAggregation = EatWhitespace extends `.${infer Remainder}` ? ParseIdentifier> extends [ `${infer FunctionName}`, `${infer Remainder}` ] ? FunctionName extends AggregateFunctions ? EatWhitespace extends `()${infer Remainder}` ? [FunctionName, EatWhitespace] : ParserError<`Expected \`()\` after \`.\` operator \`${FunctionName}\``> : ParserError<`Invalid type for \`.\` operator \`${FunctionName}\``> : ParserError<`Invalid type for \`.\` operator at \`${Remainder}\``> : Input; /** * Parses a node. * A node is one of the following: * - `*` * - a field, as defined above * - a renamed field, `renamed_field:field` * - a spread field, `...field` */ declare type ParseNode = Input extends '' ? ParserError<'Empty string'> : Input extends `*${infer Remainder}` ? [{ star: true; }, EatWhitespace] : Input extends `...${infer Remainder}` ? ParseField> extends [infer Field, `${infer Remainder}`] ? Field extends { children: unknown[]; } ? [Prettify<{ spread: true; } & Field>, EatWhitespace] : ParserError<'Unable to parse spread resource'> : ParserError<'Unable to parse spread resource'> : ParseIdentifier extends [infer Name, `${infer Remainder}`] ? EatWhitespace extends `::${infer _Remainder}` ? ParseField : EatWhitespace extends `:${infer Remainder}` ? ParseField> extends [infer Field, `${infer Remainder}`] ? Field extends { name: string; } ? [Prettify & { name: Name; }>, EatWhitespace] : ParserError<`Unable to parse renamed field`> : ParserError<`Unable to parse renamed field`> : ParseField : 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 `->${infer Remainder}` ? Remainder extends `>${infer Remainder}` ? ParseIdentifier extends [infer Name, `${infer Remainder}`] ? [Name, string, EatWhitespace] : ParserError<'Expected property name after `->>`'> : ParseIdentifier extends [infer Name, `${infer Remainder}`] ? ParseJsonAccessor extends [ infer PropertyName, infer PropertyType, `${infer Remainder}` ] ? [PropertyName, PropertyType, EatWhitespace] : [Name, Json, EatWhitespace] : ParserError<'Expected property name after `->`'> : Input; /** * Parses an embedded resource, which is an opening `(`, followed by a sequence of * 0 or more 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 `(${infer Remainder}` ? ParseNodes> extends [infer Fields, `${infer Remainder}`] ? EatWhitespace extends `)${infer Remainder}` ? [Fields, EatWhitespace] : ParserError<`Expected ")"`> : ParseNodes> extends ParserError ? EatWhitespace extends `)${infer Remainder}` ? [[], EatWhitespace] : ParseNodes> : ParserError<'Expected embedded resource fields or `)`'> : Input; /** * Parses a sequence of nodes, separated by `,`. * * Returns a tuple of ["Parsed fields", "Remainder of text"] or an error. */ declare type ParseNodes = string extends Input ? GenericStringError : ParseNodesHelper; declare type ParseNodesHelper = ParseNode extends [ infer Field, `${infer Remainder}` ] ? EatWhitespace extends `,${infer Remainder}` ? ParseNodesHelper, [Field, ...Fields]> : [[Field, ...Fields], EatWhitespace] : ParseNode; /** * 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 = string extends Query ? GenericStringError : ParseNodes> extends [infer Fields, `${infer Remainder}`] ? EatWhitespace extends '' ? Fields : ParserError<`Unexpected input: ${Remainder}`> : ParseNodes>; declare type GetResultHelper, RelationName, Relationships, Fields extends unknown[], Acc> = Fields extends [infer R] ? ConstructFieldDefinition extends SelectQueryError ? SelectQueryError : GetResultHelper & Acc> : Fields extends [infer R, ...infer Rest] ? ConstructFieldDefinition extends SelectQueryError ? SelectQueryError : GetResultHelper & Acc> : Prettify; /** * Constructs a type definition for an object based on a given PostgREST query. * * @param Schema Database schema. * @param Row Type of a row in the given table. * @param Relationships Relationships between different tables in the database. * @param Query Select query string literal to parse. */ export declare type GetResult, RelationName, Relationships, Query extends string> = ParseQuery extends unknown[] ? GetResultHelper, unknown> : ParseQuery; export {}; //# sourceMappingURL=select-query-parser.d.ts.map