Skip to content

Commit a2de421

Browse files
refactor(uploads): remove statusCallback in favor of maxStatusChecks
1 parent c6cd4d2 commit a2de421

File tree

4 files changed

+32
-54
lines changed

4 files changed

+32
-54
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,25 @@ const comments = await strava.activities.listComments({
186186

187187
### Uploading files
188188

189-
To upload a file you'll have to pass in the `data_type` as specified in Strava's API reference as well as a string `file` designating the `<filepath>/<filename>`. If you want to get updates on the status of your upload pass in `statusCallback` along with the rest of your `args` - the wrapper will check on the upload once a second until complete.
189+
To upload a file you'll have to pass in the `data_type` as specified in Strava's API reference as well as a string `file` designating the `<filepath>/<filename>`. By default no status polling is performed—the promise resolves immediately with the initial upload response. To wait until processing is complete, set `maxStatusChecks` (e.g. `300` for ~5 minutes at 1s intervals); the promise will then resolve with the final upload result.
190190

191191
Example usage:
192192

193193
```js
194194
const strava = require('strava-v3');
195+
// Resolve immediately after posting
195196
const payload = await strava.uploads.post({
197+
data_type: 'gpx',
198+
file: 'data/your_file.gpx',
199+
name: 'Epic times'
200+
});
201+
202+
// Or wait until processing is complete (polls once per second, up to maxStatusChecks times)
203+
const result = await strava.uploads.post({
196204
data_type: 'gpx',
197205
file: 'data/your_file.gpx',
198206
name: 'Epic times',
199-
statusCallback: (err,payload) => {
200-
//do something with your payload
201-
}
207+
maxStatusChecks: 300
202208
});
203209
```
204210

index.d.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
export type CallbackError = Error | { msg: string } | string;
2-
31
interface BaseArgs {
42
access_token?: string;
53
responseType?: string;
@@ -50,7 +48,6 @@ export interface UploadRouteArgs {
5048
external_id?: string;
5149
access_token?: string;
5250
maxStatusChecks?: number;
53-
statusCallback?: (error: CallbackError | null, response?: Upload) => void;
5451
}
5552

5653
export interface Upload {

lib/uploads.js

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ const { setTimeout } = require('timers/promises')
1616
* @property {0|1} [commute] - API expects integer; set to 1 to mark as commute.
1717
* @property {string} [external_id]
1818
* @property {string} [access_token]
19-
* @property {(error: import('../index').CallbackError | null, response?: Upload) => void} [statusCallback]
20-
* @property {number} [maxStatusChecks] - Max polling attempts when using statusCallback (default 300 ≈ 5 min at 1s).
19+
* @property {number} [maxStatusChecks] - Default: no status polling; promise resolves immediately with the initial upload response. If set to a positive number, poll until upload is done or this many attempts (e.g. 300 ≈ 5 min at 1s); promise then resolves with the final Upload.
2120
* @property {Record<string, string>} [formData] - Set by post(); do not pass.
2221
*/
2322

@@ -50,7 +49,7 @@ var uploads = function (client) {
5049
}
5150

5251
/**
53-
* Uploads a file to create a new activity; optionally polls status via statusCallback until done.
52+
* Uploads a file to create a new activity. By default returns immediately with the initial response. If maxStatusChecks > 0, polls until upload is done and resolves with the final Upload.
5453
* @param {PostUploadArgs} args
5554
* @returns {Promise<Upload>}
5655
*/
@@ -76,62 +75,49 @@ uploads.prototype.post = async function (args) {
7675

7776
const response = await this.client.postUpload(args)
7877

79-
// if no statusCallback, just return after posting upload
80-
if (typeof args.statusCallback === 'undefined') {
78+
const maxChecks = args.maxStatusChecks != null ? args.maxStatusChecks : 0
79+
if (maxChecks === 0) {
8180
return response
8281
}
8382

84-
// otherwise, kick off the status checking loop
85-
// and return the result of that
86-
// the callback will be called on each status check
8783
/** @type {CheckArgs} */
8884
var checkArgs = {
8985
id: response.id,
9086
access_token: args.access_token || undefined,
91-
maxChecks: args.maxStatusChecks != null ? args.maxStatusChecks : 300
87+
maxChecks: maxChecks
9288
}
93-
return await self._check(checkArgs, args.statusCallback)
89+
return await self._check(checkArgs)
9490
}
9591

9692
/**
97-
* Internal: polls upload status and invokes callback until the upload is done or maxChecks is reached.
93+
* Internal: polls upload status until the upload is done or maxChecks is reached.
9894
* @param {CheckArgs} args
99-
* @param {(error: import('../index').CallbackError | null, response?: Upload) => void} cb
10095
* @returns {Promise<Upload>}
10196
*/
102-
uploads.prototype._check = async function (args, cb) {
97+
uploads.prototype._check = async function (args) {
10398
var endpoint = 'uploads/' + args.id
10499
var self = this
105100
var maxChecks = args.maxChecks != null ? args.maxChecks : 300
106101
var attempts = 0
107102

108-
try {
109-
while (true) {
110-
attempts++
111-
const response = /** @type {Upload} */ (await this.client.getEndpoint(endpoint, args))
103+
while (true) {
104+
attempts++
105+
const response = /** @type {Upload} */ (await this.client.getEndpoint(endpoint, args))
112106

113-
const error = typeof response.error === 'undefined' ? null : response.error
114-
cb(error, response)
115-
116-
if (self._uploadIsDone(response)) {
117-
return response
118-
}
119-
120-
if (attempts >= maxChecks) {
121-
break
122-
}
107+
if (self._uploadIsDone(response)) {
108+
return response
109+
}
123110

124-
await setTimeout(1000)
111+
if (attempts >= maxChecks) {
112+
break
125113
}
126-
} catch (err) {
127-
cb(/** @type {import('../index').CallbackError} */ (err))
128-
throw err
114+
115+
await setTimeout(1000)
129116
}
130117

131118
const timeoutError = new Error(
132119
'Upload status check timed out after ' + maxChecks + ' attempts (still processing)'
133120
)
134-
cb(/** @type {import('../index').CallbackError} */ (timeoutError))
135121
throw timeoutError
136122
}
137123

test/uploads.js

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,28 +68,17 @@ describe('uploads_test', function () {
6868
status: 'Your activity is ready.'
6969
})
7070

71-
let statusCallbackCount = 0
72-
let finalPayload = null
73-
74-
await strava.uploads.post({
71+
const result = await strava.uploads.post({
7572
activity_type: 'run',
7673
sport_type: 'Run',
7774
data_type: 'gpx',
7875
name: 'test activity',
7976
file: gpxFilename,
80-
statusCallback: function (err, payload) {
81-
assert.strictEqual(err, null)
82-
statusCallbackCount++
83-
84-
if (payload.status === 'Your activity is ready.') {
85-
finalPayload = payload
86-
}
87-
}
77+
maxStatusChecks: 2 // we only mock 2 status responses
8878
})
8979

90-
assert.strictEqual(statusCallbackCount, 2)
91-
assert.strictEqual(finalPayload.activity_id, activityId)
92-
assert.strictEqual(finalPayload.status, 'Your activity is ready.')
80+
assert.strictEqual(result.activity_id, activityId)
81+
assert.strictEqual(result.status, 'Your activity is ready.')
9382
} finally {
9483
tmpFile.removeCallback()
9584
}

0 commit comments

Comments
 (0)