Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/core/postgrest-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"format": "node scripts/format.js",
"format:check": "node scripts/format.js check",
"build": "npm run clean && npm run build:cjs && npm run build:esm",
"postbuild": "cp -rf ./src/types/common ../supabase-js/src/lib/rest/types/common",
"build:cjs": "tsc -p tsconfig.json",
"build:esm": "cpy wrapper.mjs dist/esm/",
"docs": "typedoc src/index.ts --out docs/v2",
Expand All @@ -53,7 +54,7 @@
"type-check:test": "tsc --noEmit --project tsconfig.test.json",
"db:clean": "cd test/db && docker compose down --volumes",
"db:run": "cd test/db && docker compose up --detach && wait-for-localhost 3000",
"db:generate-test-types": "cd test/db && docker compose up --detach && wait-for-localhost 8080 && curl --location 'http://0.0.0.0:8080/generators/typescript?included_schemas=public,personal&detect_one_to_one_relationships=true' > ../types.generated.ts && node ../scripts/update-json-type.js && cd ../../ && npm run format"
"db:generate-test-types": "cd test/db && docker compose up --detach && wait-for-localhost 8080 && wait-for-localhost 3000 && curl --location 'http://0.0.0.0:8080/generators/typescript?included_schemas=public,personal&detect_one_to_one_relationships=true' > ../types.generated.ts && node ../../scripts/update-json-type.js && cd ../../ && npm run format"
},
"dependencies": {
"@supabase/node-fetch": "2.6.15"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const path = require('path')
* This is a cross-platform replacement for the sed command
*/
function updateJsonType() {
const filePath = path.join(__dirname, '..', 'types.generated.ts')
const filePath = path.join(__dirname, '..', 'test', 'types.generated.ts')

try {
// Read the file
Expand All @@ -23,7 +23,7 @@ function updateJsonType() {
// Write the updated content back to the file
fs.writeFileSync(filePath, updatedContent, 'utf8')

console.log('✅ Successfully updated Json type in types.generated.ts')
console.log('✅ Successfully updated Json type in test/types.generated.ts')
} catch (error) {
console.error('❌ Error updating Json type:', error.message)
process.exit(1)
Expand Down
5 changes: 2 additions & 3 deletions packages/core/postgrest-js/src/PostgrestBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
import nodeFetch from '@supabase/node-fetch'

import type {
Fetch,
PostgrestSingleResponse,
PostgrestResponseSuccess,
CheckMatchingArrayTypes,
MergePartialResult,
IsValidResultOverride,
ClientServerOptions,
} from './types'
} from './types/types'
import { ClientServerOptions, Fetch } from './types/common/common'
import PostgrestError from './PostgrestError'
import { ContainsNull } from './select-query-parser/types'

Expand Down
27 changes: 16 additions & 11 deletions packages/core/postgrest-js/src/PostgrestClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import PostgrestQueryBuilder from './PostgrestQueryBuilder'
import PostgrestFilterBuilder from './PostgrestFilterBuilder'
import { Fetch, GenericSchema, ClientServerOptions } from './types'
import { Fetch, GenericSchema, ClientServerOptions } from './types/common/common'
import { GetRpcFunctionFilterBuilderByArgs } from './types/common/rpc'

/**
* PostgREST client.
Expand Down Expand Up @@ -131,9 +132,17 @@ export default class PostgrestClient<
* `"estimated"`: Uses exact count for low numbers and planned count for high
* numbers.
*/
rpc<FnName extends string & keyof Schema['Functions'], Fn extends Schema['Functions'][FnName]>(
rpc<
FnName extends string & keyof Schema['Functions'],
Args extends Schema['Functions'][FnName]['Args'] = never,
FilterBuilder extends GetRpcFunctionFilterBuilderByArgs<
Schema,
FnName,
Args
> = GetRpcFunctionFilterBuilderByArgs<Schema, FnName, Args>,
>(
fn: FnName,
args: Fn['Args'] = {},
args: Args = {} as Args,
{
head = false,
get = false,
Expand All @@ -146,14 +155,10 @@ export default class PostgrestClient<
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Fn['Returns'] extends any[]
? Fn['Returns'][number] extends Record<string, unknown>
? Fn['Returns'][number]
: never
: never,
Fn['Returns'],
FnName,
null,
FilterBuilder['Row'],
FilterBuilder['Result'],
FilterBuilder['RelationName'],
FilterBuilder['Relationships'],
'RPC'
> {
let method: 'HEAD' | 'GET' | 'POST'
Expand Down
2 changes: 1 addition & 1 deletion packages/core/postgrest-js/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 { ClientServerOptions, GenericSchema } from './types'
import { ClientServerOptions, GenericSchema } from './types/common/common'

type FilterOperator =
| 'eq'
Expand Down
8 changes: 7 additions & 1 deletion packages/core/postgrest-js/src/PostgrestQueryBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import PostgrestFilterBuilder from './PostgrestFilterBuilder'
import { GetResult } from './select-query-parser/result'
import { ClientServerOptions, Fetch, GenericSchema, GenericTable, GenericView } from './types'
import {
ClientServerOptions,
Fetch,
GenericSchema,
GenericTable,
GenericView,
} from './types/common/common'

export default class PostgrestQueryBuilder<
ClientOptions extends ClientServerOptions,
Expand Down
26 changes: 15 additions & 11 deletions packages/core/postgrest-js/src/PostgrestTransformBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import PostgrestBuilder from './PostgrestBuilder'
import { InvalidMethodError } from './PostgrestFilterBuilder'
import PostgrestFilterBuilder, { InvalidMethodError } from './PostgrestFilterBuilder'
import { GetResult } from './select-query-parser/result'
import {
GenericSchema,
CheckMatchingArrayTypes,
ClientServerOptions,
MaxAffectedEnabled,
} from './types'
import { CheckMatchingArrayTypes, MaxAffectedEnabled } from './types/types'
import { ClientServerOptions, GenericSchema } from './types/common/common'

export default class PostgrestTransformBuilder<
ClientOptions extends ClientServerOptions,
Expand All @@ -31,11 +27,15 @@ export default class PostgrestTransformBuilder<
NewResultOne = GetResult<Schema, Row, RelationName, Relationships, Query, ClientOptions>,
>(
columns?: Query
): PostgrestTransformBuilder<
): PostgrestFilterBuilder<
ClientOptions,
Schema,
Row,
NewResultOne[],
Method extends 'RPC'
? Result extends unknown[]
? NewResultOne[]
: NewResultOne
: NewResultOne[],
RelationName,
Relationships,
Method
Expand All @@ -56,11 +56,15 @@ export default class PostgrestTransformBuilder<
.join('')
this.url.searchParams.set('select', cleanedColumns)
this.headers.append('Prefer', 'return=representation')
return this as unknown as PostgrestTransformBuilder<
return this as unknown as PostgrestFilterBuilder<
ClientOptions,
Schema,
Row,
NewResultOne[],
Method extends 'RPC'
? Result extends unknown[]
? NewResultOne[]
: NewResultOne
: NewResultOne[],
RelationName,
Relationships,
Method
Expand Down
4 changes: 2 additions & 2 deletions packages/core/postgrest-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export type {
PostgrestResponseSuccess,
PostgrestSingleResponse,
PostgrestMaybeSingleResponse,
ClientServerOptions as PostgrestClientOptions,
} from './types'
} from './types/types'
export type { ClientServerOptions as PostgrestClientOptions } from './types/common/common'
// 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'
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Credits to @bnjmnt4n (https://www.npmjs.com/package/postgrest-query)
// See https://github.com/PostgREST/postgrest/blob/2f91853cb1de18944a4556df09e52450b881cfb3/src/PostgREST/ApiRequest/QueryParams.hs#L282-L284

import { SimplifyDeep } from '../types'
import { SimplifyDeep } from '../types/types'
import { JsonPathToAccessor } from './utils'

/**
Expand Down
35 changes: 29 additions & 6 deletions packages/core/postgrest-js/src/select-query-parser/result.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { ClientServerOptions, GenericTable } from '../types'
import { ContainsNull, GenericRelationship, PostgreSQLTypes } from './types'
import { Ast, ParseQuery } from './parser'
import {
AggregateFunctions,
Expand All @@ -9,6 +7,11 @@ import {
Prettify,
TablesAndViews,
TypeScriptTypes,
ContainsNull,
GenericRelationship,
PostgreSQLTypes,
GenericTable,
ClientServerOptions,
} from './types'
import {
CheckDuplicateEmbededReference,
Expand Down Expand Up @@ -366,7 +369,7 @@ export type ProcessEmbeddedResource<
ResolveRelationship<Schema, Relationships, Field, CurrentTableOrView> extends infer Resolved
? Resolved extends {
referencedTable: Pick<GenericTable, 'Row' | 'Relationships'>
relation: GenericRelationship & { match: 'refrel' | 'col' | 'fkname' }
relation: GenericRelationship & { match: 'refrel' | 'col' | 'fkname' | 'func' }
direction: string
}
? ProcessEmbeddedResourceResult<ClientOptions, Schema, Resolved, Field, CurrentTableOrView>
Expand All @@ -385,7 +388,12 @@ type ProcessEmbeddedResourceResult<
Schema extends GenericSchema,
Resolved extends {
referencedTable: Pick<GenericTable, 'Row' | 'Relationships'>
relation: GenericRelationship & { match: 'refrel' | 'col' | 'fkname' }
relation: GenericRelationship & {
match: 'refrel' | 'col' | 'fkname' | 'func'
isNotNullable?: boolean
referencedRelation: string
isSetofReturn?: boolean
}
direction: string
},
Field extends Ast.FieldNode,
Expand All @@ -395,7 +403,11 @@ type ProcessEmbeddedResourceResult<
ClientOptions,
Schema,
Resolved['referencedTable']['Row'],
Field['name'],
// For embeded function selection, the source of truth is the 'referencedRelation'
// coming from the SetofOptions.to parameter
Resolved['relation']['match'] extends 'func'
? Resolved['relation']['referencedRelation']
: Field['name'],
Resolved['referencedTable']['Relationships'],
Field['children'] extends undefined
? []
Expand All @@ -410,7 +422,18 @@ type ProcessEmbeddedResourceResult<
? ProcessedChildren
: ProcessedChildren[]
: Resolved['relation']['isOneToOne'] extends true
? ProcessedChildren | null
? Resolved['relation']['match'] extends 'func'
? Resolved['relation']['isNotNullable'] extends true
? Resolved['relation']['isSetofReturn'] extends true
? ProcessedChildren
: // TODO: This shouldn't be necessary but is due in an inconsitency in PostgREST v12/13 where if a function
// is declared with RETURNS <table-name> instead of RETURNS SETOF <table-name> ROWS 1
// In case where there is no object matching the relations, the object will be returned with all the properties within it
// set to null, we mimic this buggy behavior for type safety an issue is opened on postgREST here:
// https://github.com/PostgREST/postgrest/issues/4234
{ [P in keyof ProcessedChildren]: ProcessedChildren[P] | null }
: ProcessedChildren | null
: ProcessedChildren | null
: ProcessedChildren[]
: // If the relation is a self-reference it'll always be considered as reverse relationship
Resolved['relation']['referencedRelation'] extends CurrentTableOrView
Expand Down
22 changes: 19 additions & 3 deletions packages/core/postgrest-js/src/select-query-parser/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import type { GenericRelationship, GenericSchema, GenericTable, Prettify } from '../types'

export type { GenericRelationship, GenericSchema, GenericTable, Prettify }
import type {
GenericRelationship,
GenericSchema,
GenericTable,
ClientServerOptions,
GenericSetofOption,
GenericFunction,
} from '../types/common/common'
import type { Prettify } from '../types/types'

export type {
GenericRelationship,
GenericSchema,
GenericTable,
ClientServerOptions,
GenericSetofOption,
Prettify,
GenericFunction,
}

export type AggregateWithoutColumnFunctions = 'count'

Expand Down
64 changes: 63 additions & 1 deletion packages/core/postgrest-js/src/select-query-parser/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
IsNonEmptyArray,
TablesAndViews,
UnionToArray,
GenericFunction,
GenericSetofOption,
} from './types'

export type IsAny<T> = 0 extends 1 & T ? true : false
Expand Down Expand Up @@ -457,7 +459,37 @@ export type ResolveForwardRelationship<
from: CurrentTableOrView
type: 'found-by-join-table'
}
: SelectQueryError<`could not find the relation between ${CurrentTableOrView} and ${Field['name']}`>
: ResolveEmbededFunctionJoinTableRelationship<
Schema,
CurrentTableOrView,
Field['name']
> extends infer FoundEmbededFunctionJoinTableRelation
? FoundEmbededFunctionJoinTableRelation extends GenericSetofOption
? {
referencedTable: TablesAndViews<Schema>[FoundEmbededFunctionJoinTableRelation['to']]
relation: {
foreignKeyName: `${Field['name']}_${CurrentTableOrView}_${FoundEmbededFunctionJoinTableRelation['to']}_forward`
columns: []
isOneToOne: FoundEmbededFunctionJoinTableRelation['isOneToOne'] extends true
? true
: false
referencedColumns: []
referencedRelation: FoundEmbededFunctionJoinTableRelation['to']
} & {
match: 'func'
isNotNullable: FoundEmbededFunctionJoinTableRelation['isNotNullable'] extends true
? true
: FoundEmbededFunctionJoinTableRelation['isSetofReturn'] extends true
? false
: true
isSetofReturn: FoundEmbededFunctionJoinTableRelation['isSetofReturn']
}
direction: 'forward'
from: CurrentTableOrView
type: 'found-by-embeded-function'
}
: SelectQueryError<`could not find the relation between ${CurrentTableOrView} and ${Field['name']}`>
: SelectQueryError<`could not find the relation between ${CurrentTableOrView} and ${Field['name']}`>
: SelectQueryError<`could not find the relation between ${CurrentTableOrView} and ${Field['name']}`>
: SelectQueryError<`could not find the relation between ${CurrentTableOrView} and ${Field['name']}`>
: SelectQueryError<`could not find the relation between ${CurrentTableOrView} and ${Field['name']}`>
Expand Down Expand Up @@ -500,6 +532,20 @@ type ResolveJoinTableRelationship<
: never
}[keyof TablesAndViews<Schema>]

type ResolveEmbededFunctionJoinTableRelationship<
Schema extends GenericSchema,
CurrentTableOrView extends keyof TablesAndViews<Schema> & string,
FieldName extends string,
> =
FindMatchingFunctionBySetofFrom<
Schema['Functions'][FieldName],
CurrentTableOrView
> extends infer Fn
? Fn extends GenericFunction
? Fn['SetofOptions']
: false
: false

export type FindJoinTableRelationship<
Schema extends GenericSchema,
CurrentTableOrView extends keyof TablesAndViews<Schema> & string,
Expand Down Expand Up @@ -589,6 +635,22 @@ export type IsStringUnion<T> = string extends T
: true
: false

type MatchingFunctionBySetofFrom<
Fn extends GenericFunction,
TableName extends string,
> = Fn['SetofOptions'] extends GenericSetofOption
? TableName extends Fn['SetofOptions']['from']
? Fn
: never
: false

type FindMatchingFunctionBySetofFrom<
FnUnion,
TableName extends string,
> = FnUnion extends infer Fn extends GenericFunction
? MatchingFunctionBySetofFrom<Fn, TableName>
: false

type ComputedField<
Schema extends GenericSchema,
RelationName extends keyof TablesAndViews<Schema>,
Expand Down
Loading
Loading