diff --git a/README.md b/README.md index 3af8081..f7c5cb8 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,6 @@ import { default as strava, Strava } from 'strava-v3'; * Create an application at [strava.com/settings/api](https://www.strava.com/settings/api) and make note of your `access_token` -### Promise API - ```js const strava = require('strava-v3') strava.config({...}) @@ -58,20 +56,129 @@ const payload = await strava.athlete.get({}) console.log(payload) ``` -### Callback API (Deprecated) +## Migrating from Callbacks to Promises +Let's walk through a practical example of how to migrate your existing callback-based usage of the strava-v3 library to a Promise-based approach. -```js +### Original Callback-Based Usage +**Before Migration:** + +```javascript const strava = require('strava-v3'); -strava.athlete.get({},function(err,payload,limits) { - if(!err) { - console.log(payload); - } - else { - console.log(err); + +// Configuring Strava with necessary credentials +strava.config({ + access_token: 'your_access_token', + client_id: 'your_client_id', + client_secret: 'your_client_secret', + redirect_uri: 'your_redirect_uri' +}); + +// Fetching athlete data using callbacks +strava.athlete.get({ id: 12345 }, function(err, athlete) { + if (err) { + return console.error('Error fetching athlete:', err); + } + + console.log('Athlete Data:', athlete); + + // Fetching athlete's activities using callbacks + strava.activities.list({ athlete_id: athlete.id }, function(err, activities) { + if (err) { + return console.error('Error fetching activities:', err); } + + console.log('Activities:', activities); + }); }); ``` +### Migrated Promise-Based Usage +**After Migration:** + +```javascript +const strava = require('strava-v3'); + +// Configuring Strava with necessary credentials +strava.config({ + access_token: 'your_access_token', + client_id: 'your_client_id', + client_secret: 'your_client_secret', + redirect_uri: 'your_redirect_uri' +}); + +// Fetching athlete data using Promises with async/await +async function fetchAthleteData(athleteId) { + try { + const athlete = await strava.athlete.get({ id: athleteId }); + console.log('Athlete Data:', athlete); + + // Fetching athlete's activities using Promises with async/await + const activities = await strava.activities.list({ athlete_id: athlete.id }); + console.log('Activities:', activities); + + } catch (err) { + console.error('Error fetching data:', err); + } +} + +// Invoke the async function +fetchAthleteData(12345); +``` + +### Key Changes Explained +1. **Removal of Callback Parameters:** + + * Before: Methods like `strava.athlete.get` and `strava.activities.list` accept a callback function as the last parameter. + * After: These methods now return Promises, eliminating the need for callback functions. + +2. **Using `async/await`:** + + * The `fetchAthleteData` function is declared as `async`, allowing the use of `await` to handle Promises in a synchronous-like manner. + * `await` pauses the execution of the function until the Promise resolves, making the code easier to read and maintain. + +3. **Centralized Error Handling:** + + * The `try-catch` block encapsulates both asynchronous operations, ensuring that any errors thrown by either `strava.athlete.get` or `strava.activities.list` are caught and handled in one place. + +4. **Elimination of Nested Callbacks:** + + * The Promise-based approach avoids deeply nested functions, reducing complexity and improving readability. + +### Alternative: Using `.then()` and `.catch()` +If you prefer not to use `async/await`, you can achieve similar results using `.then()` and `.catch()` chaining. + +**Example:** + +```javascript +const strava = require('strava-v3'); + +// Configuring Strava with necessary credentials +strava.config({ + access_token: 'your_access_token', + client_id: 'your_client_id', + client_secret: 'your_client_secret', + redirect_uri: 'your_redirect_uri' +}); + +// Fetching athlete data using Promises with .then() and .catch() +strava.athlete.get({ id: 12345 }) + .then(athlete => { + console.log('Athlete Data:', athlete); + return strava.activities.list({ athlete_id: athlete.id }); + }) + .then(activities => { + console.log('Activities:', activities); + }) + .catch(err => { + console.error('Error fetching data:', err); + }); + ``` +**Benefits:** + +* **Chainable:** Promises allow you to chain multiple asynchronous operations in a linear and manageable fashion. +* **Error Propagation:** Errors thrown in any `.then()` block are propagated down the chain to the nearest `.catch()` block. + + ## Usage ### OAuth configuration @@ -127,20 +234,15 @@ API access is designed to be as closely similar in layout as possible to Strava' ```js var strava = require('strava-v3') -// Promise API -strava..(args) - -// Callback API -strava..(args,callback) +const payload = await strava..(args); ``` Example usage: ```js -var strava = require('strava-v3'); -strava.athletes.get({id:12345},function(err,payload,limits) { - //do something with your payload, track rate limits -}); +const strava = require('strava-v3'); +const payload = await strava.athletes.get({ id: 12345 }); +// Do something with your payload, track rate limits ``` ### Overriding the default `access_token` @@ -210,8 +312,7 @@ Returns `null` if `X-Ratelimit-Limit` or `X-RateLimit-Usage` headers are not pro #### Global status In our promise API, only the response body "payload" value is returned as a -[Bluebird promise](https://bluebirdjs.com/docs/api-reference.html). To track -rate limiting we use a global counter accessible through `strava.rateLimiting`. +promise. To track rate limiting we use a global counter accessible through `strava.rateLimiting`. The rate limiting status is updated with each request. @@ -221,114 +322,92 @@ rate limiting we use a global counter accessible through `strava.rateLimiting`. // returns the current decimal fraction (from 0 to 1) of rate used. The greater of the short and long term limits. strava.rateLimiting.fractionReached(); -#### Callback interface (Rate limits) - -```js -const strava = require('strava-v3'); -strava.athlete.get({'access_token':'abcde'},function(err,payload,limits) { - //do something with your payload, track rate limits - console.log(limits); - /* - output: - { - shortTermUsage: 3, - shortTermLimit: 600, - longTermUsage: 12, - longTermLimit: 30000 - } - */ -}); -``` ### Supported API Endpoints -To used the Promise-based API, do not provide a callback. A promise will be returned. - See Strava API docs for returned data structures. #### OAuth * `strava.oauth.getRequestAccessURL(args)` -* `strava.oauth.getToken(code,done)` (Used to token exchange) -* `strava.oauth.refreshToken(code)` (Callback API not supported) -* `strava.oauth.deauthorize(args,done)` +* `strava.oauth.getToken(code)` (Used to token exchange) +* `strava.oauth.refreshToken(code)` +* `strava.oauth.deauthorize(args)` #### Athlete -* `strava.athlete.get(args,done)` -* `strava.athlete.update(args,done)` // only 'weight' can be updated. -* `strava.athlete.listActivities(args,done)` *Get list of activity summaries* -* `strava.athlete.listRoutes(args,done)` -* `strava.athlete.listClubs(args,done)` -* `strava.athlete.listZones(args,done)` +* `strava.athlete.get(args)` +* `strava.athlete.update(args)` // only 'weight' can be updated. +* `strava.athlete.listActivities(args)` *Get list of activity summaries* +* `strava.athlete.listRoutes(args)` +* `strava.athlete.listClubs(args)` +* `strava.athlete.listZones(args)` #### Athletes -* `strava.athletes.get(args,done)` *Get a single activity. args.id is required* -* `strava.athletes.stats(args,done)` +* `strava.athletes.get(args)` *Get a single activity. args.id is required* +* `strava.athletes.stats(args)` #### Activities -* `strava.activities.get(args,done)` -* `strava.activities.create(args,done)` -* `strava.activities.update(args,done)` -* `strava.activities.listFriends(args,done)` -> deprecated at 2.2.0 -* `strava.activities.listZones(args,done)` -* `strava.activities.listLaps(args,done)` -* `strava.activities.listComments(args,done)` -* `strava.activities.listKudos(args,done)` -* `strava.activities.listPhotos(args,done)` -> deprecated at 2.2.0 +* `strava.activities.get(args)` +* `strava.activities.create(args)` +* `strava.activities.update(args)` +* `strava.activities.listZones(args)` +* `strava.activities.listLaps(args)` +* `strava.activities.listComments(args)` +* `strava.activities.listKudos(args)` #### Clubs -* `strava.clubs.get(args,done)` -* `strava.clubs.listMembers(args,done)` -* `strava.clubs.listActivities(args,done)` -* `strava.clubs.listAdmins(args,done)` +* `strava.clubs.get(args)` +* `strava.clubs.listMembers(args)` +* `strava.clubs.listActivities(args)` +* `strava.clubs.listAdmins(args)` #### Gear -* `strava.gear.get(args,done)` +* `strava.gear.get(args)` #### Push Subscriptions 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)` + * `strava.pushSubscriptions.list({})` + * `strava.pushSubscriptions.create({callback_url:...})` * We set 'object\_type to "activity" and "aspect\_type" to "create" for you. - * `strava.pushSubscriptions.delete({id:...},done)` + * `strava.pushSubscriptions.delete({id:...})` #### Running Races - * `strava.runningRaces.get(args,done)` - * `strava.runningRaces.listRaces(args,done)` + * `strava.runningRaces.get(args)` + * `strava.runningRaces.listRaces(args)` #### 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' })` *file_type may also be 'tcx'* + * `strava.routes.get(args)` #### 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)` + * `strava.segments.listStarred(args)` + * `strava.segments.listEfforts(args)` + * `strava.segments.explore(args)` *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"`*. #### Segment Efforts - * `strava.segmentEfforts.get(args,done)` + * `strava.segmentEfforts.get(args)` #### Streams - * `strava.streams.activity(args,done)` - * `strava.streams.effort(args,done)` - * `strava.streams.segment(args,done)` + * `strava.streams.activity(args)` + * `strava.streams.effort(args)` + * `strava.streams.segment(args)` #### Uploads - * `strava.uploads.post(args,done)` + * `strava.uploads.post(args)` ## Error Handling @@ -336,7 +415,7 @@ Except for the OAuth calls, errors returned will be instances of `StatusCodeErro The updated version now uses Axios for HTTP requests and custom error classes for compatibility with the previous implementation. -In the Promise-based API, errors will reject the Promise. In the callback-based API (where supported), errors will pass to the `err` argument in the callback. +In the Promise-based API, errors will reject the Promise. The project no longer relies on Bluebird. Where applicable, callback handling has been removed. @@ -346,13 +425,17 @@ Example error checking: const { StatusCodeError, RequestError } = require('./axiosUtility'); // Catch a non-2xx response with the Promise API - badClient.athlete.get({}) - .catch(StatusCodeError, function (e) { - }); - - badClient.athlete.get({}, function(err, payload) { - // err will be an instance of StatusCodeError or RequestError - }); + try { + const payload = await badClient.athlete.get({}); + } catch (e) { + if (e instanceof StatusCodeError) { + // Handle non-2xx responses + } else if (e instanceof RequestError) { + // Handle technical request failures + } else { + // Handle other unexpected errors + } + } ``` The `StatusCodeError` object includes extra properties to help with debugging: diff --git a/axiosUtility.js b/axiosUtility.js index 53776c1..041001b 100644 --- a/axiosUtility.js +++ b/axiosUtility.js @@ -48,8 +48,8 @@ const httpRequest = async (options) => { responseType: options.responseType || 'json', // Support different response types maxRedirects: options.maxRedirects || 5, // Set max redirects validateStatus: options.simple === false ? () => true : undefined // Handle 'simple' option - }); - return response.data; + }) + return response.data } catch (error) { if (error.response) { throw new StatusCodeError( @@ -58,14 +58,14 @@ const httpRequest = async (options) => { error.response.data, options, error.response - ); + ) } else if (error.request) { - throw new RequestError(`No response received: ${error.message}`, options); + throw new RequestError(`No response received: ${error.message}`, options) } else { - throw new RequestError(`Request setup error: ${error.message}`, options); + throw new RequestError(`Request setup error: ${error.message}`, options) } } -}; +} /** * Function to update default headers diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..d63a5ae --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,21 @@ +import js from '@eslint/js'; +import promisePlugin from 'eslint-plugin-promise'; +import globals from 'globals'; + +export default [ + js.configs.recommended, + { + languageOptions: { + globals: { + ...globals.node, + ...globals.mocha, + }, + }, + plugins: { + promise: promisePlugin, + }, + rules: { + 'promise/prefer-await-to-then': 'error', + }, + }, +]; diff --git a/index.d.ts b/index.d.ts index 021ff9f..d0b75a4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,3 @@ -type Callback = (error: any, payload: any) => void; - interface BaseArgs { access_token?: string; } @@ -10,12 +8,9 @@ interface ApplicationBaseArgs { } export interface PushSubscriptionRoutes { - list(done?: Callback): Promise; - create( - args: CreatePushSubscriptionRouteArgs, - done?: Callback - ): Promise; - delete(args: DeletePushSubscriptionRouteArgs, done?: Callback): Promise; + list(): Promise; + create(args: CreatePushSubscriptionRouteArgs): Promise; + delete(args: DeletePushSubscriptionRouteArgs): Promise; } export interface ListPushSubscriptionResponse { @@ -41,7 +36,7 @@ export interface DeletePushSubscriptionRouteArgs extends ApplicationBaseArgs { } export interface UploadsRoutes { - post(args: UploadRouteArgs, done?: Callback): Promise; + post(args: UploadRouteArgs): Promise; } export interface UploadRouteArgs { @@ -64,26 +59,26 @@ export interface UploadResponse { } export interface SegmentsRoutes { - get(args: any, done?: Callback): Promise; - listStarred(args: any, done?: Callback): Promise; - listEfforts(args: any, done?: Callback): Promise; - listLeaderboard(args: any, done?: Callback): Promise; - explore(args: any, done?: Callback): Promise; + get(args: any): Promise; + listStarred(args: any): Promise; + listEfforts(args: any): Promise; + listLeaderboard(args: any): Promise; + explore(args: any): Promise; } export interface SegmentEffortsRoutes { - get(args: any, done?: Callback): Promise; + get(args: any): Promise; } export interface StreamsRoutes { - activity(args: any, done?: Callback): Promise; - effort(args: any, done?: Callback): Promise; - segment(args: any, done?: Callback): Promise; + activity(args: any): Promise; + effort(args: any): Promise; + segment(args: any): Promise; } export interface RoutesRoutes { - get(args: any, done?: Callback): Promise; - getFile(args: RouteFile, done?: Callback): Promise; + get(args: any): Promise; + getFile(args: RouteFile): Promise; } export interface DetailRoute extends BaseArgs { @@ -96,26 +91,23 @@ export interface RouteFile extends BaseArgs { } export interface GearRoutes { - get(args: any, done?: Callback): Promise; + get(args: any): Promise; } export interface RunningRacesRoutes { - get(args: any, done?: Callback): Promise; - listRaces(args: any, done?: Callback): Promise; + get(args: any): Promise; + listRaces(args: any): Promise; } export interface ClubsRoutes { - get(args: ClubsRoutesArgs, done?: Callback): Promise; - listMembers(args: ClubsRoutesListArgs, done?: Callback): Promise; - listActivities( - args: ClubsRoutesListArgs, - done?: Callback - ): Promise; - listAnnouncements(args: ClubsRoutesListArgs, done?: Callback): Promise; - listEvents(args: ClubsRoutesListArgs, done?: Callback): Promise; - listAdmins(args: ClubsRoutesListArgs, done?: Callback): Promise; - joinClub(args: ClubsRoutesListArgs, done?: Callback): Promise; - leaveClub(args: ClubsRoutesListArgs, done?: Callback): Promise; + get(args: ClubsRoutesArgs): Promise; + listMembers(args: ClubsRoutesListArgs): Promise; + listActivities(args: ClubsRoutesListArgs): Promise; + listAnnouncements(args: ClubsRoutesListArgs): Promise; + listEvents(args: ClubsRoutesListArgs): Promise; + listAdmins(args: ClubsRoutesListArgs): Promise; + joinClub(args: ClubsRoutesListArgs): Promise; + leaveClub(args: ClubsRoutesListArgs): Promise; } export interface ClubsRoutesArgs extends BaseArgs { @@ -144,8 +136,8 @@ export interface ClubActivity { } export interface AthletesRoutes { - get(args: AthleteRouteArgs, done?: Callback): Promise; - stats(args: any, done?: Callback): Promise; + get(args: AthleteRouteArgs): Promise; + stats(args: any): Promise; } export interface AthleteRouteArgs extends BaseArgs { @@ -242,6 +234,9 @@ type SportType = export interface DetailedActivityResponse { id: string; + external_id?: string; + upload_id?: string; + upload_id_str?: string; athlete: { resource_state: number; firstname: string; @@ -274,45 +269,60 @@ export interface DetailedActivityResponse { manual?: boolean; private?: boolean; flagged?: boolean; + workout_type?: number; + kilojoules?: number; + average_watts?: number; + device_watts?: boolean; + max_watts?: number; + weighted_average_watts?: number; average_speed?: number; max_speed?: number; has_kudoed?: boolean; hide_from_home?: boolean; gear_id?: string; + gear?: SummaryGear; description?: string; calories?: number; + photos?: PhotosSummary; + segment_efforts?: DetailedSegmentEffort[]; + device_name?: string; + embed_token?: string; + splits_metric?: Split[]; + splits_standard?: Split[]; + laps?: Lap[]; + best_efforts?: DetailedSegmentEffort[]; private_notes?: string; start_latlng?: Array; end_latlng?: Array; } export interface ActivitiesRoutes { - get(args: any, done?: Callback): Promise; - create(args: any, done?: Callback): Promise; - update(args: any, done?: Callback): Promise; - listFriends(args: any, done?: Callback): Promise; - listZones(args: any, done?: Callback): Promise; - listLaps(args: any, done?: Callback): Promise; - listComments(args: any, done?: Callback): Promise; - listKudos(args: any, done?: Callback): Promise; - listPhotos(args: any, done?: Callback): Promise; - listRelated(args: any, done?: Callback): Promise; + get(args: any): Promise; + create(args: any): Promise; + update(args: any): Promise; + listFriends(args: any): Promise; + listZones(args: any): Promise; + listLaps(args: any): Promise; + listComments(args: any): Promise; + listKudos(args: any): Promise; + listPhotos(args: any): Promise; + listRelated(args: any): Promise; } export interface AthleteRoutes { - get(args: any, done?: Callback): Promise; - update(args: any, done?: Callback): Promise; - listActivities(args: any, done?: Callback): Promise; - listRoutes(args: any, done?: Callback): Promise; - listClubs(args: any, done?: Callback): Promise; - listZones(args: any, done?: Callback): Promise; + get(args: any): Promise; + update(args: any): Promise; + listActivities(args: any): Promise; + listRoutes(args: any): Promise; + listClubs(args: any): Promise; + listZones(args: any): Promise; } export interface OAuthRoutes { getRequestAccessURL(args: any): Promise; - getToken(code: string, done?: Callback): Promise; + getToken(code: string): Promise; refreshToken(code: string): Promise; - deauthorize(args: any, done?: Callback): Promise; + deauthorize(args: any): Promise; } export interface RefreshTokenResponse { diff --git a/index.js b/index.js index ff02259..ff40c78 100644 --- a/index.js +++ b/index.js @@ -62,7 +62,7 @@ strava.defaultHttpClient = new HttpClient(async (options) => { options.headers = { ...strava.defaultRequest.defaults.headers, Authorization: 'Bearer ' + authenticator.getToken(), - ...options.headers, + ...options.headers } return await httpRequest(options) // Await the Promise }) diff --git a/lib/activities.js b/lib/activities.js index d3ca2aa..c68b67b 100644 --- a/lib/activities.js +++ b/lib/activities.js @@ -34,21 +34,23 @@ var _updateAllowedProps = [ ] //= ==== activities endpoint ===== -activities.prototype.get = function (args, done) { +activities.prototype.get = function (args) { var qs = this.client.getQS(_qsAllowedProps, args) _requireActivityId(args) var endpoint = 'activities/' + args.id + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -activities.prototype.create = function (args, done) { + +activities.prototype.create = function (args) { var endpoint = 'activities' args.body = this.client.getRequestBodyObj(_createAllowedProps, args) - return this.client.postEndpoint(endpoint, args, done) + return this.client.postEndpoint(endpoint, args) } -activities.prototype.update = function (args, done) { + +activities.prototype.update = function (args) { var form = this.client.getRequestBodyObj(_updateAllowedProps, args) _requireActivityId(args) @@ -57,36 +59,36 @@ activities.prototype.update = function (args, done) { args.form = form - return this.client.putEndpoint(endpoint, args, done) + return this.client.putEndpoint(endpoint, args) } -activities.prototype.listZones = function (args, done) { +activities.prototype.listZones = function (args) { _requireActivityId(args) var endpoint = 'activities/' + args.id + '/zones' - return this._listHelper(endpoint, args, done) + return this._listHelper(endpoint, args) } -activities.prototype.listLaps = function (args, done) { +activities.prototype.listLaps = function (args) { _requireActivityId(args) var endpoint = 'activities/' + args.id + '/laps' - return this._listHelper(endpoint, args, done) + return this._listHelper(endpoint, args) } -activities.prototype.listComments = function (args, done) { +activities.prototype.listComments = function (args) { _requireActivityId(args) var endpoint = 'activities/' + args.id + '/comments' - return this._listHelper(endpoint, args, done) + return this._listHelper(endpoint, args) } -activities.prototype.listKudos = function (args, done) { +activities.prototype.listKudos = function (args) { _requireActivityId(args) var endpoint = 'activities/' + args.id + '/kudos' - return this._listHelper(endpoint, args, done) + return this._listHelper(endpoint, args) } //= ==== activities endpoint ===== @@ -97,11 +99,11 @@ var _requireActivityId = function (args) { } } -activities.prototype._listHelper = function (endpoint, args, done) { +activities.prototype._listHelper = function (endpoint, args) { var qs = this.client.getPaginationQS(args) endpoint += '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/athlete.js b/lib/athlete.js index 9701c7c..37cb533 100644 --- a/lib/athlete.js +++ b/lib/athlete.js @@ -18,39 +18,43 @@ var _updateAllowedProps = [ ] //= ==== athlete endpoint ===== -athlete.prototype.get = function (args, done) { +athlete.prototype.get = function (args) { var endpoint = 'athlete' - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -athlete.prototype.listActivities = function (args, done) { - return this._listHelper('activities', args, done) + +athlete.prototype.listActivities = function (args) { + return this._listHelper('activities', args) } -athlete.prototype.listClubs = function (args, done) { - return this._listHelper('clubs', args, done) + +athlete.prototype.listClubs = function (args) { + return this._listHelper('clubs', args) } -athlete.prototype.listRoutes = function (args, done) { - return this._listHelper('routes', args, done) + +athlete.prototype.listRoutes = function (args) { + return this._listHelper('routes', args) } -athlete.prototype.listZones = function (args, done) { - return this._listHelper('zones', args, done) + +athlete.prototype.listZones = function (args) { + return this._listHelper('zones', args) } -athlete.prototype.update = function (args, done) { +athlete.prototype.update = function (args) { var endpoint = 'athlete' var form = this.client.getRequestBodyObj(_updateAllowedProps, args) args.form = form - return this.client.putEndpoint(endpoint, args, done) + return this.client.putEndpoint(endpoint, args) } //= ==== athlete.prototype endpoint ===== //= ==== helpers ===== -athlete.prototype._listHelper = function (listType, args, done) { +athlete.prototype._listHelper = function (listType, args) { var endpoint = 'athlete/' var qs = this.client.getQS(_qsAllowedProps, args) endpoint += listType + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/athletes.js b/lib/athletes.js index eda3fe2..430a7be 100644 --- a/lib/athletes.js +++ b/lib/athletes.js @@ -3,16 +3,17 @@ var athletes = function (client) { } //= ==== athletes endpoint ===== -athletes.prototype.get = function (args, done) { - return this._listHelper('', args, done) +athletes.prototype.get = function (args) { + return this._listHelper('', args) } -athletes.prototype.stats = function (args, done) { - return this._listHelper('stats', args, done) + +athletes.prototype.stats = function (args) { + return this._listHelper('stats', args) } //= ==== athletes endpoint ===== //= ==== helpers ===== -athletes.prototype._listHelper = function (listType, args, done) { +athletes.prototype._listHelper = function (listType, args) { var endpoint = 'athletes/' var qs = this.client.getPaginationQS(args) @@ -22,7 +23,7 @@ athletes.prototype._listHelper = function (listType, args, done) { } endpoint += args.id + '/' + listType + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/authenticator.js b/lib/authenticator.js index eebe72b..e7683fd 100644 --- a/lib/authenticator.js +++ b/lib/authenticator.js @@ -16,6 +16,7 @@ var readConfigFile = function () { if (config.client_secret) clientSecret = config.client_secret if (config.redirect_uri) redirectUri = config.redirect_uri } catch (err) { + console.error("Error reading config file:", err) // Config file does not exist. This may be a valid case if the config is // either passed directly as an argument or via environment variables } diff --git a/lib/clubs.js b/lib/clubs.js index 2f35392..be53625 100644 --- a/lib/clubs.js +++ b/lib/clubs.js @@ -3,44 +3,43 @@ var clubs = function (client) { } //= ==== clubs endpoint ===== -clubs.prototype.get = function (args, done) { +clubs.prototype.get = function (args) { var endpoint = 'clubs/' // require club id if (typeof args.id === 'undefined') { - const err = { msg: 'args must include a club id' } - return done(err) + throw new Error('args must include a club id') } endpoint += args.id - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -clubs.prototype.listMembers = function (args, done) { - return this._listHelper('members', args, done) + +clubs.prototype.listMembers = function (args) { + return this._listHelper('members', args) } -clubs.prototype.listActivities = function (args, done) { - return this._listHelper('activities', args, done) + +clubs.prototype.listActivities = function (args) { + return this._listHelper('activities', args) } -clubs.prototype.listAdmins = function (args, done) { - return this._listHelper('admins', args, done) + +clubs.prototype.listAdmins = function (args) { + return this._listHelper('admins', args) } //= ==== clubs endpoint ===== //= ==== helpers ===== -clubs.prototype._listHelper = function (listType, args, done) { +clubs.prototype._listHelper = function (listType, args) { var endpoint = 'clubs/' - var err = null var qs = this.client.getPaginationQS(args) // require club id if (typeof args.id === 'undefined') { - err = { 'msg': 'args must include a club id' } - return done(err) + throw new Error('args must include a club id') } endpoint += args.id + '/' + listType + '?' + qs - - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/gear.js b/lib/gear.js index 28aca5c..3426a27 100644 --- a/lib/gear.js +++ b/lib/gear.js @@ -2,7 +2,7 @@ var gear = function (client) { this.client = client } -gear.prototype.get = function (args, done) { +gear.prototype.get = function (args) { var endpoint = 'gear/' // require gear id @@ -11,7 +11,7 @@ gear.prototype.get = function (args, done) { } endpoint += args.id - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } module.exports = gear diff --git a/lib/httpClient.js b/lib/httpClient.js index 8103133..f845598 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -119,13 +119,11 @@ HttpClient.prototype.postUpload = async function (args = {}) { HttpClient.prototype.getPaginationQS = function (args) { // setup pagination query args var page = typeof args.page !== 'undefined' ? args.page : null - // eslint-disable-next-line camelcase var per_page = typeof args.per_page !== 'undefined' ? args.per_page : null var qa = {} var qs if (page) { qa.page = page } - // eslint-disable-next-line camelcase if (per_page !== null) { qa.per_page = per_page } qs = querystring.stringify(qa) @@ -138,7 +136,9 @@ HttpClient.prototype.getQS = function (allowedProps, args) { var qs for (var i = 0; i < allowedProps.length; i++) { - if (args.hasOwnProperty(allowedProps[i])) { qa[allowedProps[i]] = args[allowedProps[i]] } + if (Object.prototype.hasOwnProperty.call(args, allowedProps[i])) { + qa[allowedProps[i]] = args[allowedProps[i]]; + } } qs = querystring.stringify(qa) @@ -150,7 +150,9 @@ HttpClient.prototype.getRequestBodyObj = function (allowedProps, args) { var body = {} for (var i = 0; i < allowedProps.length; i++) { - if (args.hasOwnProperty(allowedProps[i])) { body[allowedProps[i]] = args[allowedProps[i]] } + if (Object.prototype.hasOwnProperty.call(args, allowedProps[i])) { + body[allowedProps[i]] = args[allowedProps[i]]; + } } return body @@ -168,10 +170,9 @@ HttpClient.prototype._requestHelper = async function (options) { try { const response = await this.request(options) - // Update rate limits using headers from the successful response rateLimiting.updateRateLimits(response.headers) - + // Return the parsed response body return JSONbig.parse(response.body) } catch (e) { @@ -179,7 +180,6 @@ HttpClient.prototype._requestHelper = async function (options) { if (e.response && e.response.headers) { rateLimiting.updateRateLimits(e.response.headers) } - // Re-throw the error to ensure it's handled elsewhere throw e } diff --git a/lib/pushSubscriptions.js b/lib/pushSubscriptions.js index 42936be..c1e1759 100644 --- a/lib/pushSubscriptions.js +++ b/lib/pushSubscriptions.js @@ -13,9 +13,9 @@ var _allowedPostProps = [ 'verify_token' ] -pushSubscriptions.prototype.create = function (args, done) { +pushSubscriptions.prototype.create = function (args) { if (typeof args.callback_url === 'undefined') { - return done({ 'msg': 'required args missing' }) + throw new Error('required args missing') } // The Strava API currently only has one valid value for these, @@ -39,10 +39,10 @@ pushSubscriptions.prototype.create = function (args, done) { url: 'push_subscriptions', method: 'POST', form: args.body - }, done) + }) } -pushSubscriptions.prototype.list = function (done) { +pushSubscriptions.prototype.list = function () { var qs = this.client.getQS(['client_secret', 'client_id'], { client_secret: authenticator.getClientSecret(), client_id: authenticator.getClientId() @@ -51,13 +51,13 @@ pushSubscriptions.prototype.list = function (done) { headers: { Authorization: null }, baseUrl: this.baseUrl, url: 'push_subscriptions?' + qs - }, done) + }) } -pushSubscriptions.prototype.delete = function (args, done) { +pushSubscriptions.prototype.delete = function (args) { // require subscription id if (typeof args.id === 'undefined') { - return done({ msg: 'args must include a push subscription id' }) + throw new Error('args must include a push subscription id') } var qs = this.client.getQS(['client_secret', 'client_id'], { @@ -70,7 +70,7 @@ pushSubscriptions.prototype.delete = function (args, done) { baseUrl: this.baseUrl, url: 'push_subscriptions/' + args.id + '?' + qs, method: 'DELETE' - }, done) + }) } module.exports = pushSubscriptions diff --git a/lib/routes.js b/lib/routes.js index 6500a96..aec262d 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -5,22 +5,22 @@ var routes = function (client) { var _qsAllowedProps = [] //= ==== routes endpoint ===== -routes.prototype.get = function (args, done) { +routes.prototype.get = function (args) { var endpoint = 'routes/' var qs = this.client.getQS(_qsAllowedProps, args) _requireRouteId(args) endpoint += args.id + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -routes.prototype.getFile = function (args, done) { +routes.prototype.getFile = function (args) { var endpoint = 'routes/' _requireRouteId(args) - this._getFileHelper(endpoint, args, done) + return this._getFileHelper(endpoint, args) } //= ==== routes endpoint ===== @@ -31,11 +31,11 @@ var _requireRouteId = function (args) { } } -routes.prototype._getFileHelper = function (endpoint, args, done) { +routes.prototype._getFileHelper = function (endpoint, args) { var qs = this.client.getQS(_qsAllowedProps, args) - endpoint += args.id + `/export_${args.file_type}` + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/runningRaces.js b/lib/runningRaces.js index 1486e9a..9930031 100644 --- a/lib/runningRaces.js +++ b/lib/runningRaces.js @@ -6,23 +6,23 @@ var _qsAllowedProps = [ 'year' ] -runningRaces.prototype.get = function (args, done) { +runningRaces.prototype.get = function (args) { var endpoint = 'running_races/' // require running race id if (typeof args.id === 'undefined') { - throw new Error('args must include an race id') + throw new Error('args must include a race id') } endpoint += args.id - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -runningRaces.prototype.listRaces = function (args, done) { +runningRaces.prototype.listRaces = function (args) { var qs = this.client.getQS(_qsAllowedProps, args) var endpoint = 'running_races?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } module.exports = runningRaces diff --git a/lib/segmentEfforts.js b/lib/segmentEfforts.js index 0b6f740..ee3c10c 100644 --- a/lib/segmentEfforts.js +++ b/lib/segmentEfforts.js @@ -3,7 +3,7 @@ var segmentEfforts = function (client) { } //= ==== segment_efforts endpoint ===== -segmentEfforts.prototype.get = function (args, done) { +segmentEfforts.prototype.get = function (args) { var endpoint = 'segment_efforts/' // require segment id @@ -12,7 +12,7 @@ segmentEfforts.prototype.get = function (args, done) { } endpoint += args.id - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== segment_efforts endpoint ===== diff --git a/lib/segments.js b/lib/segments.js index 3832773..bd12cef 100644 --- a/lib/segments.js +++ b/lib/segments.js @@ -5,7 +5,6 @@ var segments = function (client) { // Validation could be tightened up here by only allowing the properties to validate // for the single endpoint they are valid for. var _qsAllowedProps = [ - // pagination 'page', 'per_page', @@ -35,69 +34,64 @@ var _updateAllowedProps = [ ] //= ==== segments endpoint ===== -segments.prototype.get = function (args, done) { +segments.prototype.get = function (args) { var endpoint = 'segments/' this.client.getPaginationQS(args) // require segment id if (typeof args.id === 'undefined') { - const err = { msg: 'args must include an segment id' } - return done(err) + throw new Error('args must include an segment id') } endpoint += args.id - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -segments.prototype.listStarred = function (args, done) { +segments.prototype.listStarred = function (args) { var qs = this.client.getQS(_qsAllowedProps, args) var endpoint = 'segments/starred?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } -segments.prototype.starSegment = function (args, done) { +segments.prototype.starSegment = function (args) { var endpoint = 'segments/' var form = this.client.getRequestBodyObj(_updateAllowedProps, args) - var err = null if (typeof args.id === 'undefined') { - err = { msg: 'args must include an segment id' } - return done(err) + throw new Error('args must include an segment id') } endpoint += args.id + '/starred' args.form = form - return this.client.putEndpoint(endpoint, args, done) + return this.client.putEndpoint(endpoint, args) } -segments.prototype.listEfforts = function (args, done) { - return this._listHelper('all_efforts', args, done) +segments.prototype.listEfforts = function (args) { + return this._listHelper('all_efforts', args) } -segments.prototype.explore = function (args, done) { +segments.prototype.explore = function (args) { var qs = this.client.getQS(_qsAllowedProps, args) var endpoint = 'segments/explore?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== segments endpoint ===== //= ==== helpers ===== -segments.prototype._listHelper = function (listType, args, done) { +segments.prototype._listHelper = function (listType, args) { var endpoint = 'segments/' - var err = null var qs = this.client.getQS(_qsAllowedProps, args) // require segment id if (typeof args.id === 'undefined') { - err = { msg: 'args must include a segment id' } - return done(err) + throw new Error('args must include a segment id') } endpoint += args.id + '/' + listType + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/streams.js b/lib/streams.js index 2196b65..b9338fd 100644 --- a/lib/streams.js +++ b/lib/streams.js @@ -8,29 +8,29 @@ var _qsAllowedProps = [ ] //= ==== streams endpoint ===== -streams.prototype.activity = function (args, done) { +streams.prototype.activity = function (args) { var endpoint = 'activities' - return this._typeHelper(endpoint, args, done) + return this._typeHelper(endpoint, args) } -streams.prototype.effort = function (args, done) { +streams.prototype.effort = function (args) { var endpoint = 'segment_efforts' - return this._typeHelper(endpoint, args, done) + return this._typeHelper(endpoint, args) } -streams.prototype.segment = function (args, done) { +streams.prototype.segment = function (args) { var endpoint = 'segments' - return this._typeHelper(endpoint, args, done) + return this._typeHelper(endpoint, args) } -streams.prototype.route = function (args, done) { +streams.prototype.route = function (args) { var endpoint = 'routes' - return this._typeHelper(endpoint, args, done) + return this._typeHelper(endpoint, args) } //= ==== streams endpoint ===== //= ==== helpers ===== -streams.prototype._typeHelper = function (endpoint, args, done) { +streams.prototype._typeHelper = function (endpoint, args) { var qs = this.client.getQS(_qsAllowedProps, args) // require id @@ -43,7 +43,7 @@ streams.prototype._typeHelper = function (endpoint, args, done) { } endpoint += '/' + args.id + '/streams/' + args.types + '?' + qs - return this.client.getEndpoint(endpoint, args, done) + return this.client.getEndpoint(endpoint, args) } //= ==== helpers ===== diff --git a/lib/uploads.js b/lib/uploads.js index cf09f30..2c60806 100644 --- a/lib/uploads.js +++ b/lib/uploads.js @@ -11,12 +11,11 @@ var _allowedFormProps = [ 'data_type' ] -uploads.prototype.post = function (args, done) { - var self = this - +uploads.prototype.post = async function (args) { // various requirements if ( - typeof args.file === 'undefined' || typeof args.data_type === 'undefined' + typeof args.file === 'undefined' || + typeof args.data_type === 'undefined' ) { throw new Error('args must include both file and data_type') } @@ -24,41 +23,49 @@ uploads.prototype.post = function (args, done) { // setup formData for request args.formData = {} for (var i = 0; i < _allowedFormProps.length; i++) { - if (args[_allowedFormProps[i]]) { args.formData[_allowedFormProps[i]] = args[_allowedFormProps[i]] } + if (args[_allowedFormProps[i]]) { + args.formData[_allowedFormProps[i]] = args[_allowedFormProps[i]] + } } - return this.client.postUpload(args, function (err, payload) { - // finish off this branch of the call and let the - // status checking bit happen after - done(err, payload) + // Post the upload using async/await + const payload = await this.client.postUpload(args) - if (!err && args.statusCallback) { - var checkArgs = { - id: payload.id, - access_token: args.access_token - } - return self._check(checkArgs, args.statusCallback) + // If the user provided a statusCallback, start checking periodically + if (!payload.err && args.statusCallback) { + var checkArgs = { + id: payload.id, + access_token: args.access_token } - }) + // Kick off the status checks in the background + this._check(checkArgs, args.statusCallback) + } + return payload } -uploads.prototype._check = function (args, cb) { - var endpoint = 'uploads' - var self = this +uploads.prototype._check = async function (args, statusCallback) { + var endpoint = 'uploads/' + args.id - endpoint += '/' + args.id - return this.client.getEndpoint(endpoint, args, function (err, payload) { - if (!err) { - cb(err, payload) - if (!self._uploadIsDone(payload)) { - setTimeout(function () { - self._check(args, cb) - }, 1000) - } - } else { - cb(err) + try { + // Await the getEndpoint call + const payload = await this.client.getEndpoint(endpoint, args) + // Invoke the user's statusCallback with the latest status + statusCallback(null, payload) + + // If not done, schedule another check + if (!this._uploadIsDone(payload)) { + await new Promise((resolve) => { + setTimeout(resolve, 1000) + }) + // Recursively call _check + return this._check(args, statusCallback) } - }) + // If it's done, just return the final payload + return payload + } catch (err) { + statusCallback(err) + throw err + } } uploads.prototype._uploadIsDone = function (args) { @@ -68,7 +75,6 @@ uploads.prototype._uploadIsDone = function (args) { case 'Your activity is still being processed.': isDone = false break - default: isDone = true } diff --git a/package.json b/package.json index 47cade3..79b5a56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "strava-v3", - "version": "2.2.1", + "version": "3.0.0", "description": "Simple wrapper for Strava v3 API", "main": "index.js", "types": "index.d.ts", @@ -33,14 +33,14 @@ "devDependencies": { "env-restorer": "^1.0.0", "es6-promise": "^3.2.1", - "eslint": "^8.3.0", + "eslint": "^9.17.0", "eslint-config-standard": "^12.0.0", "eslint-plugin-import": "^2.17.3", "eslint-plugin-node": "^9.1.0", - "eslint-plugin-promise": "^4.1.1", + "eslint-plugin-promise": "^7.2.1", "eslint-plugin-standard": "^4.0.0", "inquirer": "^7.0.0", - "mocha": "^9.2.0", + "mocha": "^9.2.2", "mock-fs": "^4.10.1", "nock": "^11.3.4", "should": "^13.2.3", @@ -56,13 +56,6 @@ "ui": "bdd", "reporter": "spec" }, - "eslintConfig": { - "extends": "standard", - "env": { - "mocha": true, - "node": true - } - }, "engines": { "node": ">=8.0.0" } diff --git a/test/_helper.js b/test/_helper.js index df528fb..44e46ae 100644 --- a/test/_helper.js +++ b/test/_helper.js @@ -3,89 +3,76 @@ var strava = require('../') var testsHelper = {} -testsHelper.getSampleAthlete = function (done) { - strava.athlete.get({}, done) +// Retrieves the current athlete +testsHelper.getSampleAthlete = async function () { + return await strava.athlete.get({}) } -testsHelper.getSampleActivity = function (done) { - strava.athlete.listActivities({ include_all_efforts: true }, function (err, payload) { - if (err) { return done(err) } +testsHelper.getSampleActivity = async function () { + const payload = await strava.athlete.listActivities({ include_all_efforts: true }) - if (!payload.length) { return done(new Error('Must have at least one activity posted to Strava to test with.')) } - - // If we find an activity with an achievement, there's a better chance - // that it contains a segment. - // This is necessary for getSampleSegment, which uses this function. - function hasAchievement (activity) { return activity.achievement_count > 1 } + if (!payload.length) { + throw new Error('Must have at least one activity posted to Strava to test with.') + } - var withSegment = payload.filter(hasAchievement)[0] + // Look for an activity with an achievement to ensure it contains a segment + function hasAchievement (activity) { + return activity.achievement_count > 1 + } - if (!withSegment) { return done(new Error('Must have at least one activity posted to Strava with a segment effort to test with.')) } + const withSegment = payload.find(hasAchievement) + if (!withSegment) { + throw new Error('Must have at least one activity posted to Strava with a segment effort to test with.') + } - return strava.activities.get({ id: withSegment.id, include_all_efforts: true }, done) - }) + return await strava.activities.get({ id: withSegment.id, include_all_efforts: true }) } -testsHelper.getSampleClub = function (done) { - strava.athlete.listClubs({}, function (err, payload) { - if (err) { return done(err) } - - if (!payload.length) { return done(new Error('Must have joined at least one club on Strava to test with.')) } - - done(err, payload[0]) - }) +testsHelper.getSampleClub = async function () { + const payload = await strava.athlete.listClubs({}) + if (!payload.length) { + throw new Error('Must have joined at least one club on Strava to test with.') + } + return payload[0] } -testsHelper.getSampleRoute = function (done) { - strava.athlete.listRoutes({}, function (err, payload) { - if (err) { return done(err) } - - if (!payload.length) { return done(new Error('Must have created at least one route on Strava to test with.')) } - - done(err, payload[0]) - }) +testsHelper.getSampleRoute = async function () { + const payload = await strava.athlete.listRoutes({}) + if (!payload.length) { + throw new Error('Must have created at least one route on Strava to test with.') + } + return payload[0] } -testsHelper.getSampleGear = function (done) { - this.getSampleAthlete(function (err, payload) { - if (err) { return done(err) } - - var gear +testsHelper.getSampleGear = async function () { + const athlete = await this.getSampleAthlete() - if (payload.bikes && payload.bikes.length) { - gear = payload.bikes[0] - } else if (payload.shoes) { - gear = payload.shoes[0] - } else { - return done(new Error('Must post at least one bike or shoes to Strava to test with')) - } - - done(err, gear) - }) + if (athlete.bikes && athlete.bikes.length) { + return athlete.bikes[0] + } else if (athlete.shoes && athlete.shoes.length) { + return athlete.shoes[0] + } else { + throw new Error('Must post at least one bike or shoes to Strava to test with.') + } } -testsHelper.getSampleSegmentEffort = function (done) { - this.getSampleActivity(function (err, payload) { - if (err) { return done(err) } - - if (!payload.segment_efforts.length) { return done(new Error('Must have at least one segment effort posted to Strava to test with.')) } - - done(err, payload.segment_efforts[0]) - }) +testsHelper.getSampleSegmentEffort = async function () { + const activity = await this.getSampleActivity() + if (!activity.segment_efforts.length) { + throw new Error('Must have at least one segment effort posted to Strava to test with.') + } + return activity.segment_efforts[0] } -testsHelper.getSampleSegment = function (done) { - this.getSampleSegmentEffort(function (err, payload) { - if (err) { return done(err) } - - done(err, payload.segment) - }) +testsHelper.getSampleSegment = async function () { + const effort = await this.getSampleSegmentEffort() + return effort.segment } -testsHelper.getSampleRunningRace = function (done) { - strava.runningRaces.listRaces({ 'year': 2015 }, function (err, payload) { - done(err, payload[0]) - }) +testsHelper.getSampleRunningRace = async function () { + const payload = await strava.runningRaces.listRaces({ year: 2015 }) + // Races can be an empty array, but we just return the first item + return payload[0] } testsHelper.getAccessToken = function () { @@ -93,6 +80,7 @@ testsHelper.getAccessToken = function () { var config = fs.readFileSync('data/strava_config', { encoding: 'utf-8' }) return JSON.parse(config).access_token } catch (e) { + console.error("Errror getting test access token:", e) return process.env.STRAVA_ACCESS_TOKEN } } diff --git a/test/activities.js b/test/activities.js index 8620da9..a68823b 100644 --- a/test/activities.js +++ b/test/activities.js @@ -7,186 +7,184 @@ var authenticator = require('../lib/authenticator') var testActivity = {} describe('activities_test', function () { - before(function (done) { - testHelper.getSampleActivity(function (err, sampleActivity) { - if (err) { return done(err) } - + // Convert the `before` hook to an async function + before(async function (done) { + try { + await testHelper.getSampleActivity() + // We don't do much here; just ensuring we can fetch a sample activity done() - }) + } catch (err) { + done(err) + } }) describe('#create()', function () { - it('should create an activity', function (done) { - var args = { - name: 'Most Epic Ride EVER!!!', - elapsed_time: 18373, - distance: 1557840, - start_date_local: '2013-10-23T10:02:13Z', - type: 'Ride' - } - - strava.activities.create(args, function (err, payload) { - if (!err) { - testActivity = payload; - (payload.resource_state).should.be.exactly(3) - } else { - console.log(err) + it('should create an activity', async function (done) { + try { + var args = { + name: 'Most Epic Ride EVER!!!', + elapsed_time: 18373, + distance: 1557840, + start_date_local: '2013-10-23T10:02:13Z', + type: 'Ride' } + var payload = await strava.activities.create(args) + testActivity = payload + payload.resource_state.should.be.exactly(3) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#get()', function () { - it('should return information about the corresponding activity', function (done) { - strava.activities.get({ id: testActivity.id }, function (err, payload) { - if (!err) { - (payload.resource_state).should.be.exactly(3) - } else { - console.log(err) - } - + it('should return information about the corresponding activity', async function (done) { + try { + var payload = await strava.activities.get({ id: testActivity.id }) + payload.resource_state.should.be.exactly(3) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) - it('should return information about the corresponding activity (Promise API)', function () { - return strava.activities.get({ id: testActivity.id }) - .then(function (payload) { - (payload.resource_state).should.be.exactly(3) - }) + it('should return information about the corresponding activity (Promise API)', async function (done) { + try { + const payload = await strava.activities.get({ id: testActivity.id }) + payload.resource_state.should.be.exactly(3) + } catch (err) { + console.log(err) + done(err) + } }) - it('should work with a specified access token', function (done) { + it('should work with a specified access token', async function (done) { var token = testHelper.getAccessToken() - var tokenStub = sinon.stub(authenticator, 'getToken', function () { + var tokenStub = sinon.stub(authenticator, 'getToken').callsFake(() => { return undefined }) - - strava.activities.get({ - id: testActivity.id, - access_token: token - }, function (err, payload) { - should(err).be.null(); - (payload.resource_state).should.be.exactly(3) + try { + var payload = await strava.activities.get({ id: testActivity.id, access_token: token }) + should(payload).be.ok() + payload.resource_state.should.be.exactly(3) tokenStub.restore() done() - }) + } catch (err) { + tokenStub.restore() + console.log(err) + done(err) + } }) }) describe('#update()', function () { - it('should update an activity', function (done) { + it('should update an activity', async function (done) { var name = 'Run like the wind!!' var args = { id: testActivity.id, name: name } - strava.activities.update(args, function (err, payload) { - if (!err) { - (payload.resource_state).should.be.exactly(3); - (payload.name).should.be.exactly(name) - } else { - console.log(err) - } - + try { + var payload = await strava.activities.update(args) + payload.resource_state.should.be.exactly(3) + payload.name.should.be.exactly(name) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#updateSportType()', function () { - it('should update the sport type of an activity', function (done) { + it('should update the sport type of an activity', async function (done) { var sportType = 'MountainBikeRide' var args = { id: testActivity.id, sportType: sportType } - strava.activities.update(args, function (err, payload) { - if (!err) { - (payload.resource_state).should.be.exactly(3); - (payload.sportType).should.be.exactly(sportType) - } else { - console.log(err) - } - + try { + var payload = await strava.activities.update(args) + payload.resource_state.should.be.exactly(3) + payload.sportType.should.be.exactly(sportType) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) - // TODO can't test b/c this requires premium account + // TODO can't test because this requires a premium account describe('#listZones()', function () { - xit('should list heart rate and power zones relating to activity', function (done) { - strava.activities.listZones({ id: testActivity.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + xit('should list heart rate and power zones relating to activity', async function (done) { + try { + var payload = await strava.activities.listZones({ id: testActivity.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listLaps()', function () { - it('should list laps relating to activity', function (done) { - strava.activities.listLaps({ id: testActivity.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + it('should list laps relating to activity', async function (done) { + try { + var payload = await strava.activities.listLaps({ id: testActivity.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listComments()', function () { - it('should list comments relating to activity', function (done) { - strava.activities.listComments({ id: testActivity.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + it('should list comments relating to activity', async function (done) { + try { + var payload = await strava.activities.listComments({ id: testActivity.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listKudos()', function () { - it('should list kudos relating to activity', function (done) { - strava.activities.listKudos({ id: testActivity.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + it('should list kudos relating to activity', async function (done) { + try { + var payload = await strava.activities.listKudos({ id: testActivity.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) - // TODO check w/ strava dudes, this is returning undefined instead of an empty array (no photos) + // TODO check with Strava, this is returning undefined instead of an empty array (no photos) describe('#listPhotos()', function () { - xit('should list photos relating to activity', function (done) { - strava.activities.listPhotos({ id: testActivity.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + xit('should list photos relating to activity', async function (done) { + try { + var payload = await strava.activities.listPhotos({ id: testActivity.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) }) diff --git a/test/athlete.js b/test/athlete.js index bbf9688..0072f7d 100644 --- a/test/athlete.js +++ b/test/athlete.js @@ -4,109 +4,104 @@ const testHelper = require('./_helper') describe('athlete_test', function () { describe('#get()', function () { - it('should return detailed athlete information about athlete associated to access_token (level 3)', function (done) { - strava.athlete.get({}, function (err, payload) { - if (!err) { - (payload.resource_state).should.be.exactly(3) - } else { - console.log(err) - } - + it('should return detailed athlete information about athlete associated to access_token (level 3)', async function (done) { + try { + const payload = await strava.athlete.get({}) + payload.resource_state.should.be.exactly(3) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listActivities()', function () { - it('should return information about activities associated to athlete with access_token', function (done) { - var nowSeconds = Math.floor(Date.now() / 1000) - strava.athlete.listActivities({ - after: nowSeconds + 3600, - before: nowSeconds + 3600 - }, function (err, payload) { - if (!err) { - // console.log(payload); - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + it('should return information about activities associated to athlete with access_token', async function (done) { + try { + const nowSeconds = Math.floor(Date.now() / 1000) + const payload = await strava.athlete.listActivities({ + after: nowSeconds + 3600, + before: nowSeconds + 3600 + }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listClubs()', function () { - it('should return information about clubs associated to athlete with access_token', function (done) { - strava.athlete.listClubs({}, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + it('should return information about clubs associated to athlete with access_token', async function (done) { + try { + const payload = await strava.athlete.listClubs({}) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listRoutes()', function () { - it('should return information about routes associated to athlete with access_token', function (done) { - strava.athlete.listRoutes({}, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } - + it('should return information about routes associated to athlete with access_token', async function (done) { + try { + const payload = await strava.athlete.listRoutes({}) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listZones()', function () { - it('should return information about heart-rate zones associated to athlete with access_token', function (done) { - strava.athlete.listZones({}, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Object) - } else { - console.log(err) - } - + it('should return information about heart-rate zones associated to athlete with access_token', async function (done) { + try { + const payload = await strava.athlete.listZones({}) + payload.should.be.instanceof(Object) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#update()', function () { - // grab the athlete so we can revert changes - var _athletePreEdit - before(function (done) { - testHelper.getSampleAthlete(function (err, payload) { - should(err).be.null() - _athletePreEdit = payload + // Grab the athlete so we can revert changes + let _athletePreEdit + + before(async function (done) { + try { + _athletePreEdit = await testHelper.getSampleAthlete() done() - }) + } catch (err) { + done(err) + } }) - it('should update the weight of the current athlete and revert to original', function (done) { - var weight = 149 + it('should update the weight of the current athlete and revert to original', async function (done) { + try { + const weight = 149 - strava.athlete.update({ weight }, function (err, payload) { - if (!err) { - should(payload.weight).equal(weight) + // Update athlete + const payload = await strava.athlete.update({ weight }) + should(payload.weight).equal(weight) - // great! we've proven our point, let's reset the athlete data - strava.athlete.update({ city: _athletePreEdit.city }, function (err, payload) { - should(err).be.null() - should(payload.city).equal(_athletePreEdit.city) - done() - }) - } else { - console.log(err) - done() - } - }) + // revert the athlete data + const reverted = await strava.athlete.update({ city: _athletePreEdit.city }) + should(reverted.city).equal(_athletePreEdit.city) + + done() + } catch (err) { + console.log(err) + done(err) + } }) }) }) diff --git a/test/athletes.js b/test/athletes.js index 1f20e7d..4b087cf 100644 --- a/test/athletes.js +++ b/test/athletes.js @@ -5,41 +5,41 @@ var testHelper = require('./_helper') var _sampleAthlete describe('athletes', function () { - // get the athlete so we have access to an id for testing - before(function (done) { - testHelper.getSampleAthlete(function (err, payload) { - should(err).be.null() + // Get the athlete so we have access to an id for testing + before(async function (done) { + try { + const payload = await testHelper.getSampleAthlete() + should(payload).not.be.null() _sampleAthlete = payload done() - }) + } catch (err) { + done(err) + } }) describe('#get()', function () { - it('should return basic athlete information (level 2)', function (done) { - strava.athletes.get({ id: _sampleAthlete.id }, function (err, payload) { - if (!err) { - // console.log(payload); - (payload.resource_state).should.be.within(2, 3) - } else { - console.log(err) - } - + it('should return basic athlete information (level 2)', async function (done) { + try { + const payload = await strava.athletes.get({ id: _sampleAthlete.id }) + payload.resource_state.should.be.within(2, 3) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) }) describe('#stats()', function () { - it('should return athlete stats information', function (done) { - strava.athletes.stats({ id: _sampleAthlete.id }, function (err, payload) { - if (!err) { - payload.should.have.property('biggest_ride_distance') - } else { - console.log(err) - } - + it('should return athlete stats information', async function (done) { + try { + const payload = await strava.athletes.stats({ id: _sampleAthlete.id }) + payload.should.have.property('biggest_ride_distance') done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) diff --git a/test/authenticator.js b/test/authenticator.js index eb2c4b0..f49151b 100644 --- a/test/authenticator.js +++ b/test/authenticator.js @@ -12,7 +12,7 @@ var restoreAll = function () { describe('authenticator_test', function () { describe('#getToken()', function () { - it('should read the access token from the config file', function () { + it('should read the access token from the config file', async function () { mockFS({ 'data/strava_config': JSON.stringify({ 'access_token': 'abcdefghi', @@ -22,26 +22,28 @@ describe('authenticator_test', function () { }) }) delete process.env.STRAVA_ACCESS_TOKEN - authenticator.purge(); + authenticator.purge() - (authenticator.getToken()).should.be.exactly('abcdefghi') + const token = await authenticator.getToken() + token.should.be.exactly('abcdefghi') }) - it('should read the access token from the env vars', function () { + it('should read the access token from the env vars', async function () { mockFS({ 'data': {} }) process.env.STRAVA_ACCESS_TOKEN = 'abcdefghi' - authenticator.purge(); + authenticator.purge() - (authenticator.getToken()).should.be.exactly('abcdefghi') + const token = await authenticator.getToken() + token.should.be.exactly('abcdefghi') }) afterEach(restoreAll) }) describe('#getClientId()', function () { - it('should read the client id from the config file', function () { + it('should read the client id from the config file', async function () { mockFS({ 'data/strava_config': JSON.stringify({ 'access_token': 'abcdefghi', @@ -51,26 +53,28 @@ describe('authenticator_test', function () { }) }) delete process.env.STRAVA_CLIENT_ID - authenticator.purge(); + authenticator.purge() - (authenticator.getClientId()).should.be.exactly('jklmnopqr') + const clientId = await authenticator.getClientId() + clientId.should.be.exactly('jklmnopqr') }) - it('should read the client id from the env vars', function () { + it('should read the client id from the env vars', async function () { mockFS({ 'data': {} }) process.env.STRAVA_CLIENT_ID = 'abcdefghi' - authenticator.purge(); + authenticator.purge() - (authenticator.getClientId()).should.be.exactly('abcdefghi') + const clientId = await authenticator.getClientId() + clientId.should.be.exactly('abcdefghi') }) afterEach(restoreAll) }) describe('#getClientSecret()', function () { - it('should read the client secret from the config file', function () { + it('should read the client secret from the config file', async function () { mockFS({ 'data/strava_config': JSON.stringify({ 'access_token': 'abcdefghi', @@ -80,25 +84,27 @@ describe('authenticator_test', function () { }) }) delete process.env.STRAVA_CLIENT_SECRET - authenticator.purge(); + authenticator.purge() - (authenticator.getClientSecret()).should.be.exactly('stuvwxyz') + const clientSecret = await authenticator.getClientSecret() + clientSecret.should.be.exactly('stuvwxyz') }) - it('should read the client secret from the env vars', function () { + it('should read the client secret from the env vars', async function () { mockFS({ 'data': {} }) process.env.STRAVA_CLIENT_SECRET = 'abcdefghi' - authenticator.purge(); + authenticator.purge() - (authenticator.getClientSecret()).should.be.exactly('abcdefghi') + const clientSecret = await authenticator.getClientSecret() + clientSecret.should.be.exactly('abcdefghi') }) afterEach(restoreAll) }) describe('#getRedirectUri()', function () { - it('should read the redirect URI from the config file', function () { + it('should read the redirect URI from the config file', async function () { mockFS({ 'data/strava_config': JSON.stringify({ 'access_token': 'abcdefghi', @@ -108,19 +114,21 @@ describe('authenticator_test', function () { }) }) delete process.env.STRAVA_REDIRECT_URI - authenticator.purge(); + authenticator.purge() - (authenticator.getRedirectUri()).should.be.exactly('https://sample.com') + const redirectUri = await authenticator.getRedirectUri() + redirectUri.should.be.exactly('https://sample.com') }) - it('should read the redirect URI from the env vars', function () { + it('should read the redirect URI from the env vars', async function () { mockFS({ 'data': {} }) process.env.STRAVA_REDIRECT_URI = 'https://sample.com' - authenticator.purge(); + authenticator.purge() - (authenticator.getRedirectUri()).should.be.exactly('https://sample.com') + const redirectUri = await authenticator.getRedirectUri() + redirectUri.should.be.exactly('https://sample.com') }) afterEach(restoreAll) diff --git a/test/client.js b/test/client.js index e669f2a..7d7f5a5 100644 --- a/test/client.js +++ b/test/client.js @@ -2,45 +2,44 @@ require('should') const { StatusCodeError } = require('../axiosUtility') const strava = require('../') -const file = require('fs').readFileSync('data/strava_config', 'utf8') +const fs = require('fs') + +// Synchronously read and parse the configuration file +const file = fs.readFileSync('data/strava_config', 'utf8') const config = JSON.parse(file) const token = config.access_token -// Test the "client" API that is based on providing an explicit per-instance access_token -// Rather than the original global-singleton configuration design. - +// Instantiate the client with the access token const client = new strava.client(token) describe('client_test', function () { // All data fetching methods should work on the client (except Oauth). // Try client.athlete.get() as a sample describe('#athlete.get()', function () { - it('Should reject promise with StatusCodeError for non-2xx response', function (done) { - const badClient = new strava.client('BOOM') - badClient.athlete.get({}) - .catch(StatusCodeError, function (e) { - done() - }) - }) - - it('Callback interface should return StatusCodeError for non-2xx response', function (done) { + it('Should reject promise with StatusCodeError for non-2xx response', async function (done) { const badClient = new strava.client('BOOM') - badClient.athlete.get({}, function (err, payload) { - err.should.be.an.instanceOf(StatusCodeError) + try { + await badClient.athlete.get({}) + // If we make it here, the call didn’t throw, so test fails + done(new Error('Expected get() to throw StatusCodeError')) + } catch (e) { + // Assert that the error is an instance of StatusCodeError + e.should.be.an.instanceOf(StatusCodeError) done() - }) + } }) - it('should return detailed athlete information about athlete associated to access_token (level 3)', function (done) { - client.athlete.get({}, function (err, payload) { - if (!err) { - (payload.resource_state).should.be.exactly(3) - } else { - console.log(err) - } - + it('should return detailed athlete information about athlete associated to access_token (level 3)', async function (done) { + try { + const payload = await client.athlete.get({}) + // Assert that the resource_state is exactly 3 + payload.resource_state.should.be.exactly(3) done() - }) + } catch (err) { + // Log the error and fail the test + console.error(err) + done(err) + } }) }) }) diff --git a/test/clubs.js b/test/clubs.js index 6dd4910..785b223 100644 --- a/test/clubs.js +++ b/test/clubs.js @@ -5,51 +5,52 @@ var testHelper = require('./_helper') var _sampleClub describe('clubs_test', function () { - before(function (done) { - testHelper.getSampleClub(function (err, payload) { - if (err) { return done(err) } - + before(async function (done) { + try { + const payload = await testHelper.getSampleClub() _sampleClub = payload done() - }) + } catch (err) { + done(err) + } }) describe('#get()', function () { - it('should return club detailed information', function (done) { - strava.clubs.get({ id: _sampleClub.id }, function (err, payload) { - if (!err) { - (payload.resource_state).should.be.exactly(3) - } else { - console.log(err) - } + it('should return club detailed information', async function (done) { + try { + const payload = await strava.clubs.get({ id: _sampleClub.id }) + payload.resource_state.should.be.exactly(3) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listMembers()', function () { - it('should return a summary list of athletes in club', function (done) { - strava.clubs.listMembers({ id: _sampleClub.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } + it('should return a summary list of athletes in club', async function (done) { + try { + const payload = await strava.clubs.listMembers({ id: _sampleClub.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) describe('#listActivities()', function () { - it('should return a list of club activities', function (done) { - strava.clubs.listActivities({ id: _sampleClub.id }, function (err, payload) { - if (!err) { - payload.should.be.instanceof(Array) - } else { - console.log(err) - } + it('should return a list of club activities', async function (done) { + try { + const payload = await strava.clubs.listActivities({ id: _sampleClub.id }) + payload.should.be.instanceof(Array) done() - }) + } catch (err) { + console.log(err) + done(err) + } }) }) }) diff --git a/test/gear.js b/test/gear.js index 1e3ef56..56a5280 100644 --- a/test/gear.js +++ b/test/gear.js @@ -6,25 +6,30 @@ var _sampleGear describe('gear_test', function () { before(function (done) { - testHelper.getSampleGear(function (err, payload) { - if (err) { return done(err) } + testHelper.getSampleGear() + .then(function (payload) { + _sampleGear = payload - _sampleGear = payload + if (!_sampleGear || !_sampleGear.id) { + return done(new Error('At least one piece of gear posted to Strava is required for testing.')) + } - if (!_sampleGear || !_sampleGear.id) { return done(new Error('At least one piece of gear posted to Strava is required for testing.')) } - - done() - }) + done() + }) + .catch(done) }) describe('#get()', function () { it('should return detailed athlete information about gear (level 3)', function (done) { - strava.gear.get({ id: _sampleGear.id }, function (err, payload) { - if (err) { return done(err) } - - (payload.resource_state).should.be.exactly(3) - done() - }) + strava.gear.get({ id: _sampleGear.id }) + .then(function (payload) { + payload.resource_state.should.be.exactly(3) + done() + }) + .catch(function (err) { + console.log(err) + done(err) + }) }) }) }) diff --git a/test/streams.js b/test/streams.js index d8da7ac..722dd2f 100644 --- a/test/streams.js +++ b/test/streams.js @@ -20,8 +20,8 @@ describe('streams_test', function () { _sampleActivity = payload _activity_id = _sampleActivity.id - // _segmentEffort_id = _sampleActivity.segment_efforts[0].id; - // _segment_id = _sampleActivity.segment_efforts[0].segment.id; + _segmentEffort_id = _sampleActivity.segment_efforts[0].id + _segment_id = _sampleActivity.segment_efforts[0].segment.id testHelper.getSampleRoute(function (err, payload) { _route_id = payload && payload.id diff --git a/yarn.lock b/yarn.lock index 6b2a354..0fd1d2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,31 +2,88 @@ # yarn lockfile v1 -"@eslint/eslintrc@^1.0.4": - version "1.0.4" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz" +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + +"@eslint/config-array@^0.19.0": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.1.tgz#734aaea2c40be22bbb1f2a9dac687c57a6a4c984" + dependencies: + "@eslint/object-schema" "^2.1.5" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.9.0": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.9.1.tgz#31763847308ef6b7084a4505573ac9402c51f9d1" + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.0.0" - globals "^13.9.0" - ignore "^4.0.6" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" - minimatch "^3.0.4" + minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@humanwhocodes/config-array@^0.6.0": - version "0.6.0" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz" +"@eslint/js@9.17.0": + version "9.17.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.17.0.tgz#1523e586791f80376a6f8398a3964455ecc651ec" + +"@eslint/object-schema@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.5.tgz#8670a8f6258a2be5b2c620ff314a1d984c23eb2e" + +"@eslint/plugin-kit@^0.2.3": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz#2b78e7bb3755784bb13faa8932a1d994d6537792" dependencies: - "@humanwhocodes/object-schema" "^1.2.0" - debug "^4.1.1" - minimatch "^3.0.4" + levn "^0.4.1" -"@humanwhocodes/object-schema@^1.2.0": - version "1.2.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + +"@humanwhocodes/retry@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" + +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" "@types/json5@^0.0.29": version "0.0.29" @@ -36,15 +93,15 @@ version "1.1.2" resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" -acorn-jsx@^5.3.1: +acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" -acorn@^8.6.0: - version "8.6.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz" +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" dependencies: @@ -53,7 +110,7 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-colors@4.1.1, ansi-colors@^4.1.1: +ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" @@ -225,16 +282,15 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" -cross-spawn@^7.0.2: +cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" -debug@4.3.3, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: +debug@4.3.3, debug@^4.1.0, debug@^4.3.2: version "4.3.3" resolved "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" dependencies: @@ -252,6 +308,12 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + dependencies: + ms "^2.1.3" + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" @@ -280,22 +342,10 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" - dependencies: - esutils "^2.0.2" - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" -enquirer@^2.3.5: - version "2.3.6" - resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" - dependencies: - ansi-colors "^4.1.1" - env-restorer@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/env-restorer/-/env-restorer-1.0.0.tgz" @@ -404,17 +454,19 @@ eslint-plugin-node@^9.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-promise@^4.1.1: - version "4.3.1" - resolved "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz" +eslint-plugin-promise@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz#a0652195700aea40b926dc3c74b38e373377bfb0" + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" eslint-plugin-standard@^4.0.0: version "4.1.0" resolved "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz" -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz" +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -425,78 +477,68 @@ eslint-utils@^1.4.2: dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" - dependencies: - eslint-visitor-keys "^2.0.0" - eslint-visitor-keys@^1.1.0: version "1.3.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" - -eslint-visitor-keys@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz" - -eslint@^8.3.0: - version "8.3.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz" - dependencies: - "@eslint/eslintrc" "^1.0.4" - "@humanwhocodes/config-array" "^0.6.0" - ajv "^6.10.0" +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + +eslint@^9.17.0: + version "9.17.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.17.0.tgz#faa1facb5dd042172fdc520106984b5c2421bb0c" + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.19.0" + "@eslint/core" "^0.9.0" + "@eslint/eslintrc" "^3.2.0" + "@eslint/js" "9.17.0" + "@eslint/plugin-kit" "^0.2.3" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" chalk "^4.0.0" - cross-spawn "^7.0.2" + cross-spawn "^7.0.6" debug "^4.3.2" - doctrine "^3.0.0" - enquirer "^2.3.5" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.1.0" - espree "^9.1.0" - esquery "^1.4.0" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" - globals "^13.6.0" - ignore "^4.0.6" - import-fresh "^3.0.0" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.2.0" - semver "^7.2.1" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" + optionator "^0.9.3" -espree@^9.0.0, espree@^9.1.0: - version "9.1.0" - resolved "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz" +espree@^10.0.1, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" dependencies: - acorn "^8.6.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" dependencies: estraverse "^5.1.0" @@ -540,11 +582,11 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" fill-range@^7.1.1: version "7.1.1" @@ -552,9 +594,9 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -find-up@5.0.0: +find-up@5.0.0, find-up@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" dependencies: locate-path "^6.0.0" path-exists "^4.0.0" @@ -565,20 +607,20 @@ find-up@^2.1.0: dependencies: locate-path "^2.0.0" -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" + flatted "^3.2.9" + keyv "^4.5.4" flat@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" -flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz" +flatted@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" follow-redirects@^1.15.6: version "1.15.9" @@ -614,10 +656,6 @@ function-bind@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" @@ -637,9 +675,9 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -glob-parent@^6.0.1: +glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" dependencies: is-glob "^4.0.3" @@ -660,22 +698,9 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3: - version "7.1.7" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^13.6.0, globals@^13.9.0: - version "13.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz" - dependencies: - type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" growl@1.10.5: version "1.10.5" @@ -715,15 +740,15 @@ iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" - ignore@^5.1.1: version "5.1.9" resolved "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz" -import-fresh@^3.0.0, import-fresh@^3.2.1: +ignore@^5.2.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + +import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" dependencies: @@ -910,6 +935,10 @@ json-bigint@^1.0.0: dependencies: bignumber.js "^9.0.0" +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" @@ -928,6 +957,12 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + dependencies: + json-buffer "3.0.1" + levn@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" @@ -967,12 +1002,6 @@ lolex@1.3.2: version "1.3.2" resolved "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" - dependencies: - yallist "^4.0.0" - mime-db@1.51.0: version "1.51.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" @@ -987,12 +1016,24 @@ mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" -minimatch@3.0.4, minimatch@^3.0.4: +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" dependencies: brace-expansion "^1.1.7" +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + dependencies: + brace-expansion "^1.1.7" + minimist@^1.2.0, minimist@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" @@ -1003,9 +1044,9 @@ mkdirp@^0.5.0: dependencies: minimist "^1.2.5" -mocha@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.0.tgz#2bfba73d46e392901f877ab9a47b7c9c5d0275cc" +mocha@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" dependencies: "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" @@ -1020,9 +1061,9 @@ mocha@^9.2.0: he "1.2.0" js-yaml "4.1.0" log-symbols "4.1.0" - minimatch "3.0.4" + minimatch "4.2.1" ms "2.1.3" - nanoid "3.2.0" + nanoid "3.3.1" serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" @@ -1044,17 +1085,17 @@ ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" -ms@2.1.3: +ms@2.1.3, ms@^2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" mute-stream@0.0.8: version "0.0.8" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" -nanoid@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" natural-compare@^1.4.0: version "1.4.0" @@ -1111,16 +1152,16 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" dependencies: deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" + word-wrap "^1.2.5" os-tmpdir@~1.0.2: version "1.0.2" @@ -1194,10 +1235,6 @@ prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" - propagate@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz" @@ -1226,10 +1263,6 @@ regexpp@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz" -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" @@ -1252,12 +1285,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - dependencies: - glob "^7.1.3" - run-async@^2.4.0: version "2.4.1" resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" @@ -1284,12 +1311,6 @@ semver@^6.1.0: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" -semver@^7.2.1: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - dependencies: - lru-cache "^6.0.0" - serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" @@ -1397,7 +1418,7 @@ strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" @@ -1413,10 +1434,6 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - through@^2.3.6: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" @@ -1452,10 +1469,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" @@ -1486,10 +1499,6 @@ uri-js@^4.2.2: safe-buffer "^5.1.2" which-typed-array "^1.1.2" -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" - which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" @@ -1517,9 +1526,9 @@ which@2.0.2, which@^2.0.1: dependencies: isexe "^2.0.0" -word-wrap@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" workerpool@6.2.0: version "6.2.0" @@ -1541,10 +1550,6 @@ y18n@^5.0.5: version "5.0.8" resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" - yargs-parser@20.2.4, yargs-parser@^20.2.2: version "20.2.4" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz"