Fix Garmin token connection not persisting after save
All checks were successful
Deploy / deploy (push) Successful in 1m38s

Root cause: The setup-db script was missing user field definitions
(garminConnected, tokens, etc.). Production PocketBase had no such
fields, so updates silently failed to persist.

Changes:
- Add user custom fields to setup-db.ts (matches e2e harness)
- Fix status route to use strict boolean check (=== true)
- Add verification in tokens route with helpful error message
- Add ENCRYPTION_KEY to playwright config for e2e tests
- Add comprehensive e2e tests for Garmin connection flow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-13 13:20:50 +00:00
parent 3b9e023736
commit 27f084f950
6 changed files with 275 additions and 1 deletions

View File

@@ -138,6 +138,57 @@ export const DAILY_LOGS_COLLECTION: CollectionDefinition = {
*/
const REQUIRED_COLLECTIONS = [PERIOD_LOGS_COLLECTION, DAILY_LOGS_COLLECTION];
/**
* Custom fields to add to the users collection.
* These are required for Garmin integration and app functionality.
*/
const USER_CUSTOM_FIELDS = [
{ name: "garminConnected", type: "bool" },
{ name: "garminOauth1Token", type: "text" },
{ name: "garminOauth2Token", type: "text" },
{ name: "garminTokenExpiresAt", type: "date" },
{ name: "calendarToken", type: "text" },
{ name: "lastPeriodDate", type: "date" },
{ name: "cycleLength", type: "number" },
{ name: "notificationTime", type: "text" },
{ name: "timezone", type: "text" },
{ name: "activeOverrides", type: "json" },
];
/**
* Adds custom fields to the users collection if they don't already exist.
* This is idempotent - safe to run multiple times.
*/
export async function addUserFields(pb: PocketBase): Promise<void> {
const usersCollection = await pb.collections.getOne("users");
// Get existing field names
const existingFieldNames = new Set(
(usersCollection.fields || []).map((f: { name: string }) => f.name),
);
// Filter to only new fields
const newFields = USER_CUSTOM_FIELDS.filter(
(f) => !existingFieldNames.has(f.name),
);
if (newFields.length > 0) {
// Combine existing fields with new ones
const allFields = [...(usersCollection.fields || []), ...newFields];
await pb.collections.update(usersCollection.id, {
fields: allFields,
});
console.log(
` Added ${newFields.length} field(s) to users:`,
newFields.map((f) => f.name),
);
} else {
console.log(" All user fields already exist.");
}
}
/**
* Gets the names of existing collections from PocketBase.
*/
@@ -242,6 +293,10 @@ async function main(): Promise<void> {
process.exit(1);
}
// Add custom fields to users collection
console.log("Checking users collection fields...");
await addUserFields(pb);
// Get existing collections
const existingNames = await getExistingCollectionNames(pb);
console.log(