import * as SQLite from 'expo-sqlite/legacy'; import * as FileSystem from 'expo-file-system'; import { Asset } from 'expo-asset'; import { API_HOST } from 'src/constants'; import { storage } from 'src/storage'; import { fetchLastDareDbUpdate, fetchLastRegionsDbUpdate } from '@api/app'; let db1: SQLite.SQLiteDatabase | null = null; let db2: SQLite.SQLiteDatabase | null = null; let db3: SQLite.SQLiteDatabase | null = null; const nmRegionsDBname = 'nmRegions.db'; const darePlacesDBname = 'darePlaces.db'; const countriesDBname = 'nmCountries.db'; const sqliteDirectory = 'SQLite'; const sqliteFullPath = FileSystem.documentDirectory + sqliteDirectory; const DS = '/'; async function copyDatabaseFile(dbName: string, dbAsset: Asset) { console.log('DB copy start - ' + dbName); await dbAsset.downloadAsync(); await FileSystem.downloadAsync(dbAsset.uri, sqliteFullPath + DS + dbName); const dbUri = sqliteFullPath + DS + dbName; await FileSystem.copyAsync({ from: dbAsset.localUri ?? '', to: dbUri }); return dbUri; } export async function openDatabases() { try { const fileInfo = await FileSystem.getInfoAsync(sqliteFullPath); if (!fileInfo.exists) { await FileSystem.makeDirectoryAsync(sqliteFullPath, { intermediates: true }); } const nmRegionsDB = await FileSystem.getInfoAsync(sqliteFullPath + DS + nmRegionsDBname, { size: true }); if (!nmRegionsDB.exists) { await copyDatabaseFile( nmRegionsDBname, Asset.fromModule(require('../../assets/db/' + nmRegionsDBname)) ); } if (nmRegionsDB.exists && nmRegionsDB.size == 0) { await FileSystem.deleteAsync(sqliteFullPath + DS + nmRegionsDBname); await copyDatabaseFile( nmRegionsDBname, Asset.fromModule(require('../../assets/db/' + nmRegionsDBname)) ); } const darePlacesDB = await FileSystem.getInfoAsync(sqliteFullPath + DS + darePlacesDBname, { size: true }); if (!darePlacesDB.exists) { await copyDatabaseFile( darePlacesDBname, Asset.fromModule(require('../../assets/db/' + darePlacesDBname)) ); } if (darePlacesDB.exists && darePlacesDB.size == 0) { await FileSystem.deleteAsync(sqliteFullPath + DS + darePlacesDBname); await copyDatabaseFile( darePlacesDBname, Asset.fromModule(require('../../assets/db/' + darePlacesDBname)) ); } const countriesDB = await FileSystem.getInfoAsync(sqliteFullPath + DS + countriesDBname, { size: true }); if (!countriesDB.exists) { await copyDatabaseFile( countriesDBname, Asset.fromModule(require('../../assets/db/' + countriesDBname)) ); } if (countriesDB.exists && countriesDB.size == 0) { await FileSystem.deleteAsync(sqliteFullPath + DS + countriesDBname); await copyDatabaseFile( countriesDBname, Asset.fromModule(require('../../assets/db/' + countriesDBname)) ); } const openDatabase = (dbName: string) => SQLite.openDatabase(dbName); db1 = openDatabase(nmRegionsDBname); db2 = openDatabase(darePlacesDBname); db3 = openDatabase(countriesDBname); } catch (error) { console.error('openDatabases - Error:'); console.error(JSON.stringify(error, null, 2)); } } export async function refreshDatabases() { try { const fileInfo = await FileSystem.getInfoAsync(sqliteFullPath); if (!fileInfo.exists) { await FileSystem.makeDirectoryAsync(sqliteFullPath, { intermediates: true }); } await refreshNmDatabase(); await refreshDarePlacesDatabase(); await refreshCountriesDatabase(); } catch (error) { console.error('refreshDatabases - Error:'); console.error(JSON.stringify(error, null, 2)); } } export function getFirstDatabase() { return db1; } export function getSecondDatabase() { return db2; } export function getCountriesDatabase() { return db3; } const openDatabase = (dbName: string) => SQLite.openDatabase(dbName); async function refreshNmDatabase() { try { await FileSystem.deleteAsync(sqliteFullPath + DS + nmRegionsDBname, { idempotent: true }); const nmUrl = `${API_HOST}/static/app/${nmRegionsDBname}`; let nmFileUri = sqliteFullPath + DS + nmRegionsDBname; const nmResponse = await FileSystem.downloadAsync(nmUrl, nmFileUri); if (nmResponse.status !== 200) { console.error(`Failed to download the nmDb file: Status code ${nmResponse.status}`); } db1 = null; db1 = openDatabase(nmRegionsDBname); } catch (error) { console.error('refreshDatabase nmRegions - Error:'); console.error(JSON.stringify(error, null, 2)); } } async function refreshDarePlacesDatabase() { try { await FileSystem.deleteAsync(sqliteFullPath + DS + darePlacesDBname, { idempotent: true }); const dareUrl = `${API_HOST}/static/app/${darePlacesDBname}`; let dareFileUri = sqliteFullPath + DS + darePlacesDBname; const dareResponse = await FileSystem.downloadAsync(dareUrl, dareFileUri); if (dareResponse.status !== 200) { console.error(`Failed to download the dareDb file: Status code ${dareResponse.status}`); } db2 = null; db2 = openDatabase(darePlacesDBname); } catch (error) { console.error('refreshDatabase darePlaces - Error:'); console.error(JSON.stringify(error, null, 2)); } } async function refreshCountriesDatabase() { try { await FileSystem.deleteAsync(sqliteFullPath + DS + countriesDBname, { idempotent: true }); const countriesUrl = `${API_HOST}/static/app/${countriesDBname}`; let countriesFileUri = sqliteFullPath + DS + countriesDBname; const countriesResponse = await FileSystem.downloadAsync(countriesUrl, countriesFileUri); if (countriesResponse.status !== 200) { console.error( `Failed to download the countriesDb file: Status code ${countriesResponse.status}` ); } db3 = null; db3 = openDatabase(countriesDBname); } catch (error) { console.error('refreshDatabase nmCountries - Error:'); console.error(JSON.stringify(error, null, 2)); } } export async function updateNmRegionsDb(localLastDate: string) { const lastUpdate = await fetchLastRegionsDbUpdate(localLastDate); if (lastUpdate && lastUpdate.date !== localLastDate) { const dirInfo = await FileSystem.getInfoAsync(sqliteFullPath); if (!dirInfo.exists) { await FileSystem.makeDirectoryAsync(sqliteFullPath, { intermediates: true }); } await refreshNmDatabase(); storage.set('lastUpdateNmRegions', lastUpdate.date); } } export async function updateDarePlacesDb(localLastDate: string) { const lastUpdate = await fetchLastDareDbUpdate(localLastDate); if (lastUpdate && lastUpdate.date !== localLastDate) { const dirInfo = await FileSystem.getInfoAsync(sqliteFullPath); if (!dirInfo.exists) { await FileSystem.makeDirectoryAsync(sqliteFullPath, { intermediates: true }); } await refreshDarePlacesDatabase(); storage.set('lastUpdateDarePlaces', lastUpdate.date); } }