11import { browser } from '$app/environment' ;
22import { authStore } from './auth.svelte' ;
3-
3+ import { GithubProvider } from './providers/github' ;
4+ import { GDriveProvider } from './providers/gdrive' ;
5+ import type { StorageAdapter } from './providers/types' ;
46export interface Language {
57 id : string ;
68 name : string ;
@@ -120,6 +122,12 @@ class DbStore {
120122 }
121123 }
122124
125+ private getAdapter ( ) : StorageAdapter | null {
126+ if ( authStore . activeProvider === 'github' ) return new GithubProvider ( ) ;
127+ if ( authStore . activeProvider === 'gdrive' ) return new GDriveProvider ( ) ;
128+ return null ;
129+ }
130+
123131 async sync ( ) {
124132 if ( ! authStore . isValid ) {
125133 this . syncStatus = 'Offline/No Auth' ;
@@ -130,54 +138,32 @@ class DbStore {
130138 return ;
131139 }
132140
141+ const adapter = this . getAdapter ( ) ;
142+ if ( ! adapter ) {
143+ this . syncStatus = 'Local Only' ;
144+ return ;
145+ }
146+
133147 this . isLoading = true ;
134148 this . syncStatus = 'Syncing...' ;
135149 this . error = null ;
150+
136151 try {
137- const res = await fetch ( `https://api.github.com/gists/${ authStore . gistId } ` , {
138- headers : {
139- Authorization : `Bearer ${ authStore . token } ` ,
140- Accept : 'application/vnd.github.v3+json'
141- }
142- } ) ;
143- if ( ! res . ok ) throw new Error ( 'Failed to fetch gist' ) ;
144- const gist = await res . json ( ) ;
145- const file = gist . files [ 'copypasta.json' ] ;
146- if ( file && file . content ) {
147- const remoteData = JSON . parse ( file . content ) as Database ;
148- if ( remoteData ?. settings ?. languages ) {
149- remoteData . settings . languages . forEach ( ( l : Language ) => {
150- if ( l . showInMultiple === undefined ) {
151- l . showInMultiple = l . id === 'en' || l . id === 'de' ;
152- }
153- } ) ;
154- }
155- const localDate = new Date ( this . data . updatedAt || 0 ) . getTime ( ) ;
156- const remoteDate = new Date ( remoteData . updatedAt || 0 ) . getTime ( ) ;
157- const lastSynced = this . getLastSyncedAt ( ) ;
158-
159- if ( ! remoteData . updatedAt ) {
160- await this . _pushToGist ( ) ;
161- } else {
162- const isRemoteNewer = remoteDate > lastSynced ;
163- const isLocalNewer = localDate > lastSynced ;
164-
165- if ( isRemoteNewer && isLocalNewer && localDate !== remoteDate ) {
166- this . conflictData = remoteData ;
167- this . syncStatus = 'Error' ;
168- this . isLoading = false ;
169- return ;
170- } else if ( isRemoteNewer ) {
171- this . forcePull ( remoteData ) ;
172- } else if ( isLocalNewer ) {
173- await this . _pushToGist ( ) ;
174- } else {
175- this . syncStatus = 'Synced' ;
176- }
177- }
152+ const result = await adapter . sync ( this . data , this . getLastSyncedAt ( ) ) ;
153+
154+ if ( result . action === 'error' ) {
155+ this . error = result . error || 'Unknown sync error' ;
156+ this . syncStatus = 'Error' ;
157+ } else if ( result . action === 'conflict' ) {
158+ this . conflictData = result . remoteData || null ;
159+ this . syncStatus = 'Error' ;
160+ } else if ( result . action === 'pulled' && result . remoteData ) {
161+ this . forcePull ( result . remoteData ) ;
162+ } else if ( result . action === 'pushed' ) {
163+ this . setLastSyncedAt ( result . remoteDate || new Date ( this . data . updatedAt ) . getTime ( ) ) ;
164+ this . syncStatus = 'Synced' ;
178165 } else {
179- // Initialize gist if empty
180- await this . _pushToGist ( ) ;
166+ this . syncStatus = 'Synced' ;
181167 }
182168 } catch ( err ) {
183169 const e = err as Error ;
@@ -206,13 +192,13 @@ class DbStore {
206192
207193 this . _saveTimeout = setTimeout ( ( ) => {
208194 this . _saveTimeout = null ;
209- this . _pushToGist ( ) ;
195+ this . _pushToRemote ( ) ;
210196 } , 1000 ) ;
211197 }
212198
213199 async forcePush ( ) {
214200 this . conflictData = null ;
215- await this . _pushToGist ( ) ;
201+ await this . _pushToRemote ( ) ;
216202 }
217203
218204 forcePull ( remoteData : Database ) {
@@ -230,7 +216,7 @@ class DbStore {
230216 this . syncStatus = 'Synced' ;
231217 }
232218
233- private async _pushToGist ( ) {
219+ private async _pushToRemote ( ) {
234220 if ( ! authStore . isValid ) {
235221 this . syncStatus = 'Local Only' ;
236222 return ;
@@ -240,27 +226,19 @@ class DbStore {
240226 return ;
241227 }
242228
229+ const adapter = this . getAdapter ( ) ;
230+ if ( ! adapter ) {
231+ this . syncStatus = 'Local Only' ;
232+ return ;
233+ }
234+
243235 this . isLoading = true ;
244236 this . syncStatus = 'Syncing...' ;
245237 this . error = null ;
238+
246239 try {
247- const res = await fetch ( `https://api.github.com/gists/${ authStore . gistId } ` , {
248- method : 'PATCH' ,
249- headers : {
250- Authorization : `Bearer ${ authStore . token } ` ,
251- Accept : 'application/vnd.github.v3+json' ,
252- 'Content-Type' : 'application/json'
253- } ,
254- body : JSON . stringify ( {
255- files : {
256- 'copypasta.json' : {
257- content : JSON . stringify ( this . data , null , 2 )
258- }
259- }
260- } )
261- } ) ;
262- if ( ! res . ok ) throw new Error ( 'Failed to update gist' ) ;
263- this . setLastSyncedAt ( new Date ( this . data . updatedAt ) . getTime ( ) ) ;
240+ const result = await adapter . push ( this . data ) ;
241+ this . setLastSyncedAt ( result . remoteDate ) ;
264242 this . syncStatus = 'Synced' ;
265243 } catch ( err ) {
266244 const e = err as Error ;
0 commit comments