@alpamayo-solutions/colca-client 0.0.0 → 0.1.9
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 +143 -3
- package/dist/door.d.ts +155 -0
- package/dist/door.d.ts.map +1 -0
- package/dist/door.js +212 -0
- package/dist/door.js.map +1 -0
- package/dist/generated/contracts.d.ts +626 -0
- package/dist/generated/contracts.d.ts.map +1 -0
- package/dist/generated/contracts.js +39 -0
- package/dist/generated/contracts.js.map +1 -0
- package/dist/ids.d.ts +36 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +64 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/live.d.ts +148 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +500 -0
- package/dist/live.js.map +1 -0
- package/dist/stream.d.ts +54 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +85 -0
- package/dist/stream.js.map +1 -0
- package/dist/topics.d.ts +45 -0
- package/dist/topics.d.ts.map +1 -0
- package/dist/topics.js +70 -0
- package/dist/topics.js.map +1 -0
- package/package.json +66 -3
- package/LICENSE.md +0 -105
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/generated/contracts.ts"],"names":[],"mappings":"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"}
|
package/dist/ids.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derived record ids.
|
|
3
|
+
*
|
|
4
|
+
* An annotation's id is computed, not drawn: create, update and delete of one
|
|
5
|
+
* annotation are appends under the same id, so a producer that runs again
|
|
6
|
+
* overwrites its own record instead of doubling it. Every client must therefore
|
|
7
|
+
* compute it exactly as `colca-data-contracts` does — `spec/vectors.json` holds
|
|
8
|
+
* the cases that prove it, including the one where the microseconds decide.
|
|
9
|
+
*/
|
|
10
|
+
export interface AnnotationIdInput {
|
|
11
|
+
annotationTypeId: string;
|
|
12
|
+
source: string;
|
|
13
|
+
/** Unix seconds. Six decimals are part of the identity; the seventh is not. */
|
|
14
|
+
timeStart: number;
|
|
15
|
+
/** The set is sorted before hashing, so the order it arrives in does not matter. */
|
|
16
|
+
signalIds: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `SHA-256("{type}|{source}|{time:.6f}|{sorted,signals}")`, first 16 bytes,
|
|
20
|
+
* ULID-encoded.
|
|
21
|
+
*
|
|
22
|
+
* Async because it hashes with WebCrypto, the one digest both Node and a
|
|
23
|
+
* browser have without a dependency.
|
|
24
|
+
*/
|
|
25
|
+
export declare function deriveAnnotationId(input: AnnotationIdInput): Promise<string>;
|
|
26
|
+
/** The string that gets hashed. Exported for the conformance test's error messages. */
|
|
27
|
+
export declare function annotationIdMaterial({ annotationTypeId, source, timeStart, signalIds, }: AnnotationIdInput): string;
|
|
28
|
+
/**
|
|
29
|
+
* A new ULID: 48 bits of unix milliseconds, then 80 random bits. Ids made later
|
|
30
|
+
* sort later, which is the shape the node's own ids have — use it for command ids
|
|
31
|
+
* and correlation ids.
|
|
32
|
+
*/
|
|
33
|
+
export declare function newUlid(now?: number): string;
|
|
34
|
+
/** Crockford base32 over 128 bits, the 26-character ULID text. */
|
|
35
|
+
export declare function ulidFromBytes(bytes: Uint8Array): string;
|
|
36
|
+
//# sourceMappingURL=ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlF;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,EACnC,gBAAgB,EAChB,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE,iBAAiB,GAAG,MAAM,CAM5B;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,GAAE,MAAmB,GAAG,MAAM,CAYxD;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAYvD"}
|
package/dist/ids.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derived record ids.
|
|
3
|
+
*
|
|
4
|
+
* An annotation's id is computed, not drawn: create, update and delete of one
|
|
5
|
+
* annotation are appends under the same id, so a producer that runs again
|
|
6
|
+
* overwrites its own record instead of doubling it. Every client must therefore
|
|
7
|
+
* compute it exactly as `colca-data-contracts` does — `spec/vectors.json` holds
|
|
8
|
+
* the cases that prove it, including the one where the microseconds decide.
|
|
9
|
+
*/
|
|
10
|
+
const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
11
|
+
/**
|
|
12
|
+
* `SHA-256("{type}|{source}|{time:.6f}|{sorted,signals}")`, first 16 bytes,
|
|
13
|
+
* ULID-encoded.
|
|
14
|
+
*
|
|
15
|
+
* Async because it hashes with WebCrypto, the one digest both Node and a
|
|
16
|
+
* browser have without a dependency.
|
|
17
|
+
*/
|
|
18
|
+
export async function deriveAnnotationId(input) {
|
|
19
|
+
const material = annotationIdMaterial(input);
|
|
20
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(material));
|
|
21
|
+
return ulidFromBytes(new Uint8Array(digest, 0, 16));
|
|
22
|
+
}
|
|
23
|
+
/** The string that gets hashed. Exported for the conformance test's error messages. */
|
|
24
|
+
export function annotationIdMaterial({ annotationTypeId, source, timeStart, signalIds, }) {
|
|
25
|
+
if (!Number.isFinite(timeStart)) {
|
|
26
|
+
throw new Error(`timeStart must be a finite unix time, got ${String(timeStart)}`);
|
|
27
|
+
}
|
|
28
|
+
const signals = [...signalIds].sort().join(",");
|
|
29
|
+
return `${annotationTypeId}|${source}|${timeStart.toFixed(6)}|${signals}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A new ULID: 48 bits of unix milliseconds, then 80 random bits. Ids made later
|
|
33
|
+
* sort later, which is the shape the node's own ids have — use it for command ids
|
|
34
|
+
* and correlation ids.
|
|
35
|
+
*/
|
|
36
|
+
export function newUlid(now = Date.now()) {
|
|
37
|
+
if (!Number.isInteger(now) || now < 0 || now >= 2 ** 48) {
|
|
38
|
+
throw new Error(`a ULID time is whole milliseconds between 0 and 2^48, got ${String(now)}`);
|
|
39
|
+
}
|
|
40
|
+
const bytes = new Uint8Array(16);
|
|
41
|
+
let time = now;
|
|
42
|
+
for (let i = 5; i >= 0; i -= 1) {
|
|
43
|
+
bytes[i] = time % 256;
|
|
44
|
+
time = Math.floor(time / 256);
|
|
45
|
+
}
|
|
46
|
+
crypto.getRandomValues(bytes.subarray(6));
|
|
47
|
+
return ulidFromBytes(bytes);
|
|
48
|
+
}
|
|
49
|
+
/** Crockford base32 over 128 bits, the 26-character ULID text. */
|
|
50
|
+
export function ulidFromBytes(bytes) {
|
|
51
|
+
if (bytes.length !== 16) {
|
|
52
|
+
throw new Error(`a ULID is 16 bytes, got ${String(bytes.length)}`);
|
|
53
|
+
}
|
|
54
|
+
let value = 0n;
|
|
55
|
+
for (const byte of bytes)
|
|
56
|
+
value = (value << 8n) | BigInt(byte);
|
|
57
|
+
let out = "";
|
|
58
|
+
for (let i = 0; i < 26; i += 1) {
|
|
59
|
+
out = CROCKFORD[Number(value & 31n)] + out;
|
|
60
|
+
value >>= 5n;
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=ids.js.map
|
package/dist/ids.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,SAAS,GAAG,kCAAkC,CAAC;AAWrD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAwB;IAC/D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzF,OAAO,aAAa,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,oBAAoB,CAAC,EACnC,gBAAgB,EAChB,MAAM,EACN,SAAS,EACT,SAAS,GACS;IAClB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,6CAA6C,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,OAAO,GAAG,gBAAgB,IAAI,MAAM,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,MAAc,IAAI,CAAC,GAAG,EAAE;IAC9C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,6DAA6D,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,IAAI,GAAG,GAAG,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC;QACtB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;QAC3C,KAAK,KAAK,EAAE,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* colca-client — the door, in TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* const door = new Door({ baseUrl: "http://colca", service: "my-app" });
|
|
6
|
+
* const stream = new Stream(door, "annotations", door.cursorName("panels"));
|
|
7
|
+
* for await (const record of stream.follow()) {
|
|
8
|
+
* console.log(record.topic, record.payload);
|
|
9
|
+
* }
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export { Door, DoorError } from "./door.js";
|
|
13
|
+
export type { Attribution, DoorOptions, DoorRecord, FetchOptions, Gap, KvEntry, Page, PublishResult, SelfInfo, } from "./door.js";
|
|
14
|
+
export { Stream } from "./stream.js";
|
|
15
|
+
export type { FollowOptions, StreamOptions } from "./stream.js";
|
|
16
|
+
export { DEFAULT_ROOT, TOPIC_VERSION, parseTopic, topic, topicMatches, topicPrefix } from "./topics.js";
|
|
17
|
+
export type { TopicOptions, TopicParts } from "./topics.js";
|
|
18
|
+
export { annotationIdMaterial, deriveAnnotationId, newUlid, ulidFromBytes } from "./ids.js";
|
|
19
|
+
export type { AnnotationIdInput } from "./ids.js";
|
|
20
|
+
export * from "./generated/contracts.js";
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,GAAG,EACH,OAAO,EACP,IAAI,EACJ,aAAa,EACb,QAAQ,GACT,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxG,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC5F,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* colca-client — the door, in TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* const door = new Door({ baseUrl: "http://colca", service: "my-app" });
|
|
6
|
+
* const stream = new Stream(door, "annotations", door.cursorName("panels"));
|
|
7
|
+
* for await (const record of stream.follow()) {
|
|
8
|
+
* console.log(record.topic, record.payload);
|
|
9
|
+
* }
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export { Door, DoorError } from "./door.js";
|
|
13
|
+
export { Stream } from "./stream.js";
|
|
14
|
+
export { DEFAULT_ROOT, TOPIC_VERSION, parseTopic, topic, topicMatches, topicPrefix } from "./topics.js";
|
|
15
|
+
export { annotationIdMaterial, deriveAnnotationId, newUlid, ulidFromBytes } from "./ids.js";
|
|
16
|
+
// The 32 contracts, straight from the bundle the node validates against.
|
|
17
|
+
export * from "./generated/contracts.js";
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAa5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGxG,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG5F,yEAAyE;AACzE,cAAc,0BAA0B,CAAC"}
|
package/dist/live.d.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live values over MQTT, for a page or a service that wants them pushed.
|
|
3
|
+
*
|
|
4
|
+
* Colca retains the current value of every data and entity path, so a
|
|
5
|
+
* subscription brings the present state first and the changes after it. There
|
|
6
|
+
* is no snapshot to fetch and nothing to merge. What this module adds is what a
|
|
7
|
+
* long-lived client needs around that:
|
|
8
|
+
*
|
|
9
|
+
* - one connection, however many parts of a page subscribe, and an unsubscribe
|
|
10
|
+
* that ends only its own subscription;
|
|
11
|
+
* - the last value of every topic, so a second subscriber to a topic gets it at
|
|
12
|
+
* once instead of waiting for the next change;
|
|
13
|
+
* - a fresh token before the old one runs out — the node ends a session when
|
|
14
|
+
* its token expires — and every subscription sent again on the new connection;
|
|
15
|
+
* - growing, jittered waits between attempts after a drop, each with a fresh
|
|
16
|
+
* token;
|
|
17
|
+
* - commands that wait for their acknowledgement.
|
|
18
|
+
*
|
|
19
|
+
* These are values, not a log: a change that happens while the connection is
|
|
20
|
+
* being replaced is superseded by the retained value that follows. Anything that
|
|
21
|
+
* must see every record reads a stream through the door instead.
|
|
22
|
+
*
|
|
23
|
+
* mqtt.js is loaded on first use and is an optional dependency of this package.
|
|
24
|
+
*/
|
|
25
|
+
export type LiveState = "connecting" | "online" | "offline" | "closed";
|
|
26
|
+
export type Qos = 0 | 1;
|
|
27
|
+
export interface LiveValue<T = unknown> {
|
|
28
|
+
topic: string;
|
|
29
|
+
/** `undefined` when the path was retired with an empty payload. */
|
|
30
|
+
payload: T | undefined;
|
|
31
|
+
/** The value the node held when the subscription started, rather than a change. */
|
|
32
|
+
retained: boolean;
|
|
33
|
+
/** Local clock, unix milliseconds — for showing age, not for ordering records. */
|
|
34
|
+
receivedAt: number;
|
|
35
|
+
}
|
|
36
|
+
export interface SubscribeOptions {
|
|
37
|
+
/** 1 for records that must not get lost in flight, acknowledgements for instance. */
|
|
38
|
+
qos?: Qos;
|
|
39
|
+
}
|
|
40
|
+
/** A command's answer, `_Ack`. `result_code` reads like HTTP: 200 means done. */
|
|
41
|
+
export interface CommandAck {
|
|
42
|
+
correlation_id: string;
|
|
43
|
+
result_code: number;
|
|
44
|
+
message?: string;
|
|
45
|
+
performed_at?: number | null;
|
|
46
|
+
[field: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
export interface CommandOptions {
|
|
49
|
+
/** How long the command stays valid at the node, and how long to wait for its answer. */
|
|
50
|
+
timeoutMs?: number;
|
|
51
|
+
/** Where the answer arrives: every `_Ack` under the command's root, unless given. */
|
|
52
|
+
ackFilter?: string;
|
|
53
|
+
}
|
|
54
|
+
/** Nobody answered a command before it expired. */
|
|
55
|
+
export declare class CommandTimeout extends Error {
|
|
56
|
+
readonly topic: string;
|
|
57
|
+
readonly correlationId: string;
|
|
58
|
+
constructor(topic: string, correlationId: string);
|
|
59
|
+
}
|
|
60
|
+
/** What is handed to the MQTT client for each connection. */
|
|
61
|
+
export interface MqttConnectOptions {
|
|
62
|
+
clientId: string;
|
|
63
|
+
username: string;
|
|
64
|
+
password: string;
|
|
65
|
+
protocolVersion: 5;
|
|
66
|
+
clean: true;
|
|
67
|
+
keepalive: number;
|
|
68
|
+
/** Zero: reconnecting is this module's job, because every attempt needs a fresh token. */
|
|
69
|
+
reconnectPeriod: 0;
|
|
70
|
+
connectTimeout: number;
|
|
71
|
+
[option: string]: unknown;
|
|
72
|
+
}
|
|
73
|
+
/** The part of an MQTT client this module uses; mqtt.js's client fits. */
|
|
74
|
+
export interface MqttLike {
|
|
75
|
+
on(event: "connect" | "close", listener: () => void): unknown;
|
|
76
|
+
on(event: "error", listener: (error: Error) => void): unknown;
|
|
77
|
+
on(event: "message", listener: (topic: string, payload: Uint8Array, packet: {
|
|
78
|
+
retain: boolean;
|
|
79
|
+
}) => void): unknown;
|
|
80
|
+
subscribe(filters: string[], options: {
|
|
81
|
+
qos: Qos;
|
|
82
|
+
}, callback?: (error: Error | null, granted?: {
|
|
83
|
+
topic: string;
|
|
84
|
+
qos: number;
|
|
85
|
+
}[]) => void): unknown;
|
|
86
|
+
unsubscribe(filters: string[]): unknown;
|
|
87
|
+
publish(topic: string, message: string, options: {
|
|
88
|
+
qos: Qos;
|
|
89
|
+
retain: false;
|
|
90
|
+
}, callback?: (error?: Error) => void): unknown;
|
|
91
|
+
end(force?: boolean): unknown;
|
|
92
|
+
}
|
|
93
|
+
export interface LiveOptions {
|
|
94
|
+
/** The node's WebSocket door for people and applications, e.g. `wss://node:8885`. */
|
|
95
|
+
url: string;
|
|
96
|
+
/** Asked before every connection attempt; hand back a token that is valid now. */
|
|
97
|
+
token: () => string | Promise<string>;
|
|
98
|
+
/** The node requires the token's `sub` here, which is the default. Set it for a token that is not a JWT. */
|
|
99
|
+
username?: string;
|
|
100
|
+
/** Reconnect with a new token this long before the current one expires. */
|
|
101
|
+
renewBeforeMs?: number;
|
|
102
|
+
/** The first wait after a failed attempt. It doubles up to `maxRetryMs`. */
|
|
103
|
+
retryMs?: number;
|
|
104
|
+
maxRetryMs?: number;
|
|
105
|
+
clientIdPrefix?: string;
|
|
106
|
+
/** Passed to the MQTT client as they are — TLS settings for a service, for instance. */
|
|
107
|
+
mqttOptions?: Readonly<Record<string, unknown>>;
|
|
108
|
+
/** Problems the client lives through: refused connections, unreadable payloads, throwing listeners. */
|
|
109
|
+
onError?: (error: Error) => void;
|
|
110
|
+
/** How a connection is made. mqtt.js by default. */
|
|
111
|
+
connect?: (url: string, options: MqttConnectOptions) => MqttLike | Promise<MqttLike>;
|
|
112
|
+
}
|
|
113
|
+
export declare class Live {
|
|
114
|
+
#private;
|
|
115
|
+
constructor(options: LiveOptions);
|
|
116
|
+
get state(): LiveState;
|
|
117
|
+
/**
|
|
118
|
+
* Values under `filter` (MQTT wildcards allowed), the current ones first. Returns
|
|
119
|
+
* the function that ends this subscription and no other.
|
|
120
|
+
*/
|
|
121
|
+
subscribe<T = unknown>(filter: string, listener: (value: LiveValue<T>) => void, options?: SubscribeOptions): () => void;
|
|
122
|
+
/** The last value seen on a topic, if anyone is subscribed to it. */
|
|
123
|
+
latest<T = unknown>(topic: string): LiveValue<T> | undefined;
|
|
124
|
+
/** Every last value under a filter. */
|
|
125
|
+
values<T = unknown>(filter: string): LiveValue<T>[];
|
|
126
|
+
/**
|
|
127
|
+
* One record, as JSON, under this caller's identity. Nothing is queued: offline
|
|
128
|
+
* it fails at once, because a command sent minutes later is a different command.
|
|
129
|
+
* A person's session may only send commands; the node refuses anything else.
|
|
130
|
+
*/
|
|
131
|
+
publish(topic: string, payload: unknown, options?: {
|
|
132
|
+
qos?: Qos;
|
|
133
|
+
}): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Send a command and wait for its acknowledgement.
|
|
136
|
+
*
|
|
137
|
+
* `body` is the command's own fields — `params` for a `_CmdParam`, say. The
|
|
138
|
+
* correlation id and the expiry are added here, and the answer is matched by
|
|
139
|
+
* the id, wherever in the tree the executor publishes it. The promise settles
|
|
140
|
+
* with the `_Ack`, whatever its `result_code`; it rejects when nothing answers
|
|
141
|
+
* in `timeoutMs`, when the node refuses the publish, or when the client closes.
|
|
142
|
+
*/
|
|
143
|
+
command(topic: string, body?: Record<string, unknown>, options?: CommandOptions): Promise<CommandAck>;
|
|
144
|
+
/** Called on every change of the connection state; returns the function that stops it. */
|
|
145
|
+
onState(listener: (state: LiveState) => void): () => void;
|
|
146
|
+
close(): void;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}
|