diff --git a/src/select-query-parser.ts b/src/select-query-parser.ts
index 114d59d5..e44e1e44 100644
--- a/src/select-query-parser.ts
+++ b/src/select-query-parser.ts
@@ -191,6 +191,17 @@ type ConstructFieldDefinition<
Field
> = Field extends { star: true }
? Row
+ : Field extends { spread: true; original: string; children: unknown[] }
+ ? GetResultHelper<
+ Schema,
+ (Schema['Tables'] & Schema['Views'])[Field['original']]['Row'],
+ Field['original'],
+ (Schema['Tables'] & Schema['Views'])[Field['original']] extends { Relationships: infer R }
+ ? R
+ : unknown,
+ Field['children'],
+ unknown
+ >
: Field extends { name: string; original: string; hint: string; children: unknown[] }
? {
[_ in Field['name']]: GetResultHelper<
@@ -394,12 +405,20 @@ type ParseField = Input extends ''
* - `*`
* - a field, as defined above
* - a renamed field, `renamed_field:field`
+ * - a spread field, `...field`
*/
type ParseNode = Input extends ''
? ParserError<'Empty string'>
: // `*`
Input extends `*${infer Remainder}`
? [{ star: true }, EatWhitespace]
+ : // `...field`
+ Input extends `...${infer Remainder}`
+ ? ParseField> extends [infer Field, `${infer Remainder}`]
+ ? Field extends { children: unknown[] }
+ ? [Prettify<{ spread: true } & Field>, EatWhitespace]
+ : ParserError<'Unable to parse spread resource'>
+ : ParserError<'Unable to parse spread resource'>
: ParseIdentifier extends [infer Name, `${infer Remainder}`]
? EatWhitespace extends `::${infer _Remainder}`
? // `field::`
diff --git a/test/index.test-d.ts b/test/index.test-d.ts
index 68c6350e..0129f5bd 100644
--- a/test/index.test-d.ts
+++ b/test/index.test-d.ts
@@ -1,6 +1,7 @@
import { expectError, expectType } from 'tsd'
import { PostgrestClient, PostgrestSingleResponse } from '../src/index'
import { SelectQueryError } from '../src/select-query-parser'
+import { Prettify } from '../src/types'
import { Database, Json } from './types'
const REST_URL = 'http://localhost:3000'
@@ -53,6 +54,31 @@ const postgrest = new PostgrestClient(REST_URL)
expectError(postgrest.from('updatable_view').update({ non_updatable_column: 0 }))
}
+// spread resource with single column in select query
+{
+ const { data, error } = await postgrest
+ .from('messages')
+ .select('message, ...users(status)')
+ .single()
+ if (error) {
+ throw new Error(error.message)
+ }
+ expectType<{ message: string | null; status: Database['public']['Enums']['user_status'] | null }>(
+ data
+ )
+}
+
+// spread resource with all columns in select query
+{
+ const { data, error } = await postgrest.from('messages').select('message, ...users(*)').single()
+ if (error) {
+ throw new Error(error.message)
+ }
+ expectType>(
+ data
+ )
+}
+
// json accessor in select query
{
const { data, error } = await postgrest