This guide explains how to migrate from the previous IndexedDB-based version to the new API-based architecture.
- Data stored client-side in browser IndexedDB
- Single-user per browser
- No server-side component
- Dexie.js for database access
- Data stored server-side in Azure Table Storage
- Multi-user support with userId partitioning
- RESTful API with Shared Key authentication
- API client wraps HTTP calls
Before:
[Browser] → [IndexedDB]
After:
[Browser] → [API] → [Azure Table Storage]
↑
Shared Key Auth
-
Authentication:
- UI: Still uses Azure SWA (Microsoft SSO) - no changes
- API: New Shared Key authentication via
x-api-keyheader
-
Data Storage:
- Moved from client-side (IndexedDB) to server-side (Table Storage)
- Each user's data is partitioned by
userId
-
IDs:
- IndexedDB used auto-increment integers
- Table Storage uses string-based RowKeys
- API converts between them for frontend compatibility
db.tsAPI is mostly compatible, but uses HTTP under the hood
-
Update environment configuration:
Create
.env:VITE_API_URL=http://localhost:7071/api VITE_API_KEY=dev-shared-key-123
Create
api/local.settings.json:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "node", "AZURE_STORAGE_CONNECTION_STRING": "UseDevelopmentStorage=true", "API_SHARED_KEY": "dev-shared-key-123" } } -
Install dependencies:
npm install cd api && npm install && cd ..
-
Start Azurite:
azurite --silent --location ./azurite
-
Create tables:
az storage table create --name routines --connection-string "UseDevelopmentStorage=true" az storage table create --name exercises --connection-string "UseDevelopmentStorage=true"
-
Run API and UI:
# Terminal 1 cd api && npm start # Terminal 2 npm run dev
Data Migration Options:
If you have limited data, the simplest approach is to re-enter it in the new version.
Create a migration script to export from IndexedDB and import via API:
// export-data.js - Run in browser console on OLD version
async function exportData() {
const { db } = await import('./src/db.ts');
const routines = await db.routines.toArray();
const exercises = await db.exercises.toArray();
const exportData = {\n routines,\n exercises\n };
// Download as JSON
const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'pump-export.json';
a.click();
}
function blobToBase64(blob) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result.split(',')[1]);
};
reader.readAsDataURL(blob);
});
}
exportData();// import-data.js - Run via Node.js with NEW version API
const fs = require('fs');
const fetch = require('node-fetch');
const API_URL = 'http://localhost:7071/api';
const API_KEY = 'dev-shared-key-123';
const USER_ID = 'your-user-id'; // Get from Azure SWA auth
async function importData(filePath) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const headers = {
'Content-Type': 'application/json',
'x-api-key': API_KEY
};
// Import routines
const routineIdMap = new Map();
for (const routine of data.routines) {
const res = await fetch(`${API_URL}/routines?userId=${USER_ID}`, {
method: 'POST',
headers,
body: JSON.stringify({
date: routine.date,
name: routine.name,
order: routine.order,
userId: USER_ID
})
});
const created = await res.json();
routineIdMap.set(routine.id, created.id);
}
// Import exercises
const exerciseIdMap = new Map();
for (const exercise of data.exercises) {
const newRoutineId = routineIdMap.get(exercise.routineId);
const res = await fetch(`${API_URL}/exercises?userId=${USER_ID}`, {
method: 'POST',
headers,
body: JSON.stringify({
...exercise,
routineId: newRoutineId,
userId: USER_ID
})
});
const created = await res.json();
exerciseIdMap.set(exercise.id, created.id);
}
console.log('Import complete!');
}
importData('pump-export.json');To rollback to the previous version:
git checkout save-x # or whichever branch had the old versionThe old version will continue to work with its IndexedDB data unchanged.
See main README.md for Azure deployment instructions.
Key considerations:
- Use strong Shared Keys in production
- Configure CORS properly on Function App
- Set appropriate Table Storage retention policies
- Monitor API usage and costs
If you encounter issues during migration:
- Check browser console for errors
- Check Function App logs in Azure Portal
- Verify API_KEY matches between frontend and backend
- Ensure tables exist in Storage Account