nenavi 0.1.0-alpha.1 → 0.1.0-alpha.2
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/README.md +5 -3
- package/dist/cjs/client.d.ts +27 -17
- package/dist/cjs/client.js +80 -32
- package/dist/cjs/core.d.ts +8 -0
- package/dist/cjs/core.js +36 -4
- package/dist/cjs/errors.d.ts +12 -6
- package/dist/cjs/errors.js +61 -7
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client.d.ts +27 -17
- package/dist/esm/client.js +81 -33
- package/dist/esm/core.d.ts +8 -0
- package/dist/esm/core.js +36 -5
- package/dist/esm/errors.d.ts +12 -6
- package/dist/esm/errors.js +61 -7
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,12 +30,14 @@ Every supported operation of the hosted API has a method. Three helpers cover th
|
|
|
30
30
|
const answer = await client.ingest({ content: 'Jo is learning Portuguese.', user_id: 'user-1' });
|
|
31
31
|
const status = await client.events.waitForExtraction(answer.event_id, { timeout: 300_000 }); // complete or failed
|
|
32
32
|
const run = await client.reingest.run({ user_id: 'user-1' }); // starts a run and polls it every 5 seconds
|
|
33
|
-
for await (const node of client.nodes.scanAll({ user_id: 'user-1' }))
|
|
33
|
+
for await (const node of client.nodes.scanAll({ user_id: 'user-1', limit: 1000 })) {
|
|
34
|
+
console.log(node.id); // every page, 1 000 nodes each
|
|
35
|
+
}
|
|
34
36
|
```
|
|
35
37
|
|
|
36
38
|
`reingest.preview()` estimates a re-ingest without starting one; only `reingest.start()` and `reingest.run()` start a real run. A run takes at most `limit` memories, so a `complete` run can leave some for later: while `run.remaining` is above 0, call `reingest.run()` again with the same parameters to continue it.
|
|
37
39
|
|
|
38
|
-
The helpers' `timeout` and `interval` are in milliseconds, and aborting their `signal` stops them and any pending poll. A helper that runs out of time throws `WaitTimeoutError` with the last status as `lastStatus
|
|
40
|
+
The helpers' `timeout` and `interval` are in milliseconds, and aborting their `signal` stops them and any pending poll. A helper that runs out of time throws `WaitTimeoutError` with the last status as `lastStatus`, and a poll that fails inside `reingest.run()` throws its own error with `lastStatus` set the same way, so the run's `run_id` is not lost; `timeout: 0` polls once, and `reingest.run()` still starts the run. Every poll and every scan page counts against the key's request rate limit (60 a minute by default) like any other call, and `store()`, `ingest()` and `retrieve()` are never retried on a `429`. So for a large scan pass a larger `limit` (up to 1 000 nodes a page), and run background jobs with a longer `interval` or their own key. The helpers are on the client only, not on `withRawResponse`.
|
|
39
41
|
|
|
40
42
|
## Options
|
|
41
43
|
|
|
@@ -55,7 +57,7 @@ Request and response fields keep the API's snake_case names (`user_id`, `event_i
|
|
|
55
57
|
|
|
56
58
|
Every error the SDK throws is a `NenaviError`, and every class works with `instanceof`: `APIError` and its subclasses (`AuthenticationError`, `NotFoundError`, `RateLimitError`, `QuotaExceededError`, `ServiceUnavailableError` and the others) carry `status`, `reasonCode`, `detail` and `requestId`. `APIConnectionError` and `APITimeoutError` mean no response arrived. `ResponseValidationError` means a `2xx` answer had a body the SDK could not read as the operation's type: the call may have taken effect, so read its `body` (for example the `event_id` of a `store()`) and `requestId` before calling again. `body` can hold stored memory text, and `console.error(error)` or `JSON.stringify(error)` prints it: log the message and `requestId` instead.
|
|
57
59
|
|
|
58
|
-
Only `GET` methods and `ingestFast()` retry by themselves, on a `429 rate_limited` (after `Retry-After`), a `503 database_unavailable` or `lease_unavailable`, or a connection error. `store()`, `ingest()` and `retrieve()` never retry: a retried store stores the text again and counts twice against the monthly limits. `ingestFast()` sends one `Idempotency-Key` on every retry of a call
|
|
60
|
+
Only `GET` methods and `ingestFast()` retry by themselves, on a `429 rate_limited` (after `Retry-After`), a `503 database_unavailable` or `lease_unavailable`, or a connection error. `store()`, `ingest()` and `retrieve()` never retry: a retried store stores the text again and counts twice against the monthly limits. `ingestFast()` sends one `Idempotency-Key` on every retry of a call. A timeout is never retried, so to retry it by hand, pass the error's `idempotencyKey`. If you wrap `ingestFast()` in your own retry loop, make one key before the first attempt and pass it on every attempt: a call without a key gets a new one, and the service stores and meters the batch again.
|
|
59
61
|
|
|
60
62
|
## Development
|
|
61
63
|
|
package/dist/cjs/client.d.ts
CHANGED
|
@@ -12,9 +12,11 @@ declare class Resource<Raw extends boolean> {
|
|
|
12
12
|
/** A helper's options (sdks/CONTRACT.md, Helpers). */
|
|
13
13
|
export interface HelperOptions {
|
|
14
14
|
/**
|
|
15
|
-
* Milliseconds after which the helper stops
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Milliseconds after which the helper stops: a deadline. Each poll's attempt gets no
|
|
16
|
+
* more than the time left (at least 1 000 milliseconds), and a retry that would wait
|
|
17
|
+
* past it is not made; a poll the deadline stops this way throws `WaitTimeoutError`
|
|
18
|
+
* too, with the poll's error as its `cause`. 0 polls once (`run()` still starts the
|
|
19
|
+
* run, with the client's own timeout); `Infinity` waits without a limit.
|
|
18
20
|
*/
|
|
19
21
|
timeout?: number;
|
|
20
22
|
/** Milliseconds between polls. */
|
|
@@ -185,12 +187,14 @@ export declare class Learning<Raw extends boolean = false> extends Resource<Raw>
|
|
|
185
187
|
/** `client.events`: the event routes and `waitForExtraction()`. */
|
|
186
188
|
export declare class EventsWithHelpers extends Events<false> {
|
|
187
189
|
/**
|
|
188
|
-
* Poll the event's extraction status until it is `
|
|
190
|
+
* Poll the event's extraction status until it is no longer `pending` or `running`.
|
|
189
191
|
*
|
|
190
192
|
* Polls `GET /v1/events/{event_id}/extraction-status` at once and then every
|
|
191
|
-
* `interval` milliseconds (2 000), and returns the
|
|
192
|
-
*
|
|
193
|
-
* `
|
|
193
|
+
* `interval` milliseconds (2 000), and returns the first status that is not `pending`
|
|
194
|
+
* or `running`: `complete`, `failed` (returned, not thrown), or a status this SDK does
|
|
195
|
+
* not know yet. When `timeout` milliseconds (300 000) run out first, throws
|
|
196
|
+
* `WaitTimeoutError` with the last status as `lastStatus`; `timeout` is a deadline that
|
|
197
|
+
* also bounds each poll and its retries (see `HelperOptions`). Aborting `signal` stops
|
|
194
198
|
* the helper and any pending poll or retry. Each poll is an ordinary call, with the
|
|
195
199
|
* client's retries and errors, and counts against the key's request rate limit like any
|
|
196
200
|
* other call, so many waits at once can slow the key's other calls. A job can stay
|
|
@@ -211,24 +215,30 @@ export declare class NodesWithHelpers extends Nodes<false> {
|
|
|
211
215
|
* `NenaviError`, so a scan never ends early without saying so.
|
|
212
216
|
*
|
|
213
217
|
* @example
|
|
214
|
-
* for await (const node of client.nodes.scanAll({ user_id: 'user-1' }))
|
|
218
|
+
* for await (const node of client.nodes.scanAll({ user_id: 'user-1', limit: 1000 })) {
|
|
219
|
+
* console.log(node.id);
|
|
220
|
+
* }
|
|
215
221
|
*/
|
|
216
222
|
scanAll(params?: NodesScanParams, options?: RequestOptions): AsyncGenerator<NodeResponse, void, undefined>;
|
|
217
223
|
}
|
|
218
224
|
/** `client.reingest`: the re-ingest routes and `run()`. */
|
|
219
225
|
export declare class ReingestWithHelpers extends Reingest<false> {
|
|
220
226
|
/**
|
|
221
|
-
* Start a re-ingest run and poll it until its `state` is
|
|
227
|
+
* Start a re-ingest run and poll it until its `state` is final.
|
|
222
228
|
*
|
|
223
229
|
* Sends `start()` (`dry_run: false`), then polls `get()` every `interval` milliseconds
|
|
224
|
-
* (5 000) and returns the
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* `
|
|
230
|
+
* (5 000) and returns the first status whose `state` is not `pending` or `running`:
|
|
231
|
+
* `complete`, `failed` (returned, not thrown), or a state this SDK does not know yet.
|
|
232
|
+
* When nothing needs re-deriving, the service's `200` answer is returned as it is. A
|
|
233
|
+
* `409` `reingest_running` throws `ConflictError`. When `timeout` milliseconds
|
|
234
|
+
* (3 600 000) run out first, throws `WaitTimeoutError` with the last status as
|
|
235
|
+
* `lastStatus`; the run itself goes on. `timeout` is a deadline that also bounds each
|
|
236
|
+
* poll and its retries (see `HelperOptions`); it never prevents or cuts short the start,
|
|
237
|
+
* which has the client's own timeout. Aborting `signal` stops the helper and any pending
|
|
238
|
+
* poll, not the run. A poll that fails throws that call's error while the run goes on,
|
|
239
|
+
* with the last status read before it as `lastStatus`: its `run_id` lets the caller go
|
|
240
|
+
* on polling with `get()` instead of calling `run()` again, which throws `ConflictError`
|
|
241
|
+
* (`reingest_running`) until the run ends.
|
|
232
242
|
*
|
|
233
243
|
* A run takes at most `limit` memories, so a `complete` run can leave some for later
|
|
234
244
|
* (`remaining` above 0): calling `run()` again with the same parameters continues it.
|
package/dist/cjs/client.js
CHANGED
|
@@ -26,8 +26,24 @@ class Resource {
|
|
|
26
26
|
return this._core.request(call, this._raw);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
30
|
-
|
|
29
|
+
/**
|
|
30
|
+
* The states a helper keeps polling through. Any other state, one the service adds later
|
|
31
|
+
* included, is final and returned.
|
|
32
|
+
*/
|
|
33
|
+
const WORKING = new Set(['pending', 'running']);
|
|
34
|
+
/** `GET /v1/events/{event_id}/extraction-status`, for the method and its helper. */
|
|
35
|
+
function extractionStatusCall(eventId, options) {
|
|
36
|
+
return {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
path: `/v1/events/${(0, core_js_1.pathParam)(eventId)}/extraction-status`,
|
|
39
|
+
retrySafe: true,
|
|
40
|
+
options,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** `GET /v1/reingest/{run_id}`, for the method and its helper. */
|
|
44
|
+
function reingestGetCall(runId, options) {
|
|
45
|
+
return { method: 'GET', path: `/v1/reingest/${(0, core_js_1.pathParam)(runId)}`, retrySafe: true, options };
|
|
46
|
+
}
|
|
31
47
|
/** A caller's `Idempotency-Key`, or null; an empty value counts as not given. */
|
|
32
48
|
function callerKey(options) {
|
|
33
49
|
const key = (0, core_js_1.ownProperties)(options).idempotencyKey;
|
|
@@ -73,12 +89,7 @@ class Events extends Resource {
|
|
|
73
89
|
}
|
|
74
90
|
/** `GET /v1/events/{event_id}/extraction-status`. */
|
|
75
91
|
extractionStatus(eventId, options) {
|
|
76
|
-
return this._request(() => (
|
|
77
|
-
method: 'GET',
|
|
78
|
-
path: `/v1/events/${(0, core_js_1.pathParam)(eventId)}/extraction-status`,
|
|
79
|
-
retrySafe: true,
|
|
80
|
-
options,
|
|
81
|
-
}));
|
|
92
|
+
return this._request(() => extractionStatusCall(eventId, options));
|
|
82
93
|
}
|
|
83
94
|
/** `POST /v1/events/{event_id}/retry-extraction`. Not retried automatically. */
|
|
84
95
|
retryExtraction(eventId, params, options) {
|
|
@@ -244,12 +255,7 @@ class Reingest extends Resource {
|
|
|
244
255
|
}
|
|
245
256
|
/** `GET /v1/reingest/{run_id}`: the run's state, counts and usage. */
|
|
246
257
|
get(runId, options) {
|
|
247
|
-
return this._request(() => (
|
|
248
|
-
method: 'GET',
|
|
249
|
-
path: `/v1/reingest/${(0, core_js_1.pathParam)(runId)}`,
|
|
250
|
-
retrySafe: true,
|
|
251
|
-
options,
|
|
252
|
-
}));
|
|
258
|
+
return this._request(() => reingestGetCall(runId, options));
|
|
253
259
|
}
|
|
254
260
|
}
|
|
255
261
|
exports.Reingest = Reingest;
|
|
@@ -594,12 +600,14 @@ exports.Learning = Learning;
|
|
|
594
600
|
/** `client.events`: the event routes and `waitForExtraction()`. */
|
|
595
601
|
class EventsWithHelpers extends Events {
|
|
596
602
|
/**
|
|
597
|
-
* Poll the event's extraction status until it is `
|
|
603
|
+
* Poll the event's extraction status until it is no longer `pending` or `running`.
|
|
598
604
|
*
|
|
599
605
|
* Polls `GET /v1/events/{event_id}/extraction-status` at once and then every
|
|
600
|
-
* `interval` milliseconds (2 000), and returns the
|
|
601
|
-
*
|
|
602
|
-
* `
|
|
606
|
+
* `interval` milliseconds (2 000), and returns the first status that is not `pending`
|
|
607
|
+
* or `running`: `complete`, `failed` (returned, not thrown), or a status this SDK does
|
|
608
|
+
* not know yet. When `timeout` milliseconds (300 000) run out first, throws
|
|
609
|
+
* `WaitTimeoutError` with the last status as `lastStatus`; `timeout` is a deadline that
|
|
610
|
+
* also bounds each poll and its retries (see `HelperOptions`). Aborting `signal` stops
|
|
603
611
|
* the helper and any pending poll or retry. Each poll is an ordinary call, with the
|
|
604
612
|
* client's retries and errors, and counts against the key's request rate limit like any
|
|
605
613
|
* other call, so many waits at once can slow the key's other calls. A job can stay
|
|
@@ -609,10 +617,26 @@ class EventsWithHelpers extends Events {
|
|
|
609
617
|
const { timeout = 300_000, interval = 2_000, signal = null } = (0, core_js_1.ownProperties)(options);
|
|
610
618
|
const core = this._core;
|
|
611
619
|
const deadline = (0, core_js_1.helperDeadline)(core.now(), timeout, interval);
|
|
620
|
+
let lastStatus = null;
|
|
612
621
|
for (;;) {
|
|
613
|
-
|
|
614
|
-
|
|
622
|
+
let status;
|
|
623
|
+
try {
|
|
624
|
+
status = await this._request(() => ({
|
|
625
|
+
...extractionStatusCall(eventId, { signal }),
|
|
626
|
+
deadline,
|
|
627
|
+
}));
|
|
628
|
+
}
|
|
629
|
+
catch (error) {
|
|
630
|
+
// Only a poll the deadline stopped throws WaitTimeoutError; its own error is the cause.
|
|
631
|
+
if (!(error instanceof errors_js_1.WaitTimeoutError))
|
|
632
|
+
throw error;
|
|
633
|
+
const last = lastStatus === null ? 'none' : JSON.stringify(lastStatus.status);
|
|
634
|
+
throw (0, core_js_1.withCause)(new errors_js_1.WaitTimeoutError(`The extraction did not finish within ${timeout} ms: ${error.message}. The last ` +
|
|
635
|
+
`status read was ${last}.`, { lastStatus }), error.cause);
|
|
636
|
+
}
|
|
637
|
+
if (!WORKING.has(status.status))
|
|
615
638
|
return status;
|
|
639
|
+
lastStatus = status;
|
|
616
640
|
const wait = (0, core_js_1.helperWait)(core.now(), deadline, interval);
|
|
617
641
|
if (wait === null) {
|
|
618
642
|
throw new errors_js_1.WaitTimeoutError(`The extraction did not finish within ${timeout} ms; its last status was ` +
|
|
@@ -636,7 +660,9 @@ class NodesWithHelpers extends Nodes {
|
|
|
636
660
|
* `NenaviError`, so a scan never ends early without saying so.
|
|
637
661
|
*
|
|
638
662
|
* @example
|
|
639
|
-
* for await (const node of client.nodes.scanAll({ user_id: 'user-1' }))
|
|
663
|
+
* for await (const node of client.nodes.scanAll({ user_id: 'user-1', limit: 1000 })) {
|
|
664
|
+
* console.log(node.id);
|
|
665
|
+
* }
|
|
640
666
|
*/
|
|
641
667
|
async *scanAll(params, options) {
|
|
642
668
|
const given = (0, core_js_1.ownProperties)(params);
|
|
@@ -663,17 +689,21 @@ exports.NodesWithHelpers = NodesWithHelpers;
|
|
|
663
689
|
/** `client.reingest`: the re-ingest routes and `run()`. */
|
|
664
690
|
class ReingestWithHelpers extends Reingest {
|
|
665
691
|
/**
|
|
666
|
-
* Start a re-ingest run and poll it until its `state` is
|
|
692
|
+
* Start a re-ingest run and poll it until its `state` is final.
|
|
667
693
|
*
|
|
668
694
|
* Sends `start()` (`dry_run: false`), then polls `get()` every `interval` milliseconds
|
|
669
|
-
* (5 000) and returns the
|
|
670
|
-
*
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
* `
|
|
695
|
+
* (5 000) and returns the first status whose `state` is not `pending` or `running`:
|
|
696
|
+
* `complete`, `failed` (returned, not thrown), or a state this SDK does not know yet.
|
|
697
|
+
* When nothing needs re-deriving, the service's `200` answer is returned as it is. A
|
|
698
|
+
* `409` `reingest_running` throws `ConflictError`. When `timeout` milliseconds
|
|
699
|
+
* (3 600 000) run out first, throws `WaitTimeoutError` with the last status as
|
|
700
|
+
* `lastStatus`; the run itself goes on. `timeout` is a deadline that also bounds each
|
|
701
|
+
* poll and its retries (see `HelperOptions`); it never prevents or cuts short the start,
|
|
702
|
+
* which has the client's own timeout. Aborting `signal` stops the helper and any pending
|
|
703
|
+
* poll, not the run. A poll that fails throws that call's error while the run goes on,
|
|
704
|
+
* with the last status read before it as `lastStatus`: its `run_id` lets the caller go
|
|
705
|
+
* on polling with `get()` instead of calling `run()` again, which throws `ConflictError`
|
|
706
|
+
* (`reingest_running`) until the run ends.
|
|
677
707
|
*
|
|
678
708
|
* A run takes at most `limit` memories, so a `complete` run can leave some for later
|
|
679
709
|
* (`remaining` above 0): calling `run()` again with the same parameters continues it.
|
|
@@ -683,14 +713,32 @@ class ReingestWithHelpers extends Reingest {
|
|
|
683
713
|
const core = this._core;
|
|
684
714
|
const deadline = (0, core_js_1.helperDeadline)(core.now(), timeout, interval);
|
|
685
715
|
let status = await this.start(params, { signal });
|
|
686
|
-
while (status.run_id !== null && status.run_id !== undefined &&
|
|
716
|
+
while (status.run_id !== null && status.run_id !== undefined && WORKING.has(status.state)) {
|
|
687
717
|
const wait = (0, core_js_1.helperWait)(core.now(), deadline, interval);
|
|
688
718
|
if (wait === null) {
|
|
689
719
|
throw new errors_js_1.WaitTimeoutError(`The re-ingest run ${status.run_id} did not finish within ${timeout} ms; its ` +
|
|
690
720
|
`last state was ${JSON.stringify(status.state)}.`, { lastStatus: status });
|
|
691
721
|
}
|
|
692
722
|
await core.sleep(wait, signal);
|
|
693
|
-
|
|
723
|
+
const runId = status.run_id;
|
|
724
|
+
try {
|
|
725
|
+
status = await this._request(() => ({
|
|
726
|
+
...reingestGetCall(runId, { signal }),
|
|
727
|
+
deadline,
|
|
728
|
+
}));
|
|
729
|
+
}
|
|
730
|
+
catch (error) {
|
|
731
|
+
// A poll the deadline stopped throws WaitTimeoutError; its own error is the cause.
|
|
732
|
+
if (error instanceof errors_js_1.WaitTimeoutError) {
|
|
733
|
+
throw (0, core_js_1.withCause)(new errors_js_1.WaitTimeoutError(`The re-ingest run ${runId} did not finish within ${timeout} ms: ` +
|
|
734
|
+
`${error.message}. Its last state was ${JSON.stringify(status.state)}.`, { lastStatus: status }), error.cause);
|
|
735
|
+
}
|
|
736
|
+
// The run goes on; without its id the caller could only call run() again, which
|
|
737
|
+
// the service refuses with 409 until the run ends. An abort keeps its own reason.
|
|
738
|
+
if (error instanceof errors_js_1.NenaviError && !signal?.aborted)
|
|
739
|
+
error.lastStatus = status;
|
|
740
|
+
throw error;
|
|
741
|
+
}
|
|
694
742
|
}
|
|
695
743
|
return status;
|
|
696
744
|
}
|
package/dist/cjs/core.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NenaviError } from './errors.js';
|
|
1
2
|
/** The `fetch` the SDK calls: the runtime's own, or one the caller passes. */
|
|
2
3
|
export type Fetch = (input: string, init: RequestInit) => Promise<Response>;
|
|
3
4
|
export interface ClientOptions {
|
|
@@ -46,6 +47,11 @@ export interface Call {
|
|
|
46
47
|
options?: RequestOptions | undefined;
|
|
47
48
|
/** The JSON type of the answer: an object (the default), an array, or an object or null. */
|
|
48
49
|
answer?: 'object' | 'array' | 'nullable';
|
|
50
|
+
/**
|
|
51
|
+
* A helper's deadline on `Core.now`: it caps each attempt's timeout and stops a retry
|
|
52
|
+
* whose wait would end past it. Unset for an ordinary call.
|
|
53
|
+
*/
|
|
54
|
+
deadline?: number;
|
|
49
55
|
}
|
|
50
56
|
/** Encode one path parameter, so a value cannot add or change path segments. */
|
|
51
57
|
export declare function pathParam(value: string): string;
|
|
@@ -57,6 +63,8 @@ export declare function helperDeadline(now: number, timeout: number, interval: n
|
|
|
57
63
|
export declare function helperWait(now: number, deadline: number, interval: number): number | null;
|
|
58
64
|
/** Wait `ms` milliseconds, or reject with the signal's reason when it is aborted first. */
|
|
59
65
|
export declare function sleep(ms: number, signal?: AbortSignal | null): Promise<void>;
|
|
66
|
+
/** Set `cause` as the `Error` constructor does: an own property that is not enumerable. */
|
|
67
|
+
export declare function withCause<E extends Error>(error: E, cause: NenaviError): E;
|
|
60
68
|
/** Holds the configuration and sends the calls. The key is a private field. */
|
|
61
69
|
export declare class Core {
|
|
62
70
|
#private;
|
package/dist/cjs/core.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.ownProperties = ownProperties;
|
|
|
10
10
|
exports.helperDeadline = helperDeadline;
|
|
11
11
|
exports.helperWait = helperWait;
|
|
12
12
|
exports.sleep = sleep;
|
|
13
|
+
exports.withCause = withCause;
|
|
13
14
|
const errors_js_1 = require("./errors.js");
|
|
14
15
|
const version_js_1 = require("./version.js");
|
|
15
16
|
const DEFAULT_BASE_URL = 'https://api.prismemory.com';
|
|
@@ -20,6 +21,11 @@ const DEFAULT_MAX_RETRIES = 2;
|
|
|
20
21
|
const MAX_RETRY_AFTER = 60;
|
|
21
22
|
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
22
23
|
const RETRYABLE_503 = new Set(['database_unavailable', 'lease_unavailable']);
|
|
24
|
+
/**
|
|
25
|
+
* Milliseconds: the shortest attempt timeout a helper's poll gets near its deadline, so the
|
|
26
|
+
* poll at the deadline (and the one poll of `timeout: 0`) can still be answered.
|
|
27
|
+
*/
|
|
28
|
+
const MIN_POLL_TIMEOUT = 1_000;
|
|
23
29
|
/** The longest delay setTimeout keeps: a longer one fires at once. */
|
|
24
30
|
const MAX_TIMEOUT = 2_147_483_647;
|
|
25
31
|
// Visible ASCII only: what an HTTP header can carry without encoding. This is not a check
|
|
@@ -201,6 +207,21 @@ function retryWait(error, retryNumber) {
|
|
|
201
207
|
}
|
|
202
208
|
return null;
|
|
203
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* The error for a helper's poll that its deadline stopped; the helper adds its status. The
|
|
212
|
+
* poll's own error becomes its `cause`.
|
|
213
|
+
*/
|
|
214
|
+
function deadlineError(error, retrySkipped) {
|
|
215
|
+
const reason = retrySkipped
|
|
216
|
+
? `the last poll threw ${error.name}, and its retry would have waited past the deadline`
|
|
217
|
+
: `the last poll got no answer before the deadline (${error.name})`;
|
|
218
|
+
return withCause(new errors_js_1.WaitTimeoutError(reason, { idempotencyKey: error.idempotencyKey }), error);
|
|
219
|
+
}
|
|
220
|
+
/** Set `cause` as the `Error` constructor does: an own property that is not enumerable. */
|
|
221
|
+
function withCause(error, cause) {
|
|
222
|
+
Object.defineProperty(error, 'cause', { value: cause, writable: true, configurable: true });
|
|
223
|
+
return error;
|
|
224
|
+
}
|
|
204
225
|
/** The name, and the system error code when there is one, of what fetch threw. */
|
|
205
226
|
function failureName(error) {
|
|
206
227
|
const raw = error instanceof Error ? error.name : typeof error;
|
|
@@ -264,7 +285,8 @@ class Core {
|
|
|
264
285
|
if (auth && this.#apiKey === null) {
|
|
265
286
|
throw new errors_js_1.ConfigurationError('No API key: pass apiKey or set NENAVI_API_KEY. Only health() works without a key.');
|
|
266
287
|
}
|
|
267
|
-
const
|
|
288
|
+
const callTimeout = checkTimeout(options.timeout ?? this.timeout);
|
|
289
|
+
const deadline = call.deadline ?? null;
|
|
268
290
|
const maxRetries = checkMaxRetries(options.maxRetries ?? this.maxRetries);
|
|
269
291
|
const idempotencyKey = call.idempotencyKey ?? null;
|
|
270
292
|
const headers = {
|
|
@@ -288,6 +310,10 @@ class Core {
|
|
|
288
310
|
const url = `${this.baseURL}${call.path}${queryString(call.query)}`;
|
|
289
311
|
let retries = 0;
|
|
290
312
|
for (;;) {
|
|
313
|
+
// A helper's poll gets only the time left.
|
|
314
|
+
const left = deadline === null ? Infinity : Math.max(deadline - this.now(), MIN_POLL_TIMEOUT);
|
|
315
|
+
const shortened = left < callTimeout;
|
|
316
|
+
const timeout = shortened ? left : callTimeout;
|
|
291
317
|
const attempt = await this.#send(url, call.method, headers, body, timeout, signal, idempotencyKey);
|
|
292
318
|
if (attempt.response !== undefined) {
|
|
293
319
|
return this.#result(attempt.response, attempt.text, raw, idempotencyKey, call.answer ?? 'object');
|
|
@@ -295,11 +321,17 @@ class Core {
|
|
|
295
321
|
if (call.retrySafe && retries < maxRetries) {
|
|
296
322
|
const wait = retryWait(attempt.error, retries + 1);
|
|
297
323
|
if (wait !== null) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
324
|
+
if (deadline === null || this.now() + wait < deadline) {
|
|
325
|
+
retries += 1;
|
|
326
|
+
await this.sleep(wait, signal);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
throw deadlineError(attempt.error, true);
|
|
301
330
|
}
|
|
302
331
|
}
|
|
332
|
+
if (shortened && attempt.error instanceof errors_js_1.APITimeoutError) {
|
|
333
|
+
throw deadlineError(attempt.error, false);
|
|
334
|
+
}
|
|
303
335
|
throw attempt.error;
|
|
304
336
|
}
|
|
305
337
|
}
|
package/dist/cjs/errors.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
/** Base class of every error the SDK throws. */
|
|
2
2
|
export declare class NenaviError extends Error {
|
|
3
|
+
/**
|
|
4
|
+
* `value instanceof` this class, also for an error from another copy of the package.
|
|
5
|
+
* Installed below with `Object.defineProperty`.
|
|
6
|
+
*/
|
|
7
|
+
static [Symbol.hasInstance]: <T>(this: abstract new (...args: never[]) => T, value: unknown) => value is T;
|
|
3
8
|
/** The `Idempotency-Key` the call sent, or null when it sent none. */
|
|
4
9
|
idempotencyKey: string | null;
|
|
10
|
+
/**
|
|
11
|
+
* The last status a helper read before it threw: on `WaitTimeoutError`, and on the
|
|
12
|
+
* error of a poll that failed inside `reingest.run()`, where it holds the run's
|
|
13
|
+
* `run_id`. Null on other errors.
|
|
14
|
+
*/
|
|
15
|
+
lastStatus: unknown;
|
|
5
16
|
constructor(message: string, options?: {
|
|
6
17
|
idempotencyKey?: string | null;
|
|
18
|
+
lastStatus?: unknown;
|
|
7
19
|
});
|
|
8
20
|
}
|
|
9
21
|
/** No key for an operation that needs one, or an invalid option. */
|
|
@@ -11,12 +23,6 @@ export declare class ConfigurationError extends NenaviError {
|
|
|
11
23
|
}
|
|
12
24
|
/** A helper ran out of time before the work it waited for finished. */
|
|
13
25
|
export declare class WaitTimeoutError extends NenaviError {
|
|
14
|
-
/** The last status the helper read. */
|
|
15
|
-
lastStatus: unknown;
|
|
16
|
-
constructor(message: string, options?: {
|
|
17
|
-
lastStatus?: unknown;
|
|
18
|
-
idempotencyKey?: string | null;
|
|
19
|
-
});
|
|
20
26
|
}
|
|
21
27
|
export interface ResponseValidationErrorOptions {
|
|
22
28
|
status: number;
|
package/dist/cjs/errors.js
CHANGED
|
@@ -4,32 +4,79 @@
|
|
|
4
4
|
// An error holds plain values only: the status, a copy of the response headers and the
|
|
5
5
|
// parsed body. It never holds a Request, a Response or the error fetch threw, so the
|
|
6
6
|
// `Authorization` header cannot reach a message, `util.inspect` or `JSON.stringify`.
|
|
7
|
+
//
|
|
8
|
+
// The package ships an ES module build and a CommonJS build, and a process that loads
|
|
9
|
+
// both holds two copies of every class here. So that `instanceof` still works across the
|
|
10
|
+
// copies, each class's prototype carries its name under a key in the global symbol
|
|
11
|
+
// registry, and `instanceof` falls back to matching that name along the prototype chain.
|
|
7
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
13
|
exports.DETAIL_TEXT_LIMIT = exports.ServiceUnavailableError = exports.InternalServerError = exports.QuotaExceededError = exports.RateLimitError = exports.UnprocessableEntityError = exports.PayloadTooLargeError = exports.ConflictError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.BadRequestError = exports.APIError = exports.APITimeoutError = exports.APIConnectionError = exports.ResponseValidationError = exports.WaitTimeoutError = exports.ConfigurationError = exports.NenaviError = void 0;
|
|
9
14
|
exports.parseRetryAfter = parseRetryAfter;
|
|
10
15
|
exports.errorFromResponse = errorFromResponse;
|
|
16
|
+
/**
|
|
17
|
+
* The key, shared by every copy of the package, under which a prototype names its class.
|
|
18
|
+
*
|
|
19
|
+
* Copies of different versions match each other by this key and the class name alone, so
|
|
20
|
+
* the key is a contract between versions. A release that changes an error class's fields
|
|
21
|
+
* incompatibly must change the key (for example to `nenavi.error.class.v2`), so that its
|
|
22
|
+
* errors stop matching older copies' classes instead of narrowing to the old shape.
|
|
23
|
+
*/
|
|
24
|
+
const CLASS_NAME = Symbol.for('nenavi.error.class');
|
|
11
25
|
/** Base class of every error the SDK throws. */
|
|
12
26
|
class NenaviError extends Error {
|
|
13
27
|
/** The `Idempotency-Key` the call sent, or null when it sent none. */
|
|
14
28
|
idempotencyKey;
|
|
29
|
+
/**
|
|
30
|
+
* The last status a helper read before it threw: on `WaitTimeoutError`, and on the
|
|
31
|
+
* error of a poll that failed inside `reingest.run()`, where it holds the run's
|
|
32
|
+
* `run_id`. Null on other errors.
|
|
33
|
+
*/
|
|
34
|
+
lastStatus;
|
|
15
35
|
constructor(message, options = {}) {
|
|
16
36
|
super(message);
|
|
17
37
|
this.idempotencyKey = options.idempotencyKey ?? null;
|
|
38
|
+
this.lastStatus = options.lastStatus ?? null;
|
|
18
39
|
}
|
|
19
40
|
}
|
|
20
41
|
exports.NenaviError = NenaviError;
|
|
42
|
+
// The ordinary check comes first. Failing that, a class of this package matches a value
|
|
43
|
+
// whose prototype chain holds a prototype marked with the same class name, as the other
|
|
44
|
+
// copy's classes are. A subclass written outside the package keeps the ordinary check.
|
|
45
|
+
//
|
|
46
|
+
// This is defined as a property rather than written as a static method, because a loose
|
|
47
|
+
// class transform in a consumer's build turns a static method into an assignment, and
|
|
48
|
+
// assigning over the read-only `Function.prototype[Symbol.hasInstance]` throws.
|
|
49
|
+
Object.defineProperty(NenaviError, Symbol.hasInstance, {
|
|
50
|
+
value: function hasInstance(value) {
|
|
51
|
+
if (Function.prototype[Symbol.hasInstance].call(this, value))
|
|
52
|
+
return true;
|
|
53
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
const prototype = this.prototype;
|
|
57
|
+
if (typeof prototype !== 'object' || prototype === null)
|
|
58
|
+
return false;
|
|
59
|
+
if (!Object.hasOwn(prototype, CLASS_NAME))
|
|
60
|
+
return false;
|
|
61
|
+
const name = prototype[CLASS_NAME];
|
|
62
|
+
for (let link = Object.getPrototypeOf(value); link !== null; link = Object.getPrototypeOf(link)) {
|
|
63
|
+
if (Object.hasOwn(link, CLASS_NAME) &&
|
|
64
|
+
link[CLASS_NAME] === name) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
},
|
|
70
|
+
writable: true,
|
|
71
|
+
enumerable: false,
|
|
72
|
+
configurable: true,
|
|
73
|
+
});
|
|
21
74
|
/** No key for an operation that needs one, or an invalid option. */
|
|
22
75
|
class ConfigurationError extends NenaviError {
|
|
23
76
|
}
|
|
24
77
|
exports.ConfigurationError = ConfigurationError;
|
|
25
78
|
/** A helper ran out of time before the work it waited for finished. */
|
|
26
79
|
class WaitTimeoutError extends NenaviError {
|
|
27
|
-
/** The last status the helper read. */
|
|
28
|
-
lastStatus;
|
|
29
|
-
constructor(message, options = {}) {
|
|
30
|
-
super(message, options);
|
|
31
|
-
this.lastStatus = options.lastStatus ?? null;
|
|
32
|
-
}
|
|
33
80
|
}
|
|
34
81
|
exports.WaitTimeoutError = WaitTimeoutError;
|
|
35
82
|
/**
|
|
@@ -140,7 +187,8 @@ class ServiceUnavailableError extends APIError {
|
|
|
140
187
|
}
|
|
141
188
|
exports.ServiceUnavailableError = ServiceUnavailableError;
|
|
142
189
|
// Each class's name, written out so that `error.name` survives a minifier that renames
|
|
143
|
-
// classes. It sits on the prototype, so it is not an own property of an error.
|
|
190
|
+
// classes. It sits on the prototype, so it is not an own property of an error. The same
|
|
191
|
+
// name marks the prototype under CLASS_NAME for the cross-copy `instanceof` above.
|
|
144
192
|
const NAMES = [
|
|
145
193
|
[NenaviError, 'NenaviError'],
|
|
146
194
|
[ConfigurationError, 'ConfigurationError'],
|
|
@@ -168,6 +216,12 @@ for (const [ErrorClass, name] of NAMES) {
|
|
|
168
216
|
enumerable: false,
|
|
169
217
|
configurable: true,
|
|
170
218
|
});
|
|
219
|
+
Object.defineProperty(ErrorClass.prototype, CLASS_NAME, {
|
|
220
|
+
value: name,
|
|
221
|
+
writable: false,
|
|
222
|
+
enumerable: false,
|
|
223
|
+
configurable: false,
|
|
224
|
+
});
|
|
171
225
|
}
|
|
172
226
|
const BY_STATUS = {
|
|
173
227
|
400: BadRequestError,
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The SDK's version, sent in the `User-Agent` header. test/client.test.ts keeps it equal to package.json. */
|
|
2
|
-
export declare const VERSION = "0.1.0-alpha.
|
|
2
|
+
export declare const VERSION = "0.1.0-alpha.2";
|
package/dist/cjs/version.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/** The SDK's version, sent in the `User-Agent` header. test/client.test.ts keeps it equal to package.json. */
|
|
5
|
-
exports.VERSION = '0.1.0-alpha.
|
|
5
|
+
exports.VERSION = '0.1.0-alpha.2';
|
package/dist/esm/client.d.ts
CHANGED
|
@@ -12,9 +12,11 @@ declare class Resource<Raw extends boolean> {
|
|
|
12
12
|
/** A helper's options (sdks/CONTRACT.md, Helpers). */
|
|
13
13
|
export interface HelperOptions {
|
|
14
14
|
/**
|
|
15
|
-
* Milliseconds after which the helper stops
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Milliseconds after which the helper stops: a deadline. Each poll's attempt gets no
|
|
16
|
+
* more than the time left (at least 1 000 milliseconds), and a retry that would wait
|
|
17
|
+
* past it is not made; a poll the deadline stops this way throws `WaitTimeoutError`
|
|
18
|
+
* too, with the poll's error as its `cause`. 0 polls once (`run()` still starts the
|
|
19
|
+
* run, with the client's own timeout); `Infinity` waits without a limit.
|
|
18
20
|
*/
|
|
19
21
|
timeout?: number;
|
|
20
22
|
/** Milliseconds between polls. */
|
|
@@ -185,12 +187,14 @@ export declare class Learning<Raw extends boolean = false> extends Resource<Raw>
|
|
|
185
187
|
/** `client.events`: the event routes and `waitForExtraction()`. */
|
|
186
188
|
export declare class EventsWithHelpers extends Events<false> {
|
|
187
189
|
/**
|
|
188
|
-
* Poll the event's extraction status until it is `
|
|
190
|
+
* Poll the event's extraction status until it is no longer `pending` or `running`.
|
|
189
191
|
*
|
|
190
192
|
* Polls `GET /v1/events/{event_id}/extraction-status` at once and then every
|
|
191
|
-
* `interval` milliseconds (2 000), and returns the
|
|
192
|
-
*
|
|
193
|
-
* `
|
|
193
|
+
* `interval` milliseconds (2 000), and returns the first status that is not `pending`
|
|
194
|
+
* or `running`: `complete`, `failed` (returned, not thrown), or a status this SDK does
|
|
195
|
+
* not know yet. When `timeout` milliseconds (300 000) run out first, throws
|
|
196
|
+
* `WaitTimeoutError` with the last status as `lastStatus`; `timeout` is a deadline that
|
|
197
|
+
* also bounds each poll and its retries (see `HelperOptions`). Aborting `signal` stops
|
|
194
198
|
* the helper and any pending poll or retry. Each poll is an ordinary call, with the
|
|
195
199
|
* client's retries and errors, and counts against the key's request rate limit like any
|
|
196
200
|
* other call, so many waits at once can slow the key's other calls. A job can stay
|
|
@@ -211,24 +215,30 @@ export declare class NodesWithHelpers extends Nodes<false> {
|
|
|
211
215
|
* `NenaviError`, so a scan never ends early without saying so.
|
|
212
216
|
*
|
|
213
217
|
* @example
|
|
214
|
-
* for await (const node of client.nodes.scanAll({ user_id: 'user-1' }))
|
|
218
|
+
* for await (const node of client.nodes.scanAll({ user_id: 'user-1', limit: 1000 })) {
|
|
219
|
+
* console.log(node.id);
|
|
220
|
+
* }
|
|
215
221
|
*/
|
|
216
222
|
scanAll(params?: NodesScanParams, options?: RequestOptions): AsyncGenerator<NodeResponse, void, undefined>;
|
|
217
223
|
}
|
|
218
224
|
/** `client.reingest`: the re-ingest routes and `run()`. */
|
|
219
225
|
export declare class ReingestWithHelpers extends Reingest<false> {
|
|
220
226
|
/**
|
|
221
|
-
* Start a re-ingest run and poll it until its `state` is
|
|
227
|
+
* Start a re-ingest run and poll it until its `state` is final.
|
|
222
228
|
*
|
|
223
229
|
* Sends `start()` (`dry_run: false`), then polls `get()` every `interval` milliseconds
|
|
224
|
-
* (5 000) and returns the
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* `
|
|
230
|
+
* (5 000) and returns the first status whose `state` is not `pending` or `running`:
|
|
231
|
+
* `complete`, `failed` (returned, not thrown), or a state this SDK does not know yet.
|
|
232
|
+
* When nothing needs re-deriving, the service's `200` answer is returned as it is. A
|
|
233
|
+
* `409` `reingest_running` throws `ConflictError`. When `timeout` milliseconds
|
|
234
|
+
* (3 600 000) run out first, throws `WaitTimeoutError` with the last status as
|
|
235
|
+
* `lastStatus`; the run itself goes on. `timeout` is a deadline that also bounds each
|
|
236
|
+
* poll and its retries (see `HelperOptions`); it never prevents or cuts short the start,
|
|
237
|
+
* which has the client's own timeout. Aborting `signal` stops the helper and any pending
|
|
238
|
+
* poll, not the run. A poll that fails throws that call's error while the run goes on,
|
|
239
|
+
* with the last status read before it as `lastStatus`: its `run_id` lets the caller go
|
|
240
|
+
* on polling with `get()` instead of calling `run()` again, which throws `ConflictError`
|
|
241
|
+
* (`reingest_running`) until the run ends.
|
|
232
242
|
*
|
|
233
243
|
* A run takes at most `limit` memories, so a `complete` run can leave some for later
|
|
234
244
|
* (`remaining` above 0): calling `run()` again with the same parameters continues it.
|
package/dist/esm/client.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Each method describes one call: its HTTP method and path, where its fields go, and
|
|
4
4
|
// whether the SDK may retry it by itself. Core in core.ts sends it.
|
|
5
5
|
import { NenaviError, WaitTimeoutError } from './errors.js';
|
|
6
|
-
import { Core, helperDeadline, helperWait, ownProperties, pathParam, } from './core.js';
|
|
6
|
+
import { Core, helperDeadline, helperWait, ownProperties, pathParam, withCause, } from './core.js';
|
|
7
7
|
class Resource {
|
|
8
8
|
_core;
|
|
9
9
|
_raw;
|
|
@@ -23,8 +23,24 @@ class Resource {
|
|
|
23
23
|
return this._core.request(call, this._raw);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
|
|
26
|
+
/**
|
|
27
|
+
* The states a helper keeps polling through. Any other state, one the service adds later
|
|
28
|
+
* included, is final and returned.
|
|
29
|
+
*/
|
|
30
|
+
const WORKING = new Set(['pending', 'running']);
|
|
31
|
+
/** `GET /v1/events/{event_id}/extraction-status`, for the method and its helper. */
|
|
32
|
+
function extractionStatusCall(eventId, options) {
|
|
33
|
+
return {
|
|
34
|
+
method: 'GET',
|
|
35
|
+
path: `/v1/events/${pathParam(eventId)}/extraction-status`,
|
|
36
|
+
retrySafe: true,
|
|
37
|
+
options,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** `GET /v1/reingest/{run_id}`, for the method and its helper. */
|
|
41
|
+
function reingestGetCall(runId, options) {
|
|
42
|
+
return { method: 'GET', path: `/v1/reingest/${pathParam(runId)}`, retrySafe: true, options };
|
|
43
|
+
}
|
|
28
44
|
/** A caller's `Idempotency-Key`, or null; an empty value counts as not given. */
|
|
29
45
|
function callerKey(options) {
|
|
30
46
|
const key = ownProperties(options).idempotencyKey;
|
|
@@ -70,12 +86,7 @@ export class Events extends Resource {
|
|
|
70
86
|
}
|
|
71
87
|
/** `GET /v1/events/{event_id}/extraction-status`. */
|
|
72
88
|
extractionStatus(eventId, options) {
|
|
73
|
-
return this._request(() => (
|
|
74
|
-
method: 'GET',
|
|
75
|
-
path: `/v1/events/${pathParam(eventId)}/extraction-status`,
|
|
76
|
-
retrySafe: true,
|
|
77
|
-
options,
|
|
78
|
-
}));
|
|
89
|
+
return this._request(() => extractionStatusCall(eventId, options));
|
|
79
90
|
}
|
|
80
91
|
/** `POST /v1/events/{event_id}/retry-extraction`. Not retried automatically. */
|
|
81
92
|
retryExtraction(eventId, params, options) {
|
|
@@ -239,12 +250,7 @@ export class Reingest extends Resource {
|
|
|
239
250
|
}
|
|
240
251
|
/** `GET /v1/reingest/{run_id}`: the run's state, counts and usage. */
|
|
241
252
|
get(runId, options) {
|
|
242
|
-
return this._request(() => (
|
|
243
|
-
method: 'GET',
|
|
244
|
-
path: `/v1/reingest/${pathParam(runId)}`,
|
|
245
|
-
retrySafe: true,
|
|
246
|
-
options,
|
|
247
|
-
}));
|
|
253
|
+
return this._request(() => reingestGetCall(runId, options));
|
|
248
254
|
}
|
|
249
255
|
}
|
|
250
256
|
/** The claim routes: supersedences and contradictions. Not retried automatically. */
|
|
@@ -577,12 +583,14 @@ export class Learning extends Resource {
|
|
|
577
583
|
/** `client.events`: the event routes and `waitForExtraction()`. */
|
|
578
584
|
export class EventsWithHelpers extends Events {
|
|
579
585
|
/**
|
|
580
|
-
* Poll the event's extraction status until it is `
|
|
586
|
+
* Poll the event's extraction status until it is no longer `pending` or `running`.
|
|
581
587
|
*
|
|
582
588
|
* Polls `GET /v1/events/{event_id}/extraction-status` at once and then every
|
|
583
|
-
* `interval` milliseconds (2 000), and returns the
|
|
584
|
-
*
|
|
585
|
-
* `
|
|
589
|
+
* `interval` milliseconds (2 000), and returns the first status that is not `pending`
|
|
590
|
+
* or `running`: `complete`, `failed` (returned, not thrown), or a status this SDK does
|
|
591
|
+
* not know yet. When `timeout` milliseconds (300 000) run out first, throws
|
|
592
|
+
* `WaitTimeoutError` with the last status as `lastStatus`; `timeout` is a deadline that
|
|
593
|
+
* also bounds each poll and its retries (see `HelperOptions`). Aborting `signal` stops
|
|
586
594
|
* the helper and any pending poll or retry. Each poll is an ordinary call, with the
|
|
587
595
|
* client's retries and errors, and counts against the key's request rate limit like any
|
|
588
596
|
* other call, so many waits at once can slow the key's other calls. A job can stay
|
|
@@ -592,10 +600,26 @@ export class EventsWithHelpers extends Events {
|
|
|
592
600
|
const { timeout = 300_000, interval = 2_000, signal = null } = ownProperties(options);
|
|
593
601
|
const core = this._core;
|
|
594
602
|
const deadline = helperDeadline(core.now(), timeout, interval);
|
|
603
|
+
let lastStatus = null;
|
|
595
604
|
for (;;) {
|
|
596
|
-
|
|
597
|
-
|
|
605
|
+
let status;
|
|
606
|
+
try {
|
|
607
|
+
status = await this._request(() => ({
|
|
608
|
+
...extractionStatusCall(eventId, { signal }),
|
|
609
|
+
deadline,
|
|
610
|
+
}));
|
|
611
|
+
}
|
|
612
|
+
catch (error) {
|
|
613
|
+
// Only a poll the deadline stopped throws WaitTimeoutError; its own error is the cause.
|
|
614
|
+
if (!(error instanceof WaitTimeoutError))
|
|
615
|
+
throw error;
|
|
616
|
+
const last = lastStatus === null ? 'none' : JSON.stringify(lastStatus.status);
|
|
617
|
+
throw withCause(new WaitTimeoutError(`The extraction did not finish within ${timeout} ms: ${error.message}. The last ` +
|
|
618
|
+
`status read was ${last}.`, { lastStatus }), error.cause);
|
|
619
|
+
}
|
|
620
|
+
if (!WORKING.has(status.status))
|
|
598
621
|
return status;
|
|
622
|
+
lastStatus = status;
|
|
599
623
|
const wait = helperWait(core.now(), deadline, interval);
|
|
600
624
|
if (wait === null) {
|
|
601
625
|
throw new WaitTimeoutError(`The extraction did not finish within ${timeout} ms; its last status was ` +
|
|
@@ -618,7 +642,9 @@ export class NodesWithHelpers extends Nodes {
|
|
|
618
642
|
* `NenaviError`, so a scan never ends early without saying so.
|
|
619
643
|
*
|
|
620
644
|
* @example
|
|
621
|
-
* for await (const node of client.nodes.scanAll({ user_id: 'user-1' }))
|
|
645
|
+
* for await (const node of client.nodes.scanAll({ user_id: 'user-1', limit: 1000 })) {
|
|
646
|
+
* console.log(node.id);
|
|
647
|
+
* }
|
|
622
648
|
*/
|
|
623
649
|
async *scanAll(params, options) {
|
|
624
650
|
const given = ownProperties(params);
|
|
@@ -644,17 +670,21 @@ export class NodesWithHelpers extends Nodes {
|
|
|
644
670
|
/** `client.reingest`: the re-ingest routes and `run()`. */
|
|
645
671
|
export class ReingestWithHelpers extends Reingest {
|
|
646
672
|
/**
|
|
647
|
-
* Start a re-ingest run and poll it until its `state` is
|
|
673
|
+
* Start a re-ingest run and poll it until its `state` is final.
|
|
648
674
|
*
|
|
649
675
|
* Sends `start()` (`dry_run: false`), then polls `get()` every `interval` milliseconds
|
|
650
|
-
* (5 000) and returns the
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
* `
|
|
676
|
+
* (5 000) and returns the first status whose `state` is not `pending` or `running`:
|
|
677
|
+
* `complete`, `failed` (returned, not thrown), or a state this SDK does not know yet.
|
|
678
|
+
* When nothing needs re-deriving, the service's `200` answer is returned as it is. A
|
|
679
|
+
* `409` `reingest_running` throws `ConflictError`. When `timeout` milliseconds
|
|
680
|
+
* (3 600 000) run out first, throws `WaitTimeoutError` with the last status as
|
|
681
|
+
* `lastStatus`; the run itself goes on. `timeout` is a deadline that also bounds each
|
|
682
|
+
* poll and its retries (see `HelperOptions`); it never prevents or cuts short the start,
|
|
683
|
+
* which has the client's own timeout. Aborting `signal` stops the helper and any pending
|
|
684
|
+
* poll, not the run. A poll that fails throws that call's error while the run goes on,
|
|
685
|
+
* with the last status read before it as `lastStatus`: its `run_id` lets the caller go
|
|
686
|
+
* on polling with `get()` instead of calling `run()` again, which throws `ConflictError`
|
|
687
|
+
* (`reingest_running`) until the run ends.
|
|
658
688
|
*
|
|
659
689
|
* A run takes at most `limit` memories, so a `complete` run can leave some for later
|
|
660
690
|
* (`remaining` above 0): calling `run()` again with the same parameters continues it.
|
|
@@ -664,14 +694,32 @@ export class ReingestWithHelpers extends Reingest {
|
|
|
664
694
|
const core = this._core;
|
|
665
695
|
const deadline = helperDeadline(core.now(), timeout, interval);
|
|
666
696
|
let status = await this.start(params, { signal });
|
|
667
|
-
while (status.run_id !== null && status.run_id !== undefined &&
|
|
697
|
+
while (status.run_id !== null && status.run_id !== undefined && WORKING.has(status.state)) {
|
|
668
698
|
const wait = helperWait(core.now(), deadline, interval);
|
|
669
699
|
if (wait === null) {
|
|
670
700
|
throw new WaitTimeoutError(`The re-ingest run ${status.run_id} did not finish within ${timeout} ms; its ` +
|
|
671
701
|
`last state was ${JSON.stringify(status.state)}.`, { lastStatus: status });
|
|
672
702
|
}
|
|
673
703
|
await core.sleep(wait, signal);
|
|
674
|
-
|
|
704
|
+
const runId = status.run_id;
|
|
705
|
+
try {
|
|
706
|
+
status = await this._request(() => ({
|
|
707
|
+
...reingestGetCall(runId, { signal }),
|
|
708
|
+
deadline,
|
|
709
|
+
}));
|
|
710
|
+
}
|
|
711
|
+
catch (error) {
|
|
712
|
+
// A poll the deadline stopped throws WaitTimeoutError; its own error is the cause.
|
|
713
|
+
if (error instanceof WaitTimeoutError) {
|
|
714
|
+
throw withCause(new WaitTimeoutError(`The re-ingest run ${runId} did not finish within ${timeout} ms: ` +
|
|
715
|
+
`${error.message}. Its last state was ${JSON.stringify(status.state)}.`, { lastStatus: status }), error.cause);
|
|
716
|
+
}
|
|
717
|
+
// The run goes on; without its id the caller could only call run() again, which
|
|
718
|
+
// the service refuses with 409 until the run ends. An abort keeps its own reason.
|
|
719
|
+
if (error instanceof NenaviError && !signal?.aborted)
|
|
720
|
+
error.lastStatus = status;
|
|
721
|
+
throw error;
|
|
722
|
+
}
|
|
675
723
|
}
|
|
676
724
|
return status;
|
|
677
725
|
}
|
package/dist/esm/core.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NenaviError } from './errors.js';
|
|
1
2
|
/** The `fetch` the SDK calls: the runtime's own, or one the caller passes. */
|
|
2
3
|
export type Fetch = (input: string, init: RequestInit) => Promise<Response>;
|
|
3
4
|
export interface ClientOptions {
|
|
@@ -46,6 +47,11 @@ export interface Call {
|
|
|
46
47
|
options?: RequestOptions | undefined;
|
|
47
48
|
/** The JSON type of the answer: an object (the default), an array, or an object or null. */
|
|
48
49
|
answer?: 'object' | 'array' | 'nullable';
|
|
50
|
+
/**
|
|
51
|
+
* A helper's deadline on `Core.now`: it caps each attempt's timeout and stops a retry
|
|
52
|
+
* whose wait would end past it. Unset for an ordinary call.
|
|
53
|
+
*/
|
|
54
|
+
deadline?: number;
|
|
49
55
|
}
|
|
50
56
|
/** Encode one path parameter, so a value cannot add or change path segments. */
|
|
51
57
|
export declare function pathParam(value: string): string;
|
|
@@ -57,6 +63,8 @@ export declare function helperDeadline(now: number, timeout: number, interval: n
|
|
|
57
63
|
export declare function helperWait(now: number, deadline: number, interval: number): number | null;
|
|
58
64
|
/** Wait `ms` milliseconds, or reject with the signal's reason when it is aborted first. */
|
|
59
65
|
export declare function sleep(ms: number, signal?: AbortSignal | null): Promise<void>;
|
|
66
|
+
/** Set `cause` as the `Error` constructor does: an own property that is not enumerable. */
|
|
67
|
+
export declare function withCause<E extends Error>(error: E, cause: NenaviError): E;
|
|
60
68
|
/** Holds the configuration and sends the calls. The key is a private field. */
|
|
61
69
|
export declare class Core {
|
|
62
70
|
#private;
|
package/dist/esm/core.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Everything that decides what to send, whether to retry, how long to wait and which
|
|
4
4
|
// error to throw lives here. The method classes in client.ts only describe each call.
|
|
5
|
-
import { APIConnectionError, APIError, APITimeoutError, ConfigurationError, DETAIL_TEXT_LIMIT, NenaviError, RateLimitError, ResponseValidationError, ServiceUnavailableError, errorFromResponse, parseRetryAfter, } from './errors.js';
|
|
5
|
+
import { APIConnectionError, APIError, APITimeoutError, ConfigurationError, DETAIL_TEXT_LIMIT, NenaviError, RateLimitError, ResponseValidationError, ServiceUnavailableError, WaitTimeoutError, errorFromResponse, parseRetryAfter, } from './errors.js';
|
|
6
6
|
import { VERSION } from './version.js';
|
|
7
7
|
const DEFAULT_BASE_URL = 'https://api.prismemory.com';
|
|
8
8
|
/** Milliseconds per attempt. */
|
|
@@ -12,6 +12,11 @@ const DEFAULT_MAX_RETRIES = 2;
|
|
|
12
12
|
const MAX_RETRY_AFTER = 60;
|
|
13
13
|
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
14
14
|
const RETRYABLE_503 = new Set(['database_unavailable', 'lease_unavailable']);
|
|
15
|
+
/**
|
|
16
|
+
* Milliseconds: the shortest attempt timeout a helper's poll gets near its deadline, so the
|
|
17
|
+
* poll at the deadline (and the one poll of `timeout: 0`) can still be answered.
|
|
18
|
+
*/
|
|
19
|
+
const MIN_POLL_TIMEOUT = 1_000;
|
|
15
20
|
/** The longest delay setTimeout keeps: a longer one fires at once. */
|
|
16
21
|
const MAX_TIMEOUT = 2_147_483_647;
|
|
17
22
|
// Visible ASCII only: what an HTTP header can carry without encoding. This is not a check
|
|
@@ -193,6 +198,21 @@ function retryWait(error, retryNumber) {
|
|
|
193
198
|
}
|
|
194
199
|
return null;
|
|
195
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* The error for a helper's poll that its deadline stopped; the helper adds its status. The
|
|
203
|
+
* poll's own error becomes its `cause`.
|
|
204
|
+
*/
|
|
205
|
+
function deadlineError(error, retrySkipped) {
|
|
206
|
+
const reason = retrySkipped
|
|
207
|
+
? `the last poll threw ${error.name}, and its retry would have waited past the deadline`
|
|
208
|
+
: `the last poll got no answer before the deadline (${error.name})`;
|
|
209
|
+
return withCause(new WaitTimeoutError(reason, { idempotencyKey: error.idempotencyKey }), error);
|
|
210
|
+
}
|
|
211
|
+
/** Set `cause` as the `Error` constructor does: an own property that is not enumerable. */
|
|
212
|
+
export function withCause(error, cause) {
|
|
213
|
+
Object.defineProperty(error, 'cause', { value: cause, writable: true, configurable: true });
|
|
214
|
+
return error;
|
|
215
|
+
}
|
|
196
216
|
/** The name, and the system error code when there is one, of what fetch threw. */
|
|
197
217
|
function failureName(error) {
|
|
198
218
|
const raw = error instanceof Error ? error.name : typeof error;
|
|
@@ -256,7 +276,8 @@ export class Core {
|
|
|
256
276
|
if (auth && this.#apiKey === null) {
|
|
257
277
|
throw new ConfigurationError('No API key: pass apiKey or set NENAVI_API_KEY. Only health() works without a key.');
|
|
258
278
|
}
|
|
259
|
-
const
|
|
279
|
+
const callTimeout = checkTimeout(options.timeout ?? this.timeout);
|
|
280
|
+
const deadline = call.deadline ?? null;
|
|
260
281
|
const maxRetries = checkMaxRetries(options.maxRetries ?? this.maxRetries);
|
|
261
282
|
const idempotencyKey = call.idempotencyKey ?? null;
|
|
262
283
|
const headers = {
|
|
@@ -280,6 +301,10 @@ export class Core {
|
|
|
280
301
|
const url = `${this.baseURL}${call.path}${queryString(call.query)}`;
|
|
281
302
|
let retries = 0;
|
|
282
303
|
for (;;) {
|
|
304
|
+
// A helper's poll gets only the time left.
|
|
305
|
+
const left = deadline === null ? Infinity : Math.max(deadline - this.now(), MIN_POLL_TIMEOUT);
|
|
306
|
+
const shortened = left < callTimeout;
|
|
307
|
+
const timeout = shortened ? left : callTimeout;
|
|
283
308
|
const attempt = await this.#send(url, call.method, headers, body, timeout, signal, idempotencyKey);
|
|
284
309
|
if (attempt.response !== undefined) {
|
|
285
310
|
return this.#result(attempt.response, attempt.text, raw, idempotencyKey, call.answer ?? 'object');
|
|
@@ -287,11 +312,17 @@ export class Core {
|
|
|
287
312
|
if (call.retrySafe && retries < maxRetries) {
|
|
288
313
|
const wait = retryWait(attempt.error, retries + 1);
|
|
289
314
|
if (wait !== null) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
315
|
+
if (deadline === null || this.now() + wait < deadline) {
|
|
316
|
+
retries += 1;
|
|
317
|
+
await this.sleep(wait, signal);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
throw deadlineError(attempt.error, true);
|
|
293
321
|
}
|
|
294
322
|
}
|
|
323
|
+
if (shortened && attempt.error instanceof APITimeoutError) {
|
|
324
|
+
throw deadlineError(attempt.error, false);
|
|
325
|
+
}
|
|
295
326
|
throw attempt.error;
|
|
296
327
|
}
|
|
297
328
|
}
|
package/dist/esm/errors.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
/** Base class of every error the SDK throws. */
|
|
2
2
|
export declare class NenaviError extends Error {
|
|
3
|
+
/**
|
|
4
|
+
* `value instanceof` this class, also for an error from another copy of the package.
|
|
5
|
+
* Installed below with `Object.defineProperty`.
|
|
6
|
+
*/
|
|
7
|
+
static [Symbol.hasInstance]: <T>(this: abstract new (...args: never[]) => T, value: unknown) => value is T;
|
|
3
8
|
/** The `Idempotency-Key` the call sent, or null when it sent none. */
|
|
4
9
|
idempotencyKey: string | null;
|
|
10
|
+
/**
|
|
11
|
+
* The last status a helper read before it threw: on `WaitTimeoutError`, and on the
|
|
12
|
+
* error of a poll that failed inside `reingest.run()`, where it holds the run's
|
|
13
|
+
* `run_id`. Null on other errors.
|
|
14
|
+
*/
|
|
15
|
+
lastStatus: unknown;
|
|
5
16
|
constructor(message: string, options?: {
|
|
6
17
|
idempotencyKey?: string | null;
|
|
18
|
+
lastStatus?: unknown;
|
|
7
19
|
});
|
|
8
20
|
}
|
|
9
21
|
/** No key for an operation that needs one, or an invalid option. */
|
|
@@ -11,12 +23,6 @@ export declare class ConfigurationError extends NenaviError {
|
|
|
11
23
|
}
|
|
12
24
|
/** A helper ran out of time before the work it waited for finished. */
|
|
13
25
|
export declare class WaitTimeoutError extends NenaviError {
|
|
14
|
-
/** The last status the helper read. */
|
|
15
|
-
lastStatus: unknown;
|
|
16
|
-
constructor(message: string, options?: {
|
|
17
|
-
lastStatus?: unknown;
|
|
18
|
-
idempotencyKey?: string | null;
|
|
19
|
-
});
|
|
20
26
|
}
|
|
21
27
|
export interface ResponseValidationErrorOptions {
|
|
22
28
|
status: number;
|
package/dist/esm/errors.js
CHANGED
|
@@ -3,26 +3,73 @@
|
|
|
3
3
|
// An error holds plain values only: the status, a copy of the response headers and the
|
|
4
4
|
// parsed body. It never holds a Request, a Response or the error fetch threw, so the
|
|
5
5
|
// `Authorization` header cannot reach a message, `util.inspect` or `JSON.stringify`.
|
|
6
|
+
//
|
|
7
|
+
// The package ships an ES module build and a CommonJS build, and a process that loads
|
|
8
|
+
// both holds two copies of every class here. So that `instanceof` still works across the
|
|
9
|
+
// copies, each class's prototype carries its name under a key in the global symbol
|
|
10
|
+
// registry, and `instanceof` falls back to matching that name along the prototype chain.
|
|
11
|
+
/**
|
|
12
|
+
* The key, shared by every copy of the package, under which a prototype names its class.
|
|
13
|
+
*
|
|
14
|
+
* Copies of different versions match each other by this key and the class name alone, so
|
|
15
|
+
* the key is a contract between versions. A release that changes an error class's fields
|
|
16
|
+
* incompatibly must change the key (for example to `nenavi.error.class.v2`), so that its
|
|
17
|
+
* errors stop matching older copies' classes instead of narrowing to the old shape.
|
|
18
|
+
*/
|
|
19
|
+
const CLASS_NAME = Symbol.for('nenavi.error.class');
|
|
6
20
|
/** Base class of every error the SDK throws. */
|
|
7
21
|
export class NenaviError extends Error {
|
|
8
22
|
/** The `Idempotency-Key` the call sent, or null when it sent none. */
|
|
9
23
|
idempotencyKey;
|
|
24
|
+
/**
|
|
25
|
+
* The last status a helper read before it threw: on `WaitTimeoutError`, and on the
|
|
26
|
+
* error of a poll that failed inside `reingest.run()`, where it holds the run's
|
|
27
|
+
* `run_id`. Null on other errors.
|
|
28
|
+
*/
|
|
29
|
+
lastStatus;
|
|
10
30
|
constructor(message, options = {}) {
|
|
11
31
|
super(message);
|
|
12
32
|
this.idempotencyKey = options.idempotencyKey ?? null;
|
|
33
|
+
this.lastStatus = options.lastStatus ?? null;
|
|
13
34
|
}
|
|
14
35
|
}
|
|
36
|
+
// The ordinary check comes first. Failing that, a class of this package matches a value
|
|
37
|
+
// whose prototype chain holds a prototype marked with the same class name, as the other
|
|
38
|
+
// copy's classes are. A subclass written outside the package keeps the ordinary check.
|
|
39
|
+
//
|
|
40
|
+
// This is defined as a property rather than written as a static method, because a loose
|
|
41
|
+
// class transform in a consumer's build turns a static method into an assignment, and
|
|
42
|
+
// assigning over the read-only `Function.prototype[Symbol.hasInstance]` throws.
|
|
43
|
+
Object.defineProperty(NenaviError, Symbol.hasInstance, {
|
|
44
|
+
value: function hasInstance(value) {
|
|
45
|
+
if (Function.prototype[Symbol.hasInstance].call(this, value))
|
|
46
|
+
return true;
|
|
47
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const prototype = this.prototype;
|
|
51
|
+
if (typeof prototype !== 'object' || prototype === null)
|
|
52
|
+
return false;
|
|
53
|
+
if (!Object.hasOwn(prototype, CLASS_NAME))
|
|
54
|
+
return false;
|
|
55
|
+
const name = prototype[CLASS_NAME];
|
|
56
|
+
for (let link = Object.getPrototypeOf(value); link !== null; link = Object.getPrototypeOf(link)) {
|
|
57
|
+
if (Object.hasOwn(link, CLASS_NAME) &&
|
|
58
|
+
link[CLASS_NAME] === name) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
},
|
|
64
|
+
writable: true,
|
|
65
|
+
enumerable: false,
|
|
66
|
+
configurable: true,
|
|
67
|
+
});
|
|
15
68
|
/** No key for an operation that needs one, or an invalid option. */
|
|
16
69
|
export class ConfigurationError extends NenaviError {
|
|
17
70
|
}
|
|
18
71
|
/** A helper ran out of time before the work it waited for finished. */
|
|
19
72
|
export class WaitTimeoutError extends NenaviError {
|
|
20
|
-
/** The last status the helper read. */
|
|
21
|
-
lastStatus;
|
|
22
|
-
constructor(message, options = {}) {
|
|
23
|
-
super(message, options);
|
|
24
|
-
this.lastStatus = options.lastStatus ?? null;
|
|
25
|
-
}
|
|
26
73
|
}
|
|
27
74
|
/**
|
|
28
75
|
* A 2xx response whose body does not match the shape the operation answers with.
|
|
@@ -117,7 +164,8 @@ export class InternalServerError extends APIError {
|
|
|
117
164
|
export class ServiceUnavailableError extends APIError {
|
|
118
165
|
}
|
|
119
166
|
// Each class's name, written out so that `error.name` survives a minifier that renames
|
|
120
|
-
// classes. It sits on the prototype, so it is not an own property of an error.
|
|
167
|
+
// classes. It sits on the prototype, so it is not an own property of an error. The same
|
|
168
|
+
// name marks the prototype under CLASS_NAME for the cross-copy `instanceof` above.
|
|
121
169
|
const NAMES = [
|
|
122
170
|
[NenaviError, 'NenaviError'],
|
|
123
171
|
[ConfigurationError, 'ConfigurationError'],
|
|
@@ -145,6 +193,12 @@ for (const [ErrorClass, name] of NAMES) {
|
|
|
145
193
|
enumerable: false,
|
|
146
194
|
configurable: true,
|
|
147
195
|
});
|
|
196
|
+
Object.defineProperty(ErrorClass.prototype, CLASS_NAME, {
|
|
197
|
+
value: name,
|
|
198
|
+
writable: false,
|
|
199
|
+
enumerable: false,
|
|
200
|
+
configurable: false,
|
|
201
|
+
});
|
|
148
202
|
}
|
|
149
203
|
const BY_STATUS = {
|
|
150
204
|
400: BadRequestError,
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The SDK's version, sent in the `User-Agent` header. test/client.test.ts keeps it equal to package.json. */
|
|
2
|
-
export declare const VERSION = "0.1.0-alpha.
|
|
2
|
+
export declare const VERSION = "0.1.0-alpha.2";
|
package/dist/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The SDK's version, sent in the `User-Agent` header. test/client.test.ts keeps it equal to package.json. */
|
|
2
|
-
export const VERSION = '0.1.0-alpha.
|
|
2
|
+
export const VERSION = '0.1.0-alpha.2';
|