diff --git a/src/index.ts b/src/index.ts index 5faf813..a2456f6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ import { Subscriptions, Uploads, } from './resources' +import { Oauth } from './resources/oauth' import { RefreshTokenRequest } from './types' export * from './types' @@ -24,6 +25,7 @@ export class Strava { athletes: Athletes clubs: Clubs gears: Gears + oauth: Oauth routes: Routes runningRaces: RunningRaces segmentEfforts: SegmentEfforts @@ -38,6 +40,7 @@ export class Strava { this.athletes = new Athletes(this.request) this.clubs = new Clubs(this.request) this.gears = new Gears(this.request) + this.oauth = new Oauth() this.routes = new Routes(this.request) this.runningRaces = new RunningRaces(this.request) this.segmentEfforts = new SegmentEfforts(this.request) diff --git a/src/request.ts b/src/request.ts index 8399188..8386867 100644 --- a/src/request.ts +++ b/src/request.ts @@ -6,6 +6,7 @@ type RequestParams = { query?: Record body?: Record | any headers?: Record + access_token?: string } export class Request { @@ -49,7 +50,7 @@ export class Request { uri: string, params?: RequestParams, ): Promise { - await this.getAccessToken() + if (!params?.access_token) await this.getAccessToken() const query: string = params?.query && Object.keys(params?.query).length ? `?${new URLSearchParams( @@ -60,7 +61,11 @@ export class Request { ).toString()}` : '' const headers = { - Authorization: `Bearer ${this.response.access_token}`, + Authorization: `Bearer ${ + params?.access_token + ? params?.access_token + : this.response.access_token + }`, 'content-type': 'application/json', ...(params?.headers ? params.headers : {}), } diff --git a/src/resources/activities.ts b/src/resources/activities.ts index a984a66..9645af3 100644 --- a/src/resources/activities.ts +++ b/src/resources/activities.ts @@ -79,44 +79,48 @@ export class Activities { async createActivity( params: CreateActivityRequest, + access_token?: string, ): Promise { return await this.request.makeApiRequest( 'post', '/activities', - { body: params }, + { body: params, access_token }, ) } async getActivityById( params: GetActivityByIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/activities/${id}`, - { query }, + { query, access_token }, ) } async getCommentsByActivityId( params: GetCommentsByActivityIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/activities/${id}/comments`, - { query }, + { query, access_token }, ) } async getKudoersByActivityId( params: GetKudoersByActivityIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/activities/${id}/kudos`, - { query }, + { query, access_token }, ) } @@ -133,12 +137,13 @@ export class Activities { async getPhotosByActivityId( params: GetPhotosByActivityIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/activities/${id}/photos`, - { query }, + { query, access_token }, ) } @@ -154,23 +159,25 @@ export class Activities { async getZonesByActivityId( params: GetZonesByActivityIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/activities/${id}/zones`, - { query }, + { query, access_token }, ) } async updateActivityById( params: UpdateActivityByIdRequest, + access_token?: string, ): Promise { const { id, ...body } = params return await this.request.makeApiRequest( 'put', `/activities/${id}`, - { body }, + { body, access_token }, ) } } diff --git a/src/resources/athletes.ts b/src/resources/athletes.ts index ea79d10..2dcdf5e 100644 --- a/src/resources/athletes.ts +++ b/src/resources/athletes.ts @@ -16,29 +16,40 @@ export class Athletes { this.request = request } - async getLoggedInAthlete(): Promise { - return await this.request.makeApiRequest('get', '/athlete') + async getLoggedInAthlete(access_token?: string): Promise { + return await this.request.makeApiRequest( + 'get', + '/athlete', + { access_token }, + ) } - async getLoggedInAthleteZones(): Promise { - return await this.request.makeApiRequest('get', '/athlete/zones') + async getLoggedInAthleteZones(access_token?: string): Promise { + return await this.request.makeApiRequest('get', '/athlete/zones', { + access_token, + }) } - async getStats(params: getStatsRequest): Promise { + async getStats( + params: getStatsRequest, + access_token?: string, + ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', - `/athletes/${id}/stats`, + `/athletes/${id}/s tats`, + { access_token }, ) } async updateLoggedInAthlete( params: UpdateLoggedInAthleteRequest, + access_token?: string, ): Promise { return await this.request.makeApiRequest( 'put', `/athlete`, - { body: params }, + { body: params, access_token }, ) } } diff --git a/src/resources/clubs.ts b/src/resources/clubs.ts index c086d1c..f8a94e6 100644 --- a/src/resources/clubs.ts +++ b/src/resources/clubs.ts @@ -42,23 +42,25 @@ export class Clubs { async getClubActivitiesById( params: GetClubActivitiesByIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/clubs/${id}/activities`, - { query }, + { query, access_token }, ) } async getClubAdminsById( params: GetClubAdminsByIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/clubs/${id}/admins`, - { query }, + { query, access_token }, ) } @@ -72,23 +74,26 @@ export class Clubs { async getClubMembersById( params: GetClubMembersByIdRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/clubs/${id}/members`, - { query }, + { query, access_token }, ) } async getLoggedInAthleteClubs( params?: getLoggedInAthleteClubsRequest, + access_token?: string, ): Promise { return await this.request.makeApiRequest( 'get', '/athlete/clubs', { query: params, + access_token, }, ) } diff --git a/src/resources/gears.ts b/src/resources/gears.ts index 2ed6299..70a188f 100644 --- a/src/resources/gears.ts +++ b/src/resources/gears.ts @@ -12,8 +12,15 @@ export class Gears { this.request = request } - async getGearById(params: getGearByIdRequest): Promise { + async getGearById( + params: getGearByIdRequest, + access_token?: string, + ): Promise { const { id } = params - return await this.request.makeApiRequest('get', `/gear/${id}`) + return await this.request.makeApiRequest( + 'get', + `/gear/${id}`, + { access_token }, + ) } } diff --git a/src/resources/oauth.ts b/src/resources/oauth.ts new file mode 100644 index 0000000..f6e3dad --- /dev/null +++ b/src/resources/oauth.ts @@ -0,0 +1,32 @@ +import fetch from 'node-fetch' + +import { RefreshTokenRequest, RefreshTokenResponse } from '../types' + +export class Oauth { + constructor() {} + + async refreshTokens( + token: RefreshTokenRequest, + ): Promise { + if (!token) { + throw new Error('No token provided') + } + const query: string = new URLSearchParams({ + client_id: token.client_id, + client_secret: token.client_secret, + refresh_token: token.refresh_token, + grant_type: 'refresh_token', + }).toString() + + const response = await fetch( + `https://www.strava.com/oauth/token?${query}`, + { + method: 'post', + }, + ) + if (!response.ok) { + throw response + } + return (await response.json()) as RefreshTokenResponse + } +} diff --git a/src/resources/routes.ts b/src/resources/routes.ts index d3db186..1929535 100644 --- a/src/resources/routes.ts +++ b/src/resources/routes.ts @@ -26,19 +26,27 @@ export class Routes { this.request = request } - async getRouteAsGPX(params: GetRouteAsGPXRequest): Promise { + async getRouteAsGPX( + params: GetRouteAsGPXRequest, + access_token?: string, + ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', `/routes/${id}/export_gpx`, + { access_token }, ) } - async getRouteAsTCX(params: GetRouteAsTCXRequest): Promise { + async getRouteAsTCX( + params: GetRouteAsTCXRequest, + access_token?: string, + ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', `/routes/${id}/export_tcx`, + { access_token }, ) } diff --git a/src/resources/runningRaces.ts b/src/resources/runningRaces.ts index 42e4356..6a73958 100644 --- a/src/resources/runningRaces.ts +++ b/src/resources/runningRaces.ts @@ -18,21 +18,24 @@ export class RunningRaces { async getRunningRaceById( params: GetRunningRaceByIdRequest, + access_token?: string, ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', `/running_races/${id}`, + { access_token }, ) } async getRunningRaces( params?: GetRunningRacesRequest, + access_token?: string, ): Promise { return await this.request.makeApiRequest( 'get', '/running_races', - { query: params }, + { query: params, access_token }, ) } } diff --git a/src/resources/segmentEfforts.ts b/src/resources/segmentEfforts.ts index 58105a1..498e495 100644 --- a/src/resources/segmentEfforts.ts +++ b/src/resources/segmentEfforts.ts @@ -21,21 +21,24 @@ export class SegmentEfforts { async getEffortsBySegmentId( params: GetEffortsBySegmentIdRequest, + access_token?: string, ): Promise { return await this.request.makeApiRequest( 'get', '/segment_efforts', - { query: params }, + { query: params, access_token }, ) } async getSegmentEffortById( params: GetSegmentEffortByIdRequest, + access_token?: string, ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', `/segment_efforts/${id}`, + { access_token }, ) } } diff --git a/src/resources/segments.ts b/src/resources/segments.ts index 06f422c..21e56d5 100644 --- a/src/resources/segments.ts +++ b/src/resources/segments.ts @@ -33,11 +33,12 @@ export class Segments { async exploreSegments( params: ExploreSegmentsRequest, + access_token?: string, ): Promise { return await this.request.makeApiRequest( 'get', '/segments/explore', - { query: params }, + { query: params, access_token }, ) } @@ -53,20 +54,25 @@ export class Segments { async getSegmentById( params: GetSegmentByIdRequest, + access_token?: string, ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', `/segments/${id}`, + { access_token }, ) } - async starSegment(params: StarSegmentRequest): Promise { + async starSegment( + params: StarSegmentRequest, + access_token?: string, + ): Promise { const { id, ...body } = params return await this.request.makeApiRequest( 'put', `/segments/${id}/starred`, - { body }, + { body, access_token }, ) } } diff --git a/src/resources/streams.ts b/src/resources/streams.ts index fd744a7..f748e75 100644 --- a/src/resources/streams.ts +++ b/src/resources/streams.ts @@ -30,42 +30,49 @@ export class Streams { async getActivityStreams( params: GetActivityStreamsRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/activities/${id}/streams`, - { query: { ...query, key_by_type: true } }, + { query: { ...query, key_by_type: true }, access_token }, ) } - async getRouteStreams(params: GetRouteStreamsRequest): Promise { + async getRouteStreams( + params: GetRouteStreamsRequest, + access_token?: string, + ): Promise { const { id } = params return await this.request.makeApiRequest( 'get', `/routes/${id}/streams`, + { access_token }, ) } async getSegmentEffortStreams( params: GetSegmentEffortStreamsRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/segment_efforts/${id}/streams`, - { query: { ...query, key_by_type: true } }, + { query: { ...query, key_by_type: true }, access_token }, ) } async getSegmentStreams( params: GetSegmentStreamsRequest, + access_token?: string, ): Promise { const { id, ...query } = params return await this.request.makeApiRequest( 'get', `/segments/${id}/streams`, - { query: { ...query, key_by_type: true } }, + { query: { ...query, key_by_type: true }, access_token }, ) } } diff --git a/src/resources/uploads.ts b/src/resources/uploads.ts index 28a99fe..5940e5c 100644 --- a/src/resources/uploads.ts +++ b/src/resources/uploads.ts @@ -45,11 +45,15 @@ export class Uploads { }) } - async getUploadById(params: GetUploadByIdRequest): Promise { + async getUploadById( + params: GetUploadByIdRequest, + access_token?: string, + ): Promise { const { uploadId } = params return await this.request.makeApiRequest( 'get', `/uploads/${uploadId}`, + { access_token }, ) } } diff --git a/src/types.ts b/src/types.ts index 771120e..8893ff3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,7 +3,6 @@ export interface RefreshTokenRequest { client_secret: string refresh_token: string } - export interface RefreshTokenResponse { access_token: string expires_at: number