-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Monorepo] put API client code + token code at use site and refactor …
…to move out api-clients (#428) Closes DG-143 ## What changed? Why? Refactors `api/networkClients` to own package (`api-clients`) and removes non-generic code from there. Adds `invariant` too for future use and adds it in a few places. Fixes up some ESLint + TSConfig so the warnings about react not being present are gone!
- Loading branch information
Showing
63 changed files
with
537 additions
and
321 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
apps/web/src/api/types/MapLocation.ts → .../src/api/server/contentful/MapLocation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { createClient } from 'api-clients/authenticatedGraphQLClient'; | ||
import { invariant } from 'shared-core/helpers/invariant'; | ||
|
||
const SPACE_ID = process.env.CONTENTFUL_SPACE_ID; | ||
const ACCESS_TOKEN = process.env.CONTENTFUL_ACCESS_TOKEN; | ||
invariant(SPACE_ID, 'Missing CONTENTFUL_SPACE_ID env variable'); | ||
invariant(ACCESS_TOKEN, 'Missing CONTENTFUL_ACCESS_TOKEN env variable'); | ||
|
||
/** | ||
* Use this GraphQL client to make requests to Contentful from the server. | ||
*/ | ||
export const contentfulClient = createClient({ | ||
endpoint: `https://graphql.contentful.com/content/v1/spaces/${SPACE_ID}`, | ||
accessToken: ACCESS_TOKEN, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { invariant } from 'shared-core/helpers/invariant'; | ||
import { createClient } from 'api-clients/authenticatedGraphQLClient'; | ||
|
||
const ACCESS_TOKEN = process.env.GITHUB_AUTHENTICATION_TOKEN; | ||
invariant(ACCESS_TOKEN, 'Missing GITHUB_AUTHENTICATION_TOKEN env variable'); | ||
|
||
/** | ||
* Use this GraphQL client to make requests to Github from the server. | ||
*/ | ||
export const githubClient = createClient({ | ||
endpoint: 'https://api.github.com/graphql', | ||
accessToken: ACCESS_TOKEN, | ||
}); |
14 changes: 0 additions & 14 deletions
14
apps/web/src/api/server/networkClients/authenticatedGraphQLClient.ts
This file was deleted.
Oops, something went wrong.
43 changes: 0 additions & 43 deletions
43
apps/web/src/api/server/networkClients/authenticatedRestClient.ts
This file was deleted.
Oops, something went wrong.
15 changes: 0 additions & 15 deletions
15
apps/web/src/api/server/networkClients/contentfulClient.ts
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { invariant } from 'shared-core/helpers/invariant'; | ||
import { createClient } from 'api-clients/authenticatedRestClient'; | ||
|
||
/** | ||
* This is what Spotify's refresh token API returns, as raw data | ||
*/ | ||
type RawSpotifyRefreshToken = { | ||
token_type: string; | ||
access_token: string; | ||
expires_in: number; | ||
}; | ||
|
||
/** | ||
* We "expire" Spotify tokens 30 seconds early so we don't run into problems near the end | ||
* of the window. Probably unneeded but it's just math. | ||
*/ | ||
const GRACE_PERIOD_IN_MS = 30_000; | ||
|
||
/** | ||
* All the env variables we later use | ||
*/ | ||
const { SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET } = process.env; | ||
invariant(SPOTIFY_CLIENT_ID, 'Missing SPOTIFY_CLIENT_ID env variable'); | ||
invariant(SPOTIFY_CLIENT_SECRET, 'Missing SPOTIFY_CLIENT_SECRET env variable'); | ||
|
||
/** | ||
* Spotify client needs a base 64 encoded string for the client id:secret | ||
*/ | ||
const SPOTIFY_CLIENT_AUTH = Buffer.from(`${SPOTIFY_CLIENT_ID}:${SPOTIFY_CLIENT_SECRET}`).toString( | ||
'base64', | ||
); | ||
|
||
/** | ||
* Given a number of seconds in which something will expire, this function | ||
* creates a timestamp from that in milliseconds at which things expire. | ||
* We intentionally expire with an extra grace period to ensure round trips + | ||
* other things don't eat up processing time and cause us to miss the expiry timestamp. | ||
*/ | ||
function createExpirationDate(expiryDistanceInSeconds: number) { | ||
return new Date(Date.now() - GRACE_PERIOD_IN_MS + expiryDistanceInSeconds * 1000); | ||
} | ||
|
||
/** | ||
* A REST client set up to make authed calls to Spotify | ||
*/ | ||
export const spotifyClient = createClient({ | ||
endpoint: 'https://api.spotify.com/v1', | ||
accessKey: 'spotify', | ||
refreshTokenConfig: { | ||
endpoint: 'https://accounts.spotify.com/api/token', | ||
headers: { | ||
Authorization: `Basic ${SPOTIFY_CLIENT_AUTH}`, | ||
}, | ||
validate: (rawData, refreshToken) => { | ||
const { token_type: tokenType, access_token: accessToken, expires_in: expiresIn } = | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
rawData as RawSpotifyRefreshToken; | ||
invariant(tokenType === 'Bearer', `Invalid token type from Spotify ${tokenType}`); | ||
invariant(accessToken, 'Missing access token from Spotify'); | ||
|
||
// Spotify refresh tokens don't expire + we create our own expiry stamp | ||
return { | ||
refreshToken, | ||
accessToken, | ||
expiryAt: createExpirationDate(expiresIn), | ||
}; | ||
}, | ||
}, | ||
}); |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { invariant } from 'shared-core/helpers/invariant'; | ||
import { createClient } from 'api-clients/authenticatedRestClient'; | ||
|
||
/** | ||
* This is what Strava's refresh token API returns, as raw data | ||
*/ | ||
type RawStravaRefreshToken = { | ||
token_type: string; | ||
access_token: string; | ||
refresh_token: string; | ||
expires_at: number; | ||
expires_in: number; | ||
}; | ||
|
||
const { STRAVA_CLIENT_ID, STRAVA_CLIENT_SECRET, STRAVA_TOKEN_NAME } = process.env; | ||
invariant(STRAVA_TOKEN_NAME, 'Missing Strava token name (used as access key)'); | ||
invariant(STRAVA_CLIENT_ID, 'Missing Strava client id'); | ||
invariant(STRAVA_CLIENT_SECRET, 'Missing Strava client secret'); | ||
|
||
/** | ||
* A REST client set up to make authed calls to Strava | ||
*/ | ||
export const stravaClient = createClient({ | ||
endpoint: 'https://www.strava.com/api/v3', | ||
accessKey: STRAVA_TOKEN_NAME, | ||
refreshTokenConfig: { | ||
endpoint: 'https://www.strava.com/api/v3/oauth/token', | ||
data: { | ||
client_id: STRAVA_CLIENT_ID, | ||
client_secret: STRAVA_CLIENT_SECRET, | ||
}, | ||
validate: (rawData) => { | ||
const { | ||
token_type: tokenType, | ||
refresh_token: refreshToken, | ||
access_token: accessToken, | ||
expires_at: expiresAt, | ||
} = | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
rawData as RawStravaRefreshToken; | ||
invariant(tokenType === 'Bearer', `Invalid token type from Strava ${tokenType}`); | ||
invariant(refreshToken, 'Missing refresh token from Strava'); | ||
invariant(accessToken, 'Missing access token from Strava'); | ||
invariant(expiresAt, 'Missing expires at from Strava'); | ||
|
||
return { | ||
refreshToken, | ||
accessToken, | ||
// expiresAt is a timestamp in seconds! | ||
expiryAt: new Date(expiresAt * 1000), | ||
}; | ||
}, | ||
}, | ||
}); |
2 changes: 1 addition & 1 deletion
2
apps/web/src/api/server/strava/syncStravaWebhookUpdateWithDb.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
716717f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
dg – ./
dg.vercel.app
dg-git-main-dgattey.vercel.app
dg-dgattey.vercel.app
dylangattey.com