@cloudbase/wx-cloud-client-sdk 1.6.1 → 1.7.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/db/mysql/MySqlClient.d.ts +26 -0
- package/lib/db/mysql/MySqlFilterBuilder.d.ts +11 -0
- package/lib/db/mysql/MySqlQueryBuilder.d.ts +11 -0
- package/lib/db/mysql/index.d.ts +7 -0
- package/lib/db/mysql/polyfill.d.ts +72 -0
- package/lib/db/postgrest/PostgrestBuilder.d.ts +70 -0
- package/lib/db/postgrest/PostgrestClient.d.ts +73 -0
- package/lib/db/postgrest/PostgrestError.d.ts +16 -0
- package/lib/db/postgrest/PostgrestFilterBuilder.d.ts +107 -0
- package/lib/db/postgrest/PostgrestQueryBuilder.d.ts +116 -0
- package/lib/db/postgrest/PostgrestTransformBuilder.d.ts +156 -0
- package/lib/db/postgrest/constants.d.ts +3 -0
- package/lib/db/postgrest/index.d.ts +18 -0
- package/lib/db/postgrest/select-query-parser/parser.d.ts +302 -0
- package/lib/db/postgrest/select-query-parser/result.d.ts +156 -0
- package/lib/db/postgrest/select-query-parser/types.d.ts +33 -0
- package/lib/db/postgrest/select-query-parser/utils.d.ts +266 -0
- package/lib/db/postgrest/types.d.ts +109 -0
- package/lib/db/postgrest/version.d.ts +1 -0
- package/lib/index.d.ts +15 -3
- package/lib/types/index.d.ts +7 -0
- package/lib/wxCloudClientSDK.cjs.js +5084 -10
- package/lib/wxCloudClientSDK.esm.js +5084 -11
- package/lib/wxCloudClientSDK.umd.js +5084 -10
- package/package.json +5 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import PostgrestBuilder from "./PostgrestBuilder";
|
|
2
|
+
import { InvalidMethodError } from "./PostgrestFilterBuilder";
|
|
3
|
+
import { GetResult } from "./select-query-parser/result";
|
|
4
|
+
import { GenericSchema, CheckMatchingArrayTypes, ClientServerOptions, MaxAffectedEnabled } from "./types";
|
|
5
|
+
export default class PostgrestTransformBuilder<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Row extends Record<string, unknown>, Result, RelationName = unknown, Relationships = unknown, Method = unknown> extends PostgrestBuilder<ClientOptions, Result> {
|
|
6
|
+
/**
|
|
7
|
+
* Perform a SELECT on the query result.
|
|
8
|
+
*
|
|
9
|
+
* By default, `.insert()`, `.update()`, `.upsert()`, and `.delete()` do not
|
|
10
|
+
* return modified rows. By calling this method, modified rows are returned in
|
|
11
|
+
* `data`.
|
|
12
|
+
*
|
|
13
|
+
* @param columns - The columns to retrieve, separated by commas
|
|
14
|
+
*/
|
|
15
|
+
select<Query extends string = "*", NewResultOne = GetResult<Schema, Row, RelationName, Relationships, Query, ClientOptions>>(columns?: Query): PostgrestTransformBuilder<ClientOptions, Schema, Row, NewResultOne[], RelationName, Relationships, Method>;
|
|
16
|
+
order<ColumnName extends string & keyof Row>(column: ColumnName, options?: {
|
|
17
|
+
ascending?: boolean;
|
|
18
|
+
nullsFirst?: boolean;
|
|
19
|
+
referencedTable?: undefined;
|
|
20
|
+
}): this;
|
|
21
|
+
order(column: string, options?: {
|
|
22
|
+
ascending?: boolean;
|
|
23
|
+
nullsFirst?: boolean;
|
|
24
|
+
referencedTable?: string;
|
|
25
|
+
}): this;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Use `options.referencedTable` instead of `options.foreignTable`
|
|
28
|
+
*/
|
|
29
|
+
order<ColumnName extends string & keyof Row>(column: ColumnName, options?: {
|
|
30
|
+
ascending?: boolean;
|
|
31
|
+
nullsFirst?: boolean;
|
|
32
|
+
foreignTable?: undefined;
|
|
33
|
+
}): this;
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated Use `options.referencedTable` instead of `options.foreignTable`
|
|
36
|
+
*/
|
|
37
|
+
order(column: string, options?: {
|
|
38
|
+
ascending?: boolean;
|
|
39
|
+
nullsFirst?: boolean;
|
|
40
|
+
foreignTable?: string;
|
|
41
|
+
}): this;
|
|
42
|
+
/**
|
|
43
|
+
* Limit the query result by `count`.
|
|
44
|
+
*
|
|
45
|
+
* @param count - The maximum number of rows to return
|
|
46
|
+
* @param options - Named parameters
|
|
47
|
+
* @param options.referencedTable - Set this to limit rows of referenced
|
|
48
|
+
* tables instead of the parent table
|
|
49
|
+
* @param options.foreignTable - Deprecated, use `options.referencedTable`
|
|
50
|
+
* instead
|
|
51
|
+
*/
|
|
52
|
+
limit(count: number, { foreignTable, referencedTable, }?: {
|
|
53
|
+
foreignTable?: string;
|
|
54
|
+
referencedTable?: string;
|
|
55
|
+
}): this;
|
|
56
|
+
/**
|
|
57
|
+
* Limit the query result by starting at an offset `from` and ending at the offset `to`.
|
|
58
|
+
* Only records within this range are returned.
|
|
59
|
+
* This respects the query order and if there is no order clause the range could behave unexpectedly.
|
|
60
|
+
* The `from` and `to` values are 0-based and inclusive: `range(1, 3)` will include the second, third
|
|
61
|
+
* and fourth rows of the query.
|
|
62
|
+
*
|
|
63
|
+
* @param from - The starting index from which to limit the result
|
|
64
|
+
* @param to - The last index to which to limit the result
|
|
65
|
+
* @param options - Named parameters
|
|
66
|
+
* @param options.referencedTable - Set this to limit rows of referenced
|
|
67
|
+
* tables instead of the parent table
|
|
68
|
+
* @param options.foreignTable - Deprecated, use `options.referencedTable`
|
|
69
|
+
* instead
|
|
70
|
+
*/
|
|
71
|
+
range(from: number, to: number, { foreignTable, referencedTable, }?: {
|
|
72
|
+
foreignTable?: string;
|
|
73
|
+
referencedTable?: string;
|
|
74
|
+
}): this;
|
|
75
|
+
/**
|
|
76
|
+
* Set the AbortSignal for the fetch request.
|
|
77
|
+
*
|
|
78
|
+
* @param signal - The AbortSignal to use for the fetch request
|
|
79
|
+
*/
|
|
80
|
+
abortSignal(signal: AbortSignal): this;
|
|
81
|
+
/**
|
|
82
|
+
* Return `data` as a single object instead of an array of objects.
|
|
83
|
+
*
|
|
84
|
+
* Query result must be one row (e.g. using `.limit(1)`), otherwise this
|
|
85
|
+
* returns an error.
|
|
86
|
+
*/
|
|
87
|
+
single<ResultOne = Result extends (infer ResultOne)[] ? ResultOne : never>(): PostgrestBuilder<ClientOptions, ResultOne>;
|
|
88
|
+
/**
|
|
89
|
+
* Return `data` as a single object instead of an array of objects.
|
|
90
|
+
*
|
|
91
|
+
* Query result must be zero or one row (e.g. using `.limit(1)`), otherwise
|
|
92
|
+
* this returns an error.
|
|
93
|
+
*/
|
|
94
|
+
maybeSingle<ResultOne = Result extends (infer ResultOne)[] ? ResultOne : never>(): PostgrestBuilder<ClientOptions, ResultOne | null>;
|
|
95
|
+
/**
|
|
96
|
+
* Return `data` as a string in CSV format.
|
|
97
|
+
*/
|
|
98
|
+
csv(): PostgrestBuilder<ClientOptions, string>;
|
|
99
|
+
/**
|
|
100
|
+
* Return `data` as an object in [GeoJSON](https://geojson.org) format.
|
|
101
|
+
*/
|
|
102
|
+
geojson(): PostgrestBuilder<ClientOptions, Record<string, unknown>>;
|
|
103
|
+
/**
|
|
104
|
+
* Return `data` as the EXPLAIN plan for the query.
|
|
105
|
+
*
|
|
106
|
+
* You need to enable the
|
|
107
|
+
* [db_plan_enabled](https://supabase.com/docs/guides/database/debugging-performance#enabling-explain)
|
|
108
|
+
* setting before using this method.
|
|
109
|
+
*
|
|
110
|
+
* @param options - Named parameters
|
|
111
|
+
*
|
|
112
|
+
* @param options.analyze - If `true`, the query will be executed and the
|
|
113
|
+
* actual run time will be returned
|
|
114
|
+
*
|
|
115
|
+
* @param options.verbose - If `true`, the query identifier will be returned
|
|
116
|
+
* and `data` will include the output columns of the query
|
|
117
|
+
*
|
|
118
|
+
* @param options.settings - If `true`, include information on configuration
|
|
119
|
+
* parameters that affect query planning
|
|
120
|
+
*
|
|
121
|
+
* @param options.buffers - If `true`, include information on buffer usage
|
|
122
|
+
*
|
|
123
|
+
* @param options.wal - If `true`, include information on WAL record generation
|
|
124
|
+
*
|
|
125
|
+
* @param options.format - The format of the output, can be `"text"` (default)
|
|
126
|
+
* or `"json"`
|
|
127
|
+
*/
|
|
128
|
+
explain({ analyze, verbose, settings, buffers, wal, format, }?: {
|
|
129
|
+
analyze?: boolean;
|
|
130
|
+
verbose?: boolean;
|
|
131
|
+
settings?: boolean;
|
|
132
|
+
buffers?: boolean;
|
|
133
|
+
wal?: boolean;
|
|
134
|
+
format?: "json" | "text";
|
|
135
|
+
}): PostgrestBuilder<ClientOptions, string, false> | PostgrestBuilder<ClientOptions, Record<string, unknown>[], false>;
|
|
136
|
+
/**
|
|
137
|
+
* Rollback the query.
|
|
138
|
+
*
|
|
139
|
+
* `data` will still be returned, but the query is not committed.
|
|
140
|
+
*/
|
|
141
|
+
rollback(): this;
|
|
142
|
+
/**
|
|
143
|
+
* Override the type of the returned `data`.
|
|
144
|
+
*
|
|
145
|
+
* @typeParam NewResult - The new result type to override with
|
|
146
|
+
* @deprecated Use overrideTypes<yourType, { merge: false }>() method at the end of your call chain instead
|
|
147
|
+
*/
|
|
148
|
+
returns<NewResult>(): PostgrestTransformBuilder<ClientOptions, Schema, Row, CheckMatchingArrayTypes<Result, NewResult>, RelationName, Relationships, Method>;
|
|
149
|
+
/**
|
|
150
|
+
* Set the maximum number of rows that can be affected by the query.
|
|
151
|
+
* Only available in PostgREST v13+ and only works with PATCH and DELETE methods.
|
|
152
|
+
*
|
|
153
|
+
* @param value - The maximum number of rows that can be affected
|
|
154
|
+
*/
|
|
155
|
+
maxAffected(value: number): MaxAffectedEnabled<ClientOptions["PostgrestVersion"]> extends true ? Method extends "PATCH" | "DELETE" | "RPC" ? this : InvalidMethodError<"maxAffected method only available on update or delete"> : InvalidMethodError<"maxAffected method only available on postgrest 13+">;
|
|
156
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import PostgrestClient from "./PostgrestClient";
|
|
2
|
+
import PostgrestQueryBuilder from "./PostgrestQueryBuilder";
|
|
3
|
+
import PostgrestFilterBuilder from "./PostgrestFilterBuilder";
|
|
4
|
+
import PostgrestTransformBuilder from "./PostgrestTransformBuilder";
|
|
5
|
+
import PostgrestBuilder from "./PostgrestBuilder";
|
|
6
|
+
import PostgrestError from "./PostgrestError";
|
|
7
|
+
export { PostgrestClient, PostgrestQueryBuilder, PostgrestFilterBuilder, PostgrestTransformBuilder, PostgrestBuilder, PostgrestError, };
|
|
8
|
+
declare const _default: {
|
|
9
|
+
PostgrestClient: typeof PostgrestClient;
|
|
10
|
+
PostgrestQueryBuilder: typeof PostgrestQueryBuilder;
|
|
11
|
+
PostgrestFilterBuilder: typeof PostgrestFilterBuilder;
|
|
12
|
+
PostgrestTransformBuilder: typeof PostgrestTransformBuilder;
|
|
13
|
+
PostgrestBuilder: typeof PostgrestBuilder;
|
|
14
|
+
PostgrestError: typeof PostgrestError;
|
|
15
|
+
};
|
|
16
|
+
export default _default;
|
|
17
|
+
export type { PostgrestResponse, PostgrestResponseFailure, PostgrestResponseSuccess, PostgrestSingleResponse, PostgrestMaybeSingleResponse, ClientServerOptions, GetGenericDatabaseWithOptions, } from "./types";
|
|
18
|
+
export type { GetResult as UnstableGetResult } from "./select-query-parser/result";
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { SimplifyDeep } from "../types";
|
|
2
|
+
import { JsonPathToAccessor } from "./utils";
|
|
3
|
+
/**
|
|
4
|
+
* Parses a query.
|
|
5
|
+
* A query is a sequence of nodes, separated by `,`, ensuring that there is
|
|
6
|
+
* no remaining input after all nodes have been parsed.
|
|
7
|
+
*
|
|
8
|
+
* Returns an array of parsed nodes, or an error.
|
|
9
|
+
*/
|
|
10
|
+
export type ParseQuery<Query extends string> = string extends Query ? GenericStringError : ParseNodes<EatWhitespace<Query>> extends [infer Nodes, `${infer Remainder}`] ? Nodes extends Ast.Node[] ? EatWhitespace<Remainder> extends "" ? SimplifyDeep<Nodes> : ParserError<`Unexpected input: ${Remainder}`> : ParserError<"Invalid nodes array structure"> : ParseNodes<EatWhitespace<Query>>;
|
|
11
|
+
/**
|
|
12
|
+
* Notes: all `Parse*` types assume that their input strings have their whitespace
|
|
13
|
+
* removed. They return tuples of ["Return Value", "Remainder of text"] or
|
|
14
|
+
* a `ParserError`.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Parses a sequence of nodes, separated by `,`.
|
|
18
|
+
*
|
|
19
|
+
* Returns a tuple of ["Parsed fields", "Remainder of text"] or an error.
|
|
20
|
+
*/
|
|
21
|
+
type ParseNodes<Input extends string> = string extends Input ? GenericStringError : ParseNodesHelper<Input, []>;
|
|
22
|
+
type ParseNodesHelper<Input extends string, Nodes extends Ast.Node[]> = ParseNode<Input> extends [infer Node, `${infer Remainder}`] ? Node extends Ast.Node ? EatWhitespace<Remainder> extends `,${infer Remainder}` ? ParseNodesHelper<EatWhitespace<Remainder>, [...Nodes, Node]> : [[...Nodes, Node], EatWhitespace<Remainder>] : ParserError<"Invalid node type in nodes helper"> : ParseNode<Input>;
|
|
23
|
+
/**
|
|
24
|
+
* Parses a node.
|
|
25
|
+
* A node is one of the following:
|
|
26
|
+
* - `*`
|
|
27
|
+
* - a field, as defined above
|
|
28
|
+
* - a renamed field, `renamed_field:field`
|
|
29
|
+
* - a spread field, `...field`
|
|
30
|
+
*/
|
|
31
|
+
type ParseNode<Input extends string> = Input extends "" ? ParserError<"Empty string"> : Input extends `*${infer Remainder}` ? [Ast.StarNode, EatWhitespace<Remainder>] : Input extends `...${infer Remainder}` ? ParseField<EatWhitespace<Remainder>> extends [
|
|
32
|
+
infer TargetField,
|
|
33
|
+
`${infer Remainder}`
|
|
34
|
+
] ? TargetField extends Ast.FieldNode ? [{
|
|
35
|
+
type: "spread";
|
|
36
|
+
target: TargetField;
|
|
37
|
+
}, EatWhitespace<Remainder>] : ParserError<"Invalid target field type in spread"> : ParserError<`Unable to parse spread resource at \`${Input}\``> : ParseIdentifier<Input> extends [infer NameOrAlias, `${infer Remainder}`] ? EatWhitespace<Remainder> extends `::${infer _}` ? ParseField<Input> : EatWhitespace<Remainder> extends `:${infer Remainder}` ? ParseField<EatWhitespace<Remainder>> extends [
|
|
38
|
+
infer Field,
|
|
39
|
+
`${infer Remainder}`
|
|
40
|
+
] ? Field extends Ast.FieldNode ? [
|
|
41
|
+
Omit<Field, "alias"> & {
|
|
42
|
+
alias: NameOrAlias;
|
|
43
|
+
},
|
|
44
|
+
EatWhitespace<Remainder>
|
|
45
|
+
] : ParserError<"Invalid field type in alias parsing"> : ParserError<`Unable to parse renamed field at \`${Input}\``> : ParseField<Input> : ParserError<`Expected identifier at \`${Input}\``>;
|
|
46
|
+
/**
|
|
47
|
+
* Parses a field without preceding alias.
|
|
48
|
+
* A field is one of the following:
|
|
49
|
+
* - a top-level `count` field: https://docs.postgrest.org/en/v12/references/api/aggregate_functions.html#the-case-of-count
|
|
50
|
+
* - a field with an embedded resource
|
|
51
|
+
* - `field(nodes)`
|
|
52
|
+
* - `field!hint(nodes)`
|
|
53
|
+
* - `field!inner(nodes)`
|
|
54
|
+
* - `field!left(nodes)`
|
|
55
|
+
* - `field!hint!inner(nodes)`
|
|
56
|
+
* - `field!hint!left(nodes)`
|
|
57
|
+
* - a field without an embedded resource (see {@link ParseNonEmbeddedResourceField})
|
|
58
|
+
*/
|
|
59
|
+
type ParseField<Input extends string> = Input extends "" ? ParserError<"Empty string"> : ParseIdentifier<Input> extends [infer Name, `${infer Remainder}`] ? Name extends "count" ? ParseCountField<Input> : Remainder extends `!inner${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [
|
|
60
|
+
infer Children,
|
|
61
|
+
`${infer Remainder}`
|
|
62
|
+
] ? Children extends Ast.Node[] ? [
|
|
63
|
+
{
|
|
64
|
+
type: "field";
|
|
65
|
+
name: Name;
|
|
66
|
+
innerJoin: true;
|
|
67
|
+
children: Children;
|
|
68
|
+
},
|
|
69
|
+
Remainder
|
|
70
|
+
] : ParserError<"Invalid children array in inner join"> : CreateParserErrorIfRequired<ParseEmbeddedResource<EatWhitespace<Remainder>>, `Expected embedded resource after "!inner" at \`${Remainder}\``> : EatWhitespace<Remainder> extends `!left${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [
|
|
71
|
+
infer Children,
|
|
72
|
+
`${infer Remainder}`
|
|
73
|
+
] ? Children extends Ast.Node[] ? [
|
|
74
|
+
{
|
|
75
|
+
type: "field";
|
|
76
|
+
name: Name;
|
|
77
|
+
children: Children;
|
|
78
|
+
},
|
|
79
|
+
EatWhitespace<Remainder>
|
|
80
|
+
] : ParserError<"Invalid children array in left join"> : CreateParserErrorIfRequired<ParseEmbeddedResource<EatWhitespace<Remainder>>, `Expected embedded resource after "!left" at \`${EatWhitespace<Remainder>}\``> : EatWhitespace<Remainder> extends `!${infer Remainder}` ? ParseIdentifier<EatWhitespace<Remainder>> extends [
|
|
81
|
+
infer Hint,
|
|
82
|
+
`${infer Remainder}`
|
|
83
|
+
] ? EatWhitespace<Remainder> extends `!inner${infer Remainder}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [
|
|
84
|
+
infer Children,
|
|
85
|
+
`${infer Remainder}`
|
|
86
|
+
] ? Children extends Ast.Node[] ? [
|
|
87
|
+
{
|
|
88
|
+
type: "field";
|
|
89
|
+
name: Name;
|
|
90
|
+
hint: Hint;
|
|
91
|
+
innerJoin: true;
|
|
92
|
+
children: Children;
|
|
93
|
+
},
|
|
94
|
+
EatWhitespace<Remainder>
|
|
95
|
+
] : ParserError<"Invalid children array in hint inner join"> : ParseEmbeddedResource<EatWhitespace<Remainder>> : ParseEmbeddedResource<EatWhitespace<Remainder>> extends [
|
|
96
|
+
infer Children,
|
|
97
|
+
`${infer Remainder}`
|
|
98
|
+
] ? Children extends Ast.Node[] ? [
|
|
99
|
+
{
|
|
100
|
+
type: "field";
|
|
101
|
+
name: Name;
|
|
102
|
+
hint: Hint;
|
|
103
|
+
children: Children;
|
|
104
|
+
},
|
|
105
|
+
EatWhitespace<Remainder>
|
|
106
|
+
] : ParserError<"Invalid children array in hint"> : ParseEmbeddedResource<EatWhitespace<Remainder>> : ParserError<`Expected identifier after "!" at \`${EatWhitespace<Remainder>}\``> : EatWhitespace<Remainder> extends `(${infer _}` ? ParseEmbeddedResource<EatWhitespace<Remainder>> extends [
|
|
107
|
+
infer Children,
|
|
108
|
+
`${infer Remainder}`
|
|
109
|
+
] ? Children extends Ast.Node[] ? [
|
|
110
|
+
{
|
|
111
|
+
type: "field";
|
|
112
|
+
name: Name;
|
|
113
|
+
children: Children;
|
|
114
|
+
},
|
|
115
|
+
EatWhitespace<Remainder>
|
|
116
|
+
] : ParserError<"Invalid children array in field"> : ParseEmbeddedResource<EatWhitespace<Remainder>> : ParseNonEmbeddedResourceField<Input> : ParserError<`Expected identifier at \`${Input}\``>;
|
|
117
|
+
type ParseCountField<Input extends string> = ParseIdentifier<Input> extends [
|
|
118
|
+
"count",
|
|
119
|
+
`${infer Remainder}`
|
|
120
|
+
] ? (EatWhitespace<Remainder> extends `()${infer Remainder_}` ? EatWhitespace<Remainder_> : EatWhitespace<Remainder>) extends `${infer Remainder}` ? Remainder extends `::${infer _}` ? ParseFieldTypeCast<Remainder> extends [
|
|
121
|
+
infer CastType,
|
|
122
|
+
`${infer Remainder}`
|
|
123
|
+
] ? [
|
|
124
|
+
{
|
|
125
|
+
type: "field";
|
|
126
|
+
name: "count";
|
|
127
|
+
aggregateFunction: "count";
|
|
128
|
+
castType: CastType;
|
|
129
|
+
},
|
|
130
|
+
Remainder
|
|
131
|
+
] : ParseFieldTypeCast<Remainder> : [
|
|
132
|
+
{
|
|
133
|
+
type: "field";
|
|
134
|
+
name: "count";
|
|
135
|
+
aggregateFunction: "count";
|
|
136
|
+
},
|
|
137
|
+
Remainder
|
|
138
|
+
] : never : ParserError<`Expected "count" at \`${Input}\``>;
|
|
139
|
+
/**
|
|
140
|
+
* Parses an embedded resource, which is an opening `(`, followed by a sequence of
|
|
141
|
+
* 0 or more nodes separated by `,`, then a closing `)`.
|
|
142
|
+
*
|
|
143
|
+
* Returns a tuple of ["Parsed fields", "Remainder of text"], an error,
|
|
144
|
+
* or the original string input indicating that no opening `(` was found.
|
|
145
|
+
*/
|
|
146
|
+
type ParseEmbeddedResource<Input extends string> = Input extends `(${infer Remainder}` ? EatWhitespace<Remainder> extends `)${infer Remainder}` ? [[], EatWhitespace<Remainder>] : ParseNodes<EatWhitespace<Remainder>> extends [
|
|
147
|
+
infer Nodes,
|
|
148
|
+
`${infer Remainder}`
|
|
149
|
+
] ? Nodes extends Ast.Node[] ? EatWhitespace<Remainder> extends `)${infer Remainder}` ? [Nodes, EatWhitespace<Remainder>] : ParserError<`Expected ")" at \`${EatWhitespace<Remainder>}\``> : ParserError<"Invalid nodes array in embedded resource"> : ParseNodes<EatWhitespace<Remainder>> : ParserError<`Expected "(" at \`${Input}\``>;
|
|
150
|
+
/**
|
|
151
|
+
* Parses a field excluding embedded resources, without preceding field renaming.
|
|
152
|
+
* This is one of the following:
|
|
153
|
+
* - `field`
|
|
154
|
+
* - `field.aggregate()`
|
|
155
|
+
* - `field.aggregate()::type`
|
|
156
|
+
* - `field::type`
|
|
157
|
+
* - `field::type.aggregate()`
|
|
158
|
+
* - `field::type.aggregate()::type`
|
|
159
|
+
* - `field->json...`
|
|
160
|
+
* - `field->json.aggregate()`
|
|
161
|
+
* - `field->json.aggregate()::type`
|
|
162
|
+
* - `field->json::type`
|
|
163
|
+
* - `field->json::type.aggregate()`
|
|
164
|
+
* - `field->json::type.aggregate()::type`
|
|
165
|
+
*/
|
|
166
|
+
type ParseNonEmbeddedResourceField<Input extends string> = ParseIdentifier<Input> extends [infer Name, `${infer Remainder}`] ? (Remainder extends `->${infer PathAndRest}` ? ParseJsonAccessor<Remainder> extends [
|
|
167
|
+
infer PropertyName,
|
|
168
|
+
infer PropertyType,
|
|
169
|
+
`${infer Remainder}`
|
|
170
|
+
] ? [
|
|
171
|
+
{
|
|
172
|
+
type: "field";
|
|
173
|
+
name: Name;
|
|
174
|
+
alias: PropertyName;
|
|
175
|
+
castType: PropertyType;
|
|
176
|
+
jsonPath: JsonPathToAccessor<PathAndRest extends `${infer Path},${string}` ? Path : PathAndRest>;
|
|
177
|
+
},
|
|
178
|
+
Remainder
|
|
179
|
+
] : ParseJsonAccessor<Remainder> : [{
|
|
180
|
+
type: "field";
|
|
181
|
+
name: Name;
|
|
182
|
+
}, Remainder]) extends infer Parsed ? Parsed extends [infer Field, `${infer Remainder}`] ? (Remainder extends `::${infer _}` ? ParseFieldTypeCast<Remainder> extends [
|
|
183
|
+
infer CastType,
|
|
184
|
+
`${infer Remainder}`
|
|
185
|
+
] ? [Omit<Field, "castType"> & {
|
|
186
|
+
castType: CastType;
|
|
187
|
+
}, Remainder] : ParseFieldTypeCast<Remainder> : [Field, Remainder]) extends infer Parsed ? Parsed extends [infer Field, `${infer Remainder}`] ? Remainder extends `.${infer _}` ? ParseFieldAggregation<Remainder> extends [
|
|
188
|
+
infer AggregateFunction,
|
|
189
|
+
`${infer Remainder}`
|
|
190
|
+
] ? Remainder extends `::${infer _}` ? ParseFieldTypeCast<Remainder> extends [
|
|
191
|
+
infer CastType,
|
|
192
|
+
`${infer Remainder}`
|
|
193
|
+
] ? [
|
|
194
|
+
Omit<Field, "castType"> & {
|
|
195
|
+
aggregateFunction: AggregateFunction;
|
|
196
|
+
castType: CastType;
|
|
197
|
+
},
|
|
198
|
+
Remainder
|
|
199
|
+
] : ParseFieldTypeCast<Remainder> : [
|
|
200
|
+
Field & {
|
|
201
|
+
aggregateFunction: AggregateFunction;
|
|
202
|
+
},
|
|
203
|
+
Remainder
|
|
204
|
+
] : ParseFieldAggregation<Remainder> : [Field, Remainder] : Parsed : never : Parsed : never : ParserError<`Expected identifier at \`${Input}\``>;
|
|
205
|
+
/**
|
|
206
|
+
* Parses a JSON property accessor of the shape `->a->b->c`. The last accessor in
|
|
207
|
+
* the series may convert to text by using the ->> operator instead of ->.
|
|
208
|
+
*
|
|
209
|
+
* Returns a tuple of ["Last property name", "Last property type", "Remainder of text"]
|
|
210
|
+
*/
|
|
211
|
+
type ParseJsonAccessor<Input extends string> = Input extends `->${infer Remainder}` ? Remainder extends `>${infer Remainder}` ? ParseIdentifier<Remainder> extends [infer Name, `${infer Remainder}`] ? [Name, "text", EatWhitespace<Remainder>] : ParserError<"Expected property name after `->>`"> : ParseIdentifier<Remainder> extends [infer Name, `${infer Remainder}`] ? ParseJsonAccessor<Remainder> extends [
|
|
212
|
+
infer PropertyName,
|
|
213
|
+
infer PropertyType,
|
|
214
|
+
`${infer Remainder}`
|
|
215
|
+
] ? [PropertyName, PropertyType, EatWhitespace<Remainder>] : [Name, "json", EatWhitespace<Remainder>] : ParserError<"Expected property name after `->`"> : ParserError<"Expected ->">;
|
|
216
|
+
/**
|
|
217
|
+
* Parses a field typecast (`::type`), returning a tuple of ["Type", "Remainder of text"].
|
|
218
|
+
*/
|
|
219
|
+
type ParseFieldTypeCast<Input extends string> = EatWhitespace<Input> extends `::${infer Remainder}` ? ParseIdentifier<EatWhitespace<Remainder>> extends [
|
|
220
|
+
`${infer CastType}`,
|
|
221
|
+
`${infer Remainder}`
|
|
222
|
+
] ? [CastType, EatWhitespace<Remainder>] : ParserError<`Invalid type for \`::\` operator at \`${Remainder}\``> : ParserError<"Expected ::">;
|
|
223
|
+
/**
|
|
224
|
+
* Parses a field aggregation (`.max()`), returning a tuple of ["Aggregate function", "Remainder of text"]
|
|
225
|
+
*/
|
|
226
|
+
type ParseFieldAggregation<Input extends string> = EatWhitespace<Input> extends `.${infer Remainder}` ? ParseIdentifier<EatWhitespace<Remainder>> extends [
|
|
227
|
+
`${infer FunctionName}`,
|
|
228
|
+
`${infer Remainder}`
|
|
229
|
+
] ? FunctionName extends Token.AggregateFunction ? EatWhitespace<Remainder> extends `()${infer Remainder}` ? [FunctionName, EatWhitespace<Remainder>] : ParserError<`Expected \`()\` after \`.\` operator \`${FunctionName}\``> : ParserError<`Invalid type for \`.\` operator \`${FunctionName}\``> : ParserError<`Invalid type for \`.\` operator at \`${Remainder}\``> : ParserError<"Expected .">;
|
|
230
|
+
/**
|
|
231
|
+
* Parses a (possibly double-quoted) identifier.
|
|
232
|
+
* Identifiers are sequences of 1 or more letters.
|
|
233
|
+
*/
|
|
234
|
+
type ParseIdentifier<Input extends string> = ParseLetters<Input> extends [
|
|
235
|
+
infer Name,
|
|
236
|
+
`${infer Remainder}`
|
|
237
|
+
] ? [Name, EatWhitespace<Remainder>] : ParseQuotedLetters<Input> extends [infer Name, `${infer Remainder}`] ? [Name, EatWhitespace<Remainder>] : ParserError<`No (possibly double-quoted) identifier at \`${Input}\``>;
|
|
238
|
+
/**
|
|
239
|
+
* Parse a consecutive sequence of 1 or more letter, where letters are `[0-9a-zA-Z_]`.
|
|
240
|
+
*/
|
|
241
|
+
type ParseLetters<Input extends string> = string extends Input ? GenericStringError : ParseLettersHelper<Input, ""> extends [
|
|
242
|
+
`${infer Letters}`,
|
|
243
|
+
`${infer Remainder}`
|
|
244
|
+
] ? Letters extends "" ? ParserError<`Expected letter at \`${Input}\``> : [Letters, Remainder] : ParseLettersHelper<Input, "">;
|
|
245
|
+
type ParseLettersHelper<Input extends string, Acc extends string> = string extends Input ? GenericStringError : Input extends `${infer L}${infer Remainder}` ? L extends Token.Letter ? ParseLettersHelper<Remainder, `${Acc}${L}`> : [Acc, Input] : [Acc, ""];
|
|
246
|
+
/**
|
|
247
|
+
* Parse a consecutive sequence of 1 or more double-quoted letters,
|
|
248
|
+
* where letters are `[^"]`.
|
|
249
|
+
*/
|
|
250
|
+
type ParseQuotedLetters<Input extends string> = string extends Input ? GenericStringError : Input extends `"${infer Remainder}` ? ParseQuotedLettersHelper<Remainder, ""> extends [
|
|
251
|
+
`${infer Letters}`,
|
|
252
|
+
`${infer Remainder}`
|
|
253
|
+
] ? Letters extends "" ? ParserError<`Expected string at \`${Remainder}\``> : [Letters, Remainder] : ParseQuotedLettersHelper<Remainder, ""> : ParserError<`Not a double-quoted string at \`${Input}\``>;
|
|
254
|
+
type ParseQuotedLettersHelper<Input extends string, Acc extends string> = string extends Input ? GenericStringError : Input extends `${infer L}${infer Remainder}` ? L extends '"' ? [Acc, Remainder] : ParseQuotedLettersHelper<Remainder, `${Acc}${L}`> : ParserError<`Missing closing double-quote in \`"${Acc}${Input}\``>;
|
|
255
|
+
/**
|
|
256
|
+
* Trims whitespace from the left of the input.
|
|
257
|
+
*/
|
|
258
|
+
type EatWhitespace<Input extends string> = string extends Input ? GenericStringError : Input extends `${Token.Whitespace}${infer Remainder}` ? EatWhitespace<Remainder> : Input;
|
|
259
|
+
/**
|
|
260
|
+
* Creates a new {@link ParserError} if the given input is not already a parser error.
|
|
261
|
+
*/
|
|
262
|
+
type CreateParserErrorIfRequired<Input, Message extends string> = Input extends ParserError<string> ? Input : ParserError<Message>;
|
|
263
|
+
/**
|
|
264
|
+
* Parser errors.
|
|
265
|
+
*/
|
|
266
|
+
export type ParserError<Message extends string> = {
|
|
267
|
+
error: true;
|
|
268
|
+
} & Message;
|
|
269
|
+
type GenericStringError = ParserError<"Received a generic string">;
|
|
270
|
+
export declare namespace Ast {
|
|
271
|
+
type Node = FieldNode | StarNode | SpreadNode;
|
|
272
|
+
type FieldNode = {
|
|
273
|
+
type: "field";
|
|
274
|
+
name: string;
|
|
275
|
+
alias?: string;
|
|
276
|
+
hint?: string;
|
|
277
|
+
innerJoin?: true;
|
|
278
|
+
castType?: string;
|
|
279
|
+
jsonPath?: string;
|
|
280
|
+
aggregateFunction?: Token.AggregateFunction;
|
|
281
|
+
children?: Node[];
|
|
282
|
+
};
|
|
283
|
+
type StarNode = {
|
|
284
|
+
type: "star";
|
|
285
|
+
};
|
|
286
|
+
type SpreadNode = {
|
|
287
|
+
type: "spread";
|
|
288
|
+
target: FieldNode & {
|
|
289
|
+
children: Node[];
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
declare namespace Token {
|
|
294
|
+
export type Whitespace = " " | "\n" | "\t";
|
|
295
|
+
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";
|
|
296
|
+
type Alphabet = LowerAlphabet | Uppercase<LowerAlphabet>;
|
|
297
|
+
type Digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0";
|
|
298
|
+
export type Letter = Alphabet | Digit | "_";
|
|
299
|
+
export type AggregateFunction = "count" | "sum" | "avg" | "min" | "max";
|
|
300
|
+
export {};
|
|
301
|
+
}
|
|
302
|
+
export {};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { ClientServerOptions, GenericTable } from "../types";
|
|
2
|
+
import { ContainsNull, GenericRelationship, PostgreSQLTypes } from "./types";
|
|
3
|
+
import { Ast, ParseQuery } from "./parser";
|
|
4
|
+
import { AggregateFunctions, ExtractFirstProperty, GenericSchema, IsNonEmptyArray, Prettify, TablesAndViews, TypeScriptTypes } from "./types";
|
|
5
|
+
import { CheckDuplicateEmbededReference, GetComputedFields, GetFieldNodeResultName, IsAny, IsRelationNullable, IsStringUnion, JsonPathToType, ResolveRelationship, SelectQueryError } from "./utils";
|
|
6
|
+
export type SpreadOnManyEnabled<PostgrestVersion extends string | undefined> = PostgrestVersion extends `13${string}` ? true : false;
|
|
7
|
+
/**
|
|
8
|
+
* Main entry point for constructing the result type of a PostgREST query.
|
|
9
|
+
*
|
|
10
|
+
* @param Schema - Database schema.
|
|
11
|
+
* @param Row - The type of a row in the current table.
|
|
12
|
+
* @param RelationName - The name of the current table or view.
|
|
13
|
+
* @param Relationships - Relationships of the current table.
|
|
14
|
+
* @param Query - The select query string literal to parse.
|
|
15
|
+
*/
|
|
16
|
+
export type GetResult<Schema extends GenericSchema, Row extends Record<string, unknown>, RelationName, Relationships, Query extends string, ClientOptions extends ClientServerOptions> = IsAny<Schema> extends true ? ParseQuery<Query> extends infer ParsedQuery ? ParsedQuery extends Ast.Node[] ? RelationName extends string ? ProcessNodesWithoutSchema<ParsedQuery> : any : ParsedQuery : any : Relationships extends null ? ParseQuery<Query> extends infer ParsedQuery ? ParsedQuery extends Ast.Node[] ? RPCCallNodes<ParsedQuery, RelationName extends string ? RelationName : "rpc_call", Row> : ParsedQuery : Row : ParseQuery<Query> extends infer ParsedQuery ? ParsedQuery extends Ast.Node[] ? RelationName extends string ? Relationships extends GenericRelationship[] ? ProcessNodes<ClientOptions, Schema, Row, RelationName, Relationships, ParsedQuery> : SelectQueryError<"Invalid Relationships cannot infer result type"> : SelectQueryError<"Invalid RelationName cannot infer result type"> : ParsedQuery : never;
|
|
17
|
+
type ProcessSimpleFieldWithoutSchema<Field extends Ast.FieldNode> = Field["aggregateFunction"] extends AggregateFunctions ? {
|
|
18
|
+
[K in GetFieldNodeResultName<Field>]: Field["castType"] extends PostgreSQLTypes ? TypeScriptTypes<Field["castType"]> : number;
|
|
19
|
+
} : {
|
|
20
|
+
[K in GetFieldNodeResultName<Field>]: Field["castType"] extends PostgreSQLTypes ? TypeScriptTypes<Field["castType"]> : any;
|
|
21
|
+
};
|
|
22
|
+
type ProcessFieldNodeWithoutSchema<Node extends Ast.FieldNode> = IsNonEmptyArray<Node["children"]> extends true ? {
|
|
23
|
+
[K in GetFieldNodeResultName<Node>]: Node["children"] extends Ast.Node[] ? ProcessNodesWithoutSchema<Node["children"]>[] : ProcessSimpleFieldWithoutSchema<Node>;
|
|
24
|
+
} : ProcessSimpleFieldWithoutSchema<Node>;
|
|
25
|
+
/**
|
|
26
|
+
* Processes a single Node without schema and returns the resulting TypeScript type.
|
|
27
|
+
*/
|
|
28
|
+
type ProcessNodeWithoutSchema<Node extends Ast.Node> = Node extends Ast.StarNode ? any : Node extends Ast.SpreadNode ? Node["target"]["children"] extends Ast.StarNode[] ? any : Node["target"]["children"] extends Ast.FieldNode[] ? {
|
|
29
|
+
[P in Node["target"]["children"][number] as GetFieldNodeResultName<P>]: P["castType"] extends PostgreSQLTypes ? TypeScriptTypes<P["castType"]> : any;
|
|
30
|
+
} : any : Node extends Ast.FieldNode ? ProcessFieldNodeWithoutSchema<Node> : any;
|
|
31
|
+
/**
|
|
32
|
+
* Processes nodes when Schema is any, providing basic type inference
|
|
33
|
+
*/
|
|
34
|
+
type ProcessNodesWithoutSchema<Nodes extends Ast.Node[], Acc extends Record<string, unknown> = {}> = Nodes extends [infer FirstNode, ...infer RestNodes] ? FirstNode extends Ast.Node ? RestNodes extends Ast.Node[] ? ProcessNodeWithoutSchema<FirstNode> extends infer FieldResult ? FieldResult extends Record<string, unknown> ? ProcessNodesWithoutSchema<RestNodes, Acc & FieldResult> : FieldResult : any : any : any : Prettify<Acc>;
|
|
35
|
+
/**
|
|
36
|
+
* Processes a single Node from a select chained after a rpc call
|
|
37
|
+
*
|
|
38
|
+
* @param Row - The type of a row in the current table.
|
|
39
|
+
* @param RelationName - The name of the current rpc function
|
|
40
|
+
* @param NodeType - The Node to process.
|
|
41
|
+
*/
|
|
42
|
+
export type ProcessRPCNode<Row extends Record<string, unknown>, RelationName extends string, NodeType extends Ast.Node> = NodeType["type"] extends Ast.StarNode["type"] ? Row : NodeType["type"] extends Ast.FieldNode["type"] ? ProcessSimpleField<Row, RelationName, Extract<NodeType, Ast.FieldNode>> : SelectQueryError<"RPC Unsupported node type.">;
|
|
43
|
+
/**
|
|
44
|
+
* Process select call that can be chained after an rpc call
|
|
45
|
+
*/
|
|
46
|
+
export type RPCCallNodes<Nodes extends Ast.Node[], RelationName extends string, Row extends Record<string, unknown>, Acc extends Record<string, unknown> = {}> = Nodes extends [infer FirstNode, ...infer RestNodes] ? FirstNode extends Ast.Node ? RestNodes extends Ast.Node[] ? ProcessRPCNode<Row, RelationName, FirstNode> extends infer FieldResult ? FieldResult extends Record<string, unknown> ? RPCCallNodes<RestNodes, RelationName, Row, Acc & FieldResult> : FieldResult extends SelectQueryError<infer E> ? SelectQueryError<E> : SelectQueryError<"Could not retrieve a valid record or error value"> : SelectQueryError<"Processing node failed."> : SelectQueryError<"Invalid rest nodes array in RPC call"> : SelectQueryError<"Invalid first node in RPC call"> : Prettify<Acc>;
|
|
47
|
+
/**
|
|
48
|
+
* Recursively processes an array of Nodes and accumulates the resulting TypeScript type.
|
|
49
|
+
*
|
|
50
|
+
* @param Schema - Database schema.
|
|
51
|
+
* @param Row - The type of a row in the current table.
|
|
52
|
+
* @param RelationName - The name of the current table or view.
|
|
53
|
+
* @param Relationships - Relationships of the current table.
|
|
54
|
+
* @param Nodes - An array of AST nodes to process.
|
|
55
|
+
* @param Acc - Accumulator for the constructed type.
|
|
56
|
+
*/
|
|
57
|
+
export type ProcessNodes<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Row extends Record<string, unknown>, RelationName extends string, Relationships extends GenericRelationship[], Nodes extends Ast.Node[], Acc extends Record<string, unknown> = {}> = CheckDuplicateEmbededReference<Schema, RelationName, Relationships, Nodes> extends false ? Nodes extends [infer FirstNode, ...infer RestNodes] ? FirstNode extends Ast.Node ? RestNodes extends Ast.Node[] ? ProcessNode<ClientOptions, Schema, Row, RelationName, Relationships, FirstNode> extends infer FieldResult ? FieldResult extends Record<string, unknown> ? ProcessNodes<ClientOptions, Schema, Row, RelationName, Relationships, RestNodes, Acc & FieldResult> : FieldResult extends SelectQueryError<infer E> ? SelectQueryError<E> : SelectQueryError<"Could not retrieve a valid record or error value"> : SelectQueryError<"Processing node failed."> : SelectQueryError<"Invalid rest nodes array type in ProcessNodes"> : SelectQueryError<"Invalid first node type in ProcessNodes"> : Prettify<Acc> : Prettify<CheckDuplicateEmbededReference<Schema, RelationName, Relationships, Nodes>>;
|
|
58
|
+
/**
|
|
59
|
+
* Processes a single Node and returns the resulting TypeScript type.
|
|
60
|
+
*
|
|
61
|
+
* @param Schema - Database schema.
|
|
62
|
+
* @param Row - The type of a row in the current table.
|
|
63
|
+
* @param RelationName - The name of the current table or view.
|
|
64
|
+
* @param Relationships - Relationships of the current table.
|
|
65
|
+
* @param NodeType - The Node to process.
|
|
66
|
+
*/
|
|
67
|
+
export type ProcessNode<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Row extends Record<string, unknown>, RelationName extends string, Relationships extends GenericRelationship[], NodeType extends Ast.Node> = NodeType["type"] extends Ast.StarNode["type"] ? GetComputedFields<Schema, RelationName> extends never ? Row : Omit<Row, GetComputedFields<Schema, RelationName>> : NodeType["type"] extends Ast.SpreadNode["type"] ? ProcessSpreadNode<ClientOptions, Schema, Row, RelationName, Relationships, Extract<NodeType, Ast.SpreadNode>> : NodeType["type"] extends Ast.FieldNode["type"] ? ProcessFieldNode<ClientOptions, Schema, Row, RelationName, Relationships, Extract<NodeType, Ast.FieldNode>> : SelectQueryError<"Unsupported node type.">;
|
|
68
|
+
/**
|
|
69
|
+
* Processes a FieldNode and returns the resulting TypeScript type.
|
|
70
|
+
*
|
|
71
|
+
* @param Schema - Database schema.
|
|
72
|
+
* @param Row - The type of a row in the current table.
|
|
73
|
+
* @param RelationName - The name of the current table or view.
|
|
74
|
+
* @param Relationships - Relationships of the current table.
|
|
75
|
+
* @param Field - The FieldNode to process.
|
|
76
|
+
*/
|
|
77
|
+
type ProcessFieldNode<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Row extends Record<string, unknown>, RelationName extends string, Relationships extends GenericRelationship[], Field extends Ast.FieldNode> = Field["children"] extends [] ? {} : IsNonEmptyArray<Field["children"]> extends true ? ProcessEmbeddedResource<ClientOptions, Schema, Relationships, Field, RelationName> : ProcessSimpleField<Row, RelationName, Field>;
|
|
78
|
+
type ResolveJsonPathType<Value, Path extends string | undefined, CastType extends PostgreSQLTypes> = Path extends string ? JsonPathToType<Value, Path> extends never ? TypeScriptTypes<CastType> : JsonPathToType<Value, Path> extends infer PathResult ? PathResult extends string ? PathResult : IsStringUnion<PathResult> extends true ? PathResult : CastType extends "json" ? PathResult : TypeScriptTypes<CastType> : TypeScriptTypes<CastType> : TypeScriptTypes<CastType>;
|
|
79
|
+
/**
|
|
80
|
+
* Processes a simple field (without embedded resources).
|
|
81
|
+
*
|
|
82
|
+
* @param Row - The type of a row in the current table.
|
|
83
|
+
* @param RelationName - The name of the current table or view.
|
|
84
|
+
* @param Field - The FieldNode to process.
|
|
85
|
+
*/
|
|
86
|
+
type ProcessSimpleField<Row extends Record<string, unknown>, RelationName extends string, Field extends Ast.FieldNode> = Field["name"] extends keyof Row | "count" ? Field["aggregateFunction"] extends AggregateFunctions ? {
|
|
87
|
+
[K in GetFieldNodeResultName<Field>]: Field["castType"] extends PostgreSQLTypes ? TypeScriptTypes<Field["castType"]> : number;
|
|
88
|
+
} : {
|
|
89
|
+
[K in GetFieldNodeResultName<Field>]: Field["castType"] extends PostgreSQLTypes ? ResolveJsonPathType<Row[Field["name"]], Field["jsonPath"], Field["castType"]> : Row[Field["name"]];
|
|
90
|
+
} : SelectQueryError<`column '${Field["name"]}' does not exist on '${RelationName}'.`>;
|
|
91
|
+
/**
|
|
92
|
+
* Processes an embedded resource (relation).
|
|
93
|
+
*
|
|
94
|
+
* @param Schema - Database schema.
|
|
95
|
+
* @param Row - The type of a row in the current table.
|
|
96
|
+
* @param RelationName - The name of the current table or view.
|
|
97
|
+
* @param Relationships - Relationships of the current table.
|
|
98
|
+
* @param Field - The FieldNode to process.
|
|
99
|
+
*/
|
|
100
|
+
export type ProcessEmbeddedResource<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Relationships extends GenericRelationship[], Field extends Ast.FieldNode, CurrentTableOrView extends keyof TablesAndViews<Schema> & string> = ResolveRelationship<Schema, Relationships, Field, CurrentTableOrView> extends infer Resolved ? Resolved extends {
|
|
101
|
+
referencedTable: Pick<GenericTable, "Row" | "Relationships">;
|
|
102
|
+
relation: GenericRelationship & {
|
|
103
|
+
match: "refrel" | "col" | "fkname";
|
|
104
|
+
};
|
|
105
|
+
direction: string;
|
|
106
|
+
} ? ProcessEmbeddedResourceResult<ClientOptions, Schema, Resolved, Field, CurrentTableOrView> : {
|
|
107
|
+
[K in GetFieldNodeResultName<Field>]: Resolved;
|
|
108
|
+
} : {
|
|
109
|
+
[K in GetFieldNodeResultName<Field>]: SelectQueryError<"Failed to resolve relationship."> & string;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Helper type to process the result of an embedded resource.
|
|
113
|
+
*/
|
|
114
|
+
type ProcessEmbeddedResourceResult<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Resolved extends {
|
|
115
|
+
referencedTable: Pick<GenericTable, "Row" | "Relationships">;
|
|
116
|
+
relation: GenericRelationship & {
|
|
117
|
+
match: "refrel" | "col" | "fkname";
|
|
118
|
+
};
|
|
119
|
+
direction: string;
|
|
120
|
+
}, Field extends Ast.FieldNode, CurrentTableOrView extends keyof TablesAndViews<Schema>> = ProcessNodes<ClientOptions, Schema, Resolved["referencedTable"]["Row"], Field["name"], Resolved["referencedTable"]["Relationships"], Field["children"] extends undefined ? [] : Exclude<Field["children"], undefined> extends Ast.Node[] ? Exclude<Field["children"], undefined> : []> extends infer ProcessedChildren ? {
|
|
121
|
+
[K in GetFieldNodeResultName<Field>]: Resolved["direction"] extends "forward" ? Field extends {
|
|
122
|
+
innerJoin: true;
|
|
123
|
+
} ? Resolved["relation"]["isOneToOne"] extends true ? ProcessedChildren : ProcessedChildren[] : Resolved["relation"]["isOneToOne"] extends true ? ProcessedChildren | null : ProcessedChildren[] : Resolved["relation"]["referencedRelation"] extends CurrentTableOrView ? Resolved["relation"]["match"] extends "col" ? IsRelationNullable<TablesAndViews<Schema>[CurrentTableOrView], Resolved["relation"]> extends true ? ProcessedChildren | null : ProcessedChildren : ProcessedChildren[] : IsRelationNullable<TablesAndViews<Schema>[CurrentTableOrView], Resolved["relation"]> extends true ? Field extends {
|
|
124
|
+
innerJoin: true;
|
|
125
|
+
} ? ProcessedChildren : ProcessedChildren | null : ProcessedChildren;
|
|
126
|
+
} : {
|
|
127
|
+
[K in GetFieldNodeResultName<Field>]: SelectQueryError<"Failed to process embedded resource nodes."> & string;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Processes a SpreadNode by processing its target node.
|
|
131
|
+
*
|
|
132
|
+
* @param Schema - Database schema.
|
|
133
|
+
* @param Row - The type of a row in the current table.
|
|
134
|
+
* @param RelationName - The name of the current table or view.
|
|
135
|
+
* @param Relationships - Relationships of the current table.
|
|
136
|
+
* @param Spread - The SpreadNode to process.
|
|
137
|
+
*/
|
|
138
|
+
type ProcessSpreadNode<ClientOptions extends ClientServerOptions, Schema extends GenericSchema, Row extends Record<string, unknown>, RelationName extends string, Relationships extends GenericRelationship[], Spread extends Ast.SpreadNode> = ProcessNode<ClientOptions, Schema, Row, RelationName, Relationships, Spread["target"]> extends infer Result ? Result extends SelectQueryError<infer E> ? SelectQueryError<E> : ExtractFirstProperty<Result> extends unknown[] ? SpreadOnManyEnabled<ClientOptions["PostgrestVersion"]> extends true ? ProcessManyToManySpreadNodeResult<Result> : {
|
|
139
|
+
[K in Spread["target"]["name"]]: SelectQueryError<`"${RelationName}" and "${Spread["target"]["name"]}" do not form a many-to-one or one-to-one relationship spread not possible`>;
|
|
140
|
+
} : ProcessSpreadNodeResult<Result> : never;
|
|
141
|
+
/**
|
|
142
|
+
* Helper type to process the result of a many-to-many spread node.
|
|
143
|
+
* Converts all fields in the spread object into arrays.
|
|
144
|
+
*/
|
|
145
|
+
type ProcessManyToManySpreadNodeResult<Result> = Result extends Record<string, SelectQueryError<string> | null> ? Result : ExtractFirstProperty<Result> extends infer SpreadedObject ? SpreadedObject extends Array<Record<string, unknown>> ? {
|
|
146
|
+
[K in keyof SpreadedObject[number]]: Array<SpreadedObject[number][K]>;
|
|
147
|
+
} : SelectQueryError<"An error occurred spreading the many-to-many object"> : SelectQueryError<"An error occurred spreading the many-to-many object">;
|
|
148
|
+
/**
|
|
149
|
+
* Helper type to process the result of a spread node.
|
|
150
|
+
*/
|
|
151
|
+
type ProcessSpreadNodeResult<Result> = Result extends Record<string, SelectQueryError<string> | null> ? Result : ExtractFirstProperty<Result> extends infer SpreadedObject ? ContainsNull<SpreadedObject> extends true ? Exclude<{
|
|
152
|
+
[K in keyof SpreadedObject]: SpreadedObject[K] | null;
|
|
153
|
+
}, null> : Exclude<{
|
|
154
|
+
[K in keyof SpreadedObject]: SpreadedObject[K];
|
|
155
|
+
}, null> : SelectQueryError<"An error occurred spreading the object">;
|
|
156
|
+
export {};
|