Skip to content

Commit 0c468ca

Browse files
committed
feat: move rollback to a method
1 parent 1a3aab6 commit 0c468ca

File tree

5 files changed

+129
-147
lines changed

5 files changed

+129
-147
lines changed

src/PostgrestClient.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,11 @@ export default class PostgrestClient<
7979
{
8080
head = false,
8181
count,
82-
rollback = false,
8382
}: {
8483
/** When set to true, no data will be returned. */
8584
head?: boolean
8685
/** Count algorithm to use to count rows in a table. */
8786
count?: 'exact' | 'planned' | 'estimated'
88-
/** Rollback the operation */
89-
rollback?: boolean
9087
} = {}
9188
): PostgrestFilterBuilder<
9289
Function_['Returns'] extends any[]
@@ -110,7 +107,9 @@ export default class PostgrestClient<
110107
}
111108

112109
const headers = { ...this.headers }
113-
headers['Prefer'] = [count ? `count=${count}` : null, rollback ? 'tx=rollback' : null].join(',')
110+
if (count) {
111+
headers['Prefer'] = `count=${count}`
112+
}
114113

115114
return new PostgrestFilterBuilder({
116115
method,

src/PostgrestQueryBuilder.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,9 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
8787
values: Row | Row[],
8888
{
8989
count,
90-
rollback = false,
9190
}: {
9291
/** Count algorithm to use to count rows in a table. */
9392
count?: 'exact' | 'planned' | 'estimated'
94-
/** Rollback the operation */
95-
rollback?: boolean
9693
} = {}
9794
): PostgrestFilterBuilder<Table['Row'], undefined> {
9895
const method = 'POST'
@@ -102,9 +99,6 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
10299
if (count) {
103100
prefersHeaders.push(`count=${count}`)
104101
}
105-
if (rollback) {
106-
prefersHeaders.push(`tx=rollback`)
107-
}
108102
if (this.headers['Prefer']) {
109103
prefersHeaders.unshift(this.headers['Prefer'])
110104
}
@@ -140,16 +134,13 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
140134
onConflict,
141135
count,
142136
ignoreDuplicates = false,
143-
rollback = false,
144137
}: {
145138
/** By specifying the `on_conflict` query parameter, you can make UPSERT work on a column(s) that has a UNIQUE constraint. */
146139
onConflict?: string
147140
/** Count algorithm to use to count rows in a table. */
148141
count?: 'exact' | 'planned' | 'estimated'
149142
/** Specifies if duplicate rows should be ignored and not inserted. */
150143
ignoreDuplicates?: boolean
151-
/** Rollback the operation */
152-
rollback?: boolean
153144
} = {}
154145
): PostgrestFilterBuilder<Table['Row'], undefined> {
155146
const method = 'POST'
@@ -161,9 +152,6 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
161152
if (count) {
162153
prefersHeaders.push(`count=${count}`)
163154
}
164-
if (rollback) {
165-
prefersHeaders.push(`tx=rollback`)
166-
}
167155
if (this.headers['Prefer']) {
168156
prefersHeaders.unshift(this.headers['Prefer'])
169157
}
@@ -189,12 +177,9 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
189177
values: Row,
190178
{
191179
count,
192-
rollback = false,
193180
}: {
194181
/** Count algorithm to use to count rows in a table. */
195182
count?: 'exact' | 'planned' | 'estimated'
196-
/** Rollback the operation */
197-
rollback?: boolean
198183
} = {}
199184
): PostgrestFilterBuilder<Table['Row'], undefined> {
200185
const method = 'PATCH'
@@ -203,9 +188,6 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
203188
if (count) {
204189
prefersHeaders.push(`count=${count}`)
205190
}
206-
if (rollback) {
207-
prefersHeaders.push(`tx=rollback`)
208-
}
209191
if (this.headers['Prefer']) {
210192
prefersHeaders.unshift(this.headers['Prefer'])
211193
}
@@ -227,21 +209,15 @@ export default class PostgrestQueryBuilder<Table extends GenericTable> {
227209
*/
228210
delete({
229211
count,
230-
rollback = false,
231212
}: {
232213
/** Count algorithm to use to count rows in a table. */
233214
count?: 'exact' | 'planned' | 'estimated'
234-
/** Rollback the operation */
235-
rollback?: boolean
236215
} = {}): PostgrestFilterBuilder<Table['Row'], undefined> {
237216
const method = 'DELETE'
238217
const prefersHeaders = []
239218
if (count) {
240219
prefersHeaders.push(`count=${count}`)
241220
}
242-
if (rollback) {
243-
prefersHeaders.push(`tx=rollback`)
244-
}
245221
if (this.headers['Prefer']) {
246222
prefersHeaders.unshift(this.headers['Prefer'])
247223
}

src/PostgrestTransformBuilder.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,13 @@ export default class PostgrestTransformBuilder<
192192
if (format === 'json') return this as PromiseLike<PostgrestResponse<Record<string, unknown>>>
193193
else return this as PromiseLike<PostgrestSingleResponse<string>>
194194
}
195+
196+
rollback(): this {
197+
if ((this.headers['Prefer'] ?? '').trim().length > 0) {
198+
this.headers['Prefer'] += ',tx=rollback'
199+
} else {
200+
this.headers['Prefer'] = 'tx=rollback'
201+
}
202+
return this
203+
}
195204
}

test/basic.ts

Lines changed: 0 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -410,122 +410,3 @@ test('select with no match', async () => {
410410
}
411411
`)
412412
})
413-
414-
test('rollback insert/upsert', async () => {
415-
//No row at the start
416-
const res1 = await postgrest.from('users').select().eq('username', 'soedirgo')
417-
expect(res1.data).toMatchInlineSnapshot(`Array []`)
418-
419-
//Insert the row and rollback
420-
const res2 = await postgrest
421-
.from('users')
422-
.insert(
423-
{
424-
age_range: '[20,25)',
425-
catchphrase: "'cat' 'fat'",
426-
data: null,
427-
status: 'ONLINE',
428-
username: 'soedirgo',
429-
},
430-
{ rollback: true }
431-
)
432-
.select()
433-
.single()
434-
expect(res2.data).toMatchInlineSnapshot(`
435-
Object {
436-
"age_range": "[20,25)",
437-
"catchphrase": "'cat' 'fat'",
438-
"data": null,
439-
"status": "ONLINE",
440-
"username": "soedirgo",
441-
}
442-
`)
443-
444-
//Upsert the row and rollback
445-
const res3 = await postgrest
446-
.from('users')
447-
.upsert(
448-
{
449-
age_range: '[20,25)',
450-
catchphrase: "'cat' 'fat'",
451-
data: null,
452-
status: 'ONLINE',
453-
username: 'soedirgo',
454-
},
455-
{ rollback: true }
456-
)
457-
.select()
458-
.single()
459-
expect(res3.data).toMatchInlineSnapshot(`
460-
Object {
461-
"age_range": "[20,25)",
462-
"catchphrase": "'cat' 'fat'",
463-
"data": null,
464-
"status": "ONLINE",
465-
"username": "soedirgo",
466-
}
467-
`)
468-
469-
//No row at the end
470-
const res4 = await postgrest.from('users').select().eq('username', 'soedirgo')
471-
expect(res4.data).toMatchInlineSnapshot(`Array []`)
472-
})
473-
474-
test('rollback update/rpc', async () => {
475-
const res1 = await postgrest.from('users').select('status').eq('username', 'dragarcia').single()
476-
expect(res1.data).toMatchInlineSnapshot(`
477-
Object {
478-
"status": "ONLINE",
479-
}
480-
`)
481-
482-
const res2 = await postgrest
483-
.from('users')
484-
.update({ status: 'OFFLINE' }, { rollback: true })
485-
.eq('username', 'dragarcia')
486-
.select('status')
487-
.single()
488-
expect(res2.data).toMatchInlineSnapshot(`
489-
Object {
490-
"status": "OFFLINE",
491-
}
492-
`)
493-
494-
const res3 = await postgrest.rpc('offline_user', { name_param: 'dragarcia' }, { rollback: true })
495-
expect(res3.data).toMatchInlineSnapshot(`"OFFLINE"`)
496-
497-
const res4 = await postgrest.from('users').select('status').eq('username', 'dragarcia').single()
498-
expect(res4.data).toMatchInlineSnapshot(`
499-
Object {
500-
"status": "ONLINE",
501-
}
502-
`)
503-
})
504-
505-
test('rollback delete', async () => {
506-
const res1 = await postgrest.from('users').select('username').eq('username', 'dragarcia').single()
507-
expect(res1.data).toMatchInlineSnapshot(`
508-
Object {
509-
"username": "dragarcia",
510-
}
511-
`)
512-
513-
const res2 = await postgrest
514-
.from('users')
515-
.delete({ rollback: true })
516-
.eq('username', 'dragarcia')
517-
.select('username')
518-
.single()
519-
expect(res2.data).toMatchInlineSnapshot(`
520-
Object {
521-
"username": "dragarcia",
522-
}
523-
`)
524-
525-
const res3 = await postgrest.from('users').select('username').eq('username', 'dragarcia').single()
526-
expect(res3.data).toMatchInlineSnapshot(`
527-
Object {
528-
"username": "dragarcia",
529-
}
530-
`)
531-
})

test/transforms.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,120 @@ test('explain with options', async () => {
213213
}
214214
`)
215215
})
216+
217+
test('rollback insert/upsert', async () => {
218+
//No row at the start
219+
const res1 = await postgrest.from('users').select().eq('username', 'soedirgo')
220+
expect(res1.data).toMatchInlineSnapshot(`Array []`)
221+
222+
//Insert the row and rollback
223+
const res2 = await postgrest
224+
.from('users')
225+
.insert({
226+
age_range: '[20,25)',
227+
catchphrase: "'cat' 'fat'",
228+
data: null,
229+
status: 'ONLINE',
230+
username: 'soedirgo',
231+
})
232+
.select()
233+
.rollback()
234+
.single()
235+
expect(res2.data).toMatchInlineSnapshot(`
236+
Object {
237+
"age_range": "[20,25)",
238+
"catchphrase": "'cat' 'fat'",
239+
"data": null,
240+
"status": "ONLINE",
241+
"username": "soedirgo",
242+
}
243+
`)
244+
245+
//Upsert the row and rollback
246+
const res3 = await postgrest
247+
.from('users')
248+
.upsert({
249+
age_range: '[20,25)',
250+
catchphrase: "'cat' 'fat'",
251+
data: null,
252+
status: 'ONLINE',
253+
username: 'soedirgo',
254+
})
255+
.select()
256+
.rollback()
257+
.single()
258+
expect(res3.data).toMatchInlineSnapshot(`
259+
Object {
260+
"age_range": "[20,25)",
261+
"catchphrase": "'cat' 'fat'",
262+
"data": null,
263+
"status": "ONLINE",
264+
"username": "soedirgo",
265+
}
266+
`)
267+
268+
//No row at the end
269+
const res4 = await postgrest.from('users').select().eq('username', 'soedirgo')
270+
expect(res4.data).toMatchInlineSnapshot(`Array []`)
271+
})
272+
273+
test('rollback update/rpc', async () => {
274+
const res1 = await postgrest.from('users').select('status').eq('username', 'dragarcia').single()
275+
expect(res1.data).toMatchInlineSnapshot(`
276+
Object {
277+
"status": "ONLINE",
278+
}
279+
`)
280+
281+
const res2 = await postgrest
282+
.from('users')
283+
.update({ status: 'OFFLINE' })
284+
.eq('username', 'dragarcia')
285+
.select('status')
286+
.rollback()
287+
.single()
288+
expect(res2.data).toMatchInlineSnapshot(`
289+
Object {
290+
"status": "OFFLINE",
291+
}
292+
`)
293+
294+
const res3 = await postgrest.rpc('offline_user', { name_param: 'dragarcia' }).rollback()
295+
expect(res3.data).toMatchInlineSnapshot(`"OFFLINE"`)
296+
297+
const res4 = await postgrest.from('users').select('status').eq('username', 'dragarcia').single()
298+
expect(res4.data).toMatchInlineSnapshot(`
299+
Object {
300+
"status": "ONLINE",
301+
}
302+
`)
303+
})
304+
305+
test('rollback delete', async () => {
306+
const res1 = await postgrest.from('users').select('username').eq('username', 'dragarcia').single()
307+
expect(res1.data).toMatchInlineSnapshot(`
308+
Object {
309+
"username": "dragarcia",
310+
}
311+
`)
312+
313+
const res2 = await postgrest
314+
.from('users')
315+
.delete()
316+
.eq('username', 'dragarcia')
317+
.select('username')
318+
.rollback()
319+
.single()
320+
expect(res2.data).toMatchInlineSnapshot(`
321+
Object {
322+
"username": "dragarcia",
323+
}
324+
`)
325+
326+
const res3 = await postgrest.from('users').select('username').eq('username', 'dragarcia').single()
327+
expect(res3.data).toMatchInlineSnapshot(`
328+
Object {
329+
"username": "dragarcia",
330+
}
331+
`)
332+
})

0 commit comments

Comments
 (0)