Skip to content

feat(types): setup postgrest-13 types inference #618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
23 changes: 17 additions & 6 deletions src/PostgrestBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import type {
CheckMatchingArrayTypes,
MergePartialResult,
IsValidResultOverride,
ClientServerOptions,
} from './types'
import PostgrestError from './PostgrestError'
import { ContainsNull } from './select-query-parser/types'

export default abstract class PostgrestBuilder<Result, ThrowOnError extends boolean = false>
implements
export default abstract class PostgrestBuilder<
ClientOptions extends ClientServerOptions,
Result,
ThrowOnError extends boolean = false
> implements
PromiseLike<
ThrowOnError extends true ? PostgrestResponseSuccess<Result> : PostgrestSingleResponse<Result>
>
Expand All @@ -28,7 +32,7 @@ export default abstract class PostgrestBuilder<Result, ThrowOnError extends bool
protected fetch: Fetch
protected isMaybeSingle: boolean

constructor(builder: PostgrestBuilder<Result>) {
constructor(builder: PostgrestBuilder<ClientOptions, Result>) {
this.method = builder.method
this.url = builder.url
this.headers = builder.headers
Expand All @@ -53,9 +57,9 @@ export default abstract class PostgrestBuilder<Result, ThrowOnError extends bool
*
* {@link https://github.com/supabase/supabase-js/issues/92}
*/
throwOnError(): this & PostgrestBuilder<Result, true> {
throwOnError(): this & PostgrestBuilder<ClientOptions, Result, true> {
this.shouldThrowOnError = true
return this as this & PostgrestBuilder<Result, true>
return this as this & PostgrestBuilder<ClientOptions, Result, true>
}

/**
Expand Down Expand Up @@ -224,9 +228,14 @@ export default abstract class PostgrestBuilder<Result, ThrowOnError extends bool
* @typeParam NewResult - The new result type to override with
* @deprecated Use overrideTypes<yourType, { merge: false }>() method at the end of your call chain instead
*/
returns<NewResult>(): PostgrestBuilder<CheckMatchingArrayTypes<Result, NewResult>, ThrowOnError> {
returns<NewResult>(): PostgrestBuilder<
ClientOptions,
CheckMatchingArrayTypes<Result, NewResult>,
ThrowOnError
> {
/* istanbul ignore next */
return this as unknown as PostgrestBuilder<
ClientOptions,
CheckMatchingArrayTypes<Result, NewResult>,
ThrowOnError
>
Expand Down Expand Up @@ -258,6 +267,7 @@ export default abstract class PostgrestBuilder<Result, ThrowOnError extends bool
NewResult,
Options extends { merge?: boolean } = { merge: true }
>(): PostgrestBuilder<
ClientOptions,
IsValidResultOverride<Result, NewResult, false, false> extends true
? // Preserve the optionality of the result if the overriden type is an object (case of chaining with `maybeSingle`)
ContainsNull<Result> extends true
Expand All @@ -267,6 +277,7 @@ export default abstract class PostgrestBuilder<Result, ThrowOnError extends bool
ThrowOnError
> {
return this as unknown as PostgrestBuilder<
ClientOptions,
IsValidResultOverride<Result, NewResult, false, false> extends true
? // Preserve the optionality of the result if the overriden type is an object (case of chaining with `maybeSingle`)
ContainsNull<Result> extends true
Expand Down
13 changes: 8 additions & 5 deletions src/PostgrestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PostgrestQueryBuilder from './PostgrestQueryBuilder'
import PostgrestFilterBuilder from './PostgrestFilterBuilder'
import PostgrestBuilder from './PostgrestBuilder'
import { DEFAULT_HEADERS } from './constants'
import { Fetch, GenericSchema } from './types'
import { Fetch, GenericSchema, ClientServerOptions } from './types'

/**
* PostgREST client.
Expand All @@ -16,6 +16,7 @@ import { Fetch, GenericSchema } from './types'
*/
export default class PostgrestClient<
Database = any,
ClientOptions extends ClientServerOptions = { postgrestVersion: 12 },
SchemaName extends string & keyof Database = 'public' extends keyof Database
? 'public'
: string & keyof Database,
Expand Down Expand Up @@ -59,16 +60,16 @@ export default class PostgrestClient<
from<
TableName extends string & keyof Schema['Tables'],
Table extends Schema['Tables'][TableName]
>(relation: TableName): PostgrestQueryBuilder<Schema, Table, TableName>
>(relation: TableName): PostgrestQueryBuilder<ClientOptions, Schema, Table, TableName>
from<ViewName extends string & keyof Schema['Views'], View extends Schema['Views'][ViewName]>(
relation: ViewName
): PostgrestQueryBuilder<Schema, View, ViewName>
): PostgrestQueryBuilder<ClientOptions, Schema, View, ViewName>
/**
* Perform a query on a table or a view.
*
* @param relation - The table or view name to query
*/
from(relation: string): PostgrestQueryBuilder<Schema, any, any> {
from(relation: string): PostgrestQueryBuilder<ClientOptions, Schema, any, any> {
const url = new URL(`${this.url}/${relation}`)
return new PostgrestQueryBuilder(url, {
headers: { ...this.headers },
Expand All @@ -88,6 +89,7 @@ export default class PostgrestClient<
schema: DynamicSchema
): PostgrestClient<
Database,
ClientOptions,
DynamicSchema,
Database[DynamicSchema] extends GenericSchema ? Database[DynamicSchema] : any
> {
Expand Down Expand Up @@ -134,6 +136,7 @@ export default class PostgrestClient<
count?: 'exact' | 'planned' | 'estimated'
} = {}
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Fn['Returns'] extends any[]
? Fn['Returns'][number] extends Record<string, unknown>
Expand Down Expand Up @@ -176,6 +179,6 @@ export default class PostgrestClient<
body,
fetch: this.fetch,
allowEmpty: false,
} as unknown as PostgrestBuilder<Fn['Returns']>)
} as unknown as PostgrestBuilder<ClientOptions, Fn['Returns']>)
}
}
14 changes: 12 additions & 2 deletions src/PostgrestFilterBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import PostgrestTransformBuilder from './PostgrestTransformBuilder'
import { JsonPathToAccessor, JsonPathToType } from './select-query-parser/utils'
import { GenericSchema } from './types'
import { ClientServerOptions, GenericSchema } from './types'

type FilterOperator =
| 'eq'
Expand Down Expand Up @@ -69,13 +69,23 @@ type ResolveFilterRelationshipValue<
: unknown
: never

export type InvalidMethodError<S extends string> = { Error: S }

export default class PostgrestFilterBuilder<
ClientOptions extends ClientServerOptions,
Schema extends GenericSchema,
Row extends Record<string, unknown>,
Result,
RelationName = unknown,
Relationships = unknown
> extends PostgrestTransformBuilder<Schema, Row, Result, RelationName, Relationships> {
> extends PostgrestTransformBuilder<
ClientOptions,
Schema,
Row,
Result,
RelationName,
Relationships
> {
/**
* Match only rows where `column` is equal to `value`.
*
Expand Down
103 changes: 87 additions & 16 deletions src/PostgrestQueryBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import PostgrestBuilder from './PostgrestBuilder'
import PostgrestFilterBuilder from './PostgrestFilterBuilder'
import { GetResult } from './select-query-parser/result'
import { Fetch, GenericSchema, GenericTable, GenericView } from './types'
import { ClientServerOptions, Fetch, GenericSchema, GenericTable, GenericView } from './types'

export default class PostgrestQueryBuilder<
ClientOptions extends ClientServerOptions,
Schema extends GenericSchema,
Relation extends GenericTable | GenericView,
RelationName = unknown,
Expand Down Expand Up @@ -56,7 +57,14 @@ export default class PostgrestQueryBuilder<
*/
select<
Query extends string = '*',
ResultOne = GetResult<Schema, Relation['Row'], RelationName, Relationships, Query>
ResultOne = GetResult<
Schema,
Relation['Row'],
RelationName,
Relationships,
Query,
ClientOptions
>
>(
columns?: Query,
{
Expand All @@ -66,7 +74,14 @@ export default class PostgrestQueryBuilder<
head?: boolean
count?: 'exact' | 'planned' | 'estimated'
} = {}
): PostgrestFilterBuilder<Schema, Relation['Row'], ResultOne[], RelationName, Relationships> {
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
ResultOne[],
RelationName,
Relationships
> {
const method = head ? 'HEAD' : 'GET'
// Remove whitespaces except when quoted
let quoted = false
Expand Down Expand Up @@ -94,7 +109,7 @@ export default class PostgrestQueryBuilder<
schema: this.schema,
fetch: this.fetch,
allowEmpty: false,
} as unknown as PostgrestBuilder<ResultOne[]>)
} as unknown as PostgrestBuilder<ClientOptions, ResultOne[]>)
}

// TODO(v3): Make `defaultToNull` consistent for both single & bulk inserts.
Expand All @@ -103,14 +118,28 @@ export default class PostgrestQueryBuilder<
options?: {
count?: 'exact' | 'planned' | 'estimated'
}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships>
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
>
insert<Row extends Relation extends { Insert: unknown } ? Relation['Insert'] : never>(
values: Row[],
options?: {
count?: 'exact' | 'planned' | 'estimated'
defaultToNull?: boolean
}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships>
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
>
/**
* Perform an INSERT into the table or view.
*
Expand Down Expand Up @@ -146,7 +175,14 @@ export default class PostgrestQueryBuilder<
count?: 'exact' | 'planned' | 'estimated'
defaultToNull?: boolean
} = {}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships> {
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
> {
const method = 'POST'

const prefersHeaders = []
Expand Down Expand Up @@ -177,7 +213,7 @@ export default class PostgrestQueryBuilder<
body: values,
fetch: this.fetch,
allowEmpty: false,
} as unknown as PostgrestBuilder<null>)
} as unknown as PostgrestBuilder<ClientOptions, null>)
}

// TODO(v3): Make `defaultToNull` consistent for both single & bulk upserts.
Expand All @@ -188,7 +224,14 @@ export default class PostgrestQueryBuilder<
ignoreDuplicates?: boolean
count?: 'exact' | 'planned' | 'estimated'
}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships>
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
>
upsert<Row extends Relation extends { Insert: unknown } ? Relation['Insert'] : never>(
values: Row[],
options?: {
Expand All @@ -197,7 +240,14 @@ export default class PostgrestQueryBuilder<
count?: 'exact' | 'planned' | 'estimated'
defaultToNull?: boolean
}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships>
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
>
/**
* Perform an UPSERT on the table or view. Depending on the column(s) passed
* to `onConflict`, `.upsert()` allows you to perform the equivalent of
Expand Down Expand Up @@ -249,7 +299,14 @@ export default class PostgrestQueryBuilder<
count?: 'exact' | 'planned' | 'estimated'
defaultToNull?: boolean
} = {}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships> {
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
> {
const method = 'POST'

const prefersHeaders = [`resolution=${ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`]
Expand Down Expand Up @@ -282,7 +339,7 @@ export default class PostgrestQueryBuilder<
body: values,
fetch: this.fetch,
allowEmpty: false,
} as unknown as PostgrestBuilder<null>)
} as unknown as PostgrestBuilder<ClientOptions, null>)
}

/**
Expand Down Expand Up @@ -313,7 +370,14 @@ export default class PostgrestQueryBuilder<
}: {
count?: 'exact' | 'planned' | 'estimated'
} = {}
): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships> {
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
> {
const method = 'PATCH'
const prefersHeaders = []
if (this.headers['Prefer']) {
Expand All @@ -332,7 +396,7 @@ export default class PostgrestQueryBuilder<
body: values,
fetch: this.fetch,
allowEmpty: false,
} as unknown as PostgrestBuilder<null>)
} as unknown as PostgrestBuilder<ClientOptions, null>)
}

/**
Expand All @@ -358,7 +422,14 @@ export default class PostgrestQueryBuilder<
count,
}: {
count?: 'exact' | 'planned' | 'estimated'
} = {}): PostgrestFilterBuilder<Schema, Relation['Row'], null, RelationName, Relationships> {
} = {}): PostgrestFilterBuilder<
ClientOptions,
Schema,
Relation['Row'],
null,
RelationName,
Relationships
> {
const method = 'DELETE'
const prefersHeaders = []
if (count) {
Expand All @@ -376,6 +447,6 @@ export default class PostgrestQueryBuilder<
schema: this.schema,
fetch: this.fetch,
allowEmpty: false,
} as unknown as PostgrestBuilder<null>)
} as unknown as PostgrestBuilder<ClientOptions, null>)
}
}
Loading
Loading