Fix Garmin token connection not persisting after save
All checks were successful
Deploy / deploy (push) Successful in 1m38s
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:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user