@freqhole/reliquary 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worker/index.d.ts +2 -2
- package/dist/worker/index.d.ts.map +1 -1
- package/dist/worker/index.js +1 -1
- package/dist/worker/midden-worker-client.d.ts +35 -3
- package/dist/worker/midden-worker-client.d.ts.map +1 -1
- package/dist/worker/midden-worker-client.js +53 -3
- package/dist/worker/midden-worker-client.test.js +7 -1
- package/dist/worker/midden-worker-contract.d.ts +33 -1
- package/dist/worker/midden-worker-contract.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/worker/index.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ export type { ProcessedBlob, ResizeImageOptions } from "./blob-worker-logic.js";
|
|
|
2
2
|
export { BLOB_WORKER_READY_MESSAGE, OPFS_DIR as BLOB_OPFS_DIR } from "./blob-worker-logic.js";
|
|
3
3
|
export type { BlobWorkerApi } from "./blob-worker.js";
|
|
4
4
|
export { getBlobWorker, shutdownBlobWorker, hashBlake3, hashBlake3Streaming, hashSha256, base64Encode, base64Decode, processBlobBytes, writeBlobToOpfs, streamFileToOpfs, resizeImageToWebpDataUrl, generateThumbnailDataUrl, } from "./blob-worker-client.js";
|
|
5
|
-
export type { MiddenWorkerApi, MiddenWorkerIdentity, StreamInfo, } from "./midden-worker-contract.js";
|
|
5
|
+
export type { MiddenWorkerApi, MiddenWorkerIdentity, MiddenWorkerInitOptions, StreamInfo, } from "./midden-worker-contract.js";
|
|
6
6
|
export { MIDDEN_WORKER_READY_MESSAGE, MIDDEN_WORKER_READY_TIMEOUT_MS, } from "./midden-worker-contract.js";
|
|
7
7
|
export type { CreateMiddenWorker } from "./midden-worker-client.js";
|
|
8
|
-
export { WorkerBiStream, WorkerImportSession, WorkerMiddenNode } from "./midden-worker-client.js";
|
|
8
|
+
export { WorkerBiStream, WorkerImportSession, WorkerMiddenNode, WorkerRadioHandle, } from "./midden-worker-client.js";
|
|
9
9
|
export { MiddenNode } from "./midden-stub.js";
|
|
10
10
|
export type { Blake3HasherLike, MiddenBlake3Module } from "./midden-blake3.js";
|
|
11
11
|
export { loadMiddenBlake3, resetMiddenBlake3Cache } from "./midden-blake3.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/worker/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE9F,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,UAAU,GACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC;AAErC,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/worker/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE9F,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EACvB,UAAU,GACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC;AAErC,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/worker/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { BLOB_WORKER_READY_MESSAGE, OPFS_DIR as BLOB_OPFS_DIR } from "./blob-worker-logic.js";
|
|
2
2
|
export { getBlobWorker, shutdownBlobWorker, hashBlake3, hashBlake3Streaming, hashSha256, base64Encode, base64Decode, processBlobBytes, writeBlobToOpfs, streamFileToOpfs, resizeImageToWebpDataUrl, generateThumbnailDataUrl, } from "./blob-worker-client.js";
|
|
3
3
|
export { MIDDEN_WORKER_READY_MESSAGE, MIDDEN_WORKER_READY_TIMEOUT_MS, } from "./midden-worker-contract.js";
|
|
4
|
-
export { WorkerBiStream, WorkerImportSession, WorkerMiddenNode } from "./midden-worker-client.js";
|
|
4
|
+
export { WorkerBiStream, WorkerImportSession, WorkerMiddenNode, WorkerRadioHandle, } from "./midden-worker-client.js";
|
|
5
5
|
export { MiddenNode } from "./midden-stub.js";
|
|
6
6
|
export { loadMiddenBlake3, resetMiddenBlake3Cache } from "./midden-blake3.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Comlink from "comlink";
|
|
2
|
-
import { type MiddenWorkerApi, type StreamInfo, type WorkerActiveTransfer } from "./midden-worker-contract.js";
|
|
2
|
+
import { type MiddenWorkerApi, type MiddenWorkerInitOptions, type StreamInfo, type WorkerActiveTransfer } from "./midden-worker-contract.js";
|
|
3
3
|
type Api = Comlink.Remote<MiddenWorkerApi>;
|
|
4
4
|
/** main-thread face of a worker-held BiStream. implements BiStreamLike. */
|
|
5
5
|
export declare class WorkerBiStream {
|
|
@@ -12,6 +12,11 @@ export declare class WorkerBiStream {
|
|
|
12
12
|
write_message(data: Uint8Array): Promise<void>;
|
|
13
13
|
read_to_end(maxSize: number): Promise<Uint8Array>;
|
|
14
14
|
write_raw_and_finish(data: Uint8Array): Promise<void>;
|
|
15
|
+
/** newline-delimited framing (ndjson) - a separate mode from
|
|
16
|
+
* write_message/read_message's length-prefixed framing, over the same
|
|
17
|
+
* underlying stream. used by the freqhole-events/1 protocol. */
|
|
18
|
+
write_line(line: string): Promise<void>;
|
|
19
|
+
read_line(): Promise<string | null>;
|
|
15
20
|
/** fire-and-forget, matching a wasm BiStream's sync close(). */
|
|
16
21
|
close(): void;
|
|
17
22
|
}
|
|
@@ -26,6 +31,18 @@ export declare class WorkerImportSession {
|
|
|
26
31
|
finish(): Promise<string>;
|
|
27
32
|
abort(): void;
|
|
28
33
|
}
|
|
34
|
+
/** main-thread face of a worker-held RadioHandle. implements RadioHandleLike
|
|
35
|
+
* (a plain `.leave()`) - only meaningful against a worker entry that
|
|
36
|
+
* implements `tuneRadio`/`radioLeave` (e.g. spume's; skein's doesn't). */
|
|
37
|
+
export declare class WorkerRadioHandle {
|
|
38
|
+
private readonly api;
|
|
39
|
+
private readonly handleId;
|
|
40
|
+
constructor(api: Api, handleId: number);
|
|
41
|
+
/** fire-and-forget, matching a wasm RadioHandle's sync leave(). a worker
|
|
42
|
+
* entry that doesn't implement radioLeave (skein's doesn't) rejects
|
|
43
|
+
* naturally - there's nothing meaningful to do with that error here. */
|
|
44
|
+
leave(): void;
|
|
45
|
+
}
|
|
29
46
|
/**
|
|
30
47
|
* constructs (or otherwise obtains) the Worker instance hosting the midden
|
|
31
48
|
* worker entry. this package doesn't own that entry file (see
|
|
@@ -57,8 +74,10 @@ export declare class WorkerMiddenNode {
|
|
|
57
74
|
private readonly secretKey;
|
|
58
75
|
private constructor();
|
|
59
76
|
/** spawn the worker (via `createWorker`), wait for the ready handshake,
|
|
60
|
-
* create the node.
|
|
61
|
-
|
|
77
|
+
* create the node. `initOptions` is forwarded to the entry's `init` -
|
|
78
|
+
* see `MiddenWorkerInitOptions` for what an entry may choose to do with
|
|
79
|
+
* it (skein's own entry ignores it entirely; it's opt-in per entry). */
|
|
80
|
+
static create(secretKey: Uint8Array | null, createWorker: CreateMiddenWorker, initOptions?: MiddenWorkerInitOptions): Promise<WorkerMiddenNode>;
|
|
62
81
|
/** tear the worker down (identity delete/import). in-flight calls reject. */
|
|
63
82
|
terminate(): void;
|
|
64
83
|
node_id(): string;
|
|
@@ -104,6 +123,19 @@ export declare class WorkerMiddenNode {
|
|
|
104
123
|
status: number;
|
|
105
124
|
body: string;
|
|
106
125
|
}>;
|
|
126
|
+
/** alias for proxy_request, matching the real wasm MiddenNode's method
|
|
127
|
+
* name (`api_request`) - callers typed against MiddenNodeLike (which
|
|
128
|
+
* mirrors the wasm class) work unchanged against a worker-hosted node. */
|
|
129
|
+
api_request(peerAddr: string, method: string, path: string, body?: string | null): Promise<{
|
|
130
|
+
status: number;
|
|
131
|
+
body: string;
|
|
132
|
+
}>;
|
|
133
|
+
/** dispatches to the connected worker entry's proxyAdmin - rejects
|
|
134
|
+
* naturally if that entry doesn't implement it (e.g. skein's). */
|
|
135
|
+
proxy_admin(peerAddr: string, command: string, args: string): Promise<unknown>;
|
|
136
|
+
/** dispatches to the connected worker entry's tuneRadio - rejects
|
|
137
|
+
* naturally if that entry doesn't implement it (e.g. skein's). */
|
|
138
|
+
tune_radio(peerAddr: string, stationId: string | undefined, onHello: (json: string) => void, onMeta: (json: string) => void, onChunk: (seq: number, isInit: boolean, bytes: Uint8Array) => void): Promise<WorkerRadioHandle>;
|
|
107
139
|
}
|
|
108
140
|
export {};
|
|
109
141
|
//# sourceMappingURL=midden-worker-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midden-worker-client.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAC;AAKrC,KAAK,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AAa3C,2EAA2E;AAC3E,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,UAAU;IAGnC,YAAY,IAAI,MAAM;IAItB,IAAI,IAAI,MAAM;IAIR,YAAY,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI1C,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIjD,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,gEAAgE;IAChE,KAAK,IAAI,IAAI;CAKd;AAED;;cAEc;AACd,qBAAa,mBAAmB;IAGlB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;gBAEf,GAAG,EAAE,GAAG;IAI/B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAK/B,KAAK,IAAI,IAAI;CAGd;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,MAAM,CAAC;AAE9C;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO;IAOP;
|
|
1
|
+
{"version":3,"file":"midden-worker-client.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,6 +53,15 @@ export class WorkerBiStream {
|
|
|
53
53
|
async write_raw_and_finish(data) {
|
|
54
54
|
await this.api.streamWriteRawAndFinish(this.info.streamId, toTransferable(data));
|
|
55
55
|
}
|
|
56
|
+
/** newline-delimited framing (ndjson) - a separate mode from
|
|
57
|
+
* write_message/read_message's length-prefixed framing, over the same
|
|
58
|
+
* underlying stream. used by the freqhole-events/1 protocol. */
|
|
59
|
+
async write_line(line) {
|
|
60
|
+
await this.api.streamWriteLine(this.info.streamId, line);
|
|
61
|
+
}
|
|
62
|
+
async read_line() {
|
|
63
|
+
return this.api.streamReadLine(this.info.streamId);
|
|
64
|
+
}
|
|
56
65
|
/** fire-and-forget, matching a wasm BiStream's sync close(). */
|
|
57
66
|
close() {
|
|
58
67
|
this.api.streamClose(this.info.streamId).catch(() => {
|
|
@@ -82,6 +91,25 @@ export class WorkerImportSession {
|
|
|
82
91
|
void this.sessionId.then((id) => this.api.importAbort(id)).catch(() => { });
|
|
83
92
|
}
|
|
84
93
|
}
|
|
94
|
+
/** main-thread face of a worker-held RadioHandle. implements RadioHandleLike
|
|
95
|
+
* (a plain `.leave()`) - only meaningful against a worker entry that
|
|
96
|
+
* implements `tuneRadio`/`radioLeave` (e.g. spume's; skein's doesn't). */
|
|
97
|
+
export class WorkerRadioHandle {
|
|
98
|
+
api;
|
|
99
|
+
handleId;
|
|
100
|
+
constructor(api, handleId) {
|
|
101
|
+
this.api = api;
|
|
102
|
+
this.handleId = handleId;
|
|
103
|
+
}
|
|
104
|
+
/** fire-and-forget, matching a wasm RadioHandle's sync leave(). a worker
|
|
105
|
+
* entry that doesn't implement radioLeave (skein's doesn't) rejects
|
|
106
|
+
* naturally - there's nothing meaningful to do with that error here. */
|
|
107
|
+
leave() {
|
|
108
|
+
this.api.radioLeave(this.handleId).catch(() => {
|
|
109
|
+
// worker gone (or doesn't implement this) - nothing to leave
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
85
113
|
/**
|
|
86
114
|
* main-thread face of a worker-hosted MiddenNode. same snake_case method
|
|
87
115
|
* names as a wasm node so existing call sites and capability probes
|
|
@@ -104,8 +132,10 @@ export class WorkerMiddenNode {
|
|
|
104
132
|
this.secretKey = secretKey;
|
|
105
133
|
}
|
|
106
134
|
/** spawn the worker (via `createWorker`), wait for the ready handshake,
|
|
107
|
-
* create the node.
|
|
108
|
-
|
|
135
|
+
* create the node. `initOptions` is forwarded to the entry's `init` -
|
|
136
|
+
* see `MiddenWorkerInitOptions` for what an entry may choose to do with
|
|
137
|
+
* it (skein's own entry ignores it entirely; it's opt-in per entry). */
|
|
138
|
+
static async create(secretKey, createWorker, initOptions) {
|
|
109
139
|
const worker = createWorker();
|
|
110
140
|
const ready = await new Promise((resolve) => {
|
|
111
141
|
const timeout = setTimeout(() => {
|
|
@@ -143,7 +173,7 @@ export class WorkerMiddenNode {
|
|
|
143
173
|
}
|
|
144
174
|
const api = Comlink.wrap(worker);
|
|
145
175
|
try {
|
|
146
|
-
const identity = await api.init(secretKey);
|
|
176
|
+
const identity = await api.init(secretKey, initOptions);
|
|
147
177
|
log.debug(TAG, "worker node ready:", identity.nodeId.slice(0, 16) + "...");
|
|
148
178
|
return new WorkerMiddenNode(api, worker, identity.nodeId, identity.secretKey);
|
|
149
179
|
}
|
|
@@ -253,4 +283,24 @@ export class WorkerMiddenNode {
|
|
|
253
283
|
async proxy_request(peerAddr, method, path, body) {
|
|
254
284
|
return this.api.proxyRequest(peerAddr, method, path, body ?? null);
|
|
255
285
|
}
|
|
286
|
+
/** alias for proxy_request, matching the real wasm MiddenNode's method
|
|
287
|
+
* name (`api_request`) - callers typed against MiddenNodeLike (which
|
|
288
|
+
* mirrors the wasm class) work unchanged against a worker-hosted node. */
|
|
289
|
+
async api_request(peerAddr, method, path, body) {
|
|
290
|
+
return this.proxy_request(peerAddr, method, path, body);
|
|
291
|
+
}
|
|
292
|
+
// ---- admin / radio ----
|
|
293
|
+
// only meaningful against a worker entry that implements these (spume's
|
|
294
|
+
// does; skein's doesn't need to).
|
|
295
|
+
/** dispatches to the connected worker entry's proxyAdmin - rejects
|
|
296
|
+
* naturally if that entry doesn't implement it (e.g. skein's). */
|
|
297
|
+
async proxy_admin(peerAddr, command, args) {
|
|
298
|
+
return this.api.proxyAdmin(peerAddr, command, args);
|
|
299
|
+
}
|
|
300
|
+
/** dispatches to the connected worker entry's tuneRadio - rejects
|
|
301
|
+
* naturally if that entry doesn't implement it (e.g. skein's). */
|
|
302
|
+
async tune_radio(peerAddr, stationId, onHello, onMeta, onChunk) {
|
|
303
|
+
const handleId = await this.api.tuneRadio(peerAddr, stationId, Comlink.proxy(onHello), Comlink.proxy(onMeta), Comlink.proxy(onChunk));
|
|
304
|
+
return new WorkerRadioHandle(this.api, handleId);
|
|
305
|
+
}
|
|
256
306
|
}
|
|
@@ -21,6 +21,8 @@ function makeFakeApi(overrides = {}) {
|
|
|
21
21
|
streamWriteMessage: vi.fn(async () => undefined),
|
|
22
22
|
streamReadToEnd: vi.fn(async () => new Uint8Array()),
|
|
23
23
|
streamWriteRawAndFinish: vi.fn(async () => undefined),
|
|
24
|
+
streamWriteLine: vi.fn(async () => undefined),
|
|
25
|
+
streamReadLine: vi.fn(async () => null),
|
|
24
26
|
streamClose: vi.fn(async () => undefined),
|
|
25
27
|
importBlob: vi.fn(),
|
|
26
28
|
importBlobAndExportBao: vi.fn(),
|
|
@@ -47,6 +49,9 @@ function makeFakeApi(overrides = {}) {
|
|
|
47
49
|
unprotectBlob: vi.fn(),
|
|
48
50
|
computeBlake3: vi.fn(),
|
|
49
51
|
proxyRequest: vi.fn(),
|
|
52
|
+
proxyAdmin: vi.fn(),
|
|
53
|
+
tuneRadio: vi.fn(),
|
|
54
|
+
radioLeave: vi.fn(),
|
|
50
55
|
...overrides,
|
|
51
56
|
};
|
|
52
57
|
}
|
|
@@ -105,7 +110,8 @@ describe("WorkerBiStream", () => {
|
|
|
105
110
|
const stream = new WorkerBiStream(api, STREAM_INFO);
|
|
106
111
|
const original = new Uint8Array([1, 1, 1]);
|
|
107
112
|
await stream.write_raw_and_finish(original);
|
|
108
|
-
const [calledStreamId, sentBytes] = api.streamWriteRawAndFinish
|
|
113
|
+
const [calledStreamId, sentBytes] = api.streamWriteRawAndFinish
|
|
114
|
+
.mock.calls[0];
|
|
109
115
|
expect(calledStreamId).toBe(7);
|
|
110
116
|
expect(sentBytes.buffer).not.toBe(original.buffer);
|
|
111
117
|
expect(Array.from(sentBytes)).toEqual([1, 1, 1]);
|
|
@@ -11,6 +11,19 @@ export interface MiddenWorkerIdentity {
|
|
|
11
11
|
nodeId: string;
|
|
12
12
|
secretKey: Uint8Array;
|
|
13
13
|
}
|
|
14
|
+
/** optional per-instance startup config an embedding app's worker entry may
|
|
15
|
+
* read during `init`. none of these fields are interpreted by this
|
|
16
|
+
* package itself - the entry decides what, if anything, to do with them
|
|
17
|
+
* (e.g. spume's worker merges extraAlpns into its own hardcoded ALPN
|
|
18
|
+
* list, and sets relay_urls/relay_custom_only on MiddenNodeOptions when
|
|
19
|
+
* given). this just gives the client a typed way to pass through
|
|
20
|
+
* instance-specific config without baking any particular app's shape
|
|
21
|
+
* into the shared contract. */
|
|
22
|
+
export interface MiddenWorkerInitOptions {
|
|
23
|
+
relayUrls?: string[];
|
|
24
|
+
relayCustomOnly?: boolean;
|
|
25
|
+
extraAlpns?: string[];
|
|
26
|
+
}
|
|
14
27
|
/** one outgoing blob transfer in flight on the worker-hosted node - same
|
|
15
28
|
* shape as a raw wasm MiddenNode's `get_active_transfers()`
|
|
16
29
|
* (`{peerId, blake3, bytesSent, totalSize}`, see midden/src/transfers.rs). */
|
|
@@ -33,7 +46,7 @@ export interface WorkerActiveTransfer {
|
|
|
33
46
|
*/
|
|
34
47
|
export interface MiddenWorkerApi {
|
|
35
48
|
/** create the node (restoring from a persisted secret key when given). */
|
|
36
|
-
init(secretKey: Uint8Array | null): Promise<MiddenWorkerIdentity>;
|
|
49
|
+
init(secretKey: Uint8Array | null, options?: MiddenWorkerInitOptions): Promise<MiddenWorkerIdentity>;
|
|
37
50
|
openBi(peerAddr: string, alpn: string): Promise<StreamInfo>;
|
|
38
51
|
/** long-poll: resolves with the next accepted stream, or null when the
|
|
39
52
|
* endpoint closes. */
|
|
@@ -42,6 +55,11 @@ export interface MiddenWorkerApi {
|
|
|
42
55
|
streamWriteMessage(streamId: number, data: Uint8Array): Promise<void>;
|
|
43
56
|
streamReadToEnd(streamId: number, maxSize: number): Promise<Uint8Array>;
|
|
44
57
|
streamWriteRawAndFinish(streamId: number, data: Uint8Array): Promise<void>;
|
|
58
|
+
/** newline-delimited framing (ndjson) - a separate mode from
|
|
59
|
+
* streamWriteMessage/streamReadMessage's length-prefixed framing, over
|
|
60
|
+
* the same underlying stream. used by the freqhole-events/1 protocol. */
|
|
61
|
+
streamWriteLine(streamId: number, line: string): Promise<void>;
|
|
62
|
+
streamReadLine(streamId: number): Promise<string | null>;
|
|
45
63
|
/** idempotent - closing an already-closed/dead stream id is a no-op. */
|
|
46
64
|
streamClose(streamId: number): Promise<void>;
|
|
47
65
|
importBlob(data: Uint8Array): Promise<string>;
|
|
@@ -90,6 +108,20 @@ export interface MiddenWorkerApi {
|
|
|
90
108
|
status: number;
|
|
91
109
|
body: string;
|
|
92
110
|
}>;
|
|
111
|
+
/** dispatch a freqhole-admin/1 ALPN command to a peer - forwards to the
|
|
112
|
+
* wasm node's proxy_admin. args is a json-encoded string (the literal
|
|
113
|
+
* string null for no-payload commands). returns the grimoire response
|
|
114
|
+
* envelope as a plain object ({ success, message, data, errors }). */
|
|
115
|
+
proxyAdmin(peerAddr: string, command: string, args: string): Promise<unknown>;
|
|
116
|
+
/** tune into a freqhole radio broadcaster (freqhole-radio/1 ALPN) -
|
|
117
|
+
* forwards to the wasm node's tune_radio. callbacks fire
|
|
118
|
+
* fire-and-forget from the entry side, same as the download
|
|
119
|
+
* progress/chunk callbacks above. returns an opaque handle id for
|
|
120
|
+
* radioLeave. */
|
|
121
|
+
tuneRadio(peerAddr: string, stationId: string | undefined, onHello: (json: string) => void, onMeta: (json: string) => void, onChunk: (seq: number, isInit: boolean, bytes: Uint8Array) => void): Promise<number>;
|
|
122
|
+
/** close a tuned-in radio session (stops audio + meta callbacks).
|
|
123
|
+
* idempotent - closing an already-closed/unknown handle id is a no-op. */
|
|
124
|
+
radioLeave(handleId: number): Promise<void>;
|
|
93
125
|
}
|
|
94
126
|
/** message the entry must `postMessage` immediately after `Comlink.expose()`
|
|
95
127
|
* registers its message listener - and not a moment before. an rpc call
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midden-worker-contract.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-contract.ts"],"names":[],"mappings":"AAqBA;mEACmE;AACnE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;uEACuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;+EAE+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,IAAI,
|
|
1
|
+
{"version":3,"file":"midden-worker-contract.d.ts","sourceRoot":"","sources":["../../src/worker/midden-worker-contract.ts"],"names":[],"mappings":"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"}
|