Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Commit 356eb8c

Browse files
committed
fix: catch network errors
1 parent ea28ff8 commit 356eb8c

File tree

2 files changed

+57
-42
lines changed

2 files changed

+57
-42
lines changed

src/lib/types.ts

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export abstract class PostgrestBuilder<T> implements PromiseLike<PostgrestRespon
5454
protected headers!: { [key: string]: string }
5555
protected schema?: string
5656
protected body?: Partial<T> | Partial<T>[]
57-
protected shouldThrowOnError?: boolean
57+
protected shouldThrowOnError = false
5858

5959
constructor(builder: PostgrestBuilder<T>) {
6060
Object.assign(this, builder)
@@ -90,53 +90,68 @@ export abstract class PostgrestBuilder<T> implements PromiseLike<PostgrestRespon
9090
this.headers['Content-Type'] = 'application/json'
9191
}
9292

93-
return fetch(this.url.toString(), {
93+
let res = fetch(this.url.toString(), {
9494
method: this.method,
9595
headers: this.headers,
9696
body: JSON.stringify(this.body),
97-
})
98-
.then(async (res) => {
99-
let error = null
100-
let data = null
101-
let count = null
102-
103-
if (res.ok) {
104-
const isReturnMinimal = this.headers['Prefer']?.split(',').includes('return=minimal')
105-
if (this.method !== 'HEAD' && !isReturnMinimal) {
106-
const text = await res.text()
107-
if (!text) {
108-
// discard `text`
109-
} else if (this.headers['Accept'] === 'text/csv') {
110-
data = text
111-
} else {
112-
data = JSON.parse(text)
113-
}
114-
}
97+
}).then(async (res) => {
98+
let error = null
99+
let data = null
100+
let count = null
115101

116-
const countHeader = this.headers['Prefer']?.match(/count=(exact|planned|estimated)/)
117-
const contentRange = res.headers.get('content-range')?.split('/')
118-
if (countHeader && contentRange && contentRange.length > 1) {
119-
count = parseInt(contentRange[1])
102+
if (res.ok) {
103+
const isReturnMinimal = this.headers['Prefer']?.split(',').includes('return=minimal')
104+
if (this.method !== 'HEAD' && !isReturnMinimal) {
105+
const text = await res.text()
106+
if (!text) {
107+
// discard `text`
108+
} else if (this.headers['Accept'] === 'text/csv') {
109+
data = text
110+
} else {
111+
data = JSON.parse(text)
120112
}
121-
} else {
122-
error = await res.json()
113+
}
123114

124-
if (error && this.shouldThrowOnError) {
125-
throw error
126-
}
115+
const countHeader = this.headers['Prefer']?.match(/count=(exact|planned|estimated)/)
116+
const contentRange = res.headers.get('content-range')?.split('/')
117+
if (countHeader && contentRange && contentRange.length > 1) {
118+
count = parseInt(contentRange[1])
127119
}
120+
} else {
121+
error = await res.json()
128122

129-
const postgrestResponse: PostgrestResponse<T> = {
130-
error,
131-
data,
132-
count,
133-
status: res.status,
134-
statusText: res.statusText,
135-
body: data,
123+
if (error && this.shouldThrowOnError) {
124+
throw error
136125
}
126+
}
127+
128+
const postgrestResponse = {
129+
error,
130+
data,
131+
count,
132+
status: res.status,
133+
statusText: res.statusText,
134+
body: data,
135+
}
136+
137+
return postgrestResponse
138+
})
139+
if (!this.shouldThrowOnError) {
140+
res = res.catch((fetchError) => ({
141+
error: {
142+
message: `FetchError: ${fetchError.message}`,
143+
details: '',
144+
hint: '',
145+
code: fetchError.code || '',
146+
},
147+
data: null,
148+
body: null,
149+
count: null,
150+
status: 400,
151+
statusText: 'Bad Request',
152+
}))
153+
}
137154

138-
return postgrestResponse
139-
})
140-
.then(onfulfilled, onrejected)
155+
return res.then(onfulfilled, onrejected)
141156
}
142157
}

test/basic.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ test('throwOnError throws errors instead of returning them', async () => {
115115
expect(isErrorCaught).toBe(true)
116116
})
117117

118-
test('connection error', async () => {
118+
test('connection error w/o throwing', async () => {
119119
const postgrest = new PostgrestClient('http://foo.invalid')
120120
let isErrorCaught = false
121121
await postgrest
@@ -124,10 +124,10 @@ test('connection error', async () => {
124124
.then(undefined, () => {
125125
isErrorCaught = true
126126
})
127-
expect(isErrorCaught).toBe(true)
127+
expect(isErrorCaught).toBe(false)
128128
})
129129

130-
test('connection errors should work the same with throwOnError', async () => {
130+
test('connection error w/ throwOnError', async () => {
131131
const postgrest = new PostgrestClient('http://foo.invalid')
132132
let isErrorCaught = false
133133
await postgrest

0 commit comments

Comments
 (0)