Skip to content

Commit 878034b

Browse files
authored
Merge pull request #424 from supabase/fix/maybe-single
fix: partial fix for maybeSingle logging 406s
2 parents ad74608 + 8030cc0 commit 878034b

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
"scripts": {
2222
"clean": "rimraf dist docs/v2",
2323
"format": "prettier --write \"{src,test}/**/*.ts\"",
24+
"format:check": "prettier --check \"{src,test}/**/*.ts\"",
2425
"build": "run-s clean format build:*",
2526
"build:main": "tsc -p tsconfig.json",
2627
"build:module": "tsc -p tsconfig.module.json",
2728
"docs": "typedoc src/index.ts --out docs/v2",
2829
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals src/index.ts",
29-
"test": "run-s test:types db:clean db:run test:run db:clean",
30+
"test": "run-s format:check test:types db:clean db:run test:run db:clean",
3031
"test:run": "jest --runInBand",
3132
"test:update": "run-s db:clean db:run && jest --runInBand --updateSnapshot && run-s db:clean",
3233
"test:types": "run-s build:module && tsd --files test/*.test-d.ts",

src/PostgrestBuilder.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default abstract class PostgrestBuilder<Result>
1313
protected shouldThrowOnError = false
1414
protected signal?: AbortSignal
1515
protected fetch: Fetch
16-
protected allowEmpty: boolean
16+
protected isMaybeSingle: boolean
1717

1818
constructor(builder: PostgrestBuilder<Result>) {
1919
this.method = builder.method
@@ -23,7 +23,7 @@ export default abstract class PostgrestBuilder<Result>
2323
this.body = builder.body
2424
this.shouldThrowOnError = builder.shouldThrowOnError
2525
this.signal = builder.signal
26-
this.allowEmpty = builder.allowEmpty
26+
this.isMaybeSingle = builder.isMaybeSingle
2727

2828
if (builder.fetch) {
2929
this.fetch = builder.fetch
@@ -101,6 +101,28 @@ export default abstract class PostgrestBuilder<Result>
101101
if (countHeader && contentRange && contentRange.length > 1) {
102102
count = parseInt(contentRange[1])
103103
}
104+
105+
// Temporary partial fix for https://github.com/supabase/postgrest-js/issues/361
106+
// Issue persists e.g. for `.insert([...]).select().maybeSingle()`
107+
if (this.isMaybeSingle && this.method === 'GET' && Array.isArray(data)) {
108+
if (data.length > 1) {
109+
error = {
110+
// https://github.com/PostgREST/postgrest/blob/a867d79c42419af16c18c3fb019eba8df992626f/src/PostgREST/Error.hs#L553
111+
code: 'PGRST116',
112+
details: `Results contain ${data.length} rows, application/vnd.pgrst.object+json requires 1 row`,
113+
hint: null,
114+
message: 'JSON object requested, multiple (or no) rows returned',
115+
}
116+
data = null
117+
count = null
118+
status = 406
119+
statusText = 'Not Acceptable'
120+
} else if (data.length === 1) {
121+
data = data[0]
122+
} else {
123+
data = null
124+
}
125+
}
104126
} else {
105127
const body = await res.text()
106128

@@ -126,7 +148,7 @@ export default abstract class PostgrestBuilder<Result>
126148
}
127149
}
128150

129-
if (error && this.allowEmpty && error?.details?.includes('Results contain 0 rows')) {
151+
if (error && this.isMaybeSingle && error?.details?.includes('Results contain 0 rows')) {
130152
error = null
131153
status = 200
132154
statusText = 'OK'

src/PostgrestTransformBuilder.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,14 @@ export default class PostgrestTransformBuilder<
149149
maybeSingle<
150150
ResultOne = Result extends (infer ResultOne)[] ? ResultOne : never
151151
>(): PostgrestBuilder<ResultOne | null> {
152-
this.headers['Accept'] = 'application/vnd.pgrst.object+json'
153-
this.allowEmpty = true
152+
// Temporary partial fix for https://github.com/supabase/postgrest-js/issues/361
153+
// Issue persists e.g. for `.insert([...]).select().maybeSingle()`
154+
if (this.method === 'GET') {
155+
this.headers['Accept'] = 'application/json'
156+
} else {
157+
this.headers['Accept'] = 'application/vnd.pgrst.object+json'
158+
}
159+
this.isMaybeSingle = true
154160
return this as PostgrestBuilder<ResultOne | null>
155161
}
156162

test/transforms.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,28 @@ test('maybeSingle', async () => {
188188
`)
189189
})
190190

191+
test('maybeSingle', async () => {
192+
const res = await postgrest
193+
.from('users')
194+
.insert([{ username: 'a' }, { username: 'b' }])
195+
.select()
196+
.maybeSingle()
197+
expect(res).toMatchInlineSnapshot(`
198+
Object {
199+
"count": null,
200+
"data": null,
201+
"error": Object {
202+
"code": "PGRST116",
203+
"details": "Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row",
204+
"hint": null,
205+
"message": "JSON object requested, multiple (or no) rows returned",
206+
},
207+
"status": 406,
208+
"statusText": "Not Acceptable",
209+
}
210+
`)
211+
})
212+
191213
test('select on insert', async () => {
192214
const res = await postgrest.from('users').insert({ username: 'foo' }).select('status')
193215
expect(res).toMatchInlineSnapshot(`

0 commit comments

Comments
 (0)