mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
feat(fitbit): add the Fitbit connection data model and FITBIT measurement source
Lay the data-model foundation for the Fitbit/Pixel integration over the Google Health API, mirroring the WHOOP provider. No OAuth, sync, or UI yet. - Prisma: FitbitConnection (1:1 per user, encrypted access/refresh tokens) and FitbitOAuthState models, two encrypted BYO-credential columns on User, and FITBIT appended to the MeasurementSource enum. Migration 0117_v1120_fitbit_integration is additive only — one enum value plus two tables and two nullable columns, no new MeasurementType (every launch metric maps onto an existing type). - Wire the two new encrypted columns and the FitbitConnection token columns into scripts/rotate-encryption-key.ts. - FITBIT touchpoints: the read measurementSourceEnum (not the writable set), the DEFAULT_SOURCE_PRIORITY and workout-source ladders, the sources-section label map, the IntegrationKey union plus its display name, and a fitbit()/fitbitStatus() query-key pair. The source-rank SQL and read-tier collapse pick FITBIT up from the ladders with no code change. - Add the FITBIT source label to all six locale bundles and regenerate the OpenAPI contract so the source enum carries FITBIT for the iOS decoder.
This commit is contained in:
1 parent
045da70133
commit
86b2774567
18 files changed
+368
-20
No files matched your search
@@ -102,6 +102,8 @@ async function main() {
|
||||
withingsClientSecretEncrypted: true,
|
||||
whoopClientIdEncrypted: true,
|
||||
whoopClientSecretEncrypted: true,
|
||||
fitbitClientIdEncrypted: true,
|
||||
fitbitClientSecretEncrypted: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -119,6 +121,8 @@ async function main() {
|
||||
"withingsClientSecretEncrypted",
|
||||
"whoopClientIdEncrypted",
|
||||
"whoopClientSecretEncrypted",
|
||||
"fitbitClientIdEncrypted",
|
||||
"fitbitClientSecretEncrypted",
|
||||
];
|
||||
for (const field of userFields) {
|
||||
const r = await rotateField(
|
||||
@@ -176,6 +180,26 @@ async function main() {
|
||||
results.push(r);
|
||||
}
|
||||
|
||||
// ───── FitbitConnection table (accessToken / refreshToken) ─────
|
||||
const fitbit = await prisma.fitbitConnection.findMany({
|
||||
select: { id: true, accessToken: true, refreshToken: true },
|
||||
});
|
||||
for (const field of ["accessToken", "refreshToken"] as const) {
|
||||
const r = await rotateField(
|
||||
"FitbitConnection",
|
||||
field,
|
||||
fitbit,
|
||||
(f) => f[field],
|
||||
async (id, ciphertext) => {
|
||||
await prisma.fitbitConnection.update({
|
||||
where: { id },
|
||||
data: { [field]: ciphertext } as Record<string, string>,
|
||||
});
|
||||
},
|
||||
);
|
||||
results.push(r);
|
||||
}
|
||||
|
||||
// ───── AppSettings table (singleton typically) ─────
|
||||
const settings = await prisma.appSettings.findMany({
|
||||
select: {
|
||||
|
||||
Reference in new issue
Block a user