@mfxhub/sdk 0.2.0 → 0.2.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/CHANGELOG.md +16 -0
- package/dist/client.js +2 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/stream.d.ts +4 -1
- package/dist/stream.js +26 -2
- package/dist/version.d.ts +4 -0
- package/dist/version.js +5 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ Every release of `@mfxhub/sdk`, newest first. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## 0.2.2
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `stream.close()` ends the stream for good. A `next()` or a `for await` loop waiting for a message
|
|
12
|
+
ends with nothing, and a reconnect under way is given up. Before, closing while a read waited
|
|
13
|
+
made the stream reconnect and keep delivering, so a script that closed its stream did not end.
|
|
14
|
+
|
|
15
|
+
## 0.2.1
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Every request the SDK sends, and the stream's upgrade, carries
|
|
20
|
+
`User-Agent: mfx-sdk-typescript/<version>`, built from the package's own version, so MFX Hub can
|
|
21
|
+
tell which SDK and which version made each call.
|
|
22
|
+
|
|
7
23
|
## 0.2.0
|
|
8
24
|
|
|
9
25
|
### Added
|
package/dist/client.js
CHANGED
|
@@ -12,6 +12,7 @@ import { Catalog } from "./catalog.js";
|
|
|
12
12
|
import { Execution } from "./execution.js";
|
|
13
13
|
import { MfxStream } from "./stream.js";
|
|
14
14
|
import { Terminals } from "./terminals.js";
|
|
15
|
+
import { USER_AGENT } from "./version.js";
|
|
15
16
|
/** Default time a single request may take. */
|
|
16
17
|
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
17
18
|
/** How many times a rate-limited read is tried again. */
|
|
@@ -138,6 +139,7 @@ export class MfxClient {
|
|
|
138
139
|
const body = spec.body === undefined ? new Uint8Array() : Buffer.from(JSON.stringify(spec.body));
|
|
139
140
|
const headers = {
|
|
140
141
|
Accept: "application/json",
|
|
142
|
+
"User-Agent": USER_AGENT,
|
|
141
143
|
...this.#signer.headersFor(spec.method, url.pathname + url.search, body),
|
|
142
144
|
};
|
|
143
145
|
if (spec.body !== undefined)
|
package/dist/index.d.ts
CHANGED
|
@@ -25,5 +25,4 @@ export type { CreateTerminal, JournalLine, JournalOptions, PageOptions, Redundan
|
|
|
25
25
|
export { RequestSigner, SigningKey, signingMessage } from "./signing.js";
|
|
26
26
|
export { KEY_HEADER, NONCE_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER } from "./signing.js";
|
|
27
27
|
export type { components, operations, paths } from "./generated/api.js";
|
|
28
|
-
|
|
29
|
-
export declare const VERSION = "0.2.0";
|
|
28
|
+
export { VERSION } from "./version.js";
|
package/dist/index.js
CHANGED
|
@@ -16,5 +16,4 @@ export { CLOSE_LIFETIME, CLOSE_REAUTHENTICATE, CLOSE_SLOW_CONSUMER, Channel, Cha
|
|
|
16
16
|
export { Terminals, isUsable } from "./terminals.js";
|
|
17
17
|
export { RequestSigner, SigningKey, signingMessage } from "./signing.js";
|
|
18
18
|
export { KEY_HEADER, NONCE_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER } from "./signing.js";
|
|
19
|
-
|
|
20
|
-
export const VERSION = "0.2.0";
|
|
19
|
+
export { VERSION } from "./version.js";
|
package/dist/stream.d.ts
CHANGED
|
@@ -127,7 +127,10 @@ export declare class MfxStream implements AsyncIterable<StreamEvent> {
|
|
|
127
127
|
resume(channel: string): Promise<void>;
|
|
128
128
|
/** Stop watching a channel, and stop subscribing to it again after a reconnect. */
|
|
129
129
|
unsubscribe(channel: string): Promise<void>;
|
|
130
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Close the stream for good. A read waiting on it ends with null, a reconnect under way is
|
|
132
|
+
* given up, and the stream is never opened again.
|
|
133
|
+
*/
|
|
131
134
|
close(): Promise<void>;
|
|
132
135
|
[Symbol.asyncIterator](): AsyncGenerator<StreamEvent, void, undefined>;
|
|
133
136
|
/**
|
package/dist/stream.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
// The upgrade is signed exactly as a REST request is, over `GET /v1/stream`.
|
|
24
24
|
import WebSocket from "ws";
|
|
25
25
|
import { AuthError, MfxError, MfxTransportError, errorFor } from "./errors.js";
|
|
26
|
+
import { USER_AGENT } from "./version.js";
|
|
26
27
|
/** The server says why it hung up. 4001 is the one reconnecting cannot fix. */
|
|
27
28
|
export const CLOSE_REAUTHENTICATE = 4001;
|
|
28
29
|
export const CLOSE_SLOW_CONSUMER = 4008;
|
|
@@ -207,6 +208,8 @@ export class MfxStream {
|
|
|
207
208
|
refused: 0,
|
|
208
209
|
};
|
|
209
210
|
#connection = null;
|
|
211
|
+
/** The caller closed the stream: nothing reconnects it, and every read is null from here on. */
|
|
212
|
+
#closed = false;
|
|
210
213
|
/** Use {@link MfxClient.stream}. */
|
|
211
214
|
constructor(client, options = {}) {
|
|
212
215
|
this.#client = client;
|
|
@@ -225,7 +228,10 @@ export class MfxStream {
|
|
|
225
228
|
/** Opens the connection. {@link MfxClient.stream} does this for you. */
|
|
226
229
|
async open() {
|
|
227
230
|
const path = new URL(this.#url).pathname;
|
|
228
|
-
this.#connection = await this.#connect(this.#url,
|
|
231
|
+
this.#connection = await this.#connect(this.#url, {
|
|
232
|
+
...this.#client.signer.headersFor("GET", path),
|
|
233
|
+
"User-Agent": USER_AGENT,
|
|
234
|
+
});
|
|
229
235
|
return this;
|
|
230
236
|
}
|
|
231
237
|
/** Subscribe to one channel. Subscribing twice is not an error. */
|
|
@@ -254,8 +260,12 @@ export class MfxStream {
|
|
|
254
260
|
this.#channels.delete(channel);
|
|
255
261
|
await this.#send({ op: "unsubscribe", ch: channel });
|
|
256
262
|
}
|
|
257
|
-
/**
|
|
263
|
+
/**
|
|
264
|
+
* Close the stream for good. A read waiting on it ends with null, a reconnect under way is
|
|
265
|
+
* given up, and the stream is never opened again.
|
|
266
|
+
*/
|
|
258
267
|
async close() {
|
|
268
|
+
this.#closed = true;
|
|
259
269
|
const connection = this.#connection;
|
|
260
270
|
this.#connection = null;
|
|
261
271
|
if (connection !== null)
|
|
@@ -283,6 +293,9 @@ export class MfxStream {
|
|
|
283
293
|
raw = await connection.recv();
|
|
284
294
|
}
|
|
285
295
|
catch (error) {
|
|
296
|
+
// The caller's own close ends the read; it is not a drop to come back from.
|
|
297
|
+
if (this.#closed)
|
|
298
|
+
return null;
|
|
286
299
|
if (!(error instanceof StreamClosed))
|
|
287
300
|
throw error;
|
|
288
301
|
if (!(await this.#reopen(error)))
|
|
@@ -358,7 +371,14 @@ export class MfxStream {
|
|
|
358
371
|
this.#bump("reconnects");
|
|
359
372
|
// The client's own backoff, so the stream and the reads lean on this tenant's quota alike.
|
|
360
373
|
await this.#client.pause(this.#client.backoffMs(this.#stats.reconnects));
|
|
374
|
+
if (this.#closedNow())
|
|
375
|
+
return false; // closed while waiting out the backoff
|
|
361
376
|
await this.open();
|
|
377
|
+
if (this.#closedNow()) {
|
|
378
|
+
// closed while the connection was being opened: that one is closed too
|
|
379
|
+
await this.close();
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
362
382
|
for (const [channel, last] of [...this.#channels]) {
|
|
363
383
|
if (replayable(channel) && last !== null) {
|
|
364
384
|
await this.#send({ op: "resume", ch: channel, after_seq: last });
|
|
@@ -372,6 +392,10 @@ export class MfxStream {
|
|
|
372
392
|
}
|
|
373
393
|
return true;
|
|
374
394
|
}
|
|
395
|
+
/** Read afresh after an await: close() may have run while this was waiting. */
|
|
396
|
+
#closedNow() {
|
|
397
|
+
return this.#closed;
|
|
398
|
+
}
|
|
375
399
|
async #send(message) {
|
|
376
400
|
const connection = this.#connection;
|
|
377
401
|
if (connection === null)
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// This package's version, in one place: exported by the package, and named by every request.
|
|
2
|
+
/** This package's version. */
|
|
3
|
+
export const VERSION = "0.2.2";
|
|
4
|
+
/** What every request says it is, as a product token: the SDK's language and its version. */
|
|
5
|
+
export const USER_AGENT = `mfx-sdk-typescript/${VERSION}`;
|
package/package.json
CHANGED