Skip to content

Commit a9842b2

Browse files
committedJan 20, 2025·
fix: jsonpath with embeded tables
1 parent d51236a commit a9842b2

File tree

6 files changed

+80
-9
lines changed

6 files changed

+80
-9
lines changed
 

‎src/select-query-parser/utils.ts

+2
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,8 @@ export type JsonPathToAccessor<Path extends string> = Path extends `${infer P1}-
555555
? JsonPathToAccessor<Rest>
556556
: Path extends `${infer P1}::${infer _}` // Handle type casting
557557
? JsonPathToAccessor<P1>
558+
: Path extends `${infer P1}${')' | ','}${infer _}` // Handle closing parenthesis and comma
559+
? P1
558560
: Path
559561

560562
export type JsonPathToType<T, Path extends string> = Path extends ''

‎test/basic.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PostgrestClient } from '../src/index'
2-
import { Database } from './types'
2+
import { CustomUserDataType, Database } from './types'
33

44
const REST_URL = 'http://localhost:3000'
55
const postgrest = new PostgrestClient<Database>(REST_URL)
@@ -1615,7 +1615,10 @@ test('select with no match', async () => {
16151615
})
16161616

16171617
test('update with no match - return=minimal', async () => {
1618-
const res = await postgrest.from('users').update({ data: '' }).eq('username', 'missing')
1618+
const res = await postgrest
1619+
.from('users')
1620+
.update({ data: '' as unknown as CustomUserDataType })
1621+
.eq('username', 'missing')
16191622
expect(res).toMatchInlineSnapshot(`
16201623
Object {
16211624
"count": null,
@@ -1628,7 +1631,11 @@ test('update with no match - return=minimal', async () => {
16281631
})
16291632

16301633
test('update with no match - return=representation', async () => {
1631-
const res = await postgrest.from('users').update({ data: '' }).eq('username', 'missing').select()
1634+
const res = await postgrest
1635+
.from('users')
1636+
.update({ data: '' as unknown as CustomUserDataType })
1637+
.eq('username', 'missing')
1638+
.select()
16321639
expect(res).toMatchInlineSnapshot(`
16331640
Object {
16341641
"count": null,

‎test/select-query-parser/parser.test-d.ts

+33
Original file line numberDiff line numberDiff line change
@@ -662,3 +662,36 @@ import { selectParams } from '../relationships'
662662
0 as any as ParserError<'Unexpected input: ->->theme'>
663663
)
664664
}
665+
666+
// JSON accessor within embedded tables
667+
{
668+
expectType<ParseQuery<'users(data->bar->>baz, data->>en, data->bar)'>>([
669+
{
670+
type: 'field',
671+
name: 'users',
672+
children: [
673+
{
674+
type: 'field',
675+
name: 'data',
676+
alias: 'baz',
677+
castType: 'text',
678+
jsonPath: 'bar.baz',
679+
},
680+
{
681+
type: 'field',
682+
name: 'data',
683+
alias: 'en',
684+
castType: 'text',
685+
jsonPath: 'en',
686+
},
687+
{
688+
type: 'field',
689+
name: 'data',
690+
alias: 'bar',
691+
castType: 'json',
692+
jsonPath: 'bar',
693+
},
694+
],
695+
},
696+
])
697+
}

‎test/select-query-parser/result.test-d.ts

+29
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,33 @@ type SelectQueryFromTableResult<
164164
}
165165
expectType<TypeEqual<typeof result, typeof expected>>(true)
166166
}
167+
// Should work with embeded Json object accessor
168+
{
169+
let result: SelectQueryFromTableResult<'messages', `users(data->bar->baz, data->en, data->bar)`>
170+
let expected: {
171+
users: {
172+
baz: number
173+
en: 'ONE' | 'TWO' | 'THREE'
174+
bar: {
175+
baz: number
176+
}
177+
}
178+
}
179+
expectType<TypeEqual<typeof result, typeof expected>>(true)
180+
}
181+
// Should work with embeded Json string accessor
182+
{
183+
let result: SelectQueryFromTableResult<
184+
'messages',
185+
`users(data->bar->>baz, data->>en, data->>bar)`
186+
>
187+
let expected: {
188+
users: {
189+
baz: string
190+
en: 'ONE' | 'TWO' | 'THREE'
191+
bar: string
192+
}
193+
}
194+
expectType<TypeEqual<typeof result, typeof expected>>(true)
195+
}
167196
}

‎test/select-query-parser/select.test-d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { TypeEqual } from 'ts-expect'
33
import { Json } from '../../src/select-query-parser/types'
44
import { SelectQueryError } from '../../src/select-query-parser/utils'
55
import { Prettify } from '../../src/types'
6-
import { Database } from '../types'
6+
import { CustomUserDataType, Database } from '../types'
77
import { selectQueries } from '../relationships'
88

99
// This test file is here to ensure that for a query against a specfic datatabase
@@ -617,7 +617,7 @@ type Schema = Database['public']
617617
users: {
618618
age_range: unknown | null
619619
catchphrase: unknown | null
620-
data: Json | null
620+
data: CustomUserDataType | null
621621
status: Database['public']['Enums']['user_status'] | null
622622
username: string
623623
}

‎test/types.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[]
22

3-
type CustomUserDataType = {
3+
export type CustomUserDataType = {
44
foo: string
55
bar: {
66
baz: number
@@ -412,21 +412,21 @@ export type Database = {
412412
Row: {
413413
age_range: unknown | null
414414
catchphrase: unknown | null
415-
data: Json | null
415+
data: CustomUserDataType | null
416416
status: Database['public']['Enums']['user_status'] | null
417417
username: string
418418
}
419419
Insert: {
420420
age_range?: unknown | null
421421
catchphrase?: unknown | null
422-
data?: Json | null
422+
data?: CustomUserDataType | null
423423
status?: Database['public']['Enums']['user_status'] | null
424424
username: string
425425
}
426426
Update: {
427427
age_range?: unknown | null
428428
catchphrase?: unknown | null
429-
data?: Json | null
429+
data?: CustomUserDataType | null
430430
status?: Database['public']['Enums']['user_status'] | null
431431
username?: string
432432
}

0 commit comments

Comments
 (0)
Please sign in to comment.