Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions .drone.yml

This file was deleted.

6 changes: 0 additions & 6 deletions .travis.yml

This file was deleted.

145 changes: 64 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@

# strava-v3: Simple Node wrapper for Strava's v3 API
# strava-v3

A simple Node.js wrapper for Strava's v3 API

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Build Status][travis-image]][travis-url]
[![Test Suite][github-actions-image]][github-actions-url]

[npm-image]: https://img.shields.io/npm/v/strava-v3.svg?style=flat
[npm-url]: https://npmjs.org/package/strava-v3
[downloads-image]: https://img.shields.io/npm/dm/strava-v3.svg?style=flat
[downloads-url]: https://npmjs.org/package/strava-v3
[travis-image]: https://travis-ci.org/UnbounDev/node-strava-v3.svg?branch=master&style=flat
[travis-url]: https://travis-ci.org/UnbounDev/node-strava-v3

### Status
[github-actions-image]: https://github.com/node-strava/node-strava-v3/actions/workflows/on-pull-request.yml/badge.svg
[github-actions-url]: https://github.com/node-strava/node-strava-v3/actions/workflows/on-pull-request.yml

Supports many but not all Strava API endpoints:

Expand All @@ -22,7 +22,6 @@ Supports many but not all Strava API endpoints:
* `activities`
* `clubs`
* `gear`
* `running_races`
* `routes`
* `segments`
* `segment_efforts`
Expand All @@ -36,12 +35,16 @@ npm install strava-v3
```

## Import syntax

Importing only the library:
```

```js
import strava from 'strava-v3';
```

Importing both the library as well as interfaces:
```

```js
import { default as strava, Strava } from 'strava-v3';
```

Expand Down Expand Up @@ -97,15 +100,15 @@ strava.config({
"redirect_uri" : "Your apps Authorization Redirection URI (Required for oauth)",
});
```

##### Environment variables

You may alternatively supply the values via environment variables named following the convention `STRAVA_<keyName>`, so

- `STRAVA_ACCESS_TOKEN` = `access_token`
- `STRAVA_CLIENT_ID` = `client_id`
- `STRAVA_CLIENT_SECRET` = `client_secret`
- `STRAVA_REDIRECT_URI` = `redirect_uri`

* `STRAVA_ACCESS_TOKEN` = `access_token`
* `STRAVA_CLIENT_ID` = `client_id`
* `STRAVA_CLIENT_SECRET` = `client_secret`
* `STRAVA_REDIRECT_URI` = `redirect_uri`

#### Config File (Deprecated)

Expand Down Expand Up @@ -161,7 +164,7 @@ strava = new stravaApi.client(access_token);
const payload = await strava.athlete.get({})
```

Less conveniently, you can also explictly pass an `access_token` to API calls:
Less conveniently, you can also explicitly pass an `access_token` to API calls:

Example usage:

Expand All @@ -178,13 +181,14 @@ Example usage:

```js
const strava = require('strava-v3');
const payload = await strava.athlete.listFollowers({
const payload = await strava.athlete.listActivities({
page: 1,
per_page: 2
});
```

### Uploading files

To upload a file you'll have to pass in the `data_type` as specified in Strava's API reference as well as a string `file` designating the `<filepath>/<filename>`. If you want to get updates on the status of your upload pass in `statusCallback` along with the rest of your `args` - the wrapper will check on the upload once a second until complete.

Example usage:
Expand All @@ -202,6 +206,7 @@ const payload = await strava.uploads.post({
```

### Rate limits

According to Strava's API each response contains information about rate limits.
For more details see: [Rate Limits](https://developers.strava.com/docs/rate-limits/)

Expand Down Expand Up @@ -250,6 +255,7 @@ strava.athlete.get({'access_token':'abcde'},function(err,payload,limits) {
*/
});
```

### Supported API Endpoints

To used the Promise-based API, do not provide a callback. A promise will be returned.
Expand Down Expand Up @@ -301,41 +307,38 @@ See Strava API docs for returned data structures.
These methods Authenticate with a Client ID and Client Secret. Since they don't
use OAuth, they are not available on the `client` object.

* `strava.pushSubscriptions.list({},done)`
* `strava.pushSubscriptions.create({callback_url:...},done)`
* We set 'object\_type to "activity" and "aspect\_type" to "create" for you.
* `strava.pushSubscriptions.delete({id:...},done)`

#### Running Races

* `strava.runningRaces.get(args,done)`
* `strava.runningRaces.listRaces(args,done)`
* `strava.pushSubscriptions.list({},done)`
* `strava.pushSubscriptions.create({callback_url:...},done)`
* We set 'object\_type to "activity" and "aspect\_type" to "create" for you.
* `strava.pushSubscriptions.delete({id:...},done)`

#### Routes

* `strava.routes.getFile({ id: routeId, file_type: 'gpx' },done)` *file_type may also be 'tcx'*
* `strava.routes.get(args,done)`
* `strava.routes.getFile({ id: routeId, file_type: 'gpx' },done)` *file_type may also be 'tcx'*
* `strava.routes.get(args,done)`

#### Segments

* `strava.segments.get(args,done)`
* `strava.segments.listStarred(args,done)`
* `strava.segments.listEfforts(args,done)`
* `strava.segments.explore(args,done)` *Expects arg `bounds` as a comma separated string, for two points describing a rectangular boundary for the search: `"southwest corner latitutde, southwest corner longitude, northeast corner latitude, northeast corner longitude"`*.
* `strava.segments.get(args,done)`
* `strava.segments.listStarred(args,done)`
* `strava.segments.listEfforts(args,done)`
* `strava.segments.explore(args,done)` *Expects arg `bounds` as a comma separated string, for two points describing a rectangular boundary for the search: `"southwest corner latitude, southwest corner longitude, northeast corner latitude, northeast corner longitude"`*.
* `strava.segments.starSegment(args,done)`

#### Segment Efforts

* `strava.segmentEfforts.get(args,done)`
* `strava.segmentEfforts.get(args,done)`

#### Streams

* `strava.streams.activity(args,done)`
* `strava.streams.effort(args,done)`
* `strava.streams.segment(args,done)`
* `strava.streams.activity(args,done)`
* `strava.streams.effort(args,done)`
* `strava.streams.segment(args,done)`
* `strava.streams.route(args,done)`

#### Uploads

* `strava.uploads.post(args,done)`
* `strava.uploads.post(args,done)`

## Error Handling

Expand Down Expand Up @@ -369,71 +372,52 @@ Example error checking:

The `StatusCodeError` object includes extra properties to help with debugging:

- `name` is always `StatusCodeError`
- `statusCode` contains the HTTP status code
- `message` contains the response's status message and additional error details
- `data` contains the body of the response, which can be useful for debugging
- `options` contains the options used in the request
- `response` contains the response object
* `name` is always `StatusCodeError`
* `statusCode` contains the HTTP status code
* `message` contains the response's status message and additional error details
* `data` contains the body of the response, which can be useful for debugging
* `options` contains the options used in the request
* `response` contains the response object

The `RequestError` object is used for errors that occur due to technical issues, such as no response being received or request setup issues, and includes the following properties:

- `name` is always `RequestError`
- `message` contains the error message
- `options` contains the options used in the request
* `name` is always `RequestError`
* `message` contains the error message
* `options` contains the options used in the request

This update maintains feature parity with the previous implementation of `request-promise` while using the Axios HTTP client under the hood.


## Development

This package includes a full test suite runnable via `yarn test`.
It will both lint and run tests on API endpoints.

### Running the tests

Many unit tests now use nock to mock the Strava API and can run without any real credentials.
However, some integration-style tests still expect a real token and account data.
All tests use `nock` to mock the Strava API and can run without any real credentials or network access.

If you want to run the full test suite (including integration tests), you'll need to supply `data/strava_config` with an `access_token` that
has both private read and write permissions. Look in `./scripts` for a tool
to help generate this token.
Simply run:

* Make sure you've filled out all the fields in `data/strava_config`.
* Use `strava.oauth.getRequestAccessURL({scope:"view_private,write"})` to generate the request url and query it via your browser.
* Strava will prompt you (the user) to allow access, say yes and you'll be sent to your Authorization Redirection URI - the parameter `code` will be included in the redirection url.
* Exchange the `code` for a new `access_token`:

```js
// access_token is at payload.access_token
const payload = await strava.oauth.getToken(authorizationCode)
```bash
yarn test
```
Finally, the test suite has some expectations about the Strava account that it
connects for the tests to pass. The following should be true about the Strava
data in the account:

* Must have at least one activity posted on Strava
* Must have joined at least one club
* Must have added at least one piece of gear (bike or shoes)
* Must have created at least one route
* Most recent activity with an achievement should also contain a segment
The test suite will:

(Parts of the test suite already use `nock` to mock the API. Contributions to convert remaining integration tests to mocks are welcome.)

You're done! Paste the new `access_token` to `data/strava_config` and run the full tests:

`yarn test`.
* Run ESLint on all JavaScript files
* Execute all unit tests using mocked API responses

### How the tests work

- Tests use Mocha and Should.js.
- HTTP interaction is performed with Axios; tests that mock HTTP use `nock`.
* Tests use Mocha and Node.js's built-in `assert` module
* HTTP interaction is performed with Axios; all tests mock HTTP requests using `nock`

Using the provided `access_token` tests will access each endpoint individually:
The test suite validates:

* (For all `GET` endpoints) checks to ensure the correct type has been returned from the Strava.
* (For `PUT` in `athlete.update`) changes some athlete properties, then changes them back.
* (For `POST/PUT/DELETE` in `activities.create/update/delete`) first creates an activity, runs some operations on it, then deletes it.
* All `GET` endpoints return the correct data structure
* All `POST`/`PUT`/`DELETE` endpoints handle requests and responses correctly
* Error handling works as expected
* Rate limiting functionality is properly tested

## Resources

Expand All @@ -442,7 +426,6 @@ Using the provided `access_token` tests will access each endpoint individually:

## Author and Maintainer

Authored by Austin Brown <austin@unboundev.com> (http://austinjamesbrown.com/).

Currently Maintained by Mark Stosberg <mark@rideamigos.com>
Authored by Austin Brown <austin@unboundev.com> (<http://austinjamesbrown.com/>).

Currently Maintained by Mark Stosberg <mark@rideamigos.com> and Wesley Schlenker <wesley@rideamigos.com>
11 changes: 2 additions & 9 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export interface UploadResponse {
export interface SegmentsRoutes {
get(args: any, done?: Callback): Promise<any>;
listStarred(args: any, done?: Callback): Promise<any>;
starSegment(args: any, done?: Callback): Promise<any>;
listEfforts(args: any, done?: Callback): Promise<any>;
listLeaderboard(args: any, done?: Callback): Promise<any>;
explore(args: any, done?: Callback): Promise<any>;
}

Expand All @@ -80,6 +80,7 @@ export interface StreamsRoutes {
activity(args: any, done?: Callback): Promise<any>;
effort(args: any, done?: Callback): Promise<any>;
segment(args: any, done?: Callback): Promise<any>;
route(args: any, done?: Callback): Promise<any>;
}

export interface RoutesRoutes {
Expand Down Expand Up @@ -107,11 +108,7 @@ export interface ClubsRoutes {
args: ClubsRoutesListArgs,
done?: Callback
): Promise<ClubActivity[]>;
listAnnouncements(args: ClubsRoutesListArgs, done?: Callback): Promise<any>;
listEvents(args: ClubsRoutesListArgs, done?: Callback): Promise<any>;
listAdmins(args: ClubsRoutesListArgs, done?: Callback): Promise<any>;
joinClub(args: ClubsRoutesListArgs, done?: Callback): Promise<any>;
leaveClub(args: ClubsRoutesListArgs, done?: Callback): Promise<any>;
}

export interface ClubsRoutesArgs extends BaseArgs {
Expand Down Expand Up @@ -140,7 +137,6 @@ export interface ClubActivity {
}

export interface AthletesRoutes {
get(args: AthleteRouteArgs, done?: Callback): Promise<AthleteRouteResponse>;
stats(args: any, done?: Callback): Promise<any>;
}

Expand Down Expand Up @@ -286,13 +282,10 @@ export interface ActivitiesRoutes {
get(args: any, done?: Callback): Promise<DetailedActivityResponse>;
create(args: any, done?: Callback): Promise<any>;
update(args: any, done?: Callback): Promise<any>;
listFriends(args: any, done?: Callback): Promise<any>;
listZones(args: any, done?: Callback): Promise<any>;
listLaps(args: any, done?: Callback): Promise<any>;
listComments(args: any, done?: Callback): Promise<any>;
listKudos(args: any, done?: Callback): Promise<any>;
listPhotos(args: any, done?: Callback): Promise<any>;
listRelated(args: any, done?: Callback): Promise<any>;
}

export interface AthleteRoutes {
Expand Down
3 changes: 3 additions & 0 deletions lib/athlete.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ athlete.prototype.get = async function (args) {
athlete.prototype.listActivities = async function (args) {
return await this._listHelper('activities', args)
}
athlete.prototype.listRoutes = async function (args) {
return await this._listHelper('routes', args)
}
athlete.prototype.listClubs = async function (args) {
return await this._listHelper('clubs', args)
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "strava-v3",
"version": "3.2.0",
"version": "3.3.0",
"description": "Simple wrapper for Strava v3 API",
"main": "index.js",
"types": "index.d.ts",
Expand Down
Loading