Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
g12i authored Jan 27, 2025
2 parents 438d0ec + a0b56aa commit 3683018
Show file tree
Hide file tree
Showing 26 changed files with 1,757 additions and 586 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ jobs:
- run: |
npm clean-install
npm run test
- name: Coveralls
uses: coverallsapp/github-action@v2
40 changes: 32 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"docs": "typedoc src/index.ts --out docs/v2",
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals src/index.ts",
"test": "run-s format:check test:types db:clean db:run test:run db:clean && node test/smoke.cjs && node test/smoke.mjs",
"test:run": "jest --runInBand",
"test:run": "jest --runInBand --coverage",
"test:update": "run-s db:clean db:run && jest --runInBand --updateSnapshot && run-s db:clean",
"test:types": "run-s build && tsd --files 'test/**/*.test-d.ts'",
"db:clean": "cd test/db && docker compose down --volumes",
Expand All @@ -59,8 +59,9 @@
"ts-expect": "^1.3.0",
"ts-jest": "^28.0.3",
"tsd": "^0.31.2",
"type-fest": "^4.32.0",
"typedoc": "^0.22.16",
"typescript": "~4.7",
"typescript": "^4.5.5",
"wait-for-localhost-cli": "^3.0.0"
}
}
26 changes: 19 additions & 7 deletions src/PostgrestBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// @ts-ignore
import nodeFetch from '@supabase/node-fetch'

import type { Fetch, FetchOptions, PostgrestSingleResponse } from './types'
import type { Fetch, FetchOptions, PostgrestSingleResponse, PostgrestResponseSuccess } from './types'
import PostgrestError from './PostgrestError'

export default abstract class PostgrestBuilder<Result>
implements PromiseLike<PostgrestSingleResponse<Result>>
export default abstract class PostgrestBuilder<Result, ThrowOnError extends boolean = false>
implements
PromiseLike<
ThrowOnError extends true ? PostgrestResponseSuccess<Result> : PostgrestSingleResponse<Result>
>
{
protected method: 'GET' | 'HEAD' | 'POST' | 'PATCH' | 'DELETE'
protected url: URL
Expand Down Expand Up @@ -42,9 +45,9 @@ export default abstract class PostgrestBuilder<Result>
*
* {@link https://github.com/supabase/supabase-js/issues/92}
*/
throwOnError(): this {
throwOnError(): this & PostgrestBuilder<Result, true> {
this.shouldThrowOnError = true
return this
return this as this & PostgrestBuilder<Result, true>
}

/**
Expand All @@ -56,9 +59,18 @@ export default abstract class PostgrestBuilder<Result>
return this
}

then<TResult1 = PostgrestSingleResponse<Result>, TResult2 = never>(
then<
TResult1 = ThrowOnError extends true
? PostgrestResponseSuccess<Result>
: PostgrestSingleResponse<Result>,
TResult2 = never
>(
onfulfilled?:
| ((value: PostgrestSingleResponse<Result>) => TResult1 | PromiseLike<TResult1>)
| ((
value: ThrowOnError extends true
? PostgrestResponseSuccess<Result>
: PostgrestSingleResponse<Result>
) => TResult1 | PromiseLike<TResult1>)
| undefined
| null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
Expand Down
91 changes: 76 additions & 15 deletions src/PostgrestFilterBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PostgrestTransformBuilder from './PostgrestTransformBuilder'
import { JsonPathToAccessor, JsonPathToType } from './select-query-parser/utils'
import { GenericSchema } from './types'

type FilterOperator =
Expand All @@ -25,18 +26,56 @@ type FilterOperator =
| 'phfts'
| 'wfts'

export type IsStringOperator<Path extends string> = Path extends `${string}->>${string}`
? true
: false

// Match relationship filters with `table.column` syntax and resolve underlying
// column value. If not matched, fallback to generic type.
// TODO: Validate the relationship itself ala select-query-parser. Currently we
// assume that all tables have valid relationships to each other, despite
// nonexistent foreign keys.
type ResolveFilterValue<
Schema extends GenericSchema,
Row extends Record<string, unknown>,
ColumnName extends string
> = ColumnName extends `${infer RelationshipTable}.${infer Remainder}`
? Remainder extends `${infer _}.${infer _}`
? ResolveFilterValue<Schema, Row, Remainder>
: ResolveFilterRelationshipValue<Schema, RelationshipTable, Remainder>
: ColumnName extends keyof Row
? Row[ColumnName]
: // If the column selection is a jsonpath like `data->value` or `data->>value` we attempt to match
// the expected type with the parsed custom json type
IsStringOperator<ColumnName> extends true
? string
: JsonPathToType<Row, JsonPathToAccessor<ColumnName>> extends infer JsonPathValue
? JsonPathValue extends never
? never
: JsonPathValue
: never

type ResolveFilterRelationshipValue<
Schema extends GenericSchema,
RelationshipTable extends string,
RelationshipColumn extends string
> = Schema['Tables'] & Schema['Views'] extends infer TablesAndViews
? RelationshipTable extends keyof TablesAndViews
? 'Row' extends keyof TablesAndViews[RelationshipTable]
? RelationshipColumn extends keyof TablesAndViews[RelationshipTable]['Row']
? TablesAndViews[RelationshipTable]['Row'][RelationshipColumn]
: unknown
: unknown
: unknown
: never

export default class PostgrestFilterBuilder<
Schema extends GenericSchema,
Row extends Record<string, unknown>,
Result,
RelationName = unknown,
Relationships = unknown
> extends PostgrestTransformBuilder<Schema, Row, Result, RelationName, Relationships> {
eq<ColumnName extends string & keyof Row>(
column: ColumnName,
value: NonNullable<Row[ColumnName]>
): this
eq<Value extends unknown>(column: string, value: NonNullable<Value>): this
/**
* Match only rows where `column` is equal to `value`.
*
Expand All @@ -45,20 +84,35 @@ export default class PostgrestFilterBuilder<
* @param column - The column to filter on
* @param value - The value to filter with
*/
eq(column: string, value: unknown): this {
eq<ColumnName extends string>(
column: ColumnName,
value: ResolveFilterValue<Schema, Row, ColumnName> extends never
? NonNullable<unknown>
: // We want to infer the type before wrapping it into a `NonNullable` to avoid too deep
// type resolution error
ResolveFilterValue<Schema, Row, ColumnName> extends infer ResolvedFilterValue
? NonNullable<ResolvedFilterValue>
: // We should never enter this case as all the branches are covered above
never
): this {
this.url.searchParams.append(column, `eq.${value}`)
return this
}

neq<ColumnName extends string & keyof Row>(column: ColumnName, value: Row[ColumnName]): this
neq(column: string, value: unknown): this
/**
* Match only rows where `column` is not equal to `value`.
*
* @param column - The column to filter on
* @param value - The value to filter with
*/
neq(column: string, value: unknown): this {
neq<ColumnName extends string>(
column: ColumnName,
value: ResolveFilterValue<Schema, Row, ColumnName> extends never
? unknown
: ResolveFilterValue<Schema, Row, ColumnName> extends infer ResolvedFilterValue
? ResolvedFilterValue
: never
): this {
this.url.searchParams.append(column, `neq.${value}`)
return this
}
Expand Down Expand Up @@ -227,18 +281,25 @@ export default class PostgrestFilterBuilder<
return this
}

in<ColumnName extends string & keyof Row>(
column: ColumnName,
values: ReadonlyArray<Row[ColumnName]>
): this
in(column: string, values: readonly unknown[]): this
/**
* Match only rows where `column` is included in the `values` array.
*
* @param column - The column to filter on
* @param values - The values array to filter with
*/
in(column: string, values: readonly unknown[]): this {
in<ColumnName extends string>(
column: ColumnName,
values: ReadonlyArray<
ResolveFilterValue<Schema, Row, ColumnName> extends never
? unknown
: // We want to infer the type before wrapping it into a `NonNullable` to avoid too deep
// type resolution error
ResolveFilterValue<Schema, Row, ColumnName> extends infer ResolvedFilterValue
? ResolvedFilterValue
: // We should never enter this case as all the branches are covered above
never
>
): this {
const cleanedValues = Array.from(new Set(values))
.map((s) => {
// handle postgrest reserved characters
Expand Down
12 changes: 6 additions & 6 deletions src/PostgrestTransformBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export default class PostgrestTransformBuilder<
ResultOne = Result extends (infer ResultOne)[] ? ResultOne : never
>(): PostgrestBuilder<ResultOne> {
this.headers['Accept'] = 'application/vnd.pgrst.object+json'
return this as PostgrestBuilder<ResultOne>
return this as unknown as PostgrestBuilder<ResultOne>
}

/**
Expand All @@ -246,23 +246,23 @@ export default class PostgrestTransformBuilder<
this.headers['Accept'] = 'application/vnd.pgrst.object+json'
}
this.isMaybeSingle = true
return this as PostgrestBuilder<ResultOne | null>
return this as unknown as PostgrestBuilder<ResultOne | null>
}

/**
* Return `data` as a string in CSV format.
*/
csv(): PostgrestBuilder<string> {
this.headers['Accept'] = 'text/csv'
return this as PostgrestBuilder<string>
return this as unknown as PostgrestBuilder<string>
}

/**
* Return `data` as an object in [GeoJSON](https://geojson.org) format.
*/
geojson(): PostgrestBuilder<Record<string, unknown>> {
this.headers['Accept'] = 'application/geo+json'
return this as PostgrestBuilder<Record<string, unknown>>
return this as unknown as PostgrestBuilder<Record<string, unknown>>
}

/**
Expand Down Expand Up @@ -319,8 +319,8 @@ export default class PostgrestTransformBuilder<
this.headers[
'Accept'
] = `application/vnd.pgrst.plan+${format}; for="${forMediatype}"; options=${options};`
if (format === 'json') return this as PostgrestBuilder<Record<string, unknown>[]>
else return this as PostgrestBuilder<string>
if (format === 'json') return this as unknown as PostgrestBuilder<Record<string, unknown>[]>
else return this as unknown as PostgrestBuilder<string>
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ export type {
PostgrestSingleResponse,
PostgrestMaybeSingleResponse,
} from './types'
// https://github.com/supabase/postgrest-js/issues/551
// To be replaced with a helper type that only uses public types
export type { GetResult as UnstableGetResult } from './select-query-parser/result'
Loading

0 comments on commit 3683018

Please sign in to comment.