fix: make initDatabase idempotent to prevent empty history after sync

This commit is contained in:
Eddy de Vink 2026-06-27 23:27:24 +02:00
commit 3d1263b713
2 changed files with 26 additions and 10 deletions

View file

@ -1,9 +1,10 @@
import * as SQLite from 'expo-sqlite'
import { Measurement, SyncStatus } from '../types'
let db: SQLite.SQLiteDatabase
let db: SQLite.SQLiteDatabase | null = null
export async function initDatabase(): Promise<void> {
if (db) return
db = await SQLite.openDatabaseAsync('weegschaal.db')
await db.execAsync(`
CREATE TABLE IF NOT EXISTS measurements (
@ -25,7 +26,7 @@ export async function initDatabase(): Promise<void> {
}
export async function insertMeasurement(m: Measurement): Promise<void> {
await db.runAsync(
await db!.runAsync(
`INSERT INTO measurements (id, weight, bmi, bodyFatPercentage, fatMass, musclePercentage, muscleMass, visceralFat, bmr, measuredAt, createdAt, updatedAt, syncStatus)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[m.id, m.weight, m.bmi, m.bodyFatPercentage, m.fatMass, m.musclePercentage, m.muscleMass, m.visceralFat, m.bmr, m.measuredAt, m.createdAt, m.updatedAt, m.syncStatus]
@ -33,28 +34,28 @@ export async function insertMeasurement(m: Measurement): Promise<void> {
}
export async function getAllMeasurements(): Promise<Measurement[]> {
const rows = await db.getAllAsync<any>(
const rows = await db!.getAllAsync<any>(
'SELECT * FROM measurements ORDER BY measuredAt DESC'
)
return rows as Measurement[]
}
export async function getLatestMeasurement(): Promise<Measurement | null> {
const rows = await db.getAllAsync<any>(
const rows = await db!.getAllAsync<any>(
'SELECT * FROM measurements ORDER BY measuredAt DESC LIMIT 1'
)
return rows.length > 0 ? (rows[0] as Measurement) : null
}
export async function updateMeasurement(id: string, syncStatus: SyncStatus): Promise<void> {
await db.runAsync(
await db!.runAsync(
'UPDATE measurements SET syncStatus = ?, updatedAt = ? WHERE id = ?',
[syncStatus, new Date().toISOString(), id]
)
}
export async function upsertMeasurement(m: Measurement): Promise<void> {
await db.runAsync(
await db!.runAsync(
`INSERT OR REPLACE INTO measurements (id, weight, bmi, bodyFatPercentage, fatMass, musclePercentage, muscleMass, visceralFat, bmr, measuredAt, createdAt, updatedAt, syncStatus)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[m.id, m.weight, m.bmi, m.bodyFatPercentage, m.fatMass, m.musclePercentage, m.muscleMass, m.visceralFat, m.bmr, m.measuredAt, m.createdAt, m.updatedAt, m.syncStatus]
@ -62,7 +63,7 @@ export async function upsertMeasurement(m: Measurement): Promise<void> {
}
export async function getUnsyncedMeasurements(): Promise<Measurement[]> {
const rows = await db.getAllAsync<any>(
const rows = await db!.getAllAsync<any>(
"SELECT * FROM measurements WHERE syncStatus = 'local' ORDER BY updatedAt ASC"
)
return rows as Measurement[]

View file

@ -1,4 +1,3 @@
import { initDatabase, insertMeasurement, getAllMeasurements, getLatestMeasurement, updateMeasurement } from '../src/database/db'
import { Measurement } from '../src/types'
import * as SQLite from 'expo-sqlite'
@ -24,14 +23,30 @@ const mockMeasurement: Measurement = {
describe('database', () => {
let db: any
let initDatabase: any
let insertMeasurement: any
let getAllMeasurements: any
let getLatestMeasurement: any
let updateMeasurement: any
beforeEach(() => {
beforeEach(async () => {
jest.resetModules()
jest.doMock('expo-sqlite', () => ({
openDatabaseAsync: jest.fn(),
}))
db = {
execAsync: jest.fn(),
runAsync: jest.fn(),
getAllAsync: jest.fn(),
}
;(SQLite.openDatabaseAsync as jest.Mock).mockResolvedValue(db)
const sqlite = require('expo-sqlite')
;(sqlite.openDatabaseAsync as jest.Mock).mockResolvedValue(db)
const mod = require('../src/database/db')
initDatabase = mod.initDatabase
insertMeasurement = mod.insertMeasurement
getAllMeasurements = mod.getAllMeasurements
getLatestMeasurement = mod.getLatestMeasurement
updateMeasurement = mod.updateMeasurement
})
it('initDatabase creates the measurements table', async () => {