1
- import {
2
- AbstractPowerSyncDatabase ,
3
- CrudEntry ,
4
- PowerSyncBackendConnector ,
5
- UpdateType ,
6
- } from "@powersync/react-native" ;
7
- import type { SupabaseClient } from "@supabase/supabase-js" ;
1
+ import { AbstractPowerSyncDatabase , CrudEntry , PowerSyncBackendConnector , UpdateType } from '@powersync/react-native' ;
2
+ import type { SupabaseClient } from '@supabase/supabase-js' ;
8
3
9
- import { config } from " ./config" ;
10
- import { supabase } from " ./supabase" ;
4
+ import { config } from ' ./config' ;
5
+ import { supabase } from ' ./supabase' ;
11
6
12
7
/// Postgres Response codes that we cannot recover from by retrying.
13
8
const FATAL_RESPONSE_CODES = [
14
9
// Class 22 — Data Exception
15
10
// Examples include data type mismatch.
16
- new RegExp ( " ^22...$" ) ,
11
+ new RegExp ( ' ^22...$' ) ,
17
12
// Class 23 — Integrity Constraint Violation.
18
13
// Examples include NOT NULL, FOREIGN KEY and UNIQUE violations.
19
- new RegExp ( " ^23...$" ) ,
14
+ new RegExp ( ' ^23...$' ) ,
20
15
// INSUFFICIENT PRIVILEGE - typically a row-level security violation
21
- new RegExp ( " ^42501$" ) ,
16
+ new RegExp ( ' ^42501$' )
22
17
] ;
23
18
24
19
export class Connector implements PowerSyncBackendConnector {
@@ -31,23 +26,21 @@ export class Connector implements PowerSyncBackendConnector {
31
26
async fetchCredentials ( ) {
32
27
const {
33
28
data : { session } ,
34
- error,
29
+ error
35
30
} = await this . supabaseClient . auth . getSession ( ) ;
36
31
37
32
if ( ! session || error ) {
38
33
throw new Error ( `Could not fetch Supabase credentials: ${ error } ` ) ;
39
34
}
40
35
41
- console . debug ( " session expires at" , session . expires_at ) ;
36
+ console . debug ( ' session expires at' , session . expires_at ) ;
42
37
43
38
return {
44
39
client : this . supabaseClient ,
45
40
endpoint : config . powerSyncUrl ,
46
- token : session . access_token ?? "" ,
47
- expiresAt : session . expires_at
48
- ? new Date ( session . expires_at * 1000 )
49
- : undefined ,
50
- userID : session . user . id ,
41
+ token : session . access_token ?? '' ,
42
+ expiresAt : session . expires_at ? new Date ( session . expires_at * 1000 ) : undefined ,
43
+ userID : session . user . id
51
44
} ;
52
45
}
53
46
@@ -62,36 +55,35 @@ export class Connector implements PowerSyncBackendConnector {
62
55
try {
63
56
// Note: If transactional consistency is important, use database functions
64
57
// or edge functions to process the entire transaction in a single call.
65
- for ( let op of transaction . crud ) {
58
+ for ( const op of transaction . crud ) {
66
59
lastOp = op ;
67
60
const table = this . supabaseClient . from ( op . table ) ;
61
+ let result : any ;
68
62
switch ( op . op ) {
69
- case UpdateType . PUT :
63
+ case UpdateType . PUT : {
70
64
const record = { ...op . opData , id : op . id } ;
71
- const { error } = await table . upsert ( record ) ;
72
-
73
- if ( error ) {
74
- throw new Error (
75
- `Could not upsert data to Supabase ${ JSON . stringify ( error ) } ` ,
76
- ) ;
77
- }
65
+ result = await table . upsert ( record ) ;
78
66
break ;
67
+ }
79
68
case UpdateType . PATCH :
80
- await table . update ( op . opData ) . eq ( "id" , op . id ) ;
69
+ result = await table . update ( op . opData ) . eq ( 'id' , op . id ) ;
81
70
break ;
82
71
case UpdateType . DELETE :
83
- await table . delete ( ) . eq ( "id" , op . id ) ;
72
+ result = await table . delete ( ) . eq ( 'id' , op . id ) ;
84
73
break ;
85
74
}
75
+
76
+ if ( result . error ) {
77
+ console . error ( result . error ) ;
78
+ result . error . message = `Could not update Supabase. Received error: ${ result . error . message } ` ;
79
+ throw result . error ;
80
+ }
86
81
}
87
82
88
83
await transaction . complete ( ) ;
89
84
} catch ( ex : any ) {
90
85
console . debug ( ex ) ;
91
- if (
92
- typeof ex . code == "string" &&
93
- FATAL_RESPONSE_CODES . some ( ( regex ) => regex . test ( ex . code ) )
94
- ) {
86
+ if ( typeof ex . code == 'string' && FATAL_RESPONSE_CODES . some ( ( regex ) => regex . test ( ex . code ) ) ) {
95
87
/**
96
88
* Instead of blocking the queue with these errors,
97
89
* discard the (rest of the) transaction.
@@ -100,7 +92,7 @@ export class Connector implements PowerSyncBackendConnector {
100
92
* If protecting against data loss is important, save the failing records
101
93
* elsewhere instead of discarding, and/or notify the user.
102
94
*/
103
- console . error ( ` Data upload error - discarding ${ lastOp } ` , ex ) ;
95
+ console . error ( ' Data upload error - discarding:' , lastOp , ex ) ;
104
96
await transaction . complete ( ) ;
105
97
} else {
106
98
// Error may be retryable - e.g. network error or temporary server error.
0 commit comments