@miso.ai/client-sdk-core 1.14.0-beta.1 → 1.14.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/api/ask.js +78 -2
- package/dist/cjs/api/helpers.js +44 -4
- package/dist/cjs/api/history.js +4 -4
- package/dist/cjs/api/iterable.js +23 -8
- package/dist/cjs/version.js +1 -1
- package/package.json +2 -2
- package/src/api/ask.js +72 -3
- package/src/api/helpers.js +30 -1
- package/src/api/history.js +4 -4
- package/src/api/iterable.js +21 -6
- package/src/version.js +1 -1
package/dist/cjs/api/ask.js
CHANGED
|
@@ -42,7 +42,11 @@ class Ask extends _base.default {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* Retrieve multiple question-answer pairs at once
|
|
45
|
+
* Retrieve multiple question-answer pairs at once: an iterable that polls
|
|
46
|
+
* the answers endpoint, like questions(). The id set is mutable between
|
|
47
|
+
* polls: `question_ids` may be a function returning the id array, resolved
|
|
48
|
+
* for every poll, and a fixed initial array settles out record by record
|
|
49
|
+
* (see Answers).
|
|
46
50
|
*/
|
|
47
51
|
async answers(payload, options = {}) {
|
|
48
52
|
if (Array.isArray(payload)) {
|
|
@@ -50,7 +54,9 @@ class Ask extends _base.default {
|
|
|
50
54
|
question_ids: payload
|
|
51
55
|
};
|
|
52
56
|
}
|
|
53
|
-
return this
|
|
57
|
+
return new Answers(this, payload, Object.assign({
|
|
58
|
+
immediate: true
|
|
59
|
+
}, options));
|
|
54
60
|
}
|
|
55
61
|
async relatedQuestions(payload, options = {}) {
|
|
56
62
|
return this._run(NAME.RELATED_QUESTIONS, payload, options);
|
|
@@ -95,6 +101,76 @@ class Answer extends _iterable.IdBasedIterableApiStub {
|
|
|
95
101
|
return this._id;
|
|
96
102
|
}
|
|
97
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The answer contents of a set of questions, polled until settled — the id
|
|
107
|
+
* set is mutable between polls, and the stream ends when it runs dry. The
|
|
108
|
+
* question ids may be given as a function returning the id array, resolved
|
|
109
|
+
* for every poll (settled ids drop out, new ones join, at the provider's
|
|
110
|
+
* discretion); a fixed initial id array is mutable all the same — its ids
|
|
111
|
+
* settle out as their records come back finished (_settle). Each fetch's
|
|
112
|
+
* issue order acts as the response revision, so a late, outdated response
|
|
113
|
+
* is discarded by the polling.
|
|
114
|
+
*/
|
|
115
|
+
class Answers extends _iterable.IterableApiStub {
|
|
116
|
+
constructor(api, payload, options = {}) {
|
|
117
|
+
super(mergeCustomApiIterator(api, options));
|
|
118
|
+
this._api = api;
|
|
119
|
+
this._payload = payload;
|
|
120
|
+
const {
|
|
121
|
+
question_ids
|
|
122
|
+
} = payload;
|
|
123
|
+
this._pending = typeof question_ids === 'function' ? undefined : new Set(question_ids || []);
|
|
124
|
+
}
|
|
125
|
+
async _get(options) {
|
|
126
|
+
// a plain one-shot read of the current ids' answers
|
|
127
|
+
return this._api._run(NAME.ANSWERS, Object.assign({}, this._payload, {
|
|
128
|
+
question_ids: this._questionIds()
|
|
129
|
+
}), options);
|
|
130
|
+
}
|
|
131
|
+
_questionIds() {
|
|
132
|
+
return this._pending ? [...this._pending] : this._payload.question_ids();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// a fixed id set settles by the records themselves: a record that came
|
|
136
|
+
// back with its finished answer needs no further polling
|
|
137
|
+
_settle(response) {
|
|
138
|
+
if (!this._pending || !Array.isArray(response)) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
for (const record of response) {
|
|
142
|
+
if (record && record.answer !== undefined && record.finished !== false) {
|
|
143
|
+
this._pending.delete(record.question_id);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
_fetch() {
|
|
148
|
+
let index = 0;
|
|
149
|
+
return async ({
|
|
150
|
+
signal
|
|
151
|
+
} = {}) => {
|
|
152
|
+
const i = ++index; // taken at issue time: a stale response resolves with a lower revision
|
|
153
|
+
const question_ids = this._questionIds();
|
|
154
|
+
if (!question_ids || !question_ids.length) {
|
|
155
|
+
return [undefined, true, i]; // nothing left to fetch; the stream ends
|
|
156
|
+
}
|
|
157
|
+
// TODO: use single answer endpoint when array length = 1
|
|
158
|
+
const response = await this._api._run(NAME.ANSWERS, Object.assign({}, this._payload, {
|
|
159
|
+
question_ids
|
|
160
|
+
}), {
|
|
161
|
+
signal
|
|
162
|
+
});
|
|
163
|
+
this._settle(response);
|
|
164
|
+
return [response, false, i];
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// any response is progress for the stall timeout: the record-diff test of
|
|
169
|
+
// the base class reads a single answer's shape, not an array of records
|
|
170
|
+
_isUpdated() {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
98
174
|
class SearchResult extends _iterable.IdBasedIterableApiStub {
|
|
99
175
|
constructor(api, response, options = {}) {
|
|
100
176
|
super(api, '_searchGet', response.question_id, mergeCustomApiIterator(api, options));
|
package/dist/cjs/api/helpers.js
CHANGED
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
8
|
var _constants = require("../constants.js");
|
|
9
|
-
const _excluded = ["method", "headers", "timeout"]
|
|
9
|
+
const _excluded = ["method", "headers", "timeout", "retry"],
|
|
10
|
+
_excluded2 = ["method", "headers", "timeout", "body"];
|
|
10
11
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
11
12
|
class ApiHelpers {
|
|
12
13
|
constructor(client, root) {
|
|
@@ -18,18 +19,50 @@ class ApiHelpers {
|
|
|
18
19
|
let {
|
|
19
20
|
method = 'POST',
|
|
20
21
|
headers,
|
|
21
|
-
timeout
|
|
22
|
+
timeout,
|
|
23
|
+
retry
|
|
22
24
|
} = _ref,
|
|
23
25
|
options = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
24
26
|
const {
|
|
25
|
-
apiKey,
|
|
26
27
|
request = {}
|
|
27
28
|
} = this._client.options;
|
|
28
29
|
timeout = timeout || request.timeout;
|
|
30
|
+
// retries on top of the first attempt, for failures that may be
|
|
31
|
+
// transient — network errors, timeouts, and server (5xx) errors;
|
|
32
|
+
// client (4xx) and application errors are deterministic, not retried.
|
|
33
|
+
// Off by default: a retried POST is not safe for non-idempotent calls
|
|
34
|
+
// (e.g. posting a question), so it is opted in per request via the
|
|
35
|
+
// request options, or client-wide via `options.request.retry`
|
|
36
|
+
retry = retry !== undefined ? retry : request.retry || 0;
|
|
29
37
|
|
|
30
38
|
// TODO: organize arguments
|
|
31
39
|
const body = method !== 'GET' && payload != undefined ? JSON.stringify(payload) : undefined;
|
|
40
|
+
for (let attempt = 0;; attempt++) {
|
|
41
|
+
try {
|
|
42
|
+
return await this._fetch(url, Object.assign({
|
|
43
|
+
method,
|
|
44
|
+
headers,
|
|
45
|
+
timeout,
|
|
46
|
+
body
|
|
47
|
+
}, options));
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (attempt >= retry || !isRetryableFetchError(error)) {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
32
55
|
|
|
56
|
+
// one attempt; the timeout signal is created per attempt, so a retried
|
|
57
|
+
// attempt gets a full window of its own
|
|
58
|
+
async _fetch(url, _ref2) {
|
|
59
|
+
let {
|
|
60
|
+
method,
|
|
61
|
+
headers,
|
|
62
|
+
timeout,
|
|
63
|
+
body
|
|
64
|
+
} = _ref2,
|
|
65
|
+
options = _objectWithoutPropertiesLoose(_ref2, _excluded2);
|
|
33
66
|
// TODO: merge signal from options if any
|
|
34
67
|
const signal = timeout ? AbortSignal.timeout(timeout) : undefined;
|
|
35
68
|
const res = await (this._root._customFetch || fetch)(url, (0, _commons.trimObj)(Object.assign({
|
|
@@ -196,4 +229,11 @@ class ApiHelpers {
|
|
|
196
229
|
return headers;
|
|
197
230
|
}
|
|
198
231
|
}
|
|
199
|
-
|
|
232
|
+
|
|
233
|
+
// no status: a network failure, a timeout, or an unparsable body — all
|
|
234
|
+
// transport-level; 5xx: the server's own failure. A 4xx or an
|
|
235
|
+
// application-level error (2xx with `errors`) is deterministic
|
|
236
|
+
exports.default = ApiHelpers;
|
|
237
|
+
function isRetryableFetchError(error) {
|
|
238
|
+
return error.status === undefined || error.status >= 500;
|
|
239
|
+
}
|
package/dist/cjs/api/history.js
CHANGED
|
@@ -14,13 +14,13 @@ class UserHistory extends _base.default {
|
|
|
14
14
|
constructor(api) {
|
|
15
15
|
super(api, GROUP.ASK_USER_HISTORY);
|
|
16
16
|
}
|
|
17
|
-
async getThreads(options) {
|
|
18
|
-
return this._run('threads',
|
|
17
|
+
async getThreads(payload, options) {
|
|
18
|
+
return this._run('threads', payload, Object.assign({}, options, {
|
|
19
19
|
method: 'GET'
|
|
20
20
|
}));
|
|
21
21
|
}
|
|
22
|
-
async getThread(threadId, options) {
|
|
23
|
-
return this._run(`threads/${threadId}`,
|
|
22
|
+
async getThread(threadId, payload, options) {
|
|
23
|
+
return this._run(`threads/${threadId}`, payload, Object.assign({}, options, {
|
|
24
24
|
method: 'GET'
|
|
25
25
|
}));
|
|
26
26
|
}
|
package/dist/cjs/api/iterable.js
CHANGED
|
@@ -22,13 +22,7 @@ class IterableApiStub {
|
|
|
22
22
|
this._ac.abort(reason);
|
|
23
23
|
}
|
|
24
24
|
[Symbol.asyncIterator]() {
|
|
25
|
-
const fetch =
|
|
26
|
-
signal
|
|
27
|
-
} = {}) => {
|
|
28
|
-
// TODO: pass signal
|
|
29
|
-
const response = await this.get();
|
|
30
|
-
return [response, isFinished(response), revisionOf(response)];
|
|
31
|
-
};
|
|
25
|
+
const fetch = this._fetch();
|
|
32
26
|
if (typeof this._options.customIterator === 'function') {
|
|
33
27
|
return this._options.customIterator.call(this, fetch);
|
|
34
28
|
}
|
|
@@ -54,7 +48,7 @@ class IterableApiStub {
|
|
|
54
48
|
const onResponse = (response, finished) => {
|
|
55
49
|
if (finished) {
|
|
56
50
|
stac.clear();
|
|
57
|
-
} else if (
|
|
51
|
+
} else if (this._isUpdated(prevResponse, response)) {
|
|
58
52
|
stac.touch();
|
|
59
53
|
}
|
|
60
54
|
prevResponse = response;
|
|
@@ -65,6 +59,27 @@ class IterableApiStub {
|
|
|
65
59
|
onResponse
|
|
66
60
|
}, options))[Symbol.asyncIterator]();
|
|
67
61
|
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Compose the polling fetch: () => [response, finished, revision].
|
|
65
|
+
* Overridable by a subclass with its own finish or revision semantics
|
|
66
|
+
* (e.g. Answers, whose question ids may run dry).
|
|
67
|
+
*/
|
|
68
|
+
_fetch() {
|
|
69
|
+
return async ({
|
|
70
|
+
signal
|
|
71
|
+
} = {}) => {
|
|
72
|
+
// TODO: pass signal
|
|
73
|
+
const response = await this.get();
|
|
74
|
+
return [response, isFinished(response), revisionOf(response)];
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// whether the new response carries progress, keeping the stall timeout at
|
|
79
|
+
// bay; overridable by a subclass with its own response shape
|
|
80
|
+
_isUpdated(previousResponse, newResponse) {
|
|
81
|
+
return isUpdated(previousResponse, newResponse);
|
|
82
|
+
}
|
|
68
83
|
}
|
|
69
84
|
exports.IterableApiStub = IterableApiStub;
|
|
70
85
|
class IdBasedIterableApiStub extends IterableApiStub {
|
package/dist/cjs/version.js
CHANGED
package/package.json
CHANGED
package/src/api/ask.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { API, defineValues, trimObj } from '@miso.ai/commons';
|
|
2
2
|
import ApiBase from './base.js';
|
|
3
3
|
import UserHistoryV0 from './history.0.js';
|
|
4
|
-
import { IdBasedIterableApiStub } from './iterable.js';
|
|
4
|
+
import { IterableApiStub, IdBasedIterableApiStub } from './iterable.js';
|
|
5
5
|
|
|
6
6
|
const { GROUP, NAME } = API;
|
|
7
7
|
|
|
@@ -34,13 +34,17 @@ export default class Ask extends ApiBase {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Retrieve multiple question-answer pairs at once
|
|
37
|
+
* Retrieve multiple question-answer pairs at once: an iterable that polls
|
|
38
|
+
* the answers endpoint, like questions(). The id set is mutable between
|
|
39
|
+
* polls: `question_ids` may be a function returning the id array, resolved
|
|
40
|
+
* for every poll, and a fixed initial array settles out record by record
|
|
41
|
+
* (see Answers).
|
|
38
42
|
*/
|
|
39
43
|
async answers(payload, options = {}) {
|
|
40
44
|
if (Array.isArray(payload)) {
|
|
41
45
|
payload = { question_ids: payload };
|
|
42
46
|
}
|
|
43
|
-
return this
|
|
47
|
+
return new Answers(this, payload, { immediate: true, ...options });
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
async relatedQuestions(payload, options = {}) {
|
|
@@ -93,6 +97,71 @@ class Answer extends IdBasedIterableApiStub {
|
|
|
93
97
|
|
|
94
98
|
}
|
|
95
99
|
|
|
100
|
+
/**
|
|
101
|
+
* The answer contents of a set of questions, polled until settled — the id
|
|
102
|
+
* set is mutable between polls, and the stream ends when it runs dry. The
|
|
103
|
+
* question ids may be given as a function returning the id array, resolved
|
|
104
|
+
* for every poll (settled ids drop out, new ones join, at the provider's
|
|
105
|
+
* discretion); a fixed initial id array is mutable all the same — its ids
|
|
106
|
+
* settle out as their records come back finished (_settle). Each fetch's
|
|
107
|
+
* issue order acts as the response revision, so a late, outdated response
|
|
108
|
+
* is discarded by the polling.
|
|
109
|
+
*/
|
|
110
|
+
class Answers extends IterableApiStub {
|
|
111
|
+
|
|
112
|
+
constructor(api, payload, options = {}) {
|
|
113
|
+
super(mergeCustomApiIterator(api, options));
|
|
114
|
+
this._api = api;
|
|
115
|
+
this._payload = payload;
|
|
116
|
+
const { question_ids } = payload;
|
|
117
|
+
this._pending = typeof question_ids === 'function' ? undefined : new Set(question_ids || []);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async _get(options) {
|
|
121
|
+
// a plain one-shot read of the current ids' answers
|
|
122
|
+
return this._api._run(NAME.ANSWERS, { ...this._payload, question_ids: this._questionIds() }, options);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_questionIds() {
|
|
126
|
+
return this._pending ? [...this._pending] : this._payload.question_ids();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// a fixed id set settles by the records themselves: a record that came
|
|
130
|
+
// back with its finished answer needs no further polling
|
|
131
|
+
_settle(response) {
|
|
132
|
+
if (!this._pending || !Array.isArray(response)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
for (const record of response) {
|
|
136
|
+
if (record && record.answer !== undefined && record.finished !== false) {
|
|
137
|
+
this._pending.delete(record.question_id);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
_fetch() {
|
|
143
|
+
let index = 0;
|
|
144
|
+
return async ({ signal } = {}) => {
|
|
145
|
+
const i = ++index; // taken at issue time: a stale response resolves with a lower revision
|
|
146
|
+
const question_ids = this._questionIds();
|
|
147
|
+
if (!question_ids || !question_ids.length) {
|
|
148
|
+
return [undefined, true, i]; // nothing left to fetch; the stream ends
|
|
149
|
+
}
|
|
150
|
+
// TODO: use single answer endpoint when array length = 1
|
|
151
|
+
const response = await this._api._run(NAME.ANSWERS, { ...this._payload, question_ids }, { signal });
|
|
152
|
+
this._settle(response);
|
|
153
|
+
return [response, false, i];
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// any response is progress for the stall timeout: the record-diff test of
|
|
158
|
+
// the base class reads a single answer's shape, not an array of records
|
|
159
|
+
_isUpdated() {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
96
165
|
class SearchResult extends IdBasedIterableApiStub {
|
|
97
166
|
|
|
98
167
|
constructor(api, response, options = {}) {
|
package/src/api/helpers.js
CHANGED
|
@@ -13,14 +13,36 @@ export default class ApiHelpers {
|
|
|
13
13
|
method = 'POST',
|
|
14
14
|
headers,
|
|
15
15
|
timeout,
|
|
16
|
+
retry,
|
|
16
17
|
...options
|
|
17
18
|
} = {}) {
|
|
18
|
-
const {
|
|
19
|
+
const { request = {} } = this._client.options;
|
|
19
20
|
timeout = timeout || request.timeout;
|
|
21
|
+
// retries on top of the first attempt, for failures that may be
|
|
22
|
+
// transient — network errors, timeouts, and server (5xx) errors;
|
|
23
|
+
// client (4xx) and application errors are deterministic, not retried.
|
|
24
|
+
// Off by default: a retried POST is not safe for non-idempotent calls
|
|
25
|
+
// (e.g. posting a question), so it is opted in per request via the
|
|
26
|
+
// request options, or client-wide via `options.request.retry`
|
|
27
|
+
retry = retry !== undefined ? retry : (request.retry || 0);
|
|
20
28
|
|
|
21
29
|
// TODO: organize arguments
|
|
22
30
|
const body = method !== 'GET' && payload != undefined ? JSON.stringify(payload) : undefined;
|
|
23
31
|
|
|
32
|
+
for (let attempt = 0; ; attempt++) {
|
|
33
|
+
try {
|
|
34
|
+
return await this._fetch(url, { method, headers, timeout, body, ...options });
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (attempt >= retry || !isRetryableFetchError(error)) {
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// one attempt; the timeout signal is created per attempt, so a retried
|
|
44
|
+
// attempt gets a full window of its own
|
|
45
|
+
async _fetch(url, { method, headers, timeout, body, ...options }) {
|
|
24
46
|
// TODO: merge signal from options if any
|
|
25
47
|
const signal = timeout ? AbortSignal.timeout(timeout) : undefined;
|
|
26
48
|
|
|
@@ -143,3 +165,10 @@ export default class ApiHelpers {
|
|
|
143
165
|
}
|
|
144
166
|
|
|
145
167
|
}
|
|
168
|
+
|
|
169
|
+
// no status: a network failure, a timeout, or an unparsable body — all
|
|
170
|
+
// transport-level; 5xx: the server's own failure. A 4xx or an
|
|
171
|
+
// application-level error (2xx with `errors`) is deterministic
|
|
172
|
+
function isRetryableFetchError(error) {
|
|
173
|
+
return error.status === undefined || error.status >= 500;
|
|
174
|
+
}
|
package/src/api/history.js
CHANGED
|
@@ -9,12 +9,12 @@ export default class UserHistory extends ApiBase {
|
|
|
9
9
|
super(api, GROUP.ASK_USER_HISTORY);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
async getThreads(options) {
|
|
13
|
-
return this._run('threads',
|
|
12
|
+
async getThreads(payload, options) {
|
|
13
|
+
return this._run('threads', payload, { ...options, method: 'GET' });
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
async getThread(threadId, options) {
|
|
17
|
-
return this._run(`threads/${threadId}`,
|
|
16
|
+
async getThread(threadId, payload, options) {
|
|
17
|
+
return this._run(`threads/${threadId}`, payload, { ...options, method: 'GET' });
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
async updateThread(threadId, payload, options) {
|
package/src/api/iterable.js
CHANGED
|
@@ -20,11 +20,7 @@ export class IterableApiStub {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
[Symbol.asyncIterator]() {
|
|
23
|
-
const fetch =
|
|
24
|
-
// TODO: pass signal
|
|
25
|
-
const response = await this.get();
|
|
26
|
-
return [response, isFinished(response), revisionOf(response)];
|
|
27
|
-
};
|
|
23
|
+
const fetch = this._fetch();
|
|
28
24
|
|
|
29
25
|
if (typeof this._options.customIterator === 'function') {
|
|
30
26
|
return this._options.customIterator.call(this, fetch);
|
|
@@ -47,7 +43,7 @@ export class IterableApiStub {
|
|
|
47
43
|
const onResponse = (response, finished) => {
|
|
48
44
|
if (finished) {
|
|
49
45
|
stac.clear();
|
|
50
|
-
} else if (
|
|
46
|
+
} else if (this._isUpdated(prevResponse, response)) {
|
|
51
47
|
stac.touch();
|
|
52
48
|
}
|
|
53
49
|
prevResponse = response;
|
|
@@ -55,6 +51,25 @@ export class IterableApiStub {
|
|
|
55
51
|
return polling(fetch, { interval, signal, onResponse, ...options })[Symbol.asyncIterator]();
|
|
56
52
|
}
|
|
57
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Compose the polling fetch: () => [response, finished, revision].
|
|
56
|
+
* Overridable by a subclass with its own finish or revision semantics
|
|
57
|
+
* (e.g. Answers, whose question ids may run dry).
|
|
58
|
+
*/
|
|
59
|
+
_fetch() {
|
|
60
|
+
return async ({ signal } = {}) => {
|
|
61
|
+
// TODO: pass signal
|
|
62
|
+
const response = await this.get();
|
|
63
|
+
return [response, isFinished(response), revisionOf(response)];
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// whether the new response carries progress, keeping the stall timeout at
|
|
68
|
+
// bay; overridable by a subclass with its own response shape
|
|
69
|
+
_isUpdated(previousResponse, newResponse) {
|
|
70
|
+
return isUpdated(previousResponse, newResponse);
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
}
|
|
59
74
|
|
|
60
75
|
export class IdBasedIterableApiStub extends IterableApiStub {
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.14.0-beta.
|
|
1
|
+
export default '1.14.0-beta.3';
|