Adds /api/sync/push/:provider/:routeId as the user-triggered entry
point for pushing a route. The route action delegates to a new
pushes.server.ts pipeline that:
- resolves the latest route_versions row and uses that GPX (not
routes.gpx) so the bytes Wahoo gets match the snapshot the user
sees
- short-circuits on (user, route, version, provider) idempotency:
a successful prior push returns the existing remote_id without
re-calling Wahoo
- detects scope_missing before hitting Wahoo and redirects through
getAuthUrl with a base64url-encoded state carrying pushAfter +
returnTo
- refreshes tokens once on PushError({ code: "token_expired" }) and
retries the push, then updates sync_connections in place
- records every outcome in sync_pushes (insert on first attempt,
update on retry) so the UI can show success/failure state
The OAuth callback handler now decodes the state, resumes a
pushAfter pipeline server-side after exchangeCode, and handles the
?error=access_denied path with a needs_permission notice.
Also flips packages/fit/src/fitsdk.d.ts to a regular .ts side-effect
shim so journal's tsc picks up the @garmin/fitsdk module declaration
when consuming the workspace package via source.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
39 lines
1,020 B
TypeScript
39 lines
1,020 B
TypeScript
declare module "@garmin/fitsdk" {
|
|
export class Encoder {
|
|
constructor(options?: { fieldDescriptions?: unknown });
|
|
writeMesg(mesg: { mesgNum: number; [field: string]: unknown }): this;
|
|
onMesg(mesgNum: number, mesg: Record<string, unknown>): this;
|
|
close(): Uint8Array;
|
|
}
|
|
|
|
export class Stream {
|
|
static fromArrayBuffer(buf: ArrayBuffer): Stream;
|
|
static fromBuffer(buf: Uint8Array | Buffer): Stream;
|
|
}
|
|
|
|
export class Decoder {
|
|
constructor(stream: Stream);
|
|
read(opts?: Record<string, unknown>): {
|
|
messages: Record<string, Array<Record<string, unknown>>>;
|
|
errors: unknown[];
|
|
};
|
|
}
|
|
|
|
export const Profile: {
|
|
version: { major: number; minor: number };
|
|
MesgNum: {
|
|
FILE_ID: number;
|
|
FILE_CREATOR: number;
|
|
COURSE: number;
|
|
LAP: number;
|
|
RECORD: number;
|
|
EVENT: number;
|
|
[key: string]: number;
|
|
};
|
|
};
|
|
|
|
export const Utils: {
|
|
convertDateToDateTime(date: Date): number;
|
|
convertDateTimeToDate(dt: number): Date;
|
|
};
|
|
}
|