Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Commit cf6a684

Browse files
committed
feat: improved typings
BREAKING CHANGE: improved typings
1 parent 24db26e commit cf6a684

12 files changed

+644
-159
lines changed

src/PostgrestBuilder.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@ import crossFetch from 'cross-fetch'
22

33
import type { Fetch, PostgrestResponse } from './types'
44

5-
export default abstract class PostgrestBuilder<T> implements PromiseLike<PostgrestResponse<T>> {
5+
export default abstract class PostgrestBuilder<Result>
6+
implements PromiseLike<PostgrestResponse<Result>>
7+
{
68
protected method: 'GET' | 'HEAD' | 'POST' | 'PATCH' | 'DELETE'
79
protected url: URL
810
protected headers: Record<string, string>
911
protected schema?: string
10-
protected body?: Partial<T> | Partial<T>[]
12+
protected body?: unknown
1113
protected shouldThrowOnError: boolean
1214
protected signal?: AbortSignal
1315
protected fetch: Fetch
1416
protected allowEmpty: boolean
1517

16-
constructor(builder: PostgrestBuilder<T>) {
18+
constructor(builder: PostgrestBuilder<Result>) {
1719
this.method = builder.method
1820
this.url = builder.url
1921
this.headers = builder.headers
@@ -45,9 +47,9 @@ export default abstract class PostgrestBuilder<T> implements PromiseLike<Postgre
4547
return this
4648
}
4749

48-
then<TResult1 = PostgrestResponse<T>, TResult2 = never>(
50+
then<TResult1 = PostgrestResponse<Result>, TResult2 = never>(
4951
onfulfilled?:
50-
| ((value: PostgrestResponse<T>) => TResult1 | PromiseLike<TResult1>)
52+
| ((value: PostgrestResponse<Result>) => TResult1 | PromiseLike<TResult1>)
5153
| undefined
5254
| null,
5355
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null

src/PostgrestClient.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@ import PostgrestQueryBuilder from './PostgrestQueryBuilder'
22
import PostgrestFilterBuilder from './PostgrestFilterBuilder'
33
import PostgrestBuilder from './PostgrestBuilder'
44
import { DEFAULT_HEADERS } from './constants'
5-
import { Fetch } from './types'
5+
import { Fetch, GenericSchema } from './types'
66

7-
export default class PostgrestClient {
7+
export default class PostgrestClient<
8+
Database = any,
9+
SchemaName extends string & keyof Database = 'public' extends keyof Database
10+
? 'public'
11+
: string & keyof Database,
12+
Schema extends GenericSchema = Database[SchemaName] extends GenericSchema
13+
? Database[SchemaName]
14+
: any
15+
> {
816
url: string
917
headers: Record<string, string>
10-
schema?: string
18+
schema?: SchemaName
1119
fetch?: Fetch
1220
shouldThrowOnError: boolean
1321

@@ -27,7 +35,7 @@ export default class PostgrestClient {
2735
throwOnError = false,
2836
}: {
2937
headers?: Record<string, string>
30-
schema?: string
38+
schema?: SchemaName
3139
fetch?: Fetch
3240
throwOnError?: boolean
3341
} = {}
@@ -56,9 +64,12 @@ export default class PostgrestClient {
5664
*
5765
* @param table The table name to operate on.
5866
*/
59-
from<T = any>(table: string): PostgrestQueryBuilder<T> {
60-
const url = `${this.url}/${table}`
61-
return new PostgrestQueryBuilder<T>(url, {
67+
from<
68+
TableName extends string & keyof Schema['Tables'],
69+
Table extends Schema['Tables'][TableName]
70+
>(table: TableName): PostgrestQueryBuilder<Table> {
71+
const url = new URL(`${this.url}/${table}`)
72+
return new PostgrestQueryBuilder<Table>(url, {
6273
headers: { ...this.headers },
6374
schema: this.schema,
6475
fetch: this.fetch,
@@ -70,33 +81,43 @@ export default class PostgrestClient {
7081
* Perform a function call.
7182
*
7283
* @param fn The function name to call.
73-
* @param params The parameters to pass to the function call.
84+
* @param args The parameters to pass to the function call.
7485
* @param options Named parameters.
7586
* @param options.head When set to true, no data will be returned.
7687
* @param options.count Count algorithm to use to count rows in a table.
7788
*/
78-
rpc<T = any>(
79-
fn: string,
80-
params: Record<string, unknown> = {},
89+
rpc<
90+
FunctionName extends string & keyof Schema['Functions'],
91+
Function_ extends Schema['Functions'][FunctionName]
92+
>(
93+
fn: FunctionName,
94+
args: Function_['Args'] = {},
8195
{
8296
head = false,
8397
count,
8498
}: {
8599
head?: boolean
86100
count?: 'exact' | 'planned' | 'estimated'
87101
} = {}
88-
): PostgrestFilterBuilder<T> {
102+
): PostgrestFilterBuilder<
103+
Function_['Returns'] extends any[]
104+
? Function_['Returns'][number] extends Record<string, unknown>
105+
? Function_['Returns'][number]
106+
: never
107+
: never,
108+
Function_['Returns']
109+
> {
89110
let method: 'HEAD' | 'POST'
90111
const url = new URL(`${this.url}/rpc/${fn}`)
91112
let body: unknown | undefined
92113
if (head) {
93114
method = 'HEAD'
94-
Object.entries(params).forEach(([name, value]) => {
115+
Object.entries(args).forEach(([name, value]) => {
95116
url.searchParams.append(name, `${value}`)
96117
})
97118
} else {
98119
method = 'POST'
99-
body = params
120+
body = args
100121
}
101122

102123
const headers = { ...this.headers }
@@ -113,6 +134,6 @@ export default class PostgrestClient {
113134
fetch: this.fetch,
114135
shouldThrowOnError: this.shouldThrowOnError,
115136
allowEmpty: false,
116-
} as unknown as PostgrestBuilder<T>)
137+
} as unknown as PostgrestBuilder<Function_['Returns']>)
117138
}
118139
}

0 commit comments

Comments
 (0)